DxilRuntimeReflection.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilLibraryReflection.h //
  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. // Defines shader reflection for runtime usage. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #pragma once
  12. #include "DxilConstants.h"
  13. namespace hlsl {
  14. namespace RDAT {
  15. // Data Layout:
  16. // -start:
  17. // RuntimeDataHeader header;
  18. // uint32_t offsets[header.PartCount];
  19. // - for each i in header.PartCount:
  20. // - at &header + offsets[i]:
  21. // RuntimeDataPartHeader part;
  22. // - if part.Type is a Table (Function or Resource):
  23. // RuntimeDataTableHeader table;
  24. // byte TableData[table.RecordCount][table.RecordStride];
  25. // - else if part.Type is String:
  26. // byte UTF8Data[part.Size];
  27. // - else if part.Type is Index:
  28. // uint32_t IndexData[part.Size / 4];
  29. enum class RuntimeDataPartType : uint32_t { // TODO: Rename: PartType
  30. Invalid = 0,
  31. StringBuffer = 1,
  32. IndexArrays = 2,
  33. ResourceTable = 3,
  34. FunctionTable = 4,
  35. };
  36. enum RuntimeDataVersion {
  37. // Cannot be mistaken for part count from prerelease version
  38. RDAT_Version_0 = 0x10,
  39. };
  40. struct RuntimeDataHeader {
  41. uint32_t Version;
  42. uint32_t PartCount;
  43. // Followed by uint32_t array of offsets to parts
  44. // offsets are relative to the beginning of this header
  45. // offsets must be 4-byte aligned
  46. // uint32_t offsets[];
  47. };
  48. struct RuntimeDataPartHeader {
  49. RuntimeDataPartType Type;
  50. uint32_t Size; // Not including this header. Must be 4-byte aligned.
  51. // Followed by part data
  52. // byte Data[ALIGN4(Size)];
  53. };
  54. // For tables of records, such as Function and Resource tables
  55. // Stride allows for extending records, with forward and backward compatibility
  56. struct RuntimeDataTableHeader {
  57. uint32_t RecordCount;
  58. uint32_t RecordStride; // Must be 4-byte aligned.
  59. // Followed by recordCount records of recordStride size
  60. // byte TableData[RecordCount * RecordStride];
  61. };
  62. // General purpose strided table reader with casting Row() operation that
  63. // returns nullptr if stride is smaller than type, for record expansion.
  64. class TableReader {
  65. const char *m_table;
  66. uint32_t m_count;
  67. uint32_t m_stride;
  68. public:
  69. TableReader() : TableReader(nullptr, 0, 0) {}
  70. TableReader(const char *table, uint32_t count, uint32_t stride)
  71. : m_table(table), m_count(count), m_stride(stride) {}
  72. void Init(const char *table, uint32_t count, uint32_t stride) {
  73. m_table = table; m_count = count; m_stride = stride;
  74. }
  75. const char *Data() const { return m_table; }
  76. uint32_t Count() const { return m_count; }
  77. uint32_t Stride() const { return m_stride; }
  78. template<typename T>
  79. const T *Row(uint32_t index) const {
  80. if (index < m_count && sizeof(T) <= m_stride)
  81. return reinterpret_cast<const T*>(m_table + (m_stride * index));
  82. return nullptr;
  83. }
  84. };
  85. // Index table is a sequence of rows, where each row has a count as a first
  86. // element followed by the count number of elements pre computing values
  87. class IndexTableReader {
  88. private:
  89. const uint32_t *m_table;
  90. uint32_t m_size;
  91. public:
  92. class IndexRow {
  93. private:
  94. const uint32_t *m_values;
  95. const uint32_t m_count;
  96. public:
  97. IndexRow(const uint32_t *values, uint32_t count)
  98. : m_values(values), m_count(count) {}
  99. uint32_t Count() { return m_count; }
  100. uint32_t At(uint32_t i) { return m_values[i]; }
  101. };
  102. IndexTableReader() : m_table(nullptr), m_size(0) {}
  103. IndexTableReader(const uint32_t *table, uint32_t size)
  104. : m_table(table), m_size(size) {}
  105. void SetTable(const uint32_t *table) { m_table = table; }
  106. void SetSize(uint32_t size) { m_size = size; }
  107. IndexRow getRow(uint32_t i) { return IndexRow(&m_table[i] + 1, m_table[i]); }
  108. };
  109. class StringTableReader {
  110. const char *m_table;
  111. uint32_t m_size;
  112. public:
  113. StringTableReader() : m_table(nullptr), m_size(0) {}
  114. StringTableReader(const char *table, uint32_t size)
  115. : m_table(table), m_size(size) {}
  116. const char *Get(uint32_t offset) const {
  117. _Analysis_assume_(offset < m_size && m_table &&
  118. m_table[m_size - 1] == '\0');
  119. return m_table + offset;
  120. }
  121. };
  122. enum class DxilResourceFlag : uint32_t {
  123. None = 0,
  124. UAVGloballyCoherent = 1 << 0,
  125. UAVCounter = 1 << 1,
  126. UAVRasterizerOrderedView = 1 << 2,
  127. DynamicIndexing = 1 << 3,
  128. };
  129. struct RuntimeDataResourceInfo {
  130. uint32_t Class; // hlsl::DXIL::ResourceClass
  131. uint32_t Kind; // hlsl::DXIL::ResourceKind
  132. uint32_t ID; // id per class
  133. uint32_t Space;
  134. uint32_t LowerBound;
  135. uint32_t UpperBound;
  136. uint32_t Name; // resource name as an offset for string table
  137. uint32_t Flags; // hlsl::RDAT::DxilResourceFlag
  138. };
  139. struct RuntimeDataFunctionInfo {
  140. uint32_t Name; // offset for string table
  141. uint32_t UnmangledName; // offset for string table
  142. uint32_t Resources; // index to an index table
  143. uint32_t FunctionDependencies; // index to a list of functions that function
  144. // depends on
  145. uint32_t ShaderKind;
  146. uint32_t PayloadSizeInBytes; // 1) hit, miss, or closest shader: payload count
  147. // 2) call shader: parameter size
  148. uint32_t AttributeSizeInBytes; // attribute size for closest hit and any hit
  149. uint32_t FeatureInfo1; // first 32 bits of feature flag
  150. uint32_t FeatureInfo2; // second 32 bits of feature flag
  151. uint32_t ShaderStageFlag; // valid shader stage flag.
  152. uint32_t MinShaderTarget; // minimum shader target.
  153. };
  154. class ResourceTableReader;
  155. class FunctionTableReader;
  156. struct RuntimeDataContext {
  157. StringTableReader *pStringTableReader;
  158. IndexTableReader *pIndexTableReader;
  159. ResourceTableReader *pResourceTableReader;
  160. FunctionTableReader *pFunctionTableReader;
  161. };
  162. class ResourceReader {
  163. private:
  164. const RuntimeDataResourceInfo *m_ResourceInfo;
  165. RuntimeDataContext *m_Context;
  166. public:
  167. ResourceReader(const RuntimeDataResourceInfo *resInfo,
  168. RuntimeDataContext *context)
  169. : m_ResourceInfo(resInfo), m_Context(context) {}
  170. hlsl::DXIL::ResourceClass GetResourceClass() const {
  171. return !m_ResourceInfo ? hlsl::DXIL::ResourceClass::Invalid
  172. : (hlsl::DXIL::ResourceClass)m_ResourceInfo->Class;
  173. }
  174. uint32_t GetSpace() const { return !m_ResourceInfo ? 0 : m_ResourceInfo->Space; }
  175. uint32_t GetLowerBound() const { return !m_ResourceInfo ? 0 : m_ResourceInfo->LowerBound; }
  176. uint32_t GetUpperBound() const { return !m_ResourceInfo ? 0 : m_ResourceInfo->UpperBound; }
  177. hlsl::DXIL::ResourceKind GetResourceKind() const {
  178. return !m_ResourceInfo ? hlsl::DXIL::ResourceKind::Invalid
  179. : (hlsl::DXIL::ResourceKind)m_ResourceInfo->Kind;
  180. }
  181. uint32_t GetID() const { return !m_ResourceInfo ? 0 : m_ResourceInfo->ID; }
  182. const char *GetName() const {
  183. return !m_ResourceInfo ? ""
  184. : m_Context->pStringTableReader->Get(m_ResourceInfo->Name);
  185. }
  186. uint32_t GetFlags() const { return !m_ResourceInfo ? 0 : m_ResourceInfo->Flags; }
  187. };
  188. class ResourceTableReader {
  189. private:
  190. TableReader m_Table;
  191. RuntimeDataContext *m_Context;
  192. uint32_t m_CBufferCount;
  193. uint32_t m_SamplerCount;
  194. uint32_t m_SRVCount;
  195. uint32_t m_UAVCount;
  196. public:
  197. ResourceTableReader()
  198. : m_Context(nullptr), m_CBufferCount(0),
  199. m_SamplerCount(0), m_SRVCount(0), m_UAVCount(0){};
  200. void SetResourceInfo(const char *ptr, uint32_t count, uint32_t recordStride) {
  201. m_Table.Init(ptr, count, recordStride);
  202. // Assuming that resources are in order of CBuffer, Sampler, SRV, and UAV,
  203. // count the number for each resource class
  204. m_CBufferCount = 0;
  205. m_SamplerCount = 0;
  206. m_SRVCount = 0;
  207. m_UAVCount = 0;
  208. for (uint32_t i = 0; i < count; ++i) {
  209. const RuntimeDataResourceInfo *curPtr =
  210. m_Table.Row<RuntimeDataResourceInfo>(i);
  211. if (curPtr->Class == (uint32_t)hlsl::DXIL::ResourceClass::CBuffer)
  212. m_CBufferCount++;
  213. else if (curPtr->Class == (uint32_t)hlsl::DXIL::ResourceClass::Sampler)
  214. m_SamplerCount++;
  215. else if (curPtr->Class == (uint32_t)hlsl::DXIL::ResourceClass::SRV)
  216. m_SRVCount++;
  217. else if (curPtr->Class == (uint32_t)hlsl::DXIL::ResourceClass::UAV)
  218. m_UAVCount++;
  219. }
  220. }
  221. void SetContext(RuntimeDataContext *context) { m_Context = context; }
  222. uint32_t GetNumResources() const {
  223. return m_CBufferCount + m_SamplerCount + m_SRVCount + m_UAVCount;
  224. }
  225. ResourceReader GetItem(uint32_t i) const {
  226. _Analysis_assume_(i < GetNumResources());
  227. return ResourceReader(m_Table.Row<RuntimeDataResourceInfo>(i), m_Context);
  228. }
  229. uint32_t GetNumCBuffers() const { return m_CBufferCount; }
  230. ResourceReader GetCBuffer(uint32_t i) {
  231. _Analysis_assume_(i < m_CBufferCount);
  232. return ResourceReader(m_Table.Row<RuntimeDataResourceInfo>(i), m_Context);
  233. }
  234. uint32_t GetNumSamplers() const { return m_SamplerCount; }
  235. ResourceReader GetSampler(uint32_t i) {
  236. _Analysis_assume_(i < m_SamplerCount);
  237. uint32_t offset = (m_CBufferCount + i);
  238. return ResourceReader(m_Table.Row<RuntimeDataResourceInfo>(offset), m_Context);
  239. }
  240. uint32_t GetNumSRVs() const { return m_SRVCount; }
  241. ResourceReader GetSRV(uint32_t i) {
  242. _Analysis_assume_(i < m_SRVCount);
  243. uint32_t offset = (m_CBufferCount + m_SamplerCount + i);
  244. return ResourceReader(m_Table.Row<RuntimeDataResourceInfo>(offset), m_Context);
  245. }
  246. uint32_t GetNumUAVs() const { return m_UAVCount; }
  247. ResourceReader GetUAV(uint32_t i) {
  248. _Analysis_assume_(i < m_UAVCount);
  249. uint32_t offset = (m_CBufferCount + m_SamplerCount + m_SRVCount + i);
  250. return ResourceReader(m_Table.Row<RuntimeDataResourceInfo>(offset), m_Context);
  251. }
  252. };
  253. class FunctionReader {
  254. private:
  255. const RuntimeDataFunctionInfo *m_RuntimeDataFunctionInfo;
  256. RuntimeDataContext *m_Context;
  257. public:
  258. FunctionReader() : m_RuntimeDataFunctionInfo(nullptr), m_Context(nullptr) {}
  259. FunctionReader(const RuntimeDataFunctionInfo *functionInfo,
  260. RuntimeDataContext *context)
  261. : m_RuntimeDataFunctionInfo(functionInfo), m_Context(context) {}
  262. const char *GetName() const {
  263. return !m_RuntimeDataFunctionInfo ? ""
  264. : m_Context->pStringTableReader->Get(m_RuntimeDataFunctionInfo->Name);
  265. }
  266. const char *GetUnmangledName() const {
  267. return !m_RuntimeDataFunctionInfo ? ""
  268. : m_Context->pStringTableReader->Get(
  269. m_RuntimeDataFunctionInfo->UnmangledName);
  270. }
  271. uint64_t GetFeatureFlag() const {
  272. return (static_cast<uint64_t>(GetFeatureInfo2()) << 32)
  273. | static_cast<uint64_t>(GetFeatureInfo1());
  274. }
  275. uint32_t GetFeatureInfo1() const {
  276. return !m_RuntimeDataFunctionInfo ? 0
  277. : m_RuntimeDataFunctionInfo->FeatureInfo1;
  278. }
  279. uint32_t GetFeatureInfo2() const {
  280. return !m_RuntimeDataFunctionInfo ? 0
  281. : m_RuntimeDataFunctionInfo->FeatureInfo2;
  282. }
  283. uint32_t GetShaderStageFlag() const {
  284. return !m_RuntimeDataFunctionInfo ? 0
  285. : m_RuntimeDataFunctionInfo->ShaderStageFlag;
  286. }
  287. uint32_t GetMinShaderTarget() const {
  288. return !m_RuntimeDataFunctionInfo ? 0
  289. : m_RuntimeDataFunctionInfo->MinShaderTarget;
  290. }
  291. uint32_t GetNumResources() const {
  292. if (!m_RuntimeDataFunctionInfo ||
  293. m_RuntimeDataFunctionInfo->Resources == UINT_MAX)
  294. return 0;
  295. return m_Context->pIndexTableReader->getRow(
  296. m_RuntimeDataFunctionInfo->Resources).Count();
  297. }
  298. ResourceReader GetResource(uint32_t i) const {
  299. if (!m_RuntimeDataFunctionInfo)
  300. return ResourceReader(nullptr, m_Context);
  301. uint32_t resIndex = m_Context->pIndexTableReader->getRow(
  302. m_RuntimeDataFunctionInfo->Resources).At(i);
  303. return m_Context->pResourceTableReader->GetItem(resIndex);
  304. }
  305. uint32_t GetNumDependencies() const {
  306. if (!m_RuntimeDataFunctionInfo ||
  307. m_RuntimeDataFunctionInfo->FunctionDependencies == UINT_MAX)
  308. return 0;
  309. return m_Context->pIndexTableReader->getRow(
  310. m_RuntimeDataFunctionInfo->FunctionDependencies).Count();
  311. }
  312. const char *GetDependency(uint32_t i) const {
  313. if (!m_RuntimeDataFunctionInfo)
  314. return "";
  315. uint32_t resIndex = m_Context->pIndexTableReader->getRow(
  316. m_RuntimeDataFunctionInfo->FunctionDependencies).At(i);
  317. return m_Context->pStringTableReader->Get(resIndex);
  318. }
  319. uint32_t GetPayloadSizeInBytes() const {
  320. return !m_RuntimeDataFunctionInfo ? 0
  321. : m_RuntimeDataFunctionInfo->PayloadSizeInBytes;
  322. }
  323. uint32_t GetAttributeSizeInBytes() const {
  324. return !m_RuntimeDataFunctionInfo ? 0
  325. : m_RuntimeDataFunctionInfo->AttributeSizeInBytes;
  326. }
  327. // payload (hit shaders) and parameters (call shaders) are mutually exclusive
  328. uint32_t GetParameterSizeInBytes() const {
  329. return !m_RuntimeDataFunctionInfo ? 0
  330. : m_RuntimeDataFunctionInfo->PayloadSizeInBytes;
  331. }
  332. hlsl::DXIL::ShaderKind GetShaderKind() const {
  333. return !m_RuntimeDataFunctionInfo ? hlsl::DXIL::ShaderKind::Invalid
  334. : (hlsl::DXIL::ShaderKind)m_RuntimeDataFunctionInfo->ShaderKind;
  335. }
  336. };
  337. class FunctionTableReader {
  338. private:
  339. TableReader m_Table;
  340. RuntimeDataContext *m_context;
  341. public:
  342. FunctionTableReader() : m_context(nullptr) {}
  343. FunctionReader GetItem(uint32_t i) const {
  344. return FunctionReader(m_Table.Row<RuntimeDataFunctionInfo>(i), m_context);
  345. }
  346. uint32_t GetNumFunctions() const { return m_Table.Count(); }
  347. void SetFunctionInfo(const char *ptr, uint32_t count, uint32_t recordStride) {
  348. m_Table.Init(ptr, count, recordStride);
  349. }
  350. void SetContext(RuntimeDataContext *context) { m_context = context; }
  351. };
  352. class DxilRuntimeData {
  353. private:
  354. uint32_t m_TableCount;
  355. StringTableReader m_StringReader;
  356. IndexTableReader m_IndexTableReader;
  357. ResourceTableReader m_ResourceTableReader;
  358. FunctionTableReader m_FunctionTableReader;
  359. RuntimeDataContext m_Context;
  360. public:
  361. DxilRuntimeData();
  362. DxilRuntimeData(const char *ptr, size_t size);
  363. // initializing reader from RDAT. return true if no error has occured.
  364. bool InitFromRDAT(const void *pRDAT, size_t size);
  365. // read prerelease data:
  366. bool InitFromRDAT_Prerelease(const void *pRDAT, size_t size);
  367. FunctionTableReader *GetFunctionTableReader();
  368. ResourceTableReader *GetResourceTableReader();
  369. };
  370. //////////////////////////////////
  371. /// structures for library runtime
  372. typedef struct DxilResourceDesc {
  373. uint32_t Class; // hlsl::DXIL::ResourceClass
  374. uint32_t Kind; // hlsl::DXIL::ResourceKind
  375. uint32_t ID; // id per class
  376. uint32_t Space;
  377. uint32_t UpperBound;
  378. uint32_t LowerBound;
  379. LPCWSTR Name;
  380. uint32_t Flags; // hlsl::RDAT::DxilResourceFlag
  381. } DxilResourceDesc;
  382. typedef struct DxilFunctionDesc {
  383. LPCWSTR Name;
  384. LPCWSTR UnmangledName;
  385. uint32_t NumResources;
  386. const DxilResourceDesc * const*Resources;
  387. uint32_t NumFunctionDependencies;
  388. const LPCWSTR *FunctionDependencies;
  389. uint32_t ShaderKind;
  390. uint32_t PayloadSizeInBytes; // 1) hit, miss, or closest shader: payload count
  391. // 2) call shader: parameter size
  392. uint32_t AttributeSizeInBytes; // attribute size for closest hit and any hit
  393. uint32_t FeatureInfo1; // first 32 bits of feature flag
  394. uint32_t FeatureInfo2; // second 32 bits of feature flag
  395. uint32_t ShaderStageFlag; // valid shader stage flag.
  396. uint32_t MinShaderTarget; // minimum shader target.
  397. } DxilFunctionDesc;
  398. typedef struct DxilSubobjectDesc {
  399. } DxilSubobjectDesc;
  400. typedef struct DxilLibraryDesc {
  401. uint32_t NumFunctions;
  402. DxilFunctionDesc *pFunction;
  403. uint32_t NumResources;
  404. DxilResourceDesc *pResource;
  405. uint32_t NumSubobjects;
  406. DxilSubobjectDesc *pSubobjects;
  407. } DxilLibraryDesc;
  408. class DxilRuntimeReflection {
  409. public:
  410. virtual ~DxilRuntimeReflection() {}
  411. // This call will allocate memory for GetLibraryReflection call
  412. virtual bool InitFromRDAT(const void *pRDAT, size_t size) = 0;
  413. // DxilRuntimeReflection owns the memory pointed to by DxilLibraryDesc
  414. virtual const DxilLibraryDesc GetLibraryReflection() = 0;
  415. };
  416. DxilRuntimeReflection *CreateDxilRuntimeReflection();
  417. } // namespace RDAT
  418. } // namespace hlsl