DxilRootSignature.cpp 63 KB

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