DxilSignature.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilSignature.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/Support/Global.h"
  10. #include "dxc/HLSL/DxilSignature.h"
  11. #include "dxc/HLSL/DxilSignatureAllocator.h"
  12. #include "dxc/HLSL/DxilSigPoint.h"
  13. using std::vector;
  14. using std::unique_ptr;
  15. namespace hlsl {
  16. //------------------------------------------------------------------------------
  17. //
  18. // Singnature methods.
  19. //
  20. DxilSignature::DxilSignature(DXIL::ShaderKind shaderKind, DXIL::SignatureKind sigKind)
  21. : m_sigPointKind(SigPoint::GetKind(shaderKind, sigKind, /*isPatchConstantFunction*/false, /*isSpecialInput*/false)) {}
  22. DxilSignature::DxilSignature(DXIL::SigPointKind sigPointKind)
  23. : m_sigPointKind(sigPointKind) {}
  24. DxilSignature::~DxilSignature() {
  25. }
  26. bool DxilSignature::IsInput() const {
  27. return SigPoint::GetSigPoint(m_sigPointKind)->IsInput();
  28. }
  29. bool DxilSignature::IsOutput() const {
  30. return SigPoint::GetSigPoint(m_sigPointKind)->IsOutput();
  31. }
  32. unique_ptr<DxilSignatureElement> DxilSignature::CreateElement() {
  33. return unique_ptr<DxilSignatureElement>(new DxilSignatureElement(m_sigPointKind));
  34. }
  35. unsigned DxilSignature::AppendElement(std::unique_ptr<DxilSignatureElement> pSE, bool bSetID) {
  36. DXASSERT_NOMSG((unsigned)m_Elements.size() < UINT_MAX);
  37. unsigned Id = (unsigned)m_Elements.size();
  38. if (bSetID) {
  39. pSE->SetID(Id);
  40. }
  41. m_Elements.emplace_back(std::move(pSE));
  42. return Id;
  43. }
  44. DxilSignatureElement &DxilSignature::GetElement(unsigned idx) {
  45. return *m_Elements[idx].get();
  46. }
  47. const DxilSignatureElement &DxilSignature::GetElement(unsigned idx) const {
  48. return *m_Elements[idx].get();
  49. }
  50. const std::vector<std::unique_ptr<DxilSignatureElement> > &DxilSignature::GetElements() const {
  51. return m_Elements;
  52. }
  53. namespace {
  54. static bool ShouldBeAllocated(const DxilSignatureElement *SE) {
  55. DXIL::SemanticInterpretationKind I = SE->GetInterpretation();
  56. switch (I) {
  57. case DXIL::SemanticInterpretationKind::NA:
  58. case DXIL::SemanticInterpretationKind::NotInSig:
  59. case DXIL::SemanticInterpretationKind::NotPacked:
  60. case DXIL::SemanticInterpretationKind::Shadow:
  61. return false;
  62. }
  63. return true;
  64. }
  65. } // anonymous namespace
  66. bool DxilSignature::IsFullyAllocated() const {
  67. for (auto &SE : m_Elements) {
  68. if (!ShouldBeAllocated(SE.get()))
  69. continue;
  70. if (!SE->IsAllocated())
  71. return false;
  72. }
  73. return true;
  74. }
  75. unsigned DxilSignature::NumVectorsUsed(unsigned streamIndex) const {
  76. unsigned NumVectors = 0;
  77. for (auto &SE : m_Elements) {
  78. if (SE->IsAllocated() && SE->GetOutputStream() == streamIndex)
  79. NumVectors = std::max(NumVectors, (unsigned)SE->GetStartRow() + SE->GetRows());
  80. }
  81. return NumVectors;
  82. }
  83. unsigned DxilSignature::PackElements(DXIL::PackingStrategy packing) {
  84. unsigned rowsUsed = 0;
  85. // Transfer to elements derived from DxilSignatureAllocator::PackElement
  86. std::vector<DxilPackElement> packElements;
  87. for (auto &SE : m_Elements) {
  88. if (ShouldBeAllocated(SE.get()))
  89. packElements.emplace_back(SE.get());
  90. }
  91. if (m_sigPointKind == DXIL::SigPointKind::GSOut) {
  92. // Special case due to support for multiple streams
  93. DxilSignatureAllocator alloc[4] = {32, 32, 32, 32};
  94. std::vector<DxilSignatureAllocator::PackElement*> elements[4];
  95. for (auto &SE : packElements) {
  96. elements[SE.Get()->GetOutputStream()].push_back(&SE);
  97. }
  98. for (unsigned i = 0; i < 4; ++i) {
  99. if (!elements[i].empty()) {
  100. unsigned streamRowsUsed = 0;
  101. switch (packing) {
  102. case DXIL::PackingStrategy::PrefixStable:
  103. streamRowsUsed = alloc[i].PackPrefixStable(elements[i], 0, 32);
  104. break;
  105. case DXIL::PackingStrategy::Optimized:
  106. streamRowsUsed = alloc[i].PackOptimized(elements[i], 0, 32);
  107. break;
  108. default:
  109. DXASSERT(false, "otherwise, invalid packing strategy supplied");
  110. }
  111. if (streamRowsUsed > rowsUsed)
  112. rowsUsed = streamRowsUsed;
  113. }
  114. }
  115. // rowsUsed isn't really meaningful in this case.
  116. return rowsUsed;
  117. }
  118. const SigPoint *SP = SigPoint::GetSigPoint(m_sigPointKind);
  119. DXIL::PackingKind PK = SP->GetPackingKind();
  120. switch (PK) {
  121. case DXIL::PackingKind::None:
  122. // no packing.
  123. break;
  124. case DXIL::PackingKind::InputAssembler:
  125. // incrementally assign each element that belongs in the signature to the start of the next free row
  126. for (auto &SE : packElements) {
  127. SE.SetLocation(rowsUsed, 0);
  128. rowsUsed += SE.GetRows();
  129. }
  130. break;
  131. case DXIL::PackingKind::Vertex:
  132. case DXIL::PackingKind::PatchConstant: {
  133. DxilSignatureAllocator alloc(32);
  134. std::vector<DxilSignatureAllocator::PackElement*> elements;
  135. elements.reserve(packElements.size());
  136. for (auto &SE : packElements){
  137. elements.push_back(&SE);
  138. }
  139. switch (packing) {
  140. case DXIL::PackingStrategy::PrefixStable:
  141. rowsUsed = alloc.PackPrefixStable(elements, 0, 32);
  142. break;
  143. case DXIL::PackingStrategy::Optimized:
  144. rowsUsed = alloc.PackOptimized(elements, 0, 32);
  145. break;
  146. default:
  147. DXASSERT(false, "otherwise, invalid packing strategy supplied");
  148. }
  149. }
  150. break;
  151. case DXIL::PackingKind::Target:
  152. // for SV_Target, assign rows according to semantic index, the rest are unassigned (-1)
  153. // Note: Overlapping semantic indices should be checked elsewhere
  154. for (auto &SE : packElements) {
  155. if (SE.GetKind() != DXIL::SemanticKind::Target)
  156. continue;
  157. unsigned row = SE.Get()->GetSemanticStartIndex();
  158. SE.SetLocation(row, 0);
  159. DXASSERT(SE.GetRows() == 1, "otherwise, SV_Target output not broken into separate rows earlier");
  160. row += SE.GetRows();
  161. if (rowsUsed < row)
  162. rowsUsed = row;
  163. }
  164. break;
  165. case DXIL::PackingKind::Invalid:
  166. default:
  167. DXASSERT(false, "unexpected PackingKind.");
  168. }
  169. return rowsUsed;
  170. }
  171. } // namespace hlsl
  172. #include <algorithm>
  173. #include "dxc/HLSL/DxilSignatureAllocator.inl"
  174. #include "dxc/HLSL/DxilSigPoint.inl"
  175. #include "dxc/HLSL/DxilPipelineStateValidation.h"
  176. #include <functional>
  177. #include "dxc/HLSL/ViewIDPipelineValidation.inl"