DxilRootSignature.cpp 63 KB

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