DxilRootSignature.cpp 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilRootSignature.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. // Provides support for manipulating root signature structures. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/HLSL/DxilConstants.h"
  12. #include "dxc/HLSL/DxilRootSignature.h"
  13. #include "dxc/HLSL/DxilPipelineStateValidation.h"
  14. #include "dxc/Support/Global.h"
  15. #include "dxc/Support/WinIncludes.h"
  16. #include "dxc/Support/FileIOHelper.h"
  17. #include "dxc/dxcapi.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. #include "llvm/IR/DiagnosticPrinter.h"
  20. #include <string>
  21. #include <algorithm>
  22. #include <utility>
  23. #include <vector>
  24. #include <set>
  25. using namespace llvm;
  26. using std::string;
  27. namespace hlsl {
  28. DEFINE_ENUM_FLAG_OPERATORS(DxilRootSignatureFlags)
  29. DEFINE_ENUM_FLAG_OPERATORS(DxilRootDescriptorFlags)
  30. DEFINE_ENUM_FLAG_OPERATORS(DxilDescriptorRangeType)
  31. DEFINE_ENUM_FLAG_OPERATORS(DxilDescriptorRangeFlags)
  32. // Execute (error) and throw.
  33. #define EAT(x) { (x); throw ::hlsl::Exception(E_FAIL); }
  34. //////////////////////////////////////////////////////////////////////////////
  35. // Root signature handler.
  36. RootSignatureHandle::RootSignatureHandle(RootSignatureHandle&& other) {
  37. m_pDesc = nullptr;
  38. m_pSerialized = nullptr;
  39. std::swap(m_pDesc, other.m_pDesc);
  40. std::swap(m_pSerialized, other.m_pSerialized);
  41. }
  42. void RootSignatureHandle::Assign(const DxilVersionedRootSignatureDesc *pDesc,
  43. IDxcBlob *pSerialized) {
  44. Clear();
  45. m_pDesc = pDesc;
  46. m_pSerialized = pSerialized;
  47. if (m_pSerialized)
  48. m_pSerialized->AddRef();
  49. }
  50. void RootSignatureHandle::Clear() {
  51. hlsl::DeleteRootSignature(m_pDesc);
  52. m_pDesc = nullptr;
  53. if (m_pSerialized != nullptr) {
  54. m_pSerialized->Release();
  55. m_pSerialized = nullptr;
  56. }
  57. }
  58. const uint8_t *RootSignatureHandle::GetSerializedBytes() const {
  59. DXASSERT_NOMSG(m_pSerialized != nullptr);
  60. return (uint8_t *)m_pSerialized->GetBufferPointer();
  61. }
  62. unsigned RootSignatureHandle::GetSerializedSize() const {
  63. DXASSERT_NOMSG(m_pSerialized != nullptr);
  64. return m_pSerialized->GetBufferSize();
  65. }
  66. void RootSignatureHandle::EnsureSerializedAvailable() {
  67. DXASSERT_NOMSG(!IsEmpty());
  68. if (m_pSerialized == nullptr) {
  69. CComPtr<IDxcBlob> pResult;
  70. hlsl::SerializeRootSignature(m_pDesc, &pResult, nullptr, false);
  71. IFTBOOL(pResult != nullptr, E_FAIL);
  72. m_pSerialized = pResult.Detach();
  73. }
  74. }
  75. void RootSignatureHandle::Deserialize() {
  76. DXASSERT_NOMSG(m_pSerialized && !m_pDesc);
  77. DeserializeRootSignature((uint8_t*)m_pSerialized->GetBufferPointer(), (uint32_t)m_pSerialized->GetBufferSize(), &m_pDesc);
  78. }
  79. void RootSignatureHandle::LoadSerialized(const uint8_t *pData,
  80. unsigned length) {
  81. DXASSERT_NOMSG(IsEmpty());
  82. IDxcBlobEncoding *pCreated;
  83. IFT(DxcCreateBlobWithEncodingOnHeapCopy(pData, length, CP_UTF8, &pCreated));
  84. m_pSerialized = pCreated;
  85. }
  86. //////////////////////////////////////////////////////////////////////////////
  87. // Simple serializer.
  88. class SimpleSerializer {
  89. struct Segment {
  90. void *pData;
  91. unsigned cbSize;
  92. bool bOwner;
  93. unsigned Offset;
  94. Segment *pNext;
  95. };
  96. public:
  97. SimpleSerializer();
  98. ~SimpleSerializer();
  99. HRESULT AddBlock(void *pData, unsigned cbSize, unsigned *pOffset);
  100. HRESULT ReserveBlock(void **ppData, unsigned cbSize, unsigned *pOffset);
  101. HRESULT Compact(_Out_writes_bytes_(cbSize) char *pData, unsigned cbSize);
  102. unsigned GetSize();
  103. protected:
  104. unsigned m_cbSegments;
  105. Segment *m_pSegment;
  106. Segment **m_ppSegment;
  107. };
  108. SimpleSerializer::SimpleSerializer() {
  109. m_cbSegments = 0;
  110. m_pSegment = nullptr;
  111. m_ppSegment = &m_pSegment;
  112. }
  113. SimpleSerializer::~SimpleSerializer() {
  114. while (m_pSegment) {
  115. Segment *pSegment = m_pSegment;
  116. m_pSegment = pSegment->pNext;
  117. if (pSegment->bOwner) {
  118. delete pSegment->pData;
  119. }
  120. delete pSegment;
  121. }
  122. }
  123. HRESULT SimpleSerializer::AddBlock(void *pData, unsigned cbSize,
  124. unsigned *pOffset) {
  125. Segment *pSegment = nullptr;
  126. IFRBOOL(!(cbSize != 0 && pData == nullptr), E_FAIL);
  127. IFROOM(pSegment = new (std::nothrow) Segment);
  128. pSegment->pData = pData;
  129. m_cbSegments = (m_cbSegments + 3) & ~3;
  130. pSegment->Offset = m_cbSegments;
  131. pSegment->cbSize = cbSize;
  132. pSegment->bOwner = false;
  133. pSegment->pNext = nullptr;
  134. m_cbSegments += pSegment->cbSize;
  135. *m_ppSegment = pSegment;
  136. m_ppSegment = &pSegment->pNext;
  137. if (pOffset != nullptr) {
  138. *pOffset = pSegment->Offset;
  139. }
  140. return S_OK;
  141. }
  142. HRESULT SimpleSerializer::ReserveBlock(void **ppData, unsigned cbSize,
  143. unsigned *pOffset) {
  144. HRESULT hr = S_OK;
  145. Segment *pSegment = nullptr;
  146. void *pClonedData = nullptr;
  147. IFCOOM(pSegment = new (std::nothrow) Segment);
  148. pSegment->pData = nullptr;
  149. IFCOOM(pClonedData = new (std::nothrow) char[cbSize]);
  150. pSegment->pData = pClonedData;
  151. m_cbSegments = (m_cbSegments + 3) & ~3;
  152. pSegment->Offset = m_cbSegments;
  153. pSegment->cbSize = cbSize;
  154. pSegment->bOwner = true;
  155. pSegment->pNext = nullptr;
  156. m_cbSegments += pSegment->cbSize;
  157. *m_ppSegment = pSegment;
  158. m_ppSegment = &pSegment->pNext;
  159. *ppData = pClonedData;
  160. if (pOffset) {
  161. *pOffset = pSegment->Offset;
  162. }
  163. Cleanup:
  164. if (FAILED(hr)) {
  165. delete[] pClonedData;
  166. delete pSegment;
  167. }
  168. return hr;
  169. }
  170. HRESULT SimpleSerializer::Compact(_Out_writes_bytes_(cbSize) char *pData,
  171. unsigned cbSize) {
  172. unsigned cb = GetSize();
  173. IFRBOOL(cb <= cbSize, E_FAIL);
  174. DXASSERT_NOMSG(cb <= UINT32_MAX / 2);
  175. char *p = (char *)pData;
  176. cb = 0;
  177. for (Segment *pSegment = m_pSegment; pSegment; pSegment = pSegment->pNext) {
  178. unsigned cbAlign = ((cb + 3) & ~3) - cb;
  179. _Analysis_assume_(p + cbAlign <= pData + cbSize);
  180. memset(p, 0xab, cbAlign);
  181. p += cbAlign;
  182. cb += cbAlign;
  183. _Analysis_assume_(p + pSegment->cbSize <= pData + cbSize);
  184. memcpy(p, pSegment->pData, pSegment->cbSize);
  185. p += pSegment->cbSize;
  186. cb += pSegment->cbSize;
  187. }
  188. // Trailing zeros
  189. _Analysis_assume_(p + cbSize - cb <= pData + cbSize);
  190. memset(p, 0xab, cbSize - cb);
  191. return S_OK;
  192. }
  193. unsigned SimpleSerializer::GetSize() {
  194. // Round up to 4==sizeof(unsigned).
  195. return ((m_cbSegments + 3) >> 2) * 4;
  196. }
  197. //////////////////////////////////////////////////////////////////////////////
  198. // Interval helper.
  199. template <typename T>
  200. class CIntervalCollection {
  201. private:
  202. std::set<T> m_set;
  203. public:
  204. const T* FindIntersectingInterval(const T &I) {
  205. auto it = m_set.find(I);
  206. if (it != m_set.end())
  207. return &*it;
  208. return nullptr;
  209. }
  210. void Insert(const T& value) {
  211. auto result = m_set.insert(value);
  212. UNREFERENCED_PARAMETER(result);
  213. #if DBG
  214. DXASSERT(result.second, "otherwise interval collides with existing in collection");
  215. #endif
  216. }
  217. };
  218. //////////////////////////////////////////////////////////////////////////////
  219. // Verifier classes.
  220. class DescriptorTableVerifier {
  221. public:
  222. void Verify(const DxilDescriptorRange1 *pRanges, unsigned NumRanges,
  223. unsigned iRTS, DiagnosticPrinter &DiagPrinter);
  224. };
  225. class StaticSamplerVerifier {
  226. public:
  227. void Verify(const DxilStaticSamplerDesc *pDesc, DiagnosticPrinter &DiagPrinter);
  228. };
  229. class RootSignatureVerifier {
  230. public:
  231. RootSignatureVerifier();
  232. ~RootSignatureVerifier();
  233. void AllowReservedRegisterSpace(bool bAllow);
  234. // Call this before calling VerifyShader, as it accumulates root signature state.
  235. void VerifyRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature,
  236. DiagnosticPrinter &DiagPrinter);
  237. void VerifyShader(DxilShaderVisibility VisType,
  238. const void *pPSVData,
  239. uint32_t PSVSize,
  240. DiagnosticPrinter &DiagPrinter);
  241. typedef enum NODE_TYPE {
  242. DESCRIPTOR_TABLE_ENTRY,
  243. ROOT_DESCRIPTOR,
  244. ROOT_CONSTANT,
  245. STATIC_SAMPLER
  246. } NODE_TYPE;
  247. private:
  248. static const unsigned kMinVisType = (unsigned)DxilShaderVisibility::All;
  249. static const unsigned kMaxVisType = (unsigned)DxilShaderVisibility::Pixel;
  250. static const unsigned kMinDescType = (unsigned)DxilDescriptorRangeType::SRV;
  251. static const unsigned kMaxDescType = (unsigned)DxilDescriptorRangeType::Sampler;
  252. struct RegisterRange {
  253. NODE_TYPE nt;
  254. unsigned space;
  255. unsigned lb; // inclusive lower bound
  256. unsigned ub; // inclusive upper bound
  257. unsigned iRP;
  258. unsigned iDTS;
  259. // Sort by space, then lower bound.
  260. bool operator<(const RegisterRange& other) const {
  261. return space < other.space ||
  262. (space == other.space && ub < other.lb);
  263. }
  264. // Like a regular -1,0,1 comparison, but 0 indicates overlap.
  265. int overlap(const RegisterRange& other) const {
  266. if (space < other.space) return -1;
  267. if (space > other.space) return 1;
  268. if (ub < other.lb) return -1;
  269. if (lb > other.ub) return 1;
  270. return 0;
  271. }
  272. // Check containment.
  273. bool contains(const RegisterRange& other) const {
  274. return (space == other.space) && (lb <= other.lb && other.ub <= ub);
  275. }
  276. };
  277. typedef CIntervalCollection<RegisterRange> RegisterRanges;
  278. void AddRegisterRange(unsigned iRTS, NODE_TYPE nt, unsigned iDTS,
  279. DxilDescriptorRangeType DescType,
  280. DxilShaderVisibility VisType,
  281. unsigned NumRegisters, unsigned BaseRegister,
  282. unsigned RegisterSpace, DiagnosticPrinter &DiagPrinter);
  283. const RegisterRange *FindCoveringInterval(DxilDescriptorRangeType RangeType,
  284. DxilShaderVisibility VisType,
  285. unsigned Num,
  286. unsigned LB,
  287. unsigned Space);
  288. RegisterRanges &
  289. GetRanges(DxilShaderVisibility VisType, DxilDescriptorRangeType DescType) {
  290. return RangeKinds[(unsigned)VisType][(unsigned)DescType];
  291. }
  292. RegisterRanges RangeKinds[kMaxVisType + 1][kMaxDescType + 1];
  293. bool m_bAllowReservedRegisterSpace;
  294. DxilRootSignatureFlags m_RootSignatureFlags;
  295. };
  296. void DescriptorTableVerifier::Verify(const DxilDescriptorRange1 *pRanges,
  297. uint32_t NumRanges, uint32_t iRP,
  298. DiagnosticPrinter &DiagPrinter) {
  299. bool bHasSamplers = false;
  300. bool bHasResources = false;
  301. uint64_t iAppendStartSlot = 0;
  302. for (unsigned iDTS = 0; iDTS < NumRanges; iDTS++) {
  303. const DxilDescriptorRange1 *pRange = &pRanges[iDTS];
  304. switch (pRange->RangeType) {
  305. case DxilDescriptorRangeType::SRV:
  306. case DxilDescriptorRangeType::UAV:
  307. case DxilDescriptorRangeType::CBV:
  308. bHasResources = true;
  309. break;
  310. case DxilDescriptorRangeType::Sampler:
  311. bHasSamplers = true;
  312. break;
  313. default:
  314. EAT(DiagPrinter << "Unsupported RangeType value " << (uint32_t)pRange->RangeType
  315. << " (descriptor table slot [" << iDTS << "], root parameter [" << iRP << "]).\n");
  316. }
  317. // Samplers cannot be mixed with other resources.
  318. if (bHasResources && bHasSamplers) {
  319. EAT(DiagPrinter << "Samplers cannot be mixed with other "
  320. << "resource types in a descriptor table (root "
  321. << "parameter [" << iRP << "]).\n");
  322. }
  323. // NumDescriptors is not 0.
  324. if (pRange->NumDescriptors == 0) {
  325. EAT(DiagPrinter << "NumDescriptors cannot be 0 (descriptor "
  326. << "table slot [" << iDTS << "], root parameter [" << iRP << "]).\n");
  327. }
  328. // Range start.
  329. uint64_t iStartSlot = iAppendStartSlot;
  330. if (pRange->OffsetInDescriptorsFromTableStart != DxilDescriptorRangeOffsetAppend) {
  331. iStartSlot = pRange->OffsetInDescriptorsFromTableStart;
  332. }
  333. if (iStartSlot > UINT_MAX) {
  334. EAT(DiagPrinter << "Cannot append range with implicit lower "
  335. << "bound after an unbounded range (descriptor "
  336. << "table slot [" << iDTS << "], root parameter [" << iRP << "]).\n");
  337. }
  338. // Descriptor range and shader register range overlow.
  339. if (pRange->NumDescriptors != UINT_MAX) {
  340. // Bounded range.
  341. uint64_t ub1 = (uint64_t)pRange->BaseShaderRegister +
  342. (uint64_t)pRange->NumDescriptors - 1ull;
  343. if (ub1 > UINT_MAX) {
  344. EAT(DiagPrinter << "Overflow for shader register range: "
  345. << "BaseShaderRegister=" << pRange->BaseShaderRegister
  346. << ", NumDescriptor=" << pRange->NumDescriptors
  347. << "; (descriptor table slot [" << iDTS
  348. << "], root parameter [" << iRP << "]).\n");
  349. }
  350. uint64_t ub2 = (uint64_t)iStartSlot + (uint64_t)pRange->NumDescriptors - 1ull;
  351. if (ub2 > UINT_MAX) {
  352. EAT(DiagPrinter << "Overflow for descriptor range (descriptor "
  353. << "table slot [" << iDTS << "], root parameter [" << iRP << "])\n");
  354. }
  355. iAppendStartSlot = iStartSlot + (uint64_t)pRange->NumDescriptors;
  356. } else {
  357. // Unbounded range.
  358. iAppendStartSlot = 1ull + (uint64_t)UINT_MAX;
  359. }
  360. }
  361. }
  362. RootSignatureVerifier::RootSignatureVerifier() {
  363. m_RootSignatureFlags = DxilRootSignatureFlags::None;
  364. m_bAllowReservedRegisterSpace = false;
  365. }
  366. RootSignatureVerifier::~RootSignatureVerifier() {}
  367. void RootSignatureVerifier::AllowReservedRegisterSpace(bool bAllow) {
  368. m_bAllowReservedRegisterSpace = bAllow;
  369. }
  370. const char* RangeTypeString(DxilDescriptorRangeType rt)
  371. {
  372. static const char *RangeType[] = {"SRV", "UAV", "CBV", "SAMPLER"};
  373. return (rt <= DxilDescriptorRangeType::Sampler) ? RangeType[(unsigned)rt]
  374. : "unknown";
  375. }
  376. const char *VisTypeString(DxilShaderVisibility vis) {
  377. static const char *Vis[] = {"ALL", "VERTEX", "HULL",
  378. "DOMAIN", "GEOMETRY", "PIXEL"};
  379. unsigned idx = (unsigned)vis;
  380. return vis <= DxilShaderVisibility::Pixel ? Vis[idx] : "unknown";
  381. }
  382. static bool IsDxilShaderVisibility(DxilShaderVisibility v) {
  383. return v <= DxilShaderVisibility::Pixel;
  384. }
  385. void RootSignatureVerifier::AddRegisterRange(unsigned iRP,
  386. NODE_TYPE nt,
  387. unsigned iDTS,
  388. DxilDescriptorRangeType DescType,
  389. DxilShaderVisibility VisType,
  390. unsigned NumRegisters,
  391. unsigned BaseRegister,
  392. unsigned RegisterSpace,
  393. DiagnosticPrinter &DiagPrinter) {
  394. RegisterRange interval;
  395. interval.space = RegisterSpace;
  396. interval.lb = BaseRegister;
  397. interval.ub = (NumRegisters != UINT_MAX) ? BaseRegister + NumRegisters - 1 : UINT_MAX;
  398. interval.nt = nt;
  399. interval.iDTS = iDTS;
  400. interval.iRP = iRP;
  401. if (!m_bAllowReservedRegisterSpace &&
  402. (RegisterSpace >= DxilSystemReservedRegisterSpaceValuesStart) &&
  403. (RegisterSpace <= DxilSystemReservedRegisterSpaceValuesEnd)) {
  404. if (nt == DESCRIPTOR_TABLE_ENTRY) {
  405. EAT(DiagPrinter << "Root parameter [" << iRP << "] descriptor table entry [" << iDTS
  406. << "] specifies RegisterSpace=" << std::hex << RegisterSpace
  407. << ", which is invalid since RegisterSpace values in the range "
  408. << "[" << std::hex << DxilSystemReservedRegisterSpaceValuesStart
  409. << "," << std::hex << DxilSystemReservedRegisterSpaceValuesEnd
  410. << "] are reserved for system use.\n");
  411. }
  412. else {
  413. EAT(DiagPrinter << "Root parameter [" << iRP
  414. << "] specifies RegisterSpace=" << std::hex << RegisterSpace
  415. << ", which is invalid since RegisterSpace values in the range "
  416. << "[" << std::hex << DxilSystemReservedRegisterSpaceValuesStart
  417. << "," << std::hex << DxilSystemReservedRegisterSpaceValuesEnd
  418. << "] are reserved for system use.\n");
  419. }
  420. }
  421. const RegisterRange *pNode = nullptr;
  422. DxilShaderVisibility NodeVis = VisType;
  423. if (VisType == DxilShaderVisibility::All) {
  424. // Check for overlap with each visibility type.
  425. for (unsigned iVT = kMinVisType; iVT <= kMaxVisType; iVT++) {
  426. pNode = GetRanges((DxilShaderVisibility)iVT, DescType).FindIntersectingInterval(interval);
  427. if (pNode != nullptr)
  428. break;
  429. }
  430. } else {
  431. // Check for overlap with the same visibility.
  432. pNode = GetRanges(VisType, DescType).FindIntersectingInterval(interval);
  433. // Check for overlap with ALL visibility.
  434. if (pNode == nullptr) {
  435. pNode = GetRanges(DxilShaderVisibility::All, DescType).FindIntersectingInterval(interval);
  436. NodeVis = DxilShaderVisibility::All;
  437. }
  438. }
  439. if (pNode != nullptr) {
  440. const int strSize = 132;
  441. char testString[strSize];
  442. char nodeString[strSize];
  443. switch (nt) {
  444. case DESCRIPTOR_TABLE_ENTRY:
  445. StringCchPrintfA(testString, strSize, "(root parameter [%u], visibility %s, descriptor table slot [%u])",
  446. iRP, VisTypeString(VisType), iDTS);
  447. break;
  448. case ROOT_DESCRIPTOR:
  449. case ROOT_CONSTANT:
  450. StringCchPrintfA(testString, strSize, "(root parameter [%u], visibility %s)",
  451. iRP, VisTypeString(VisType));
  452. break;
  453. case STATIC_SAMPLER:
  454. StringCchPrintfA(testString, strSize, "(static sampler [%u], visibility %s)",
  455. iRP, VisTypeString(VisType));
  456. break;
  457. default:
  458. DXASSERT_NOMSG(false);
  459. break;
  460. }
  461. switch (pNode->nt)
  462. {
  463. case DESCRIPTOR_TABLE_ENTRY:
  464. StringCchPrintfA(nodeString, strSize, "(root parameter[%u], visibility %s, descriptor table slot [%u])",
  465. pNode->iRP, VisTypeString(NodeVis), pNode->iDTS);
  466. break;
  467. case ROOT_DESCRIPTOR:
  468. case ROOT_CONSTANT:
  469. StringCchPrintfA(nodeString, strSize, "(root parameter [%u], visibility %s)",
  470. pNode->iRP, VisTypeString(NodeVis));
  471. break;
  472. case STATIC_SAMPLER:
  473. StringCchPrintfA(nodeString, strSize, "(static sampler [%u], visibility %s)",
  474. pNode->iRP, VisTypeString(NodeVis));
  475. break;
  476. default:
  477. DXASSERT_NOMSG(false);
  478. break;
  479. }
  480. EAT(DiagPrinter << "Shader register range of type " << RangeTypeString(DescType)
  481. << " " << testString << " overlaps with another "
  482. << "shader register range " << nodeString << ".\n");
  483. }
  484. // Insert node.
  485. GetRanges(VisType, DescType).Insert(interval);
  486. }
  487. const RootSignatureVerifier::RegisterRange *
  488. RootSignatureVerifier::FindCoveringInterval(DxilDescriptorRangeType RangeType,
  489. DxilShaderVisibility VisType,
  490. unsigned Num,
  491. unsigned LB,
  492. unsigned Space) {
  493. RegisterRange RR;
  494. RR.space = Space;
  495. RR.lb = LB;
  496. RR.ub = LB + Num - 1;
  497. const RootSignatureVerifier::RegisterRange *pRange = GetRanges(DxilShaderVisibility::All, RangeType).FindIntersectingInterval(RR);
  498. if (!pRange && VisType != DxilShaderVisibility::All) {
  499. pRange = GetRanges(VisType, RangeType).FindIntersectingInterval(RR);
  500. }
  501. if (pRange && !pRange->contains(RR)) {
  502. pRange = nullptr;
  503. }
  504. return pRange;
  505. }
  506. static DxilDescriptorRangeType GetRangeType(DxilRootParameterType RPT) {
  507. switch (RPT) {
  508. case DxilRootParameterType::CBV: return DxilDescriptorRangeType::CBV;
  509. case DxilRootParameterType::SRV: return DxilDescriptorRangeType::SRV;
  510. case DxilRootParameterType::UAV: return DxilDescriptorRangeType::UAV;
  511. default:
  512. break;
  513. }
  514. DXASSERT_NOMSG(false);
  515. return DxilDescriptorRangeType::SRV;
  516. }
  517. void RootSignatureVerifier::VerifyRootSignature(
  518. const DxilVersionedRootSignatureDesc *pVersionedRootSignature,
  519. DiagnosticPrinter &DiagPrinter) {
  520. const DxilVersionedRootSignatureDesc *pUpconvertedRS = nullptr;
  521. // Up-convert root signature to the latest RS version.
  522. ConvertRootSignature(pVersionedRootSignature, DxilRootSignatureVersion::Version_1_1, &pUpconvertedRS);
  523. DXASSERT_NOMSG(pUpconvertedRS->Version == DxilRootSignatureVersion::Version_1_1);
  524. // Ensure this gets deleted as necessary.
  525. struct SigGuard {
  526. const DxilVersionedRootSignatureDesc *Orig, *Guard;
  527. SigGuard(const DxilVersionedRootSignatureDesc *pOrig, const DxilVersionedRootSignatureDesc *pGuard)
  528. : Orig(pOrig), Guard(pGuard) { }
  529. ~SigGuard() {
  530. if (Orig != Guard) {
  531. DeleteRootSignature(Guard);
  532. }
  533. }
  534. };
  535. SigGuard S(pVersionedRootSignature, pUpconvertedRS);
  536. const DxilRootSignatureDesc1 *pRootSignature = &pUpconvertedRS->Desc_1_1;
  537. // Flags (assume they are bits that can be combined with OR).
  538. if ((pRootSignature->Flags & ~DxilRootSignatureFlags::ValidFlags) != DxilRootSignatureFlags::None) {
  539. EAT(DiagPrinter << "Unsupported bit-flag set (root signature flags "
  540. << std::hex << (uint32_t)pRootSignature->Flags << ").\n");
  541. }
  542. m_RootSignatureFlags = pRootSignature->Flags;
  543. for (unsigned iRP = 0; iRP < pRootSignature->NumParameters; iRP++) {
  544. const DxilRootParameter1 *pSlot = &pRootSignature->pParameters[iRP];
  545. // Shader visibility.
  546. DxilShaderVisibility Visibility = pSlot->ShaderVisibility;
  547. if (!IsDxilShaderVisibility(Visibility)) {
  548. EAT(DiagPrinter << "Unsupported ShaderVisibility value " << (uint32_t)Visibility
  549. << " (root parameter [" << iRP << "]).\n");
  550. }
  551. DxilRootParameterType ParameterType = pSlot->ParameterType;
  552. switch (ParameterType) {
  553. case DxilRootParameterType::DescriptorTable: {
  554. DescriptorTableVerifier DTV;
  555. DTV.Verify(pSlot->DescriptorTable.pDescriptorRanges,
  556. pSlot->DescriptorTable.NumDescriptorRanges, iRP, DiagPrinter);
  557. for (unsigned iDTS = 0; iDTS < pSlot->DescriptorTable.NumDescriptorRanges; iDTS++) {
  558. const DxilDescriptorRange1 *pRange = &pSlot->DescriptorTable.pDescriptorRanges[iDTS];
  559. unsigned RangeFlags = (unsigned)pRange->Flags;
  560. // Verify range flags.
  561. if (RangeFlags & ~(unsigned)DxilDescriptorRangeFlags::ValidFlags) {
  562. EAT(DiagPrinter << "Unsupported bit-flag set (descriptor range flags "
  563. << (uint32_t)pRange->Flags << ").\n");
  564. }
  565. switch (pRange->RangeType) {
  566. case DxilDescriptorRangeType::Sampler: {
  567. if (RangeFlags & (unsigned)(DxilDescriptorRangeFlags::DataVolatile |
  568. DxilDescriptorRangeFlags::DataStatic |
  569. DxilDescriptorRangeFlags::DataStaticWhileSetAtExecute)) {
  570. EAT(DiagPrinter << "Sampler descriptor ranges can't specify DATA_* flags "
  571. << "since there is no data pointed to by samplers "
  572. << "(descriptor range flags " << (uint32_t)pRange->Flags << ").\n");
  573. }
  574. break;
  575. }
  576. default: {
  577. unsigned NumDataFlags = 0;
  578. if (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataVolatile) { NumDataFlags++; }
  579. if (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataStatic) { NumDataFlags++; }
  580. if (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataStaticWhileSetAtExecute) { NumDataFlags++; }
  581. if (NumDataFlags > 1) {
  582. EAT(DiagPrinter << "Descriptor range flags cannot specify more than one DATA_* flag "
  583. << "at a time (descriptor range flags " << (uint32_t)pRange->Flags << ").\n");
  584. }
  585. if ((RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataStatic) &&
  586. (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DescriptorsVolatile)) {
  587. EAT(DiagPrinter << "Descriptor range flags cannot specify DESCRIPTORS_VOLATILE with the DATA_STATIC flag at the same time (descriptor range flags " << (uint32_t)pRange->Flags << "). "
  588. << "DATA_STATIC_WHILE_SET_AT_EXECUTE is fine to combine with DESCRIPTORS_VOLATILE, since DESCRIPTORS_VOLATILE still requires descriptors don't change during execution. \n");
  589. }
  590. break;
  591. }
  592. }
  593. AddRegisterRange(iRP,
  594. DESCRIPTOR_TABLE_ENTRY,
  595. iDTS,
  596. pRange->RangeType,
  597. Visibility,
  598. pRange->NumDescriptors,
  599. pRange->BaseShaderRegister,
  600. pRange->RegisterSpace,
  601. DiagPrinter);
  602. }
  603. break;
  604. }
  605. case DxilRootParameterType::Constants32Bit:
  606. AddRegisterRange(iRP,
  607. ROOT_CONSTANT,
  608. (unsigned)-1,
  609. DxilDescriptorRangeType::CBV,
  610. Visibility,
  611. 1,
  612. pSlot->Constants.ShaderRegister,
  613. pSlot->Constants.RegisterSpace,
  614. DiagPrinter);
  615. break;
  616. case DxilRootParameterType::CBV:
  617. case DxilRootParameterType::SRV:
  618. case DxilRootParameterType::UAV: {
  619. // Verify root descriptor flags.
  620. unsigned Flags = (unsigned)pSlot->Descriptor.Flags;
  621. if (Flags & ~(unsigned)DxilRootDescriptorFlags::ValidFlags) {
  622. EAT(DiagPrinter << "Unsupported bit-flag set (root descriptor flags " << std::hex << Flags << ").\n");
  623. }
  624. unsigned NumDataFlags = 0;
  625. if (Flags & (unsigned)DxilRootDescriptorFlags::DataVolatile) { NumDataFlags++; }
  626. if (Flags & (unsigned)DxilRootDescriptorFlags::DataStatic) { NumDataFlags++; }
  627. if (Flags & (unsigned)DxilRootDescriptorFlags::DataStaticWhileSetAtExecute) { NumDataFlags++; }
  628. if (NumDataFlags > 1) {
  629. EAT(DiagPrinter << "Root descriptor flags cannot specify more "
  630. << "than one DATA_* flag at a time (root "
  631. << "descriptor flags " << NumDataFlags << ").\n");
  632. }
  633. AddRegisterRange(iRP, ROOT_DESCRIPTOR, (unsigned)-1,
  634. GetRangeType(ParameterType), Visibility, 1,
  635. pSlot->Descriptor.ShaderRegister,
  636. pSlot->Descriptor.RegisterSpace, DiagPrinter);
  637. break;
  638. }
  639. default:
  640. EAT(DiagPrinter << "Unsupported ParameterType value " << (uint32_t)ParameterType
  641. << " (root parameter " << iRP << ")\n");
  642. }
  643. }
  644. for (unsigned iSS = 0; iSS < pRootSignature->NumStaticSamplers; iSS++) {
  645. const DxilStaticSamplerDesc *pSS = &pRootSignature->pStaticSamplers[iSS];
  646. // Shader visibility.
  647. DxilShaderVisibility Visibility = pSS->ShaderVisibility;
  648. if (!IsDxilShaderVisibility(Visibility)) {
  649. EAT(DiagPrinter << "Unsupported ShaderVisibility value " << (uint32_t)Visibility
  650. << " (static sampler [" << iSS << "]).\n");
  651. }
  652. StaticSamplerVerifier SSV;
  653. SSV.Verify(pSS, DiagPrinter);
  654. AddRegisterRange(iSS, STATIC_SAMPLER, (unsigned)-1,
  655. DxilDescriptorRangeType::Sampler, Visibility, 1,
  656. pSS->ShaderRegister, pSS->RegisterSpace, DiagPrinter);
  657. }
  658. }
  659. void RootSignatureVerifier::VerifyShader(DxilShaderVisibility VisType,
  660. const void *pPSVData,
  661. uint32_t PSVSize,
  662. DiagnosticPrinter &DiagPrinter) {
  663. DxilPipelineStateValidation PSV;
  664. IFTBOOL(PSV.InitFromPSV0(pPSVData, PSVSize), E_INVALIDARG);
  665. bool bShaderDeniedByRootSig = false;
  666. switch (VisType) {
  667. case DxilShaderVisibility::Vertex:
  668. if ((m_RootSignatureFlags & DxilRootSignatureFlags::DenyVertexShaderRootAccess) != DxilRootSignatureFlags::None) {
  669. bShaderDeniedByRootSig = true;
  670. }
  671. break;
  672. case DxilShaderVisibility::Hull:
  673. if ((m_RootSignatureFlags & DxilRootSignatureFlags::DenyHullShaderRootAccess) != DxilRootSignatureFlags::None) {
  674. bShaderDeniedByRootSig = true;
  675. }
  676. break;
  677. case DxilShaderVisibility::Domain:
  678. if ((m_RootSignatureFlags & DxilRootSignatureFlags::DenyDomainShaderRootAccess) != DxilRootSignatureFlags::None) {
  679. bShaderDeniedByRootSig = true;
  680. }
  681. break;
  682. case DxilShaderVisibility::Geometry:
  683. if ((m_RootSignatureFlags & DxilRootSignatureFlags::DenyGeometryShaderRootAccess) != DxilRootSignatureFlags::None) {
  684. bShaderDeniedByRootSig = true;
  685. }
  686. break;
  687. case DxilShaderVisibility::Pixel:
  688. if ((m_RootSignatureFlags & DxilRootSignatureFlags::DenyPixelShaderRootAccess) != DxilRootSignatureFlags::None) {
  689. bShaderDeniedByRootSig = true;
  690. }
  691. break;
  692. default:
  693. break;
  694. }
  695. bool bShaderHasRootBindings = false;
  696. for (unsigned iResource = 0; iResource < PSV.GetBindCount(); iResource++) {
  697. const PSVResourceBindInfo0 *pBindInfo0 = PSV.GetPSVResourceBindInfo0(iResource);
  698. DXASSERT_NOMSG(pBindInfo0);
  699. unsigned Space = pBindInfo0->Space;
  700. unsigned LB = pBindInfo0->LowerBound;
  701. unsigned UB = pBindInfo0->UpperBound;
  702. unsigned Num = (UB != UINT_MAX) ? (UB - LB + 1) : 1;
  703. PSVResourceType ResType = (PSVResourceType)pBindInfo0->ResType;
  704. switch(ResType) {
  705. case PSVResourceType::Sampler: {
  706. bShaderHasRootBindings = true;
  707. auto pCoveringRange = FindCoveringInterval(DxilDescriptorRangeType::Sampler, VisType, Num, LB, Space);
  708. if(!pCoveringRange) {
  709. EAT(DiagPrinter << "Shader sampler descriptor range (RegisterSpace=" << Space
  710. << ", NumDescriptors=" << Num << ", BaseShaderRegister=" << LB
  711. << ") is not fully bound in root signature.\n");
  712. }
  713. break;
  714. }
  715. case PSVResourceType::SRVTyped:
  716. case PSVResourceType::SRVRaw:
  717. case PSVResourceType::SRVStructured: {
  718. bShaderHasRootBindings = true;
  719. auto pCoveringRange = FindCoveringInterval(DxilDescriptorRangeType::SRV, VisType, Num, LB, Space);
  720. if (pCoveringRange) {
  721. if(pCoveringRange->nt == ROOT_DESCRIPTOR && ResType == PSVResourceType::SRVTyped) {
  722. EAT(DiagPrinter << "A Shader is declaring a resource object as a texture using "
  723. << "a register mapped to a root descriptor SRV (RegisterSpace=" << Space
  724. << ", ShaderRegister=" << LB << "). "
  725. << "SRV or UAV root descriptors can only be Raw or Structured buffers.\n");
  726. }
  727. }
  728. else {
  729. EAT(DiagPrinter << "Shader SRV descriptor range (RegisterSpace=" << Space
  730. << ", NumDescriptors=" << Num << ", BaseShaderRegister=" << LB
  731. << ") is not fully bound in root signature.\n");
  732. }
  733. break;
  734. }
  735. case PSVResourceType::UAVTyped:
  736. case PSVResourceType::UAVRaw:
  737. case PSVResourceType::UAVStructured:
  738. case PSVResourceType::UAVStructuredWithCounter: {
  739. bShaderHasRootBindings = true;
  740. auto pCoveringRange = FindCoveringInterval(DxilDescriptorRangeType::UAV, VisType, Num, LB, Space);
  741. if (pCoveringRange) {
  742. if (pCoveringRange->nt == ROOT_DESCRIPTOR) {
  743. if (ResType == PSVResourceType::UAVTyped) {
  744. EAT(DiagPrinter << "A shader is declaring a typed UAV using a register mapped "
  745. << "to a root descriptor UAV (RegisterSpace=" << Space
  746. << ", ShaderRegister=" << LB << "). "
  747. << "SRV or UAV root descriptors can only be Raw or Structured buffers.\n");
  748. }
  749. if (ResType == PSVResourceType::UAVStructuredWithCounter) {
  750. EAT(DiagPrinter << "A Shader is declaring a structured UAV with counter using "
  751. << "a register mapped to a root descriptor UAV (RegisterSpace=" << Space
  752. << ", ShaderRegister=" << LB << "). "
  753. << "SRV or UAV root descriptors can only be Raw or Structured buffers.\n");
  754. }
  755. }
  756. }
  757. else {
  758. EAT(DiagPrinter << "Shader UAV descriptor range (RegisterSpace=" << Space
  759. << ", NumDescriptors=" << Num << ", BaseShaderRegister=" << LB
  760. << ") is not fully bound in root signature.\n");
  761. }
  762. break;
  763. }
  764. case PSVResourceType::CBV: {
  765. bShaderHasRootBindings = true;
  766. auto pCoveringRange = FindCoveringInterval(DxilDescriptorRangeType::CBV, VisType, Num, LB, Space);
  767. if (!pCoveringRange) {
  768. EAT(DiagPrinter << "Shader CBV descriptor range (RegisterSpace=" << Space
  769. << ", NumDescriptors=" << Num << ", BaseShaderRegister=" << LB
  770. << ") is not fully bound in root signature.\n");
  771. }
  772. break;
  773. }
  774. default:
  775. break;
  776. }
  777. }
  778. if (bShaderHasRootBindings && bShaderDeniedByRootSig) {
  779. EAT(DiagPrinter << "Shader has root bindings but root signature uses a DENY flag "
  780. << "to disallow root binding access to the shader stage.\n");
  781. }
  782. }
  783. BOOL isNaN(const float &a) {
  784. static const unsigned exponentMask = 0x7f800000;
  785. static const unsigned mantissaMask = 0x007fffff;
  786. unsigned u = *(const unsigned *)&a;
  787. return (((u & exponentMask) == exponentMask) && (u & mantissaMask)); // NaN
  788. }
  789. static bool IsDxilTextureAddressMode(DxilTextureAddressMode v) {
  790. return DxilTextureAddressMode::Wrap <= v &&
  791. v <= DxilTextureAddressMode::MirrorOnce;
  792. }
  793. static bool IsDxilComparisonFunc(DxilComparisonFunc v) {
  794. return DxilComparisonFunc::Never <= v && v <= DxilComparisonFunc::Always;
  795. }
  796. // This validation closely mirrors CCreateSamplerStateValidator's checks
  797. void StaticSamplerVerifier::Verify(const DxilStaticSamplerDesc* pDesc,
  798. DiagnosticPrinter &DiagPrinter) {
  799. if (!pDesc) {
  800. EAT(DiagPrinter << "Static sampler: A nullptr pSamplerDesc was specified.\n");
  801. }
  802. bool bIsComparison = false;
  803. switch (pDesc->Filter) {
  804. case DxilFilter::MINIMUM_MIN_MAG_MIP_POINT:
  805. case DxilFilter::MINIMUM_MIN_MAG_POINT_MIP_LINEAR:
  806. case DxilFilter::MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT:
  807. case DxilFilter::MINIMUM_MIN_POINT_MAG_MIP_LINEAR:
  808. case DxilFilter::MINIMUM_MIN_LINEAR_MAG_MIP_POINT:
  809. case DxilFilter::MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  810. case DxilFilter::MINIMUM_MIN_MAG_LINEAR_MIP_POINT:
  811. case DxilFilter::MINIMUM_MIN_MAG_MIP_LINEAR:
  812. case DxilFilter::MINIMUM_ANISOTROPIC:
  813. case DxilFilter::MAXIMUM_MIN_MAG_MIP_POINT:
  814. case DxilFilter::MAXIMUM_MIN_MAG_POINT_MIP_LINEAR:
  815. case DxilFilter::MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT:
  816. case DxilFilter::MAXIMUM_MIN_POINT_MAG_MIP_LINEAR:
  817. case DxilFilter::MAXIMUM_MIN_LINEAR_MAG_MIP_POINT:
  818. case DxilFilter::MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  819. case DxilFilter::MAXIMUM_MIN_MAG_LINEAR_MIP_POINT:
  820. case DxilFilter::MAXIMUM_MIN_MAG_MIP_LINEAR:
  821. case DxilFilter::MAXIMUM_ANISOTROPIC:
  822. break;
  823. case DxilFilter::MIN_MAG_MIP_POINT:
  824. case DxilFilter::MIN_MAG_POINT_MIP_LINEAR:
  825. case DxilFilter::MIN_POINT_MAG_LINEAR_MIP_POINT:
  826. case DxilFilter::MIN_POINT_MAG_MIP_LINEAR:
  827. case DxilFilter::MIN_LINEAR_MAG_MIP_POINT:
  828. case DxilFilter::MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  829. case DxilFilter::MIN_MAG_LINEAR_MIP_POINT:
  830. case DxilFilter::MIN_MAG_MIP_LINEAR:
  831. case DxilFilter::ANISOTROPIC:
  832. break;
  833. case DxilFilter::COMPARISON_MIN_MAG_MIP_POINT:
  834. case DxilFilter::COMPARISON_MIN_MAG_POINT_MIP_LINEAR:
  835. case DxilFilter::COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT:
  836. case DxilFilter::COMPARISON_MIN_POINT_MAG_MIP_LINEAR:
  837. case DxilFilter::COMPARISON_MIN_LINEAR_MAG_MIP_POINT:
  838. case DxilFilter::COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  839. case DxilFilter::COMPARISON_MIN_MAG_LINEAR_MIP_POINT:
  840. case DxilFilter::COMPARISON_MIN_MAG_MIP_LINEAR:
  841. case DxilFilter::COMPARISON_ANISOTROPIC:
  842. bIsComparison = true;
  843. break;
  844. default:
  845. EAT(DiagPrinter << "Static sampler: Filter unrecognized.\n");
  846. }
  847. if (!IsDxilTextureAddressMode(pDesc->AddressU)) {
  848. EAT(DiagPrinter << "Static sampler: AddressU unrecognized.\n");
  849. }
  850. if (!IsDxilTextureAddressMode(pDesc->AddressV)) {
  851. EAT(DiagPrinter << "Static sampler: AddressV unrecognized.\n");
  852. }
  853. if (!IsDxilTextureAddressMode(pDesc->AddressW)) {
  854. EAT(DiagPrinter << "Static sampler: AddressW unrecognized.\n");
  855. }
  856. if (isNaN(pDesc->MipLODBias) || (pDesc->MipLODBias < DxilMipLodBiaxMin) ||
  857. (pDesc->MipLODBias > DxilMipLodBiaxMax)) {
  858. EAT(DiagPrinter << "Static sampler: MipLODBias must be in the "
  859. << "range [" << DxilMipLodBiaxMin << " to " << DxilMipLodBiaxMax
  860. <<"]. " << pDesc->MipLODBias << "specified.\n");
  861. }
  862. if (pDesc->MaxAnisotropy > DxilMapAnisotropy) {
  863. EAT(DiagPrinter << "Static sampler: MaxAnisotropy must be in "
  864. << "the range [0 to " << DxilMapAnisotropy << "]. "
  865. << pDesc->MaxAnisotropy << " specified.\n");
  866. }
  867. if (bIsComparison && !IsDxilComparisonFunc(pDesc->ComparisonFunc)) {
  868. EAT(DiagPrinter << "Static sampler: ComparisonFunc unrecognized.");
  869. }
  870. if (isNaN(pDesc->MinLOD)) {
  871. EAT(DiagPrinter << "Static sampler: MinLOD be in the range [-INF to +INF]. "
  872. << pDesc->MinLOD << " specified.\n");
  873. }
  874. if (isNaN(pDesc->MaxLOD)) {
  875. EAT(DiagPrinter << "Static sampler: MaxLOD be in the range [-INF to +INF]. "
  876. << pDesc->MaxLOD << " specified.\n");
  877. }
  878. }
  879. //////////////////////////////////////////////////////////////////////////////
  880. template <typename T>
  881. void DeleteRootSignatureTemplate(const T &RS) {
  882. for (unsigned i = 0; i < RS.NumParameters; i++) {
  883. const auto &P = RS.pParameters[i];
  884. if (P.ParameterType == DxilRootParameterType::DescriptorTable) {
  885. delete[] P.DescriptorTable.pDescriptorRanges;
  886. }
  887. }
  888. delete[] RS.pParameters;
  889. delete[] RS.pStaticSamplers;
  890. }
  891. void DeleteRootSignature(const DxilVersionedRootSignatureDesc * pRootSignature)
  892. {
  893. if (pRootSignature == nullptr)
  894. return;
  895. switch (pRootSignature->Version)
  896. {
  897. case DxilRootSignatureVersion::Version_1_0:
  898. DeleteRootSignatureTemplate<DxilRootSignatureDesc>(pRootSignature->Desc_1_0);
  899. break;
  900. case DxilRootSignatureVersion::Version_1_1:
  901. default:
  902. DXASSERT(pRootSignature->Version == DxilRootSignatureVersion::Version_1_1, "else version is incorrect");
  903. DeleteRootSignatureTemplate<DxilRootSignatureDesc1>(pRootSignature->Desc_1_1);
  904. break;
  905. }
  906. delete pRootSignature;
  907. }
  908. // GetFlags/SetFlags overloads.
  909. static DxilRootDescriptorFlags GetFlags(const DxilRootDescriptor &)
  910. {
  911. // Upconvert root parameter flags to be volatile.
  912. return DxilRootDescriptorFlags::DataVolatile;
  913. }
  914. static void SetFlags(DxilRootDescriptor &, DxilRootDescriptorFlags)
  915. {
  916. // Drop the flags; none existed in rs_1_0.
  917. }
  918. static DxilRootDescriptorFlags GetFlags(const DxilRootDescriptor1 &D)
  919. {
  920. return D.Flags;
  921. }
  922. static void SetFlags(DxilRootDescriptor1 &D, DxilRootDescriptorFlags Flags)
  923. {
  924. D.Flags = Flags;
  925. }
  926. static DxilRootDescriptorFlags GetFlags(const DxilContainerRootDescriptor1 &D)
  927. {
  928. return (DxilRootDescriptorFlags)D.Flags;
  929. }
  930. static void SetFlags(DxilContainerRootDescriptor1 &D, DxilRootDescriptorFlags Flags)
  931. {
  932. D.Flags = (uint32_t)Flags;
  933. }
  934. static DxilDescriptorRangeFlags GetFlags(const DxilDescriptorRange &D)
  935. {
  936. // Upconvert range flags to be volatile.
  937. DxilDescriptorRangeFlags Flags = DxilDescriptorRangeFlags::DescriptorsVolatile;
  938. // Sampler does not have data.
  939. if (D.RangeType != DxilDescriptorRangeType::Sampler)
  940. Flags = (DxilDescriptorRangeFlags)((unsigned)Flags | (unsigned)DxilDescriptorRangeFlags::DataVolatile);
  941. return Flags;
  942. }
  943. static void SetFlags(DxilDescriptorRange &, DxilDescriptorRangeFlags)
  944. {
  945. }
  946. static DxilDescriptorRangeFlags GetFlags(const DxilContainerDescriptorRange &D)
  947. {
  948. // Upconvert range flags to be volatile.
  949. DxilDescriptorRangeFlags Flags = DxilDescriptorRangeFlags::DescriptorsVolatile;
  950. // Sampler does not have data.
  951. if (D.RangeType != (uint32_t)DxilDescriptorRangeType::Sampler)
  952. Flags |= DxilDescriptorRangeFlags::DataVolatile;
  953. return Flags;
  954. }
  955. static void SetFlags(DxilContainerDescriptorRange &, DxilDescriptorRangeFlags)
  956. {
  957. }
  958. static DxilDescriptorRangeFlags GetFlags(const DxilDescriptorRange1 &D)
  959. {
  960. return D.Flags;
  961. }
  962. static void SetFlags(DxilDescriptorRange1 &D, DxilDescriptorRangeFlags Flags)
  963. {
  964. D.Flags = Flags;
  965. }
  966. static DxilDescriptorRangeFlags GetFlags(const DxilContainerDescriptorRange1 &D)
  967. {
  968. return (DxilDescriptorRangeFlags)D.Flags;
  969. }
  970. static void SetFlags(DxilContainerDescriptorRange1 &D, DxilDescriptorRangeFlags Flags)
  971. {
  972. D.Flags = (uint32_t)Flags;
  973. }
  974. template<typename IN_DXIL_ROOT_SIGNATURE_DESC,
  975. typename OUT_DXIL_ROOT_SIGNATURE_DESC,
  976. typename OUT_DXIL_ROOT_PARAMETER,
  977. typename OUT_DXIL_ROOT_DESCRIPTOR,
  978. typename OUT_DXIL_DESCRIPTOR_RANGE>
  979. void ConvertRootSignatureTemplate(const IN_DXIL_ROOT_SIGNATURE_DESC &DescIn,
  980. DxilRootSignatureVersion DescVersionOut,
  981. OUT_DXIL_ROOT_SIGNATURE_DESC &DescOut)
  982. {
  983. const IN_DXIL_ROOT_SIGNATURE_DESC *pDescIn = &DescIn;
  984. OUT_DXIL_ROOT_SIGNATURE_DESC *pDescOut = &DescOut;
  985. // Root signature descriptor.
  986. pDescOut->Flags = pDescIn->Flags;
  987. pDescOut->NumParameters = 0;
  988. pDescOut->NumStaticSamplers = 0;
  989. // Intialize all pointers early so that clean up works properly.
  990. pDescOut->pParameters = nullptr;
  991. pDescOut->pStaticSamplers = nullptr;
  992. // Root signature parameters.
  993. if (pDescIn->NumParameters > 0) {
  994. pDescOut->pParameters = new OUT_DXIL_ROOT_PARAMETER[pDescIn->NumParameters];
  995. pDescOut->NumParameters = pDescIn->NumParameters;
  996. memset((void *)pDescOut->pParameters, 0, pDescOut->NumParameters*sizeof(OUT_DXIL_ROOT_PARAMETER));
  997. }
  998. for (unsigned iRP = 0; iRP < pDescIn->NumParameters; iRP++) {
  999. const auto &ParamIn = pDescIn->pParameters[iRP];
  1000. OUT_DXIL_ROOT_PARAMETER &ParamOut = (OUT_DXIL_ROOT_PARAMETER &)pDescOut->pParameters[iRP];
  1001. ParamOut.ParameterType = ParamIn.ParameterType;
  1002. ParamOut.ShaderVisibility = ParamIn.ShaderVisibility;
  1003. switch (ParamIn.ParameterType) {
  1004. case DxilRootParameterType::DescriptorTable: {
  1005. ParamOut.DescriptorTable.pDescriptorRanges = nullptr;
  1006. unsigned NumRanges = ParamIn.DescriptorTable.NumDescriptorRanges;
  1007. if (NumRanges > 0) {
  1008. ParamOut.DescriptorTable.pDescriptorRanges = new OUT_DXIL_DESCRIPTOR_RANGE[NumRanges];
  1009. ParamOut.DescriptorTable.NumDescriptorRanges = NumRanges;
  1010. }
  1011. for (unsigned i = 0; i < NumRanges; i++) {
  1012. const auto &RangeIn = ParamIn.DescriptorTable.pDescriptorRanges[i];
  1013. OUT_DXIL_DESCRIPTOR_RANGE &RangeOut = (OUT_DXIL_DESCRIPTOR_RANGE &)ParamOut.DescriptorTable.pDescriptorRanges[i];
  1014. RangeOut.RangeType = RangeIn.RangeType;
  1015. RangeOut.NumDescriptors = RangeIn.NumDescriptors;
  1016. RangeOut.BaseShaderRegister = RangeIn.BaseShaderRegister;
  1017. RangeOut.RegisterSpace = RangeIn.RegisterSpace;
  1018. RangeOut.OffsetInDescriptorsFromTableStart = RangeIn.OffsetInDescriptorsFromTableStart;
  1019. DxilDescriptorRangeFlags Flags = GetFlags(RangeIn);
  1020. SetFlags(RangeOut, Flags);
  1021. }
  1022. break;
  1023. }
  1024. case DxilRootParameterType::Constants32Bit: {
  1025. ParamOut.Constants.Num32BitValues = ParamIn.Constants.Num32BitValues;
  1026. ParamOut.Constants.ShaderRegister = ParamIn.Constants.ShaderRegister;
  1027. ParamOut.Constants.RegisterSpace = ParamIn.Constants.RegisterSpace;
  1028. break;
  1029. }
  1030. case DxilRootParameterType::CBV:
  1031. case DxilRootParameterType::SRV:
  1032. case DxilRootParameterType::UAV: {
  1033. ParamOut.Descriptor.ShaderRegister = ParamIn.Descriptor.ShaderRegister;
  1034. ParamOut.Descriptor.RegisterSpace = ParamIn.Descriptor.RegisterSpace;
  1035. DxilRootDescriptorFlags Flags = GetFlags(ParamIn.Descriptor);
  1036. SetFlags(ParamOut.Descriptor, Flags);
  1037. break;
  1038. }
  1039. default:
  1040. IFT(E_FAIL);
  1041. }
  1042. }
  1043. // Static samplers.
  1044. if (pDescIn->NumStaticSamplers > 0) {
  1045. pDescOut->pStaticSamplers = new DxilStaticSamplerDesc[pDescIn->NumStaticSamplers];
  1046. pDescOut->NumStaticSamplers = pDescIn->NumStaticSamplers;
  1047. memcpy((void*)pDescOut->pStaticSamplers, pDescIn->pStaticSamplers, pDescOut->NumStaticSamplers*sizeof(DxilStaticSamplerDesc));
  1048. }
  1049. }
  1050. void ConvertRootSignature(const DxilVersionedRootSignatureDesc * pRootSignatureIn,
  1051. DxilRootSignatureVersion RootSignatureVersionOut,
  1052. const DxilVersionedRootSignatureDesc ** ppRootSignatureOut) {
  1053. IFTBOOL(pRootSignatureIn != nullptr && ppRootSignatureOut != nullptr, E_INVALIDARG);
  1054. *ppRootSignatureOut = nullptr;
  1055. if (pRootSignatureIn->Version == RootSignatureVersionOut){
  1056. // No conversion. Return the original root signature pointer; no cloning.
  1057. *ppRootSignatureOut = pRootSignatureIn;
  1058. return;
  1059. }
  1060. DxilVersionedRootSignatureDesc *pRootSignatureOut = nullptr;
  1061. try {
  1062. pRootSignatureOut = new DxilVersionedRootSignatureDesc();
  1063. memset(pRootSignatureOut, 0, sizeof(*pRootSignatureOut));
  1064. // Convert root signature.
  1065. switch (RootSignatureVersionOut) {
  1066. case DxilRootSignatureVersion::Version_1_0:
  1067. switch (pRootSignatureIn->Version) {
  1068. case DxilRootSignatureVersion::Version_1_1:
  1069. pRootSignatureOut->Version = DxilRootSignatureVersion::Version_1_0;
  1070. ConvertRootSignatureTemplate<
  1071. DxilRootSignatureDesc1,
  1072. DxilRootSignatureDesc,
  1073. DxilRootParameter,
  1074. DxilRootDescriptor,
  1075. DxilDescriptorRange>(pRootSignatureIn->Desc_1_1,
  1076. DxilRootSignatureVersion::Version_1_0,
  1077. pRootSignatureOut->Desc_1_0);
  1078. break;
  1079. default:
  1080. IFT(E_INVALIDARG);
  1081. }
  1082. break;
  1083. case DxilRootSignatureVersion::Version_1_1:
  1084. switch (pRootSignatureIn->Version) {
  1085. case DxilRootSignatureVersion::Version_1_0:
  1086. pRootSignatureOut->Version = DxilRootSignatureVersion::Version_1_1;
  1087. ConvertRootSignatureTemplate<
  1088. DxilRootSignatureDesc,
  1089. DxilRootSignatureDesc1,
  1090. DxilRootParameter1,
  1091. DxilRootDescriptor1,
  1092. DxilDescriptorRange1>(pRootSignatureIn->Desc_1_0,
  1093. DxilRootSignatureVersion::Version_1_1,
  1094. pRootSignatureOut->Desc_1_1);
  1095. break;
  1096. default:
  1097. IFT(E_INVALIDARG);
  1098. }
  1099. break;
  1100. default:
  1101. IFT(E_INVALIDARG);
  1102. break;
  1103. }
  1104. }
  1105. catch (...) {
  1106. DeleteRootSignature(pRootSignatureOut);
  1107. throw;
  1108. }
  1109. *ppRootSignatureOut = pRootSignatureOut;
  1110. }
  1111. template<typename T_ROOT_SIGNATURE_DESC,
  1112. typename T_ROOT_PARAMETER,
  1113. typename T_ROOT_DESCRIPTOR_INTERNAL,
  1114. typename T_DESCRIPTOR_RANGE_INTERNAL>
  1115. void SerializeRootSignatureTemplate(_In_ const T_ROOT_SIGNATURE_DESC* pRootSignature,
  1116. DxilRootSignatureVersion DescVersion,
  1117. _COM_Outptr_ IDxcBlob** ppBlob,
  1118. DiagnosticPrinter &DiagPrinter,
  1119. _In_ bool bAllowReservedRegisterSpace) {
  1120. DxilContainerRootSignatureDesc RS;
  1121. uint32_t Offset;
  1122. SimpleSerializer Serializer;
  1123. IFT(Serializer.AddBlock(&RS, sizeof(RS), &Offset));
  1124. IFTBOOL(Offset == 0, E_FAIL);
  1125. const T_ROOT_SIGNATURE_DESC *pRS = pRootSignature;
  1126. RS.Version = (uint32_t)DescVersion;
  1127. RS.Flags = (uint32_t)pRS->Flags;
  1128. RS.NumParameters = pRS->NumParameters;
  1129. RS.NumStaticSamplers = pRS->NumStaticSamplers;
  1130. DxilContainerRootParameter *pRP;
  1131. IFT(Serializer.ReserveBlock((void**)&pRP,
  1132. sizeof(DxilContainerRootParameter)*RS.NumParameters, &RS.RootParametersOffset));
  1133. for (uint32_t iRP = 0; iRP < RS.NumParameters; iRP++) {
  1134. const T_ROOT_PARAMETER *pInRP = &pRS->pParameters[iRP];
  1135. DxilContainerRootParameter *pOutRP = &pRP[iRP];
  1136. pOutRP->ParameterType = (uint32_t)pInRP->ParameterType;
  1137. pOutRP->ShaderVisibility = (uint32_t)pInRP->ShaderVisibility;
  1138. switch (pInRP->ParameterType) {
  1139. case DxilRootParameterType::DescriptorTable: {
  1140. DxilContainerRootDescriptorTable *p1;
  1141. IFT(Serializer.ReserveBlock((void**)&p1,
  1142. sizeof(DxilContainerRootDescriptorTable),
  1143. &pOutRP->PayloadOffset));
  1144. p1->NumDescriptorRanges = pInRP->DescriptorTable.NumDescriptorRanges;
  1145. T_DESCRIPTOR_RANGE_INTERNAL *p2;
  1146. IFT(Serializer.ReserveBlock((void**)&p2,
  1147. sizeof(T_DESCRIPTOR_RANGE_INTERNAL)*p1->NumDescriptorRanges,
  1148. &p1->DescriptorRangesOffset));
  1149. for (uint32_t i = 0; i < p1->NumDescriptorRanges; i++) {
  1150. p2[i].RangeType = (uint32_t)pInRP->DescriptorTable.pDescriptorRanges[i].RangeType;
  1151. p2[i].NumDescriptors = pInRP->DescriptorTable.pDescriptorRanges[i].NumDescriptors;
  1152. p2[i].BaseShaderRegister = pInRP->DescriptorTable.pDescriptorRanges[i].BaseShaderRegister;
  1153. p2[i].RegisterSpace = pInRP->DescriptorTable.pDescriptorRanges[i].RegisterSpace;
  1154. p2[i].OffsetInDescriptorsFromTableStart = pInRP->DescriptorTable.pDescriptorRanges[i].OffsetInDescriptorsFromTableStart;
  1155. DxilDescriptorRangeFlags Flags = GetFlags(pInRP->DescriptorTable.pDescriptorRanges[i]);
  1156. SetFlags(p2[i], Flags);
  1157. }
  1158. break;
  1159. }
  1160. case DxilRootParameterType::Constants32Bit: {
  1161. DxilRootConstants *p;
  1162. IFT(Serializer.ReserveBlock((void**)&p, sizeof(DxilRootConstants), &pOutRP->PayloadOffset));
  1163. p->Num32BitValues = pInRP->Constants.Num32BitValues;
  1164. p->ShaderRegister = pInRP->Constants.ShaderRegister;
  1165. p->RegisterSpace = pInRP->Constants.RegisterSpace;
  1166. break;
  1167. }
  1168. case DxilRootParameterType::CBV:
  1169. case DxilRootParameterType::SRV:
  1170. case DxilRootParameterType::UAV: {
  1171. T_ROOT_DESCRIPTOR_INTERNAL *p;
  1172. IFT(Serializer.ReserveBlock((void**)&p, sizeof(T_ROOT_DESCRIPTOR_INTERNAL), &pOutRP->PayloadOffset));
  1173. p->ShaderRegister = pInRP->Descriptor.ShaderRegister;
  1174. p->RegisterSpace = pInRP->Descriptor.RegisterSpace;
  1175. DxilRootDescriptorFlags Flags = GetFlags(pInRP->Descriptor);
  1176. SetFlags(*p, Flags);
  1177. break;
  1178. }
  1179. default:
  1180. EAT(DiagPrinter << "D3DSerializeRootSignature: unknown root parameter type ("
  1181. << (uint32_t)pInRP->ParameterType << ")\n");
  1182. }
  1183. }
  1184. DxilStaticSamplerDesc *pSS;
  1185. unsigned StaticSamplerSize = sizeof(DxilStaticSamplerDesc)*RS.NumStaticSamplers;
  1186. IFT(Serializer.ReserveBlock((void**)&pSS, StaticSamplerSize, &RS.StaticSamplersOffset));
  1187. memcpy(pSS, pRS->pStaticSamplers, StaticSamplerSize);
  1188. // Create the result blob.
  1189. CDxcMallocHeapPtr<char> bytes(DxcGetThreadMallocNoRef());
  1190. CComPtr<IDxcBlob> pBlob;
  1191. unsigned cb = Serializer.GetSize();
  1192. DXASSERT_NOMSG((cb & 0x3) == 0);
  1193. IFTBOOL(bytes.Allocate(cb), E_OUTOFMEMORY);
  1194. IFT(Serializer.Compact(bytes.m_pData, cb));
  1195. IFT(DxcCreateBlobOnHeap(bytes.m_pData, cb, ppBlob));
  1196. bytes.Detach(); // Ownership transfered to ppBlob.
  1197. }
  1198. _Use_decl_annotations_
  1199. void SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature,
  1200. IDxcBlob **ppBlob, IDxcBlobEncoding **ppErrorBlob,
  1201. bool bAllowReservedRegisterSpace) {
  1202. DXASSERT_NOMSG(pRootSignature != nullptr);
  1203. DXASSERT_NOMSG(ppBlob != nullptr);
  1204. DXASSERT_NOMSG(ppErrorBlob != nullptr);
  1205. *ppBlob = nullptr;
  1206. *ppErrorBlob = nullptr;
  1207. RootSignatureVerifier RSV;
  1208. // TODO: change SerializeRootSignature to take raw_ostream&
  1209. string DiagString;
  1210. raw_string_ostream DiagStream(DiagString);
  1211. DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
  1212. // Verify root signature.
  1213. RSV.AllowReservedRegisterSpace(bAllowReservedRegisterSpace);
  1214. try {
  1215. RSV.VerifyRootSignature(pRootSignature, DiagPrinter);
  1216. switch (pRootSignature->Version)
  1217. {
  1218. case DxilRootSignatureVersion::Version_1_0:
  1219. SerializeRootSignatureTemplate<
  1220. DxilRootSignatureDesc,
  1221. DxilRootParameter,
  1222. DxilRootDescriptor,
  1223. DxilContainerDescriptorRange>(&pRootSignature->Desc_1_0,
  1224. DxilRootSignatureVersion::Version_1_0,
  1225. ppBlob, DiagPrinter,
  1226. bAllowReservedRegisterSpace);
  1227. break;
  1228. case DxilRootSignatureVersion::Version_1_1:
  1229. default:
  1230. DXASSERT(pRootSignature->Version == DxilRootSignatureVersion::Version_1_1, "else VerifyRootSignature didn't validate");
  1231. SerializeRootSignatureTemplate<
  1232. DxilRootSignatureDesc1,
  1233. DxilRootParameter1,
  1234. DxilContainerRootDescriptor1,
  1235. DxilContainerDescriptorRange1>(&pRootSignature->Desc_1_1,
  1236. DxilRootSignatureVersion::Version_1_1,
  1237. ppBlob, DiagPrinter,
  1238. bAllowReservedRegisterSpace);
  1239. break;
  1240. }
  1241. } catch (...) {
  1242. DiagStream.flush();
  1243. DxcCreateBlobWithEncodingOnHeapCopy(DiagString.c_str(), DiagString.size(), CP_UTF8, ppErrorBlob);
  1244. }
  1245. }
  1246. //=============================================================================
  1247. //
  1248. // CVersionedRootSignatureDeserializer.
  1249. //
  1250. //=============================================================================
  1251. class CVersionedRootSignatureDeserializer {
  1252. protected:
  1253. const DxilVersionedRootSignatureDesc *m_pRootSignature;
  1254. const DxilVersionedRootSignatureDesc *m_pRootSignature10;
  1255. const DxilVersionedRootSignatureDesc *m_pRootSignature11;
  1256. public:
  1257. CVersionedRootSignatureDeserializer();
  1258. ~CVersionedRootSignatureDeserializer();
  1259. void Initialize(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
  1260. _In_ uint32_t SrcDataSizeInBytes);
  1261. const DxilVersionedRootSignatureDesc *GetRootSignatureDescAtVersion(DxilRootSignatureVersion convertToVersion);
  1262. const DxilVersionedRootSignatureDesc *GetUnconvertedRootSignatureDesc();
  1263. };
  1264. CVersionedRootSignatureDeserializer::CVersionedRootSignatureDeserializer()
  1265. : m_pRootSignature(nullptr)
  1266. , m_pRootSignature10(nullptr)
  1267. , m_pRootSignature11(nullptr) {
  1268. }
  1269. CVersionedRootSignatureDeserializer::~CVersionedRootSignatureDeserializer() {
  1270. DeleteRootSignature(m_pRootSignature10);
  1271. DeleteRootSignature(m_pRootSignature11);
  1272. }
  1273. void CVersionedRootSignatureDeserializer::Initialize(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
  1274. _In_ uint32_t SrcDataSizeInBytes) {
  1275. const DxilVersionedRootSignatureDesc *pRootSignature = nullptr;
  1276. DeserializeRootSignature(pSrcData, SrcDataSizeInBytes, &pRootSignature);
  1277. switch (pRootSignature->Version) {
  1278. case DxilRootSignatureVersion::Version_1_0:
  1279. m_pRootSignature10 = pRootSignature;
  1280. break;
  1281. case DxilRootSignatureVersion::Version_1_1:
  1282. m_pRootSignature11 = pRootSignature;
  1283. break;
  1284. default:
  1285. DeleteRootSignature(pRootSignature);
  1286. return;
  1287. }
  1288. m_pRootSignature = pRootSignature;
  1289. }
  1290. const DxilVersionedRootSignatureDesc *
  1291. CVersionedRootSignatureDeserializer::GetUnconvertedRootSignatureDesc() {
  1292. return m_pRootSignature;
  1293. }
  1294. const DxilVersionedRootSignatureDesc *
  1295. CVersionedRootSignatureDeserializer::GetRootSignatureDescAtVersion(DxilRootSignatureVersion ConvertToVersion) {
  1296. switch (ConvertToVersion) {
  1297. case DxilRootSignatureVersion::Version_1_0:
  1298. if (m_pRootSignature10 == nullptr) {
  1299. ConvertRootSignature(m_pRootSignature,
  1300. ConvertToVersion,
  1301. (const DxilVersionedRootSignatureDesc **)&m_pRootSignature10);
  1302. }
  1303. return m_pRootSignature10;
  1304. case DxilRootSignatureVersion::Version_1_1:
  1305. if (m_pRootSignature11 == nullptr) {
  1306. ConvertRootSignature(m_pRootSignature,
  1307. ConvertToVersion,
  1308. (const DxilVersionedRootSignatureDesc **)&m_pRootSignature11);
  1309. }
  1310. return m_pRootSignature11;
  1311. default:
  1312. IFTBOOL(false, E_FAIL);
  1313. }
  1314. return nullptr;
  1315. }
  1316. template<typename T_ROOT_SIGNATURE_DESC,
  1317. typename T_ROOT_PARAMETER,
  1318. typename T_ROOT_DESCRIPTOR,
  1319. typename T_ROOT_DESCRIPTOR_INTERNAL,
  1320. typename T_DESCRIPTOR_RANGE,
  1321. typename T_DESCRIPTOR_RANGE_INTERNAL>
  1322. void DeserializeRootSignatureTemplate(_In_reads_bytes_(SrcDataSizeInBytes) const void *pSrcData,
  1323. _In_ uint32_t SrcDataSizeInBytes,
  1324. DxilRootSignatureVersion DescVersion,
  1325. T_ROOT_SIGNATURE_DESC &RootSignatureDesc) {
  1326. // Note that in case of failure, outside code must deallocate memory.
  1327. T_ROOT_SIGNATURE_DESC *pRootSignature = &RootSignatureDesc;
  1328. const char *pData = (const char *)pSrcData;
  1329. const char *pMaxPtr = pData + SrcDataSizeInBytes;
  1330. UNREFERENCED_PARAMETER(DescVersion);
  1331. DXASSERT_NOMSG(((uint32_t*)pData)[0] == (uint32_t)DescVersion);
  1332. // Root signature.
  1333. IFTBOOL(pData + sizeof(DxilContainerRootSignatureDesc) <= pMaxPtr, E_FAIL);
  1334. DxilContainerRootSignatureDesc *pRS = (DxilContainerRootSignatureDesc *)pData;
  1335. pRootSignature->Flags = (DxilRootSignatureFlags)pRS->Flags;
  1336. pRootSignature->NumParameters = pRS->NumParameters;
  1337. pRootSignature->NumStaticSamplers = pRS->NumStaticSamplers;
  1338. // Intialize all pointers early so that clean up works properly.
  1339. pRootSignature->pParameters = nullptr;
  1340. pRootSignature->pStaticSamplers = nullptr;
  1341. size_t s = sizeof(DxilContainerRootParameter)*pRS->NumParameters;
  1342. DxilContainerRootParameter *pInRTS = (DxilContainerRootParameter *)(pData + pRS->RootParametersOffset);
  1343. IFTBOOL(((char*)pInRTS) + s <= pMaxPtr, E_FAIL);
  1344. if (pRootSignature->NumParameters) {
  1345. pRootSignature->pParameters = new T_ROOT_PARAMETER[pRootSignature->NumParameters];
  1346. }
  1347. memset((void *)pRootSignature->pParameters, 0, s);
  1348. for(unsigned iRP = 0; iRP < pRootSignature->NumParameters; iRP++) {
  1349. DxilRootParameterType ParameterType = (DxilRootParameterType)pInRTS[iRP].ParameterType;
  1350. T_ROOT_PARAMETER *pOutRTS = (T_ROOT_PARAMETER *)&pRootSignature->pParameters[iRP];
  1351. pOutRTS->ParameterType = ParameterType;
  1352. pOutRTS->ShaderVisibility = (DxilShaderVisibility)pInRTS[iRP].ShaderVisibility;
  1353. switch(ParameterType) {
  1354. case DxilRootParameterType::DescriptorTable: {
  1355. DxilContainerRootDescriptorTable *p1 = (DxilContainerRootDescriptorTable*)(pData + pInRTS[iRP].PayloadOffset);
  1356. IFTBOOL((char*)p1 + sizeof(DxilContainerRootDescriptorTable) <= pMaxPtr, E_FAIL);
  1357. pOutRTS->DescriptorTable.NumDescriptorRanges = p1->NumDescriptorRanges;
  1358. pOutRTS->DescriptorTable.pDescriptorRanges = nullptr;
  1359. T_DESCRIPTOR_RANGE_INTERNAL *p2 = (T_DESCRIPTOR_RANGE_INTERNAL*)(pData + p1->DescriptorRangesOffset);
  1360. IFTBOOL((char*)p2 + sizeof(T_DESCRIPTOR_RANGE_INTERNAL) <= pMaxPtr, E_FAIL);
  1361. if (p1->NumDescriptorRanges) {
  1362. pOutRTS->DescriptorTable.pDescriptorRanges = new T_DESCRIPTOR_RANGE[p1->NumDescriptorRanges];
  1363. }
  1364. for (unsigned i = 0; i < p1->NumDescriptorRanges; i++) {
  1365. T_DESCRIPTOR_RANGE *p3 = (T_DESCRIPTOR_RANGE *)&pOutRTS->DescriptorTable.pDescriptorRanges[i];
  1366. p3->RangeType = (DxilDescriptorRangeType)p2[i].RangeType;
  1367. p3->NumDescriptors = p2[i].NumDescriptors;
  1368. p3->BaseShaderRegister = p2[i].BaseShaderRegister;
  1369. p3->RegisterSpace = p2[i].RegisterSpace;
  1370. p3->OffsetInDescriptorsFromTableStart = p2[i].OffsetInDescriptorsFromTableStart;
  1371. DxilDescriptorRangeFlags Flags = GetFlags(p2[i]);
  1372. SetFlags(*p3, Flags);
  1373. }
  1374. break;
  1375. }
  1376. case DxilRootParameterType::Constants32Bit: {
  1377. DxilRootConstants *p = (DxilRootConstants*)(pData + pInRTS[iRP].PayloadOffset);
  1378. IFTBOOL((char*)p + sizeof(DxilRootConstants) <= pMaxPtr, E_FAIL);
  1379. pOutRTS->Constants.Num32BitValues = p->Num32BitValues;
  1380. pOutRTS->Constants.ShaderRegister = p->ShaderRegister;
  1381. pOutRTS->Constants.RegisterSpace = p->RegisterSpace;
  1382. break;
  1383. }
  1384. case DxilRootParameterType::CBV:
  1385. case DxilRootParameterType::SRV:
  1386. case DxilRootParameterType::UAV: {
  1387. T_ROOT_DESCRIPTOR *p = (T_ROOT_DESCRIPTOR *)(pData + pInRTS[iRP].PayloadOffset);
  1388. IFTBOOL((char*)p + sizeof(T_ROOT_DESCRIPTOR) <= pMaxPtr, E_FAIL);
  1389. pOutRTS->Descriptor.ShaderRegister = p->ShaderRegister;
  1390. pOutRTS->Descriptor.RegisterSpace = p->RegisterSpace;
  1391. DxilRootDescriptorFlags Flags = GetFlags(*p);
  1392. SetFlags(pOutRTS->Descriptor, Flags);
  1393. break;
  1394. }
  1395. default:
  1396. IFT(E_FAIL);
  1397. }
  1398. }
  1399. s = sizeof(DxilStaticSamplerDesc)*pRS->NumStaticSamplers;
  1400. DxilStaticSamplerDesc *pInSS = (DxilStaticSamplerDesc *)(pData + pRS->StaticSamplersOffset);
  1401. IFTBOOL(((char*)pInSS) + s <= pMaxPtr, E_FAIL);
  1402. if (pRootSignature->NumStaticSamplers) {
  1403. pRootSignature->pStaticSamplers = new DxilStaticSamplerDesc[pRootSignature->NumStaticSamplers];
  1404. }
  1405. memcpy((void*)pRootSignature->pStaticSamplers, pInSS, s);
  1406. }
  1407. _Use_decl_annotations_
  1408. void DeserializeRootSignature(const void *pSrcData,
  1409. uint32_t SrcDataSizeInBytes,
  1410. const DxilVersionedRootSignatureDesc **ppRootSignature) {
  1411. DxilVersionedRootSignatureDesc *pRootSignature = nullptr;
  1412. IFTBOOL(pSrcData != nullptr && SrcDataSizeInBytes != 0 && ppRootSignature != nullptr, E_INVALIDARG);
  1413. IFTBOOL(*ppRootSignature == nullptr, E_INVALIDARG);
  1414. const char *pData = (const char *)pSrcData;
  1415. IFTBOOL(pData + sizeof(uint32_t) < pData + SrcDataSizeInBytes, E_FAIL);
  1416. DxilRootSignatureVersion Version = (DxilRootSignatureVersion)((uint32_t*)pData)[0];
  1417. pRootSignature = new DxilVersionedRootSignatureDesc();
  1418. try {
  1419. switch (Version) {
  1420. case DxilRootSignatureVersion::Version_1_0:
  1421. pRootSignature->Version = DxilRootSignatureVersion::Version_1_0;
  1422. DeserializeRootSignatureTemplate<
  1423. DxilRootSignatureDesc,
  1424. DxilRootParameter,
  1425. DxilRootDescriptor,
  1426. DxilRootDescriptor,
  1427. DxilDescriptorRange,
  1428. DxilContainerDescriptorRange>(pSrcData,
  1429. SrcDataSizeInBytes,
  1430. DxilRootSignatureVersion::Version_1_0,
  1431. pRootSignature->Desc_1_0);
  1432. break;
  1433. case DxilRootSignatureVersion::Version_1_1:
  1434. pRootSignature->Version = DxilRootSignatureVersion::Version_1_1;
  1435. DeserializeRootSignatureTemplate<
  1436. DxilRootSignatureDesc1,
  1437. DxilRootParameter1,
  1438. DxilRootDescriptor1,
  1439. DxilContainerRootDescriptor1,
  1440. DxilDescriptorRange1,
  1441. DxilContainerDescriptorRange1>(pSrcData,
  1442. SrcDataSizeInBytes,
  1443. DxilRootSignatureVersion::Version_1_1,
  1444. pRootSignature->Desc_1_1);
  1445. break;
  1446. default:
  1447. IFT(E_FAIL);
  1448. break;
  1449. }
  1450. } catch(...) {
  1451. DeleteRootSignature(pRootSignature);
  1452. throw;
  1453. }
  1454. *ppRootSignature = pRootSignature;
  1455. }
  1456. static DxilShaderVisibility GetVisibilityType(DXIL::ShaderKind ShaderKind) {
  1457. switch(ShaderKind) {
  1458. case DXIL::ShaderKind::Pixel: return DxilShaderVisibility::Pixel;
  1459. case DXIL::ShaderKind::Vertex: return DxilShaderVisibility::Vertex;
  1460. case DXIL::ShaderKind::Geometry: return DxilShaderVisibility::Geometry;
  1461. case DXIL::ShaderKind::Hull: return DxilShaderVisibility::Hull;
  1462. case DXIL::ShaderKind::Domain: return DxilShaderVisibility::Domain;
  1463. default: return DxilShaderVisibility::All;
  1464. }
  1465. }
  1466. _Use_decl_annotations_
  1467. bool VerifyRootSignatureWithShaderPSV(const DxilVersionedRootSignatureDesc *pDesc,
  1468. DXIL::ShaderKind ShaderKind,
  1469. const void *pPSVData,
  1470. uint32_t PSVSize,
  1471. llvm::raw_ostream &DiagStream) {
  1472. try {
  1473. RootSignatureVerifier RSV;
  1474. DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
  1475. RSV.VerifyRootSignature(pDesc, DiagPrinter);
  1476. RSV.VerifyShader(GetVisibilityType(ShaderKind), pPSVData, PSVSize, DiagPrinter);
  1477. } catch (...) {
  1478. return false;
  1479. }
  1480. return true;
  1481. }
  1482. } // namespace hlsl