ComputeViewIdState.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // ComputeViewIdState.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "dxc/HLSL/ComputeViewIdState.h"
  10. #include "dxc/Support/Global.h"
  11. #include "dxc/HLSL/DxilModule.h"
  12. #include "dxc/HLSL/DxilOperations.h"
  13. #include "dxc/HLSL/DxilInstructions.h"
  14. #include "llvm/IR/LLVMContext.h"
  15. #include "llvm/IR/Module.h"
  16. #include "llvm/IR/Function.h"
  17. #include "llvm/IR/Operator.h"
  18. #include "llvm/Pass.h"
  19. #include "llvm/IR/LegacyPassManager.h"
  20. #include "llvm/Support/Debug.h"
  21. #include "llvm/IR/CFG.h"
  22. #include "llvm/Analysis/CallGraph.h"
  23. #include <algorithm>
  24. using namespace llvm;
  25. using namespace llvm::legacy;
  26. using namespace hlsl;
  27. using llvm::legacy::PassManager;
  28. using llvm::legacy::FunctionPassManager;
  29. using std::vector;
  30. using std::unordered_set;
  31. using std::unordered_map;
  32. #define DXILVIEWID_DBG 0
  33. #define DEBUG_TYPE "viewid"
  34. DxilViewIdState::DxilViewIdState(DxilModule *pDxilModule) : m_pModule(pDxilModule) {}
  35. unsigned DxilViewIdState::getNumInputSigScalars() const { return m_NumInputSigScalars; }
  36. unsigned DxilViewIdState::getNumOutputSigScalars(unsigned StreamId) const { return m_NumOutputSigScalars[StreamId]; }
  37. unsigned DxilViewIdState::getNumPCSigScalars() const { return m_NumPCSigScalars; }
  38. const DxilViewIdState::OutputsDependentOnViewIdType &DxilViewIdState::getOutputsDependentOnViewId(unsigned StreamId) const { return m_OutputsDependentOnViewId[StreamId]; }
  39. const DxilViewIdState::OutputsDependentOnViewIdType &DxilViewIdState::getPCOutputsDependentOnViewId() const { return m_PCOutputsDependentOnViewId; }
  40. const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getInputsContributingToOutputs(unsigned StreamId) const { return m_InputsContributingToOutputs[StreamId]; }
  41. const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getInputsContributingToPCOutputs() const { return m_InputsContributingToPCOutputs; }
  42. const DxilViewIdState::InputsContributingToOutputType &DxilViewIdState::getPCInputsContributingToOutputs() const { return m_PCInputsContributingToOutputs; }
  43. namespace {
  44. void PrintOutputsDependentOnViewId(
  45. llvm::raw_ostream &OS, llvm::StringRef SetName, unsigned NumOutputs,
  46. const DxilViewIdState::OutputsDependentOnViewIdType
  47. &OutputsDependentOnViewId) {
  48. OS << SetName << " dependent on ViewId: { ";
  49. bool bFirst = true;
  50. for (unsigned i = 0; i < NumOutputs; i++) {
  51. if (OutputsDependentOnViewId[i]) {
  52. if (!bFirst)
  53. OS << ", ";
  54. OS << i;
  55. bFirst = false;
  56. }
  57. }
  58. OS << " }\n";
  59. }
  60. void PrintInputsContributingToOutputs(
  61. llvm::raw_ostream &OS, llvm::StringRef InputSetName,
  62. llvm::StringRef OutputSetName,
  63. const DxilViewIdState::InputsContributingToOutputType
  64. &InputsContributingToOutputs) {
  65. OS << InputSetName << " contributing to computation of " << OutputSetName
  66. << ":\n";
  67. for (auto &it : InputsContributingToOutputs) {
  68. unsigned outIdx = it.first;
  69. auto &Inputs = it.second;
  70. OS << "output " << outIdx << " depends on inputs: { ";
  71. bool bFirst = true;
  72. for (unsigned i : Inputs) {
  73. if (!bFirst)
  74. OS << ", ";
  75. OS << i;
  76. bFirst = false;
  77. }
  78. OS << " }\n";
  79. }
  80. }
  81. } // namespace
  82. void DxilViewIdState::PrintSets(llvm::raw_ostream &OS) {
  83. const ShaderModel *pSM = m_pModule->GetShaderModel();
  84. OS << "ViewId state: \n";
  85. if (!pSM->IsGS()) {
  86. OS << "Number of inputs: " << m_NumInputSigScalars <<
  87. ", outputs: " << m_NumOutputSigScalars[0] <<
  88. ", patchconst: " << m_NumPCSigScalars << "\n";
  89. } else {
  90. OS << "Number of inputs: " << m_NumInputSigScalars <<
  91. ", outputs: { " << m_NumOutputSigScalars[0] << ", " << m_NumOutputSigScalars[1] << ", " <<
  92. m_NumOutputSigScalars[2] << ", " << m_NumOutputSigScalars[3] << " }" <<
  93. ", patchconst: " << m_NumPCSigScalars << "\n";
  94. }
  95. if (!pSM->IsGS()) {
  96. PrintOutputsDependentOnViewId(OS, "Outputs", m_NumOutputSigScalars[0], m_OutputsDependentOnViewId[0]);
  97. } else {
  98. PrintOutputsDependentOnViewId(OS, "Outputs for Stream0", m_NumOutputSigScalars[0], m_OutputsDependentOnViewId[0]);
  99. PrintOutputsDependentOnViewId(OS, "Outputs for Stream1", m_NumOutputSigScalars[1], m_OutputsDependentOnViewId[1]);
  100. PrintOutputsDependentOnViewId(OS, "Outputs for Stream2", m_NumOutputSigScalars[2], m_OutputsDependentOnViewId[2]);
  101. PrintOutputsDependentOnViewId(OS, "Outputs for Stream3", m_NumOutputSigScalars[3], m_OutputsDependentOnViewId[3]);
  102. }
  103. if (pSM->IsHS()) {
  104. PrintOutputsDependentOnViewId(OS, "PCOutputs", m_NumPCSigScalars, m_PCOutputsDependentOnViewId);
  105. }
  106. if (!pSM->IsGS()) {
  107. PrintInputsContributingToOutputs(OS, "Inputs", "Outputs", m_InputsContributingToOutputs[0]);
  108. } else {
  109. PrintInputsContributingToOutputs(OS, "Inputs", "Outputs for Stream0", m_InputsContributingToOutputs[0]);
  110. PrintInputsContributingToOutputs(OS, "Inputs", "Outputs for Stream1", m_InputsContributingToOutputs[1]);
  111. PrintInputsContributingToOutputs(OS, "Inputs", "Outputs for Stream2", m_InputsContributingToOutputs[2]);
  112. PrintInputsContributingToOutputs(OS, "Inputs", "Outputs for Stream3", m_InputsContributingToOutputs[3]);
  113. }
  114. if (pSM->IsHS()) {
  115. PrintInputsContributingToOutputs(OS, "Inputs", "PCOutputs", m_InputsContributingToPCOutputs);
  116. } else if (pSM->IsDS()) {
  117. PrintInputsContributingToOutputs(OS, "PCInputs", "Outputs", m_PCInputsContributingToOutputs);
  118. }
  119. OS << "\n";
  120. }
  121. void DxilViewIdState::Clear() {
  122. m_NumInputSigScalars = 0;
  123. for (unsigned i = 0; i < kNumStreams; i++) {
  124. m_NumOutputSigScalars[i] = 0;
  125. m_OutputsDependentOnViewId[i].reset();
  126. m_InputsContributingToOutputs[i].clear();
  127. }
  128. m_NumPCSigScalars = 0;
  129. m_PCOutputsDependentOnViewId.reset();
  130. m_InputsContributingToPCOutputs.clear();
  131. m_PCInputsContributingToOutputs.clear();
  132. m_SerializedState.clear();
  133. }
  134. namespace {
  135. unsigned RoundUpToUINT(unsigned x) { return (x + 31) / 32; }
  136. void SerializeOutputsDependentOnViewId(
  137. unsigned NumOutputs,
  138. const DxilViewIdState::OutputsDependentOnViewIdType
  139. &OutputsDependentOnViewId,
  140. unsigned *&pData) {
  141. unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
  142. // Serialize output dependence on ViewId.
  143. for (unsigned i = 0; i < NumOutUINTs; i++) {
  144. unsigned x = 0;
  145. for (unsigned j = 0; j < std::min(32u, NumOutputs - 32u * i); j++) {
  146. if (OutputsDependentOnViewId[i * 32 + j]) {
  147. x |= (1u << j);
  148. }
  149. }
  150. *pData++ = x;
  151. }
  152. }
  153. void SerializeInputsContributingToOutput(
  154. unsigned NumInputs, unsigned NumOutputs,
  155. const DxilViewIdState::InputsContributingToOutputType
  156. &InputsContributingToOutputs,
  157. unsigned *&pData) {
  158. unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
  159. // Serialize output dependence on inputs.
  160. for (unsigned outputIdx = 0; outputIdx < NumOutputs; outputIdx++) {
  161. auto it = InputsContributingToOutputs.find(outputIdx);
  162. if (it != InputsContributingToOutputs.end()) {
  163. for (unsigned inputIdx : it->second) {
  164. unsigned w = outputIdx / 32;
  165. unsigned b = outputIdx % 32;
  166. pData[inputIdx * NumOutUINTs + w] |= (1u << b);
  167. }
  168. }
  169. }
  170. pData += NumInputs * NumOutUINTs;
  171. }
  172. } // namespace
  173. void DxilViewIdState::Serialize() {
  174. const ShaderModel *pSM = m_pModule->GetShaderModel();
  175. m_SerializedState.clear();
  176. // Compute serialized state size in UINTs.
  177. unsigned NumInputs = getNumInputSigScalars();
  178. unsigned NumStreams = pSM->IsGS() ? kNumStreams : 1;
  179. unsigned Size = 0;
  180. Size += 1; // #Inputs.
  181. for (unsigned StreamId = 0; StreamId < NumStreams; StreamId++) {
  182. Size += 1; // #Outputs for stream StreamId.
  183. unsigned NumOutputs = getNumOutputSigScalars(StreamId);
  184. unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
  185. if (m_bUsesViewId) {
  186. Size += NumOutUINTs; // m_OutputsDependentOnViewId[StreamId]
  187. }
  188. Size += NumInputs * NumOutUINTs; // m_InputsContributingToOutputs[StreamId]
  189. }
  190. if (pSM->IsHS() || pSM->IsDS()) {
  191. Size += 1; // #PatchConstant.
  192. unsigned NumPCs = getNumPCSigScalars();
  193. unsigned NumPCUINTs = RoundUpToUINT(NumPCs);
  194. if (pSM->IsHS()) {
  195. if (m_bUsesViewId) {
  196. Size += NumPCUINTs; // m_PCOutputsDependentOnViewId
  197. }
  198. Size += NumInputs * NumPCUINTs; // m_InputsContributingToPCOutputs
  199. } else {
  200. unsigned NumOutputs = getNumOutputSigScalars(0);
  201. unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
  202. Size += NumPCs * NumOutUINTs; // m_PCInputsContributingToOutputs
  203. }
  204. }
  205. m_SerializedState.resize(Size);
  206. std::fill(m_SerializedState.begin(), m_SerializedState.end(), 0u);
  207. // Serialize ViewId state.
  208. unsigned *pData = &m_SerializedState[0];
  209. *pData++ = NumInputs;
  210. for (unsigned StreamId = 0; StreamId < NumStreams; StreamId++) {
  211. unsigned NumOutputs = getNumOutputSigScalars(StreamId);
  212. *pData++ = NumOutputs;
  213. if (m_bUsesViewId) {
  214. SerializeOutputsDependentOnViewId(
  215. NumOutputs, m_OutputsDependentOnViewId[StreamId], pData);
  216. }
  217. SerializeInputsContributingToOutput(
  218. NumInputs, NumOutputs, m_InputsContributingToOutputs[StreamId], pData);
  219. }
  220. if (pSM->IsHS() || pSM->IsDS()) {
  221. unsigned NumPCs = getNumPCSigScalars();
  222. *pData++ = NumPCs;
  223. if (pSM->IsHS()) {
  224. if (m_bUsesViewId) {
  225. SerializeOutputsDependentOnViewId(NumPCs, m_PCOutputsDependentOnViewId,
  226. pData);
  227. }
  228. SerializeInputsContributingToOutput(
  229. NumInputs, NumPCs, m_InputsContributingToPCOutputs, pData);
  230. } else {
  231. unsigned NumOutputs = getNumOutputSigScalars(0);
  232. SerializeInputsContributingToOutput(
  233. NumPCs, NumOutputs, m_PCInputsContributingToOutputs, pData);
  234. }
  235. }
  236. DXASSERT_NOMSG(pData == (&m_SerializedState[0] + Size));
  237. }
  238. const vector<unsigned> &DxilViewIdState::GetSerialized() {
  239. if (m_SerializedState.empty())
  240. Serialize();
  241. return m_SerializedState;
  242. }
  243. const vector<unsigned> &DxilViewIdState::GetSerialized() const {
  244. return m_SerializedState;
  245. }
  246. namespace {
  247. unsigned DeserializeOutputsDependentOnViewId(
  248. unsigned NumOutputs,
  249. DxilViewIdState::OutputsDependentOnViewIdType &OutputsDependentOnViewId,
  250. const unsigned *pData, unsigned DataSize) {
  251. unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
  252. IFTBOOL(NumOutUINTs <= DataSize, DXC_E_GENERAL_INTERNAL_ERROR);
  253. // Deserialize output dependence on ViewId.
  254. for (unsigned i = 0; i < NumOutUINTs; i++) {
  255. unsigned x = *pData++;
  256. for (unsigned j = 0; j < std::min(32u, NumOutputs - 32u * i); j++) {
  257. if (x & (1u << j)) {
  258. OutputsDependentOnViewId[i * 32 + j] = true;
  259. }
  260. }
  261. }
  262. return NumOutUINTs;
  263. }
  264. unsigned DeserializeInputsContributingToOutput(
  265. unsigned NumInputs, unsigned NumOutputs,
  266. DxilViewIdState::InputsContributingToOutputType
  267. &InputsContributingToOutputs,
  268. const unsigned *pData, unsigned DataSize) {
  269. unsigned NumOutUINTs = RoundUpToUINT(NumOutputs);
  270. unsigned Size = NumInputs * NumOutUINTs;
  271. IFTBOOL(Size <= DataSize, DXC_E_GENERAL_INTERNAL_ERROR);
  272. // Deserialize output dependence on inputs.
  273. for (unsigned inputIdx = 0; inputIdx < NumInputs; inputIdx++) {
  274. for (unsigned outputIdx = 0; outputIdx < NumOutputs; outputIdx++) {
  275. unsigned w = outputIdx / 32;
  276. unsigned b = outputIdx % 32;
  277. if (pData[inputIdx * NumOutUINTs + w] & (1u << b)) {
  278. InputsContributingToOutputs[outputIdx].insert(inputIdx);
  279. }
  280. }
  281. }
  282. return Size;
  283. }
  284. } // namespace
  285. void DxilViewIdState::Deserialize(const unsigned *pData,
  286. unsigned DataSizeInUINTs) {
  287. Clear();
  288. m_SerializedState.resize(DataSizeInUINTs);
  289. memcpy(m_SerializedState.data(), pData, DataSizeInUINTs * sizeof(unsigned));
  290. const ShaderModel *pSM = m_pModule->GetShaderModel();
  291. m_bUsesViewId = m_pModule->m_ShaderFlags.GetViewID();
  292. unsigned ConsumedUINTs = 0;
  293. IFTBOOL(DataSizeInUINTs - ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
  294. unsigned NumInputs = pData[ConsumedUINTs++];
  295. m_NumInputSigScalars = NumInputs;
  296. unsigned NumStreams = pSM->IsGS() ? kNumStreams : 1;
  297. for (unsigned StreamId = 0; StreamId < NumStreams; StreamId++) {
  298. IFTBOOL(DataSizeInUINTs - ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
  299. unsigned NumOutputs = pData[ConsumedUINTs++];
  300. m_NumOutputSigScalars[StreamId] = NumOutputs;
  301. if (m_bUsesViewId) {
  302. ConsumedUINTs += DeserializeOutputsDependentOnViewId(
  303. NumOutputs, m_OutputsDependentOnViewId[StreamId],
  304. &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
  305. }
  306. ConsumedUINTs += DeserializeInputsContributingToOutput(
  307. NumInputs, NumOutputs, m_InputsContributingToOutputs[StreamId],
  308. &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
  309. }
  310. if (pSM->IsHS() || pSM->IsDS()) {
  311. IFTBOOL(DataSizeInUINTs - ConsumedUINTs >= 1, DXC_E_GENERAL_INTERNAL_ERROR);
  312. unsigned NumPCs = pData[ConsumedUINTs++];
  313. m_NumPCSigScalars = NumPCs;
  314. if (pSM->IsHS()) {
  315. if (m_bUsesViewId) {
  316. ConsumedUINTs += DeserializeOutputsDependentOnViewId(
  317. NumPCs, m_PCOutputsDependentOnViewId, &pData[ConsumedUINTs],
  318. DataSizeInUINTs - ConsumedUINTs);
  319. }
  320. ConsumedUINTs += DeserializeInputsContributingToOutput(
  321. NumInputs, NumPCs, m_InputsContributingToPCOutputs,
  322. &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
  323. } else {
  324. unsigned NumOutputs = getNumOutputSigScalars(0);
  325. ConsumedUINTs += DeserializeInputsContributingToOutput(
  326. NumPCs, NumOutputs, m_PCInputsContributingToOutputs,
  327. &pData[ConsumedUINTs], DataSizeInUINTs - ConsumedUINTs);
  328. }
  329. }
  330. DXASSERT_NOMSG(ConsumedUINTs == DataSizeInUINTs);
  331. }