DxilRootSignature.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369
  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/DxilRootSignature.h"
  12. #include "dxc/Support/Global.h"
  13. #include "dxc/Support/WinIncludes.h"
  14. #include "dxc/Support/FileIOHelper.h"
  15. #include "dxc/dxcapi.h"
  16. #include <algorithm>
  17. #include <utility>
  18. #include <vector>
  19. namespace hlsl {
  20. DEFINE_ENUM_FLAG_OPERATORS(DxilRootSignatureFlags)
  21. DEFINE_ENUM_FLAG_OPERATORS(DxilRootDescriptorFlags)
  22. DEFINE_ENUM_FLAG_OPERATORS(DxilDescriptorRangeType)
  23. DEFINE_ENUM_FLAG_OPERATORS(DxilDescriptorRangeFlags)
  24. //////////////////////////////////////////////////////////////////////////////
  25. // Error handling helper.
  26. static void ErrorRootSignature(IStream *pStream, const char *pFormat, ...) {
  27. va_list ArgList;
  28. char Buf[2048];
  29. if (pStream == nullptr)
  30. return;
  31. va_start(ArgList, pFormat);
  32. HRESULT hr = StringCchVPrintfA(Buf, _countof(Buf), pFormat, ArgList);
  33. va_end(ArgList);
  34. ULONG written;
  35. IFT(hr);
  36. IFT(pStream->Write(Buf, strlen(Buf), &written));
  37. }
  38. //////////////////////////////////////////////////////////////////////////////
  39. // Root signature handler.
  40. RootSignatureHandle::RootSignatureHandle(RootSignatureHandle&& other) {
  41. m_pDesc = nullptr;
  42. m_pSerialized = nullptr;
  43. std::swap(m_pDesc, other.m_pDesc);
  44. std::swap(m_pSerialized, other.m_pSerialized);
  45. }
  46. void RootSignatureHandle::Assign(const DxilVersionedRootSignatureDesc *pDesc,
  47. IDxcBlob *pSerialized) {
  48. Clear();
  49. m_pDesc = pDesc;
  50. m_pSerialized = pSerialized;
  51. if (m_pSerialized)
  52. m_pSerialized->AddRef();
  53. }
  54. void RootSignatureHandle::Clear() {
  55. hlsl::DeleteRootSignature(m_pDesc);
  56. m_pDesc = nullptr;
  57. if (m_pSerialized != nullptr) {
  58. m_pSerialized->Release();
  59. m_pSerialized = nullptr;
  60. }
  61. }
  62. const uint8_t *RootSignatureHandle::GetSerializedBytes() const {
  63. DXASSERT_NOMSG(m_pSerialized != nullptr);
  64. return (uint8_t *)m_pSerialized->GetBufferPointer();
  65. }
  66. unsigned RootSignatureHandle::GetSerializedSize() const {
  67. DXASSERT_NOMSG(m_pSerialized != nullptr);
  68. return m_pSerialized->GetBufferSize();
  69. }
  70. void RootSignatureHandle::EnsureSerializedAvailable() {
  71. DXASSERT_NOMSG(!IsEmpty());
  72. if (m_pSerialized == nullptr) {
  73. CComPtr<IDxcBlob> pResult;
  74. hlsl::SerializeRootSignature(m_pDesc, &pResult, nullptr, false);
  75. IFTBOOL(pResult != nullptr, E_FAIL);
  76. m_pSerialized = pResult.Detach();
  77. }
  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_bcount(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 = NULL;
  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 = NULL;
  132. m_cbSegments += pSegment->cbSize;
  133. *m_ppSegment = pSegment;
  134. m_ppSegment = &pSegment->pNext;
  135. if (pOffset != NULL) {
  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 = NULL;
  144. void *pClonedData = NULL;
  145. IFCOOM(pSegment = new (std::nothrow) Segment);
  146. pSegment->pData = NULL;
  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 = NULL;
  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_bcount(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::vector<T> m_set;
  201. public:
  202. T* FindIntersectingInterval(const T &I) {
  203. DXASSERT(m_set.size() < INT_MAX,
  204. "else too many interval entries, and min<max check can undeflow");
  205. int mid, min = 0, max = (int)m_set.size();
  206. while (min < max) {
  207. mid = (min + max) / 2;
  208. T &R = m_set[mid];
  209. int order = I.overlap(R);
  210. if (order == 0) return &R;
  211. if (order < 0)
  212. max = mid - 1;
  213. else
  214. min = mid + 1;
  215. }
  216. return nullptr;
  217. }
  218. void Insert(const T& value) {
  219. // Find the first element that is greater or equal to value.
  220. auto it = std::lower_bound(m_set.begin(), m_set.end(), value);
  221. if (it == m_set.end()) {
  222. m_set.push_back(value);
  223. }
  224. else {
  225. m_set.insert(it, value);
  226. #if DBG
  227. // Verify that the insertion didn't violate disjoint range assumptions.
  228. for (size_t i = 1; i < m_set.size(); ++i) {
  229. DXASSERT_NOMSG(m_set[i - 1].overlap(m_set[i]));
  230. DXASSERT_NOMSG(m_set[i - 1].space < m_set[i].space ||
  231. m_set[i - 1].ub < m_set[i].lb);
  232. }
  233. #endif
  234. }
  235. }
  236. };
  237. //////////////////////////////////////////////////////////////////////////////
  238. // Verifier classes.
  239. class DescriptorTableVerifier {
  240. public:
  241. HRESULT Verify(const DxilDescriptorRange1 *pRanges, unsigned NumRanges,
  242. unsigned iRTS, IStream *pErrors);
  243. };
  244. class StaticSamplerVerifier {
  245. public:
  246. HRESULT Verify(const DxilStaticSamplerDesc *pDesc, IStream *pErrors);
  247. };
  248. class RootSignatureVerifier {
  249. public:
  250. RootSignatureVerifier();
  251. ~RootSignatureVerifier();
  252. // Call this before calling VerifyShader, as it accumulates root signature
  253. // state.
  254. HRESULT
  255. VerifyRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature,
  256. IStream *pErrors);
  257. void AllowReservedRegisterSpace(bool bAllow);
  258. typedef enum NODE_TYPE {
  259. DESCRIPTOR_TABLE_ENTRY,
  260. ROOT_DESCRIPTOR,
  261. ROOT_CONSTANT,
  262. STATIC_SAMPLER
  263. } NODE_TYPE;
  264. private:
  265. static const unsigned kMinVisType = (unsigned)DxilShaderVisibility::All;
  266. static const unsigned kMaxVisType = (unsigned)DxilShaderVisibility::Pixel;
  267. static const unsigned kMinDescType = (unsigned)DxilDescriptorRangeType::SRV;
  268. static const unsigned kMaxDescType = (unsigned)DxilDescriptorRangeType::Sampler;
  269. struct RegisterRange {
  270. NODE_TYPE nt;
  271. unsigned space;
  272. unsigned lb; // inclusive lower bound
  273. unsigned ub; // inclusive upper bound
  274. unsigned iRP;
  275. unsigned iDTS;
  276. // Sort by space, then lower bound.
  277. bool operator<(const RegisterRange& other) const {
  278. return space < other.space ||
  279. (space == other.space && lb < other.lb);
  280. }
  281. // Like a regular -1,0,1 comparison, but 0 indicates overlap.
  282. int overlap(const RegisterRange& other) const {
  283. if (space < other.space) return -1;
  284. if (space > other.space) return 1;
  285. if (ub < other.lb) return -1;
  286. if (lb > other.ub) return 1;
  287. return 0;
  288. }
  289. };
  290. typedef CIntervalCollection<RegisterRange> RegisterRanges;
  291. HRESULT AddRegisterRange(unsigned iRTS, NODE_TYPE nt, unsigned iDTS,
  292. DxilDescriptorRangeType DescType,
  293. DxilShaderVisibility VisType,
  294. unsigned NumRegisters, unsigned BaseRegister,
  295. unsigned RegisterSpace, IStream *pErrors);
  296. RegisterRanges &
  297. GetRanges(DxilShaderVisibility VisType, DxilDescriptorRangeType DescType) {
  298. return RangeKinds[(unsigned)VisType][(unsigned)DescType];
  299. }
  300. RegisterRanges RangeKinds[kMaxVisType + 1][kMaxDescType + 1];
  301. bool m_bAllowReservedRegisterSpace;
  302. DxilRootSignatureFlags m_RootSignatureFlags;
  303. };
  304. HRESULT DescriptorTableVerifier::Verify(const DxilDescriptorRange1 *pRanges,
  305. UINT NumRanges, UINT iRP,
  306. IStream *pErrors) {
  307. bool bHasSamplers = false;
  308. bool bHasResources = false;
  309. UINT64 iAppendStartSlot = 0;
  310. for (UINT iDTS = 0; iDTS < NumRanges; iDTS++) {
  311. const DxilDescriptorRange1 *pRange = &pRanges[iDTS];
  312. switch (pRange->RangeType) {
  313. case DxilDescriptorRangeType::SRV:
  314. case DxilDescriptorRangeType::UAV:
  315. case DxilDescriptorRangeType::CBV:
  316. bHasResources = true;
  317. break;
  318. case DxilDescriptorRangeType::Sampler:
  319. bHasSamplers = true;
  320. break;
  321. default:
  322. ErrorRootSignature(pErrors,
  323. "Unsupported RangeType value %u (descriptor table slot [%u], root parameter [%u]).\n",
  324. pRange->RangeType, iDTS, iRP);
  325. return E_FAIL;
  326. }
  327. // Samplers cannot be mixed with other resources.
  328. if (bHasResources && bHasSamplers) {
  329. ErrorRootSignature(pErrors, "Samplers cannot be mixed with other "
  330. "resource types in a descriptor table (root "
  331. "parameter [%u]).\n",
  332. iRP);
  333. return E_FAIL;
  334. }
  335. // NumDescriptors is not 0.
  336. if (pRange->NumDescriptors == 0) {
  337. ErrorRootSignature(pErrors, "NumDescriptors cannot be 0 (descriptor "
  338. "table slot [%u], root parameter [%u]).\n",
  339. iDTS, iRP);
  340. return E_FAIL;
  341. }
  342. // Range start.
  343. UINT64 iStartSlot = iAppendStartSlot;
  344. if (pRange->OffsetInDescriptorsFromTableStart !=
  345. DxilDescriptorRangeOffsetAppend) {
  346. iStartSlot = pRange->OffsetInDescriptorsFromTableStart;
  347. }
  348. if (iStartSlot > UINT_MAX) {
  349. ErrorRootSignature(pErrors, "Cannot append range with implicit lower "
  350. "bound after an unbounded range (descriptor "
  351. "table slot [%u], root parameter [%u]).\n",
  352. iDTS, iRP);
  353. return E_FAIL;
  354. }
  355. // Descriptor range and shader register range overlow.
  356. if (pRange->NumDescriptors != UINT_MAX) {
  357. // Bounded range.
  358. UINT64 ub1 = (UINT64)pRange->BaseShaderRegister +
  359. (UINT64)pRange->NumDescriptors - 1ull;
  360. if (ub1 > UINT_MAX) {
  361. ErrorRootSignature(
  362. pErrors, "Overflow for shader register range: "
  363. "BaseShaderRegister=%u, NumDescriptor=%u; (descriptor "
  364. "table slot [%u], root parameter [%u]).\n",
  365. pRange->BaseShaderRegister, pRange->NumDescriptors, iDTS, iRP);
  366. return E_FAIL;
  367. }
  368. UINT64 ub2 = (UINT64)iStartSlot + (UINT64)pRange->NumDescriptors - 1ull;
  369. if (ub2 > UINT_MAX) {
  370. ErrorRootSignature(pErrors, "Overflow for descriptor range (descriptor "
  371. "table slot [%u], root parameter [%u])\n",
  372. iDTS, iRP);
  373. return E_FAIL;
  374. }
  375. iAppendStartSlot = iStartSlot + (UINT64)pRange->NumDescriptors;
  376. } else {
  377. // Unbounded range.
  378. iAppendStartSlot = 1ull + (UINT64)UINT_MAX;
  379. }
  380. }
  381. return S_OK;
  382. }
  383. RootSignatureVerifier::RootSignatureVerifier() {
  384. m_RootSignatureFlags = DxilRootSignatureFlags::None;
  385. m_bAllowReservedRegisterSpace = false;
  386. }
  387. RootSignatureVerifier::~RootSignatureVerifier() {}
  388. void RootSignatureVerifier::AllowReservedRegisterSpace(bool bAllow) {
  389. m_bAllowReservedRegisterSpace = bAllow;
  390. }
  391. const char* RangeTypeString(DxilDescriptorRangeType rt)
  392. {
  393. static const char *RangeType[] = {"SRV", "UAV", "CBV", "SAMPLER"};
  394. return (rt <= DxilDescriptorRangeType::Sampler) ? RangeType[(unsigned)rt]
  395. : "unknown";
  396. }
  397. const char *VisTypeString(DxilShaderVisibility vis) {
  398. static const char *Vis[] = {"ALL", "VERTEX", "HULL",
  399. "DOMAIN", "GEOMETRY", "PIXEL"};
  400. unsigned idx = (unsigned)vis;
  401. return vis <= DxilShaderVisibility::Pixel ? Vis[idx] : "unknown";
  402. }
  403. static bool IsDxilShaderVisibility(DxilShaderVisibility v) {
  404. return v <= DxilShaderVisibility::Pixel;
  405. }
  406. HRESULT RootSignatureVerifier::AddRegisterRange(unsigned iRP,
  407. NODE_TYPE nt,
  408. unsigned iDTS,
  409. DxilDescriptorRangeType DescType,
  410. DxilShaderVisibility VisType,
  411. unsigned NumRegisters,
  412. unsigned BaseRegister,
  413. unsigned RegisterSpace,
  414. IStream *pErrors)
  415. {
  416. RegisterRange interval;
  417. interval.space = RegisterSpace;
  418. interval.lb = BaseRegister;
  419. interval.ub = (NumRegisters != UINT_MAX) ? BaseRegister + NumRegisters - 1 : UINT_MAX;
  420. interval.nt = nt;
  421. interval.iDTS = iDTS;
  422. interval.iRP = iRP;
  423. if (!m_bAllowReservedRegisterSpace &&
  424. (RegisterSpace >= DxilSystemReservedRegisterSpaceValuesStart) &&
  425. (RegisterSpace <= DxilSystemReservedRegisterSpaceValuesEnd))
  426. {
  427. if (nt == DESCRIPTOR_TABLE_ENTRY)
  428. {
  429. ErrorRootSignature(pErrors,
  430. "Root parameter [%u] descriptor table entry [%u] specifies RegisterSpace=%#x, which is invalid since RegisterSpace values in the range [%#x,%#x] are reserved for system use.\n",
  431. iRP, iDTS, RegisterSpace, DxilSystemReservedRegisterSpaceValuesStart, DxilSystemReservedRegisterSpaceValuesEnd);
  432. return E_FAIL;
  433. }
  434. else
  435. {
  436. ErrorRootSignature(pErrors,
  437. "Root parameter [%u] specifies RegisterSpace=%#x, which is invalid since RegisterSpace values in the range [%#x,%#x] are reserved for system use.\n",
  438. iRP, RegisterSpace, DxilSystemReservedRegisterSpaceValuesStart, DxilSystemReservedRegisterSpaceValuesEnd);
  439. return E_FAIL;
  440. }
  441. }
  442. RegisterRange *pNode = NULL;
  443. DxilShaderVisibility NodeVis = VisType;
  444. if (VisType == DxilShaderVisibility::All) {
  445. // Check for overlap with each visibility type.
  446. for (unsigned iVT = kMinVisType; iVT <= kMaxVisType; iVT++) {
  447. pNode = GetRanges((DxilShaderVisibility)iVT, DescType)
  448. .FindIntersectingInterval(interval);
  449. if (pNode != NULL)
  450. break;
  451. }
  452. } else {
  453. // Check for overlap with the same visibility.
  454. pNode = GetRanges(VisType, DescType).FindIntersectingInterval(interval);
  455. // Check for overlap with ALL visibility.
  456. if (pNode == NULL) {
  457. pNode = GetRanges(DxilShaderVisibility::All, DescType)
  458. .FindIntersectingInterval(interval);
  459. NodeVis = DxilShaderVisibility::All;
  460. }
  461. }
  462. if (pNode != NULL)
  463. {
  464. const int strSize = 132;
  465. char testString[strSize];
  466. char nodeString[strSize];
  467. switch (nt)
  468. {
  469. case DESCRIPTOR_TABLE_ENTRY:
  470. StringCchPrintfA(testString, strSize, "(root parameter [%u], visibility %s, descriptor table slot [%u])",
  471. iRP, VisTypeString(VisType), iDTS);
  472. break;
  473. case ROOT_DESCRIPTOR:
  474. case ROOT_CONSTANT:
  475. StringCchPrintfA(testString, strSize, "(root parameter [%u], visibility %s)",
  476. iRP, VisTypeString(VisType));
  477. break;
  478. case STATIC_SAMPLER:
  479. StringCchPrintfA(testString, strSize, "(static sampler [%u], visibility %s)",
  480. iRP, VisTypeString(VisType));
  481. break;
  482. default:
  483. DXASSERT_NOMSG(false);
  484. break;
  485. }
  486. switch (pNode->nt)
  487. {
  488. case DESCRIPTOR_TABLE_ENTRY:
  489. StringCchPrintfA(nodeString, strSize, "(root parameter[%u], visibility %s, descriptor table slot [%u])",
  490. pNode->iRP, VisTypeString(NodeVis), pNode->iDTS);
  491. break;
  492. case ROOT_DESCRIPTOR:
  493. case ROOT_CONSTANT:
  494. StringCchPrintfA(nodeString, strSize, "(root parameter [%u], visibility %s)",
  495. pNode->iRP, VisTypeString(NodeVis));
  496. break;
  497. case STATIC_SAMPLER:
  498. StringCchPrintfA(nodeString, strSize, "(static sampler [%u], visibility %s)",
  499. pNode->iRP, VisTypeString(NodeVis));
  500. break;
  501. default:
  502. DXASSERT_NOMSG(false);
  503. break;
  504. }
  505. ErrorRootSignature(pErrors,
  506. "Shader register range of type %s %s overlaps with another shader register range %s.\n",
  507. RangeTypeString(DescType), testString, nodeString);
  508. return E_FAIL;
  509. }
  510. // Insert node.
  511. GetRanges(VisType, DescType).Insert(interval);
  512. return S_OK;
  513. }
  514. static DxilDescriptorRangeType GetRangeType(DxilRootParameterType RPT) {
  515. switch (RPT) {
  516. case DxilRootParameterType::CBV: return DxilDescriptorRangeType::CBV;
  517. case DxilRootParameterType::SRV: return DxilDescriptorRangeType::SRV;
  518. case DxilRootParameterType::UAV: return DxilDescriptorRangeType::UAV;
  519. }
  520. DXASSERT_NOMSG(false);
  521. return DxilDescriptorRangeType::SRV;
  522. }
  523. HRESULT RootSignatureVerifier::VerifyRootSignature(const DxilVersionedRootSignatureDesc *pVersionedRootSignature,
  524. IStream *pErrors)
  525. {
  526. const DxilVersionedRootSignatureDesc *pUpconvertedRS = NULL;
  527. if (pVersionedRootSignature == nullptr) {
  528. return E_INVALIDARG;
  529. }
  530. // Up-convert root signature to the latest RS version.
  531. ConvertRootSignature(pVersionedRootSignature, DxilRootSignatureVersion::Version_1_1, &pUpconvertedRS);
  532. DXASSERT_NOMSG(pUpconvertedRS->Version == DxilRootSignatureVersion::Version_1_1);
  533. // Ensure this gets deleted as necessary.
  534. struct SigGuard {
  535. const DxilVersionedRootSignatureDesc *Orig, *Guard;
  536. SigGuard(const DxilVersionedRootSignatureDesc *pOrig, const DxilVersionedRootSignatureDesc *pGuard)
  537. : Orig(pOrig), Guard(pGuard) { }
  538. ~SigGuard() {
  539. if (Orig != Guard) {
  540. DeleteRootSignature(Guard);
  541. }
  542. }
  543. };
  544. SigGuard S(pVersionedRootSignature, pUpconvertedRS);
  545. const DxilRootSignatureDesc1 *pRootSignature = &pUpconvertedRS->Desc_1_1;
  546. // Flags (assume they are bits that can be combined with OR).
  547. if ((unsigned)(pRootSignature->Flags & ~DxilRootSignatureFlags::ValidFlags) != 0)
  548. {
  549. ErrorRootSignature(pErrors,
  550. "Unsupported bit-flag set (root signature flags %x).\n", pRootSignature->Flags);
  551. return E_FAIL;
  552. }
  553. m_RootSignatureFlags = pRootSignature->Flags;
  554. for (unsigned iRP = 0; iRP < pRootSignature->NumParameters; iRP++)
  555. {
  556. const DxilRootParameter1 *pSlot = &pRootSignature->pParameters[iRP];
  557. // Shader visibility.
  558. DxilShaderVisibility Visibility = pSlot->ShaderVisibility;
  559. if (!IsDxilShaderVisibility(Visibility)) {
  560. ErrorRootSignature(pErrors,
  561. "Unsupported ShaderVisibility value %u (root parameter [%u]).\n", Visibility, iRP);
  562. return E_FAIL;
  563. }
  564. DxilRootParameterType ParameterType = pSlot->ParameterType;
  565. switch (ParameterType)
  566. {
  567. case DxilRootParameterType::DescriptorTable:
  568. {
  569. DescriptorTableVerifier DTV;
  570. IFR(DTV.Verify(pSlot->DescriptorTable.pDescriptorRanges,
  571. pSlot->DescriptorTable.NumDescriptorRanges, iRP, pErrors));
  572. for (unsigned iDTS = 0; iDTS < pSlot->DescriptorTable.NumDescriptorRanges; iDTS++)
  573. {
  574. const DxilDescriptorRange1 *pRange = &pSlot->DescriptorTable.pDescriptorRanges[iDTS];
  575. unsigned RangeFlags = (unsigned)pRange->Flags;
  576. // Verify range flags.
  577. if (RangeFlags & ~(unsigned)DxilDescriptorRangeFlags::ValidFlags)
  578. {
  579. ErrorRootSignature(pErrors,
  580. "Unsupported bit-flag set (descriptor range flags %x).\n", pRange->Flags);
  581. return E_FAIL;
  582. }
  583. switch (pRange->RangeType)
  584. {
  585. case DxilDescriptorRangeType::Sampler:
  586. {
  587. if (RangeFlags & (unsigned)(
  588. DxilDescriptorRangeFlags::DataVolatile |
  589. DxilDescriptorRangeFlags::DataStatic |
  590. DxilDescriptorRangeFlags::DataStaticWhileSetAtExecute))
  591. {
  592. ErrorRootSignature(pErrors,
  593. "Sampler descriptor ranges can't specify DATA_* flags since there is no data pointed to by samplers (descriptor range flags %x).\n", pRange->Flags);
  594. return E_FAIL;
  595. }
  596. break;
  597. }
  598. default:
  599. {
  600. unsigned NumDataFlags = 0;
  601. if (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataVolatile) { NumDataFlags++; }
  602. if (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataStatic) { NumDataFlags++; }
  603. if (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataStaticWhileSetAtExecute) { NumDataFlags++; }
  604. if (NumDataFlags > 1)
  605. {
  606. ErrorRootSignature(pErrors,
  607. "Descriptor range flags cannot specify more than one DATA_* flag at a time (descriptor range flags %x).\n", pRange->Flags);
  608. return E_FAIL;
  609. }
  610. if ((RangeFlags & (unsigned)DxilDescriptorRangeFlags::DataStatic) && (RangeFlags & (unsigned)DxilDescriptorRangeFlags::DescriptorsVolatile))
  611. {
  612. ErrorRootSignature(pErrors,
  613. "Descriptor range flags cannot specify DESCRIPTORS_VOLATILE with the DATA_STATIC flag at the same time (descriptor range flags %x). "
  614. "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", pRange->Flags);
  615. return E_FAIL;
  616. }
  617. break;
  618. }
  619. }
  620. IFR(AddRegisterRange(iRP,
  621. DESCRIPTOR_TABLE_ENTRY,
  622. iDTS,
  623. pRange->RangeType,
  624. Visibility,
  625. pRange->NumDescriptors,
  626. pRange->BaseShaderRegister,
  627. pRange->RegisterSpace,
  628. pErrors));
  629. }
  630. break;
  631. }
  632. case DxilRootParameterType::Constants32Bit:
  633. IFR(AddRegisterRange(iRP,
  634. ROOT_CONSTANT,
  635. (unsigned)-1,
  636. DxilDescriptorRangeType::CBV,
  637. Visibility,
  638. 1,
  639. pSlot->Constants.ShaderRegister,
  640. pSlot->Constants.RegisterSpace,
  641. pErrors));
  642. break;
  643. case DxilRootParameterType::CBV:
  644. case DxilRootParameterType::SRV:
  645. case DxilRootParameterType::UAV:
  646. {
  647. // Verify root descriptor flags.
  648. unsigned Flags = (unsigned)pSlot->Descriptor.Flags;
  649. if (Flags & ~(unsigned)DxilRootDescriptorFlags::ValidFlags)
  650. {
  651. ErrorRootSignature(pErrors,
  652. "Unsupported bit-flag set (root descriptor flags %x).\n", Flags);
  653. return E_FAIL;
  654. }
  655. unsigned NumDataFlags = 0;
  656. if (Flags & (unsigned)DxilRootDescriptorFlags::DataVolatile) { NumDataFlags++; }
  657. if (Flags & (unsigned)DxilRootDescriptorFlags::DataStatic) { NumDataFlags++; }
  658. if (Flags & (unsigned)DxilRootDescriptorFlags::DataStaticWhileSetAtExecute) { NumDataFlags++; }
  659. if (NumDataFlags > 1) {
  660. ErrorRootSignature(pErrors, "Root descriptor flags cannot specify more "
  661. "than one DATA_* flag at a time (root "
  662. "descriptor flags %x).\n",
  663. Flags);
  664. return E_FAIL;
  665. }
  666. IFR(AddRegisterRange(iRP, ROOT_DESCRIPTOR, (unsigned)-1,
  667. GetRangeType(ParameterType), Visibility, 1,
  668. pSlot->Descriptor.ShaderRegister,
  669. pSlot->Descriptor.RegisterSpace, pErrors));
  670. break;
  671. }
  672. default:
  673. ErrorRootSignature(pErrors,
  674. "Unsupported ParameterType value %u (root parameter %u)\n", ParameterType, iRP);
  675. return E_FAIL;
  676. }
  677. }
  678. for (unsigned iSS = 0; iSS < pRootSignature->NumStaticSamplers; iSS++)
  679. {
  680. const DxilStaticSamplerDesc *pSS = &pRootSignature->pStaticSamplers[iSS];
  681. // Shader visibility.
  682. DxilShaderVisibility Visibility = pSS->ShaderVisibility;
  683. if (!IsDxilShaderVisibility(Visibility)) {
  684. ErrorRootSignature(pErrors,
  685. "Unsupported ShaderVisibility value %u (static sampler [%u]).\n", Visibility, iSS);
  686. return E_FAIL;
  687. }
  688. StaticSamplerVerifier SSV;
  689. IFR(SSV.Verify(pSS, pErrors));
  690. IFR(AddRegisterRange(iSS, STATIC_SAMPLER, (unsigned)-1,
  691. DxilDescriptorRangeType::Sampler, Visibility, 1,
  692. pSS->ShaderRegister, pSS->RegisterSpace, pErrors));
  693. }
  694. return S_OK;
  695. }
  696. BOOL isNaN(const float &a) {
  697. static const unsigned exponentMask = 0x7f800000;
  698. static const unsigned mantissaMask = 0x007fffff;
  699. unsigned u = *(const unsigned *)&a;
  700. return (((u & exponentMask) == exponentMask) && (u & mantissaMask)); // NaN
  701. }
  702. static bool IsDxilTextureAddressMode(DxilTextureAddressMode v) {
  703. return DxilTextureAddressMode::Wrap <= v &&
  704. v <= DxilTextureAddressMode::MirrorOnce;
  705. }
  706. static bool IsDxilComparisonFunc(DxilComparisonFunc v) {
  707. return DxilComparisonFunc::Never <= v && v <= DxilComparisonFunc::Always;
  708. }
  709. // This validation closely mirrors CCreateSamplerStateValidator's checks
  710. HRESULT StaticSamplerVerifier::Verify(const DxilStaticSamplerDesc* pDesc, IStream* pErrors)
  711. {
  712. if (!pDesc) {
  713. ErrorRootSignature(pErrors,
  714. "Static sampler: A NULL pSamplerDesc was specified.");
  715. return E_INVALIDARG;
  716. }
  717. bool bIsComparison = false;
  718. switch (pDesc->Filter)
  719. {
  720. case DxilFilter::MINIMUM_MIN_MAG_MIP_POINT:
  721. case DxilFilter::MINIMUM_MIN_MAG_POINT_MIP_LINEAR:
  722. case DxilFilter::MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT:
  723. case DxilFilter::MINIMUM_MIN_POINT_MAG_MIP_LINEAR:
  724. case DxilFilter::MINIMUM_MIN_LINEAR_MAG_MIP_POINT:
  725. case DxilFilter::MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  726. case DxilFilter::MINIMUM_MIN_MAG_LINEAR_MIP_POINT:
  727. case DxilFilter::MINIMUM_MIN_MAG_MIP_LINEAR:
  728. case DxilFilter::MINIMUM_ANISOTROPIC:
  729. case DxilFilter::MAXIMUM_MIN_MAG_MIP_POINT:
  730. case DxilFilter::MAXIMUM_MIN_MAG_POINT_MIP_LINEAR:
  731. case DxilFilter::MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT:
  732. case DxilFilter::MAXIMUM_MIN_POINT_MAG_MIP_LINEAR:
  733. case DxilFilter::MAXIMUM_MIN_LINEAR_MAG_MIP_POINT:
  734. case DxilFilter::MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  735. case DxilFilter::MAXIMUM_MIN_MAG_LINEAR_MIP_POINT:
  736. case DxilFilter::MAXIMUM_MIN_MAG_MIP_LINEAR:
  737. case DxilFilter::MAXIMUM_ANISOTROPIC:
  738. break;
  739. case DxilFilter::MIN_MAG_MIP_POINT:
  740. case DxilFilter::MIN_MAG_POINT_MIP_LINEAR:
  741. case DxilFilter::MIN_POINT_MAG_LINEAR_MIP_POINT:
  742. case DxilFilter::MIN_POINT_MAG_MIP_LINEAR:
  743. case DxilFilter::MIN_LINEAR_MAG_MIP_POINT:
  744. case DxilFilter::MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  745. case DxilFilter::MIN_MAG_LINEAR_MIP_POINT:
  746. case DxilFilter::MIN_MAG_MIP_LINEAR:
  747. case DxilFilter::ANISOTROPIC:
  748. break;
  749. case DxilFilter::COMPARISON_MIN_MAG_MIP_POINT:
  750. case DxilFilter::COMPARISON_MIN_MAG_POINT_MIP_LINEAR:
  751. case DxilFilter::COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT:
  752. case DxilFilter::COMPARISON_MIN_POINT_MAG_MIP_LINEAR:
  753. case DxilFilter::COMPARISON_MIN_LINEAR_MAG_MIP_POINT:
  754. case DxilFilter::COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR:
  755. case DxilFilter::COMPARISON_MIN_MAG_LINEAR_MIP_POINT:
  756. case DxilFilter::COMPARISON_MIN_MAG_MIP_LINEAR:
  757. case DxilFilter::COMPARISON_ANISOTROPIC:
  758. bIsComparison = true;
  759. break;
  760. default:
  761. ErrorRootSignature(pErrors, "Static sampler: Filter unrecognized.");
  762. return E_FAIL;
  763. }
  764. if (!IsDxilTextureAddressMode(pDesc->AddressU)) {
  765. ErrorRootSignature(pErrors, "Static sampler: AddressU unrecognized.");
  766. return E_FAIL;
  767. }
  768. if (!IsDxilTextureAddressMode(pDesc->AddressV)) {
  769. ErrorRootSignature(pErrors, "Static sampler: AddressV unrecognized.");
  770. return E_FAIL;
  771. }
  772. if (!IsDxilTextureAddressMode(pDesc->AddressW)) {
  773. ErrorRootSignature(pErrors, "Static sampler: AddressW unrecognized.");
  774. return E_FAIL;
  775. }
  776. if (isNaN(pDesc->MipLODBias) || (pDesc->MipLODBias < DxilMipLodBiaxMin) ||
  777. (pDesc->MipLODBias > DxilMipLodBiaxMax)) {
  778. ErrorRootSignature(pErrors, "Static sampler: MipLODBias must be in the "
  779. "range [%f to %f]. %f specified.",
  780. DxilMipLodBiaxMin, DxilMipLodBiaxMax, pDesc->MipLODBias);
  781. return E_FAIL;
  782. }
  783. if (pDesc->MaxAnisotropy > DxilMapAnisotropy)
  784. {
  785. ErrorRootSignature(pErrors,
  786. "Static sampler: MaxAnisotropy must be in the range [0 to %d]. %d specified.",
  787. DxilMapAnisotropy, pDesc->MaxAnisotropy);
  788. return E_FAIL;
  789. }
  790. if (bIsComparison && !IsDxilComparisonFunc(pDesc->ComparisonFunc)) {
  791. ErrorRootSignature(pErrors, "Static sampler: ComparisonFunc unrecognized.");
  792. return E_FAIL;
  793. }
  794. if (isNaN(pDesc->MinLOD)) {
  795. ErrorRootSignature(
  796. pErrors,
  797. "Static sampler: MinLOD be in the range [-INF to +INF]. %f specified.",
  798. pDesc->MinLOD);
  799. return E_FAIL;
  800. }
  801. if (isNaN(pDesc->MaxLOD)) {
  802. ErrorRootSignature(
  803. pErrors,
  804. "Static sampler: MaxLOD be in the range [-INF to +INF]. %f specified.",
  805. pDesc->MaxLOD);
  806. return E_FAIL;
  807. }
  808. return S_OK;
  809. }
  810. //////////////////////////////////////////////////////////////////////////////
  811. template <typename T>
  812. void DeleteRootSignatureTemplate(const T &RS) {
  813. for (unsigned i = 0; i < RS.NumParameters; i++) {
  814. const auto &P = RS.pParameters[i];
  815. if (P.ParameterType == DxilRootParameterType::DescriptorTable) {
  816. delete[] P.DescriptorTable.pDescriptorRanges;
  817. }
  818. }
  819. delete[] RS.pParameters;
  820. delete[] RS.pStaticSamplers;
  821. }
  822. void DeleteRootSignature(const DxilVersionedRootSignatureDesc * pRootSignature)
  823. {
  824. if (pRootSignature == nullptr)
  825. return;
  826. switch (pRootSignature->Version)
  827. {
  828. case DxilRootSignatureVersion::Version_1_0:
  829. DeleteRootSignatureTemplate<DxilRootSignatureDesc>(pRootSignature->Desc_1_0);
  830. break;
  831. case DxilRootSignatureVersion::Version_1_1:
  832. default:
  833. DXASSERT(pRootSignature->Version == DxilRootSignatureVersion::Version_1_1, "else version is incorrect");
  834. DeleteRootSignatureTemplate<DxilRootSignatureDesc1>(pRootSignature->Desc_1_1);
  835. break;
  836. }
  837. delete pRootSignature;
  838. }
  839. // GetFlags/SetFlags overloads.
  840. static DxilRootDescriptorFlags GetFlags(const DxilRootDescriptor &)
  841. {
  842. // Upconvert root parameter flags to be volatile.
  843. return DxilRootDescriptorFlags::DataVolatile;
  844. }
  845. static void SetFlags(DxilRootDescriptor &, DxilRootDescriptorFlags)
  846. {
  847. // Drop the flags; none existed in rs_1_0.
  848. }
  849. static DxilRootDescriptorFlags GetFlags(const DxilRootDescriptor1 &D)
  850. {
  851. return D.Flags;
  852. }
  853. static void SetFlags(DxilRootDescriptor1 &D, DxilRootDescriptorFlags Flags)
  854. {
  855. D.Flags = Flags;
  856. }
  857. static DxilRootDescriptorFlags GetFlags(const DxilContainerRootDescriptor1 &D)
  858. {
  859. return (DxilRootDescriptorFlags)D.Flags;
  860. }
  861. static void SetFlags(DxilContainerRootDescriptor1 &D, DxilRootDescriptorFlags Flags)
  862. {
  863. D.Flags = (uint32_t)Flags;
  864. }
  865. static DxilDescriptorRangeFlags GetFlags(const DxilDescriptorRange &D)
  866. {
  867. // Upconvert range flags to be volatile.
  868. DxilDescriptorRangeFlags Flags = DxilDescriptorRangeFlags::DescriptorsVolatile;
  869. // Sampler does not have data.
  870. if (D.RangeType != DxilDescriptorRangeType::Sampler)
  871. Flags = (DxilDescriptorRangeFlags)((unsigned)Flags | (unsigned)DxilDescriptorRangeFlags::DataVolatile);
  872. return Flags;
  873. }
  874. static void SetFlags(DxilDescriptorRange &, DxilDescriptorRangeFlags)
  875. {
  876. }
  877. static DxilDescriptorRangeFlags GetFlags(const DxilContainerDescriptorRange &D)
  878. {
  879. // Upconvert range flags to be volatile.
  880. DxilDescriptorRangeFlags Flags = DxilDescriptorRangeFlags::DescriptorsVolatile;
  881. // Sampler does not have data.
  882. if (D.RangeType != (uint32_t)DxilDescriptorRangeType::Sampler)
  883. Flags |= DxilDescriptorRangeFlags::DataVolatile;
  884. return Flags;
  885. }
  886. static void SetFlags(DxilContainerDescriptorRange &, DxilDescriptorRangeFlags)
  887. {
  888. }
  889. static DxilDescriptorRangeFlags GetFlags(const DxilDescriptorRange1 &D)
  890. {
  891. return D.Flags;
  892. }
  893. static void SetFlags(DxilDescriptorRange1 &D, DxilDescriptorRangeFlags Flags)
  894. {
  895. D.Flags = Flags;
  896. }
  897. static DxilDescriptorRangeFlags GetFlags(const DxilContainerDescriptorRange1 &D)
  898. {
  899. return (DxilDescriptorRangeFlags)D.Flags;
  900. }
  901. static void SetFlags(DxilContainerDescriptorRange1 &D, DxilDescriptorRangeFlags Flags)
  902. {
  903. D.Flags = (uint32_t)Flags;
  904. }
  905. template<typename IN_DXIL_ROOT_SIGNATURE_DESC,
  906. typename OUT_DXIL_ROOT_SIGNATURE_DESC,
  907. typename OUT_DXIL_ROOT_PARAMETER,
  908. typename OUT_DXIL_ROOT_DESCRIPTOR,
  909. typename OUT_DXIL_DESCRIPTOR_RANGE>
  910. HRESULT ConvertRootSignatureTemplate(const IN_DXIL_ROOT_SIGNATURE_DESC & DescIn,
  911. DxilRootSignatureVersion DescVersionOut,
  912. OUT_DXIL_ROOT_SIGNATURE_DESC & DescOut)
  913. {
  914. HRESULT hr = S_OK;
  915. const IN_DXIL_ROOT_SIGNATURE_DESC * pDescIn = &DescIn;
  916. OUT_DXIL_ROOT_SIGNATURE_DESC * pDescOut = &DescOut;
  917. // Root signature descriptor.
  918. pDescOut->Flags = pDescIn->Flags;
  919. pDescOut->NumParameters = 0;
  920. pDescOut->NumStaticSamplers = 0;
  921. // Intialize all pointers early so that clean up works properly.
  922. pDescOut->pParameters = NULL;
  923. pDescOut->pStaticSamplers = NULL;
  924. // Root signature parameters.
  925. if (pDescIn->NumParameters > 0)
  926. {
  927. IFCOOM(pDescOut->pParameters = new (std::nothrow) OUT_DXIL_ROOT_PARAMETER[pDescIn->NumParameters]);
  928. pDescOut->NumParameters = pDescIn->NumParameters;
  929. memset((void *)pDescOut->pParameters, 0, pDescOut->NumParameters*sizeof(OUT_DXIL_ROOT_PARAMETER));
  930. }
  931. for (unsigned iRP = 0; iRP < pDescIn->NumParameters; iRP++)
  932. {
  933. const auto & ParamIn = pDescIn->pParameters[iRP];
  934. OUT_DXIL_ROOT_PARAMETER & ParamOut = (OUT_DXIL_ROOT_PARAMETER &)pDescOut->pParameters[iRP];
  935. ParamOut.ParameterType = ParamIn.ParameterType;
  936. ParamOut.ShaderVisibility = ParamIn.ShaderVisibility;
  937. switch (ParamIn.ParameterType)
  938. {
  939. case DxilRootParameterType::DescriptorTable:
  940. {
  941. ParamOut.DescriptorTable.pDescriptorRanges = NULL;
  942. unsigned NumRanges = ParamIn.DescriptorTable.NumDescriptorRanges;
  943. if (NumRanges > 0)
  944. {
  945. IFCOOM(ParamOut.DescriptorTable.pDescriptorRanges = new (std::nothrow) OUT_DXIL_DESCRIPTOR_RANGE[NumRanges]);
  946. ParamOut.DescriptorTable.NumDescriptorRanges = NumRanges;
  947. }
  948. for (unsigned i = 0; i < NumRanges; i++)
  949. {
  950. const auto & RangeIn = ParamIn.DescriptorTable.pDescriptorRanges[i];
  951. OUT_DXIL_DESCRIPTOR_RANGE & RangeOut = (OUT_DXIL_DESCRIPTOR_RANGE &)ParamOut.DescriptorTable.pDescriptorRanges[i];
  952. RangeOut.RangeType = RangeIn.RangeType;
  953. RangeOut.NumDescriptors = RangeIn.NumDescriptors;
  954. RangeOut.BaseShaderRegister = RangeIn.BaseShaderRegister;
  955. RangeOut.RegisterSpace = RangeIn.RegisterSpace;
  956. RangeOut.OffsetInDescriptorsFromTableStart = RangeIn.OffsetInDescriptorsFromTableStart;
  957. DxilDescriptorRangeFlags Flags = GetFlags(RangeIn);
  958. SetFlags(RangeOut, Flags);
  959. }
  960. break;
  961. }
  962. case DxilRootParameterType::Constants32Bit:
  963. {
  964. ParamOut.Constants.Num32BitValues = ParamIn.Constants.Num32BitValues;
  965. ParamOut.Constants.ShaderRegister = ParamIn.Constants.ShaderRegister;
  966. ParamOut.Constants.RegisterSpace = ParamIn.Constants.RegisterSpace;
  967. break;
  968. }
  969. case DxilRootParameterType::CBV:
  970. case DxilRootParameterType::SRV:
  971. case DxilRootParameterType::UAV:
  972. {
  973. ParamOut.Descriptor.ShaderRegister = ParamIn.Descriptor.ShaderRegister;
  974. ParamOut.Descriptor.RegisterSpace = ParamIn.Descriptor.RegisterSpace;
  975. DxilRootDescriptorFlags Flags = GetFlags(ParamIn.Descriptor);
  976. SetFlags(ParamOut.Descriptor, Flags);
  977. break;
  978. }
  979. default:
  980. IFC(E_FAIL);
  981. }
  982. }
  983. // Static samplers.
  984. if (pDescIn->NumStaticSamplers > 0)
  985. {
  986. IFCOOM(pDescOut->pStaticSamplers = new (std::nothrow) DxilStaticSamplerDesc[pDescIn->NumStaticSamplers]);
  987. pDescOut->NumStaticSamplers = pDescIn->NumStaticSamplers;
  988. memcpy((void*)pDescOut->pStaticSamplers, pDescIn->pStaticSamplers, pDescOut->NumStaticSamplers*sizeof(DxilStaticSamplerDesc));
  989. }
  990. Cleanup:
  991. // Note that in case of failure, outside code must deallocate memory.
  992. return hr;
  993. }
  994. void ConvertRootSignature(const DxilVersionedRootSignatureDesc * pRootSignatureIn,
  995. DxilRootSignatureVersion RootSignatureVersionOut,
  996. const DxilVersionedRootSignatureDesc ** ppRootSignatureOut)
  997. {
  998. HRESULT hr = S_OK;
  999. DxilVersionedRootSignatureDesc *pRootSignatureOut = NULL;
  1000. if (pRootSignatureIn == NULL || ppRootSignatureOut == NULL)
  1001. {
  1002. IFC(E_INVALIDARG);
  1003. }
  1004. *ppRootSignatureOut = NULL;
  1005. if (pRootSignatureIn->Version == RootSignatureVersionOut)
  1006. {
  1007. // No conversion. Return the original root signature pointer; no cloning.
  1008. *ppRootSignatureOut = pRootSignatureIn;
  1009. goto Cleanup;
  1010. }
  1011. IFCOOM(pRootSignatureOut = new (std::nothrow) DxilVersionedRootSignatureDesc());
  1012. memset(pRootSignatureOut, 0, sizeof(*pRootSignatureOut));
  1013. // Convert root signature.
  1014. switch (RootSignatureVersionOut)
  1015. {
  1016. case DxilRootSignatureVersion::Version_1_0:
  1017. switch (pRootSignatureIn->Version)
  1018. {
  1019. case DxilRootSignatureVersion::Version_1_1:
  1020. pRootSignatureOut->Version = DxilRootSignatureVersion::Version_1_0;
  1021. hr = ConvertRootSignatureTemplate<
  1022. DxilRootSignatureDesc1,
  1023. DxilRootSignatureDesc,
  1024. DxilRootParameter,
  1025. DxilRootDescriptor,
  1026. DxilDescriptorRange>(pRootSignatureIn->Desc_1_1,
  1027. DxilRootSignatureVersion::Version_1_0,
  1028. pRootSignatureOut->Desc_1_0);
  1029. IFC(hr);
  1030. break;
  1031. default:
  1032. IFC(E_INVALIDARG);
  1033. }
  1034. break;
  1035. case DxilRootSignatureVersion::Version_1_1:
  1036. switch (pRootSignatureIn->Version)
  1037. {
  1038. case DxilRootSignatureVersion::Version_1_0:
  1039. pRootSignatureOut->Version = DxilRootSignatureVersion::Version_1_1;
  1040. hr = ConvertRootSignatureTemplate<
  1041. DxilRootSignatureDesc,
  1042. DxilRootSignatureDesc1,
  1043. DxilRootParameter1,
  1044. DxilRootDescriptor1,
  1045. DxilDescriptorRange1>(pRootSignatureIn->Desc_1_0,
  1046. DxilRootSignatureVersion::Version_1_1,
  1047. pRootSignatureOut->Desc_1_1);
  1048. IFC(hr);
  1049. break;
  1050. default:
  1051. IFC(E_INVALIDARG);
  1052. }
  1053. break;
  1054. default:
  1055. IFC(E_INVALIDARG);
  1056. break;
  1057. }
  1058. *ppRootSignatureOut = pRootSignatureOut;
  1059. Cleanup:
  1060. if (FAILED(hr)) {
  1061. DeleteRootSignature(pRootSignatureOut);
  1062. IFT(hr);
  1063. }
  1064. }
  1065. template<typename T_ROOT_SIGNATURE_DESC,
  1066. typename T_ROOT_PARAMETER,
  1067. typename T_ROOT_DESCRIPTOR_INTERNAL,
  1068. typename T_DESCRIPTOR_RANGE_INTERNAL>
  1069. HRESULT SerializeRootSignatureTemplate(__in const T_ROOT_SIGNATURE_DESC* pRootSignature,
  1070. DxilRootSignatureVersion DescVersion,
  1071. _COM_Outptr_ IDxcBlob** ppBlob,
  1072. _COM_Outptr_ IStream* pErrors,
  1073. __in bool bAllowReservedRegisterSpace)
  1074. {
  1075. DxilContainerRootSignatureDesc RS;
  1076. UINT Offset;
  1077. SimpleSerializer Serializer;
  1078. IFR(Serializer.AddBlock(&RS, sizeof(RS), &Offset));
  1079. IFRBOOL(Offset == 0, E_FAIL);
  1080. const T_ROOT_SIGNATURE_DESC *pRS = pRootSignature;
  1081. RS.Version = (uint32_t)DescVersion;
  1082. RS.Flags = (uint32_t)pRS->Flags;
  1083. RS.NumParameters = pRS->NumParameters;
  1084. RS.NumStaticSamplers = pRS->NumStaticSamplers;
  1085. DxilContainerRootParameter *pRP;
  1086. IFR(Serializer.ReserveBlock((void**)&pRP,
  1087. sizeof(DxilContainerRootParameter)*RS.NumParameters, &RS.RootParametersOffset));
  1088. for (UINT iRP = 0; iRP < RS.NumParameters; iRP++)
  1089. {
  1090. const T_ROOT_PARAMETER *pInRP = &pRS->pParameters[iRP];
  1091. DxilContainerRootParameter *pOutRP = &pRP[iRP];
  1092. pOutRP->ParameterType = (uint32_t)pInRP->ParameterType;
  1093. pOutRP->ShaderVisibility = (uint32_t)pInRP->ShaderVisibility;
  1094. switch (pInRP->ParameterType)
  1095. {
  1096. case DxilRootParameterType::DescriptorTable:
  1097. {
  1098. DxilContainerRootDescriptorTable *p1;
  1099. IFR(Serializer.ReserveBlock((void**)&p1,
  1100. sizeof(DxilContainerRootDescriptorTable), &pOutRP->PayloadOffset));
  1101. p1->NumDescriptorRanges = pInRP->DescriptorTable.NumDescriptorRanges;
  1102. T_DESCRIPTOR_RANGE_INTERNAL *p2;
  1103. IFR(Serializer.ReserveBlock((void**)&p2,
  1104. sizeof(T_DESCRIPTOR_RANGE_INTERNAL)*p1->NumDescriptorRanges, &p1->DescriptorRangesOffset));
  1105. for (UINT i = 0; i < p1->NumDescriptorRanges; i++)
  1106. {
  1107. p2[i].RangeType = (uint32_t)pInRP->DescriptorTable.pDescriptorRanges[i].RangeType;
  1108. p2[i].NumDescriptors = pInRP->DescriptorTable.pDescriptorRanges[i].NumDescriptors;
  1109. p2[i].BaseShaderRegister = pInRP->DescriptorTable.pDescriptorRanges[i].BaseShaderRegister;
  1110. p2[i].RegisterSpace = pInRP->DescriptorTable.pDescriptorRanges[i].RegisterSpace;
  1111. p2[i].OffsetInDescriptorsFromTableStart = pInRP->DescriptorTable.pDescriptorRanges[i].OffsetInDescriptorsFromTableStart;
  1112. DxilDescriptorRangeFlags Flags = GetFlags(pInRP->DescriptorTable.pDescriptorRanges[i]);
  1113. SetFlags(p2[i], Flags);
  1114. }
  1115. break;
  1116. }
  1117. case DxilRootParameterType::Constants32Bit:
  1118. {
  1119. DxilRootConstants *p;
  1120. IFR(Serializer.ReserveBlock((void**)&p, sizeof(DxilRootConstants), &pOutRP->PayloadOffset));
  1121. p->Num32BitValues = pInRP->Constants.Num32BitValues;
  1122. p->ShaderRegister = pInRP->Constants.ShaderRegister;
  1123. p->RegisterSpace = pInRP->Constants.RegisterSpace;
  1124. break;
  1125. }
  1126. case DxilRootParameterType::CBV:
  1127. case DxilRootParameterType::SRV:
  1128. case DxilRootParameterType::UAV:
  1129. {
  1130. T_ROOT_DESCRIPTOR_INTERNAL *p;
  1131. IFR(Serializer.ReserveBlock((void**)&p, sizeof(T_ROOT_DESCRIPTOR_INTERNAL), &pOutRP->PayloadOffset));
  1132. p->ShaderRegister = pInRP->Descriptor.ShaderRegister;
  1133. p->RegisterSpace = pInRP->Descriptor.RegisterSpace;
  1134. DxilRootDescriptorFlags Flags = GetFlags(pInRP->Descriptor);
  1135. SetFlags(*p, Flags);
  1136. break;
  1137. }
  1138. default:
  1139. ErrorRootSignature(pErrors,
  1140. "D3DSerializeRootSignature: unknown root parameter type (%u)\n", pInRP->ParameterType);
  1141. return E_FAIL;
  1142. }
  1143. }
  1144. DxilStaticSamplerDesc *pSS;
  1145. unsigned StaticSamplerSize = sizeof(DxilStaticSamplerDesc)*RS.NumStaticSamplers;
  1146. IFR(Serializer.ReserveBlock((void**)&pSS, StaticSamplerSize, &RS.StaticSamplersOffset));
  1147. memcpy(pSS, pRS->pStaticSamplers, StaticSamplerSize);
  1148. // Create the result blob.
  1149. CComHeapPtr<char> bytes;
  1150. CComPtr<IDxcBlob> pBlob;
  1151. unsigned cb = Serializer.GetSize();
  1152. DXASSERT_NOMSG((cb & 0x3) == 0);
  1153. if (!bytes.AllocateBytes(cb))
  1154. return E_OUTOFMEMORY;
  1155. IFR(Serializer.Compact(bytes.m_pData, cb));
  1156. IFR(DxcCreateBlobOnHeap(bytes.m_pData, cb, ppBlob));
  1157. bytes.Detach(); // Ownership transfered to ppBlob.
  1158. return S_OK;
  1159. }
  1160. _Use_decl_annotations_
  1161. void
  1162. SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature,
  1163. IDxcBlob **ppBlob, IDxcBlobEncoding **ppErrorBlob,
  1164. bool bAllowReservedRegisterSpace) {
  1165. DXASSERT_NOMSG(pRootSignature != nullptr);
  1166. DXASSERT_NOMSG(ppBlob != nullptr);
  1167. DXASSERT_NOMSG(ppErrorBlob != nullptr);
  1168. *ppBlob = nullptr;
  1169. *ppErrorBlob = nullptr;
  1170. RootSignatureVerifier RSV;
  1171. CComPtr<AbstractMemoryStream> pErrors;
  1172. CComPtr<IMalloc> pMalloc;
  1173. IFT(CoGetMalloc(1, &pMalloc));
  1174. IFT(CreateMemoryStream(pMalloc, &pErrors));
  1175. // Verify root signature.
  1176. RSV.AllowReservedRegisterSpace(bAllowReservedRegisterSpace);
  1177. if (FAILED(RSV.VerifyRootSignature(pRootSignature, pErrors))) {
  1178. IFT(DxcCreateBlobWithEncodingFromStream(pErrors, true, CP_UTF8, ppErrorBlob));
  1179. return;
  1180. }
  1181. switch (pRootSignature->Version)
  1182. {
  1183. case DxilRootSignatureVersion::Version_1_0:
  1184. SerializeRootSignatureTemplate<
  1185. DxilRootSignatureDesc,
  1186. DxilRootParameter,
  1187. DxilRootDescriptor,
  1188. DxilContainerDescriptorRange>(&pRootSignature->Desc_1_0,
  1189. DxilRootSignatureVersion::Version_1_0,
  1190. ppBlob, pErrors,
  1191. bAllowReservedRegisterSpace);
  1192. break;
  1193. case DxilRootSignatureVersion::Version_1_1:
  1194. default:
  1195. DXASSERT(pRootSignature->Version == DxilRootSignatureVersion::Version_1_1, "else VerifyRootSignature didn't validate");
  1196. SerializeRootSignatureTemplate<
  1197. DxilRootSignatureDesc1,
  1198. DxilRootParameter1,
  1199. DxilContainerRootDescriptor1,
  1200. DxilContainerDescriptorRange1>(&pRootSignature->Desc_1_1,
  1201. DxilRootSignatureVersion::Version_1_1,
  1202. ppBlob, pErrors,
  1203. bAllowReservedRegisterSpace);
  1204. break;
  1205. }
  1206. }
  1207. } // namespace hlsl