DxilSignature.cpp 7.8 KB

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