DxilContainer.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilContainer.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. // Provides declarations for the DXIL container format. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #pragma once
  12. #ifndef __DXC_CONTAINER__
  13. #define __DXC_CONTAINER__
  14. #include <stdint.h>
  15. #include <iterator>
  16. #include "dxc/DXIL/DxilConstants.h"
  17. #include "dxc/Support/WinAdapter.h"
  18. struct IDxcContainerReflection;
  19. namespace llvm { class Module; }
  20. namespace hlsl {
  21. class AbstractMemoryStream;
  22. class RootSignatureHandle;
  23. class DxilModule;
  24. #pragma pack(push, 1)
  25. static const size_t DxilContainerHashSize = 16;
  26. static const uint16_t DxilContainerVersionMajor = 1; // Current major version
  27. static const uint16_t DxilContainerVersionMinor = 0; // Current minor version
  28. static const uint32_t DxilContainerMaxSize = 0x80000000; // Max size for container.
  29. /// Use this type to represent the hash for the full container.
  30. struct DxilContainerHash {
  31. uint8_t Digest[DxilContainerHashSize];
  32. };
  33. enum class DxilShaderHashFlags : uint32_t {
  34. None = 0, // No flags defined.
  35. IncludesSource = 1, // This flag indicates that the shader hash was computed
  36. // taking into account source information (-Zss)
  37. };
  38. typedef struct DxilShaderHash {
  39. uint32_t Flags; // DxilShaderHashFlags
  40. uint8_t Digest[DxilContainerHashSize];
  41. } DxilShaderHash;
  42. struct DxilContainerVersion {
  43. uint16_t Major;
  44. uint16_t Minor;
  45. };
  46. /// Use this type to describe a DXIL container of parts.
  47. struct DxilContainerHeader {
  48. uint32_t HeaderFourCC;
  49. DxilContainerHash Hash;
  50. DxilContainerVersion Version;
  51. uint32_t ContainerSizeInBytes; // From start of this header
  52. uint32_t PartCount;
  53. // Structure is followed by uint32_t PartOffset[PartCount];
  54. // The offset is to a DxilPartHeader.
  55. };
  56. /// Use this type to describe the size and type of a DXIL container part.
  57. struct DxilPartHeader {
  58. uint32_t PartFourCC; // Four char code for part type.
  59. uint32_t PartSize; // Byte count for PartData.
  60. // Structure is followed by uint8_t PartData[PartSize].
  61. };
  62. #define DXIL_FOURCC(ch0, ch1, ch2, ch3) ( \
  63. (uint32_t)(uint8_t)(ch0) | (uint32_t)(uint8_t)(ch1) << 8 | \
  64. (uint32_t)(uint8_t)(ch2) << 16 | (uint32_t)(uint8_t)(ch3) << 24 \
  65. )
  66. enum DxilFourCC {
  67. DFCC_Container = DXIL_FOURCC('D', 'X', 'B', 'C'), // for back-compat with tools that look for DXBC containers
  68. DFCC_ResourceDef = DXIL_FOURCC('R', 'D', 'E', 'F'),
  69. DFCC_InputSignature = DXIL_FOURCC('I', 'S', 'G', '1'),
  70. DFCC_OutputSignature = DXIL_FOURCC('O', 'S', 'G', '1'),
  71. DFCC_PatchConstantSignature = DXIL_FOURCC('P', 'S', 'G', '1'),
  72. DFCC_ShaderStatistics = DXIL_FOURCC('S', 'T', 'A', 'T'),
  73. DFCC_ShaderDebugInfoDXIL = DXIL_FOURCC('I', 'L', 'D', 'B'),
  74. DFCC_ShaderDebugName = DXIL_FOURCC('I', 'L', 'D', 'N'),
  75. DFCC_FeatureInfo = DXIL_FOURCC('S', 'F', 'I', '0'),
  76. DFCC_PrivateData = DXIL_FOURCC('P', 'R', 'I', 'V'),
  77. DFCC_RootSignature = DXIL_FOURCC('R', 'T', 'S', '0'),
  78. DFCC_DXIL = DXIL_FOURCC('D', 'X', 'I', 'L'),
  79. DFCC_PipelineStateValidation = DXIL_FOURCC('P', 'S', 'V', '0'),
  80. DFCC_RuntimeData = DXIL_FOURCC('R', 'D', 'A', 'T'),
  81. DFCC_ShaderHash = DXIL_FOURCC('H', 'A', 'S', 'H'),
  82. DFCC_ShaderSourceInfo = DXIL_FOURCC('S', 'R', 'C', 'I'),
  83. DFCC_CompilerVersion = DXIL_FOURCC('V', 'E', 'R', 'S'),
  84. };
  85. #undef DXIL_FOURCC
  86. struct DxilShaderFeatureInfo {
  87. uint64_t FeatureFlags;
  88. };
  89. // DXIL program information.
  90. struct DxilBitcodeHeader {
  91. uint32_t DxilMagic; // ACSII "DXIL".
  92. uint32_t DxilVersion; // DXIL version.
  93. uint32_t BitcodeOffset; // Offset to LLVM bitcode (from start of header).
  94. uint32_t BitcodeSize; // Size of LLVM bitcode.
  95. };
  96. static const uint32_t DxilMagicValue = 0x4C495844; // 'DXIL'
  97. struct DxilProgramHeader {
  98. uint32_t ProgramVersion; /// Major and minor version, including type.
  99. uint32_t SizeInUint32; /// Size in uint32_t units including this header.
  100. DxilBitcodeHeader BitcodeHeader; /// Bitcode-specific header.
  101. // Followed by uint8_t[BitcodeHeader.BitcodeOffset]
  102. };
  103. struct DxilProgramSignature {
  104. uint32_t ParamCount;
  105. uint32_t ParamOffset;
  106. };
  107. enum class DxilProgramSigMinPrecision : uint32_t {
  108. Default = 0,
  109. Float16 = 1,
  110. Float2_8 = 2,
  111. Reserved = 3,
  112. SInt16 = 4,
  113. UInt16 = 5,
  114. Any16 = 0xf0,
  115. Any10 = 0xf1
  116. };
  117. // Corresponds to D3D_NAME and D3D10_SB_NAME
  118. enum class DxilProgramSigSemantic : uint32_t {
  119. Undefined = 0,
  120. Position = 1,
  121. ClipDistance = 2,
  122. CullDistance = 3,
  123. RenderTargetArrayIndex = 4,
  124. ViewPortArrayIndex = 5,
  125. VertexID = 6,
  126. PrimitiveID = 7,
  127. InstanceID = 8,
  128. IsFrontFace = 9,
  129. SampleIndex = 10,
  130. FinalQuadEdgeTessfactor = 11,
  131. FinalQuadInsideTessfactor = 12,
  132. FinalTriEdgeTessfactor = 13,
  133. FinalTriInsideTessfactor = 14,
  134. FinalLineDetailTessfactor = 15,
  135. FinalLineDensityTessfactor = 16,
  136. Barycentrics = 23,
  137. ShadingRate = 24,
  138. CullPrimitive = 25,
  139. Target = 64,
  140. Depth = 65,
  141. Coverage = 66,
  142. DepthGE = 67,
  143. DepthLE = 68,
  144. StencilRef = 69,
  145. InnerCoverage = 70,
  146. };
  147. enum class DxilProgramSigCompType : uint32_t {
  148. Unknown = 0,
  149. UInt32 = 1,
  150. SInt32 = 2,
  151. Float32 = 3,
  152. UInt16 = 4,
  153. SInt16 = 5,
  154. Float16 = 6,
  155. UInt64 = 7,
  156. SInt64 = 8,
  157. Float64 = 9,
  158. };
  159. struct DxilProgramSignatureElement {
  160. uint32_t Stream; // Stream index (parameters must appear in non-decreasing stream order)
  161. uint32_t SemanticName; // Offset to LPCSTR from start of DxilProgramSignature.
  162. uint32_t SemanticIndex; // Semantic Index
  163. DxilProgramSigSemantic SystemValue; // Semantic type. Similar to DxilSemantic::Kind, but a serialized rather than processing rep.
  164. DxilProgramSigCompType CompType; // Type of bits.
  165. uint32_t Register; // Register Index (row index)
  166. uint8_t Mask; // Mask (column allocation)
  167. union // Unconditional cases useful for validation of shader linkage.
  168. {
  169. uint8_t NeverWrites_Mask; // For an output signature, the shader the signature belongs to never
  170. // writes the masked components of the output register.
  171. uint8_t AlwaysReads_Mask; // For an input signature, the shader the signature belongs to always
  172. // reads the masked components of the input register.
  173. };
  174. uint16_t Pad;
  175. DxilProgramSigMinPrecision MinPrecision; // Minimum precision of input/output data
  176. };
  177. // Easy to get this wrong. Earlier assertions can help determine
  178. static_assert(sizeof(DxilProgramSignatureElement) == 0x20, "else DxilProgramSignatureElement is misaligned");
  179. struct DxilShaderDebugName {
  180. uint16_t Flags; // Reserved, must be set to zero.
  181. uint16_t NameLength; // Length of the debug name, without null terminator.
  182. // Followed by NameLength bytes of the UTF-8-encoded name.
  183. // Followed by a null terminator.
  184. // Followed by [0-3] zero bytes to align to a 4-byte boundary.
  185. };
  186. static const size_t MinDxilShaderDebugNameSize = sizeof(DxilShaderDebugName) + 4;
  187. struct DxilCompilerVersion {
  188. uint16_t Major;
  189. uint16_t Minor;
  190. uint32_t VersionFlags;
  191. uint32_t CommitCount;
  192. uint32_t VersionStringListSizeInBytes;
  193. // Followed by VersionStringListSizeInBytes bytes, containing up to two null-terminated strings, sequentially:
  194. // 1. CommitSha
  195. // 1. CustomVersionString
  196. // Followed by [0-3] zero bytes to align to a 4-byte boundary.
  197. };
  198. // Source Info part has the following top level structure:
  199. //
  200. // DxilSourceInfo
  201. //
  202. // DxilSourceInfoSection
  203. // char Data[]
  204. // (0-3 zero bytes to align to a 4-byte boundary)
  205. //
  206. // DxilSourceInfoSection
  207. // char Data[]
  208. // (0-3 zero bytes to align to a 4-byte boundary)
  209. //
  210. // ...
  211. //
  212. // DxilSourceInfoSection
  213. // char Data[]
  214. // (0-3 zero bytes to align to a 4-byte boundary)
  215. //
  216. // Each DxilSourceInfoSection is followed by a blob of Data.
  217. // The each type of data has its own internal structure:
  218. //
  219. // ================ 1. Source Names ==================================
  220. //
  221. // DxilSourceInfo_SourceNames
  222. //
  223. // DxilSourceInfo_SourceNamesEntry
  224. // char Name[ NameSizeInBytes ]
  225. // (0-3 zero bytes to align to a 4-byte boundary)
  226. //
  227. // DxilSourceInfo_SourceNamesEntry
  228. // char Name[ NameSizeInBytes ]
  229. // (0-3 zero bytes to align to a 4-byte boundary)
  230. //
  231. // ...
  232. //
  233. // DxilSourceInfo_SourceNamesEntry
  234. // char Name[ NameSizeInBytes ]
  235. // (0-3 zero bytes to align to a 4-byte boundary)
  236. //
  237. // ================ 2. Source Contents ==================================
  238. //
  239. // DxilSourceInfo_SourceContents
  240. // char Entries[CompressedEntriesSizeInBytes]
  241. //
  242. // `Entries` may be compressed. Here is the uncompressed structure:
  243. //
  244. // DxilSourceInfo_SourcesContentsEntry
  245. // char Content[ ContentSizeInBytes ]
  246. // (0-3 zero bytes to align to a 4-byte boundary)
  247. //
  248. // DxilSourceInfo_SourcesContentsEntry
  249. // char Content[ ContentSizeInBytes ]
  250. // (0-3 zero bytes to align to a 4-byte boundary)
  251. //
  252. // ...
  253. //
  254. // DxilSourceInfo_SourcesContentsEntry
  255. // char Content[ ContentSizeInBytes ]
  256. // (0-3 zero bytes to align to a 4-byte boundary)
  257. //
  258. // ================ 3. Args ==================================
  259. //
  260. // DxilSourceInfo_Args
  261. //
  262. // char ArgName[]; char NullTerm;
  263. // char ArgValue[]; char NullTerm;
  264. //
  265. // char ArgName[]; char NullTerm;
  266. // char ArgValue[]; char NullTerm;
  267. //
  268. // ...
  269. //
  270. // char ArgName[]; char NullTerm;
  271. // char ArgValue[]; char NullTerm;
  272. //
  273. struct DxilSourceInfo {
  274. uint32_t AlignedSizeInBytes; // Total size of the contents including this header
  275. uint16_t Flags; // Reserved, must be set to zero.
  276. uint16_t SectionCount; // The number of sections in the source info.
  277. };
  278. enum class DxilSourceInfoSectionType : uint16_t {
  279. SourceContents = 0,
  280. SourceNames = 1,
  281. Args = 2,
  282. };
  283. struct DxilSourceInfoSection {
  284. uint32_t AlignedSizeInBytes; // Size of the section, including this header, and the padding. Aligned to 4-byte boundary.
  285. uint16_t Flags; // Reserved, must be set to zero.
  286. DxilSourceInfoSectionType Type; // The type of data following this header.
  287. };
  288. struct DxilSourceInfo_Args {
  289. uint32_t Flags; // Reserved, must be set to zero.
  290. uint32_t SizeInBytes; // Length of all argument pairs, including their null terminators, not including this header.
  291. uint32_t Count; // Number of arguments.
  292. // Followed by `Count` argument pairs.
  293. //
  294. // For example, given the following arguments:
  295. // /T ps_6_0 -EMain -D MyDefine=1 /DMyOtherDefine=2 -Zi MyShader.hlsl
  296. //
  297. // The argument pair data becomes:
  298. // T\0ps_6_0\0
  299. // E\0Main\0
  300. // D\0MyDefine=1\0
  301. // D\0MyOtherDefine=2\0
  302. // Zi\0\0
  303. // \0MyShader.hlsl\0
  304. //
  305. };
  306. struct DxilSourceInfo_SourceNames {
  307. uint32_t Flags; // Reserved, must be set to 0.
  308. uint32_t Count; // The number of data entries
  309. uint16_t EntriesSizeInBytes; // The total size of the data entries following this header.
  310. // Followed by `Count` data entries with the header DxilSourceInfo_SourceNamesEntry
  311. };
  312. struct DxilSourceInfo_SourceNamesEntry {
  313. uint32_t AlignedSizeInBytes; // Size of the data including this header and padding. Aligned to 4-byte boundary.
  314. uint32_t Flags; // Reserved, must be set to 0.
  315. uint32_t NameSizeInBytes; // Size of the file name, *including* the null terminator.
  316. uint32_t ContentSizeInBytes; // Size of the file content, *including* the null terminator.
  317. // Followed by NameSizeInBytes bytes of the UTF-8-encoded file name (including null terminator).
  318. // Followed by [0-3] zero bytes to align to a 4-byte boundary.
  319. };
  320. enum class DxilSourceInfo_SourceContentsCompressType : uint16_t {
  321. None,
  322. Zlib
  323. };
  324. struct DxilSourceInfo_SourceContents {
  325. uint32_t AlignedSizeInBytes; // Size of the entry including this header. Aligned to 4-byte boundary.
  326. uint16_t Flags; // Reserved, must be set to 0.
  327. DxilSourceInfo_SourceContentsCompressType CompressType; // The type of compression used to compress the data
  328. uint32_t EntriesSizeInBytes; // The size of the data entries following this header.
  329. uint32_t UncompressedEntriesSizeInBytes; // Total size of the data entries when uncompressed.
  330. uint32_t Count; // The number of data entries
  331. // Followed by (compressed) `Count` data entries with the header DxilSourceInfo_SourceContentsEntry
  332. };
  333. struct DxilSourceInfo_SourceContentsEntry {
  334. uint32_t AlignedSizeInBytes; // Size of the entry including this header and padding. Aligned to 4-byte boundary.
  335. uint32_t Flags; // Reserved, must be set to 0.
  336. uint32_t ContentSizeInBytes; // Size of the data following this header, *including* the null terminator
  337. // Followed by NameSizeInBytes bytes of the UTF-8-encoded content (including null terminator).
  338. // Followed by [0-3] zero bytes to align to a 4-byte boundary.
  339. };
  340. #pragma pack(pop)
  341. /// Gets a part header by index.
  342. inline const DxilPartHeader *
  343. GetDxilContainerPart(const DxilContainerHeader *pHeader, uint32_t index) {
  344. const uint8_t *pLinearContainer = reinterpret_cast<const uint8_t *>(pHeader);
  345. const uint32_t *pPartOffsetTable =
  346. reinterpret_cast<const uint32_t *>(pHeader + 1);
  347. return reinterpret_cast<const DxilPartHeader *>(
  348. pLinearContainer + pPartOffsetTable[index]);
  349. }
  350. /// Gets a part header by index.
  351. inline DxilPartHeader *GetDxilContainerPart(DxilContainerHeader *pHeader,
  352. uint32_t index) {
  353. return const_cast<DxilPartHeader *>(GetDxilContainerPart(
  354. reinterpret_cast<const DxilContainerHeader *>(pHeader), index));
  355. }
  356. /// Gets the part data from the header.
  357. inline const char *GetDxilPartData(const DxilPartHeader *pPart) {
  358. return reinterpret_cast<const char *>(pPart + 1);
  359. }
  360. /// Gets the part data from the header.
  361. inline char *GetDxilPartData(DxilPartHeader *pPart) {
  362. return reinterpret_cast<char *>(pPart + 1);
  363. }
  364. /// Gets a part header by fourCC
  365. DxilPartHeader *GetDxilPartByType(DxilContainerHeader *pHeader,
  366. DxilFourCC fourCC);
  367. /// Gets a part header by fourCC
  368. const DxilPartHeader *
  369. GetDxilPartByType(const DxilContainerHeader *pHeader,
  370. DxilFourCC fourCC);
  371. /// Returns valid DxilProgramHeader. nullptr if does not exist.
  372. DxilProgramHeader *GetDxilProgramHeader(DxilContainerHeader *pHeader, DxilFourCC fourCC);
  373. /// Returns valid DxilProgramHeader. nullptr if does not exist.
  374. const DxilProgramHeader *
  375. GetDxilProgramHeader(const DxilContainerHeader *pHeader, DxilFourCC fourCC);
  376. /// Initializes container with the specified values.
  377. void InitDxilContainer(_Out_ DxilContainerHeader *pHeader, uint32_t partCount,
  378. uint32_t containerSizeInBytes);
  379. /// Checks whether pHeader claims by signature to be a DXIL container
  380. /// and the length is at least sizeof(DxilContainerHeader).
  381. const DxilContainerHeader *IsDxilContainerLike(const void *ptr, size_t length);
  382. DxilContainerHeader *IsDxilContainerLike(void *ptr, size_t length);
  383. /// Checks whether the DXIL container is valid and in-bounds.
  384. bool IsValidDxilContainer(const DxilContainerHeader *pHeader, size_t length);
  385. /// Use this type as a unary predicate functor.
  386. struct DxilPartIsType {
  387. uint32_t IsFourCC;
  388. DxilPartIsType(uint32_t FourCC) : IsFourCC(FourCC) { }
  389. bool operator()(const DxilPartHeader *pPart) const {
  390. return pPart->PartFourCC == IsFourCC;
  391. }
  392. };
  393. /// Use this type as an iterator over the part headers.
  394. struct DxilPartIterator : public std::iterator<std::input_iterator_tag,
  395. const DxilContainerHeader *> {
  396. const DxilContainerHeader *pHeader;
  397. uint32_t index;
  398. DxilPartIterator(const DxilContainerHeader *h, uint32_t i)
  399. : pHeader(h), index(i) {}
  400. // increment
  401. DxilPartIterator &operator++() {
  402. ++index;
  403. return *this;
  404. }
  405. DxilPartIterator operator++(int) {
  406. DxilPartIterator result(pHeader, index);
  407. ++index;
  408. return result;
  409. }
  410. // input iterator - compare and deref
  411. bool operator==(const DxilPartIterator &other) const {
  412. return index == other.index && pHeader == other.pHeader;
  413. }
  414. bool operator!=(const DxilPartIterator &other) const {
  415. return index != other.index || pHeader != other.pHeader;
  416. }
  417. const DxilPartHeader *operator*() const {
  418. return GetDxilContainerPart(pHeader, index);
  419. }
  420. };
  421. DxilPartIterator begin(const DxilContainerHeader *pHeader);
  422. DxilPartIterator end(const DxilContainerHeader *pHeader);
  423. inline bool IsValidDxilBitcodeHeader(const DxilBitcodeHeader *pHeader,
  424. uint32_t length) {
  425. return length > sizeof(DxilBitcodeHeader) &&
  426. pHeader->BitcodeOffset + pHeader->BitcodeSize >
  427. pHeader->BitcodeOffset &&
  428. length >= pHeader->BitcodeOffset + pHeader->BitcodeSize &&
  429. pHeader->DxilMagic == DxilMagicValue;
  430. }
  431. inline void InitBitcodeHeader(DxilBitcodeHeader &header,
  432. uint32_t dxilVersion,
  433. uint32_t bitcodeSize) {
  434. header.DxilMagic = DxilMagicValue;
  435. header.DxilVersion = dxilVersion;
  436. header.BitcodeOffset = sizeof(DxilBitcodeHeader);
  437. header.BitcodeSize = bitcodeSize;
  438. }
  439. inline void GetDxilProgramBitcode(const DxilProgramHeader *pHeader,
  440. const char **pBitcode,
  441. uint32_t *pBitcodeLength) {
  442. *pBitcode = reinterpret_cast<const char *>(&pHeader->BitcodeHeader) +
  443. pHeader->BitcodeHeader.BitcodeOffset;
  444. *pBitcodeLength = pHeader->BitcodeHeader.BitcodeSize;
  445. }
  446. inline bool IsValidDxilProgramHeader(const DxilProgramHeader *pHeader,
  447. uint32_t length) {
  448. return length >= sizeof(DxilProgramHeader) &&
  449. length >= (pHeader->SizeInUint32 * sizeof(uint32_t)) &&
  450. IsValidDxilBitcodeHeader(
  451. &pHeader->BitcodeHeader,
  452. length - offsetof(DxilProgramHeader, BitcodeHeader));
  453. }
  454. inline void InitProgramHeader(DxilProgramHeader &header, uint32_t shaderVersion,
  455. uint32_t dxilVersion,
  456. uint32_t bitcodeSize) {
  457. header.ProgramVersion = shaderVersion;
  458. header.SizeInUint32 =
  459. sizeof(DxilProgramHeader) / sizeof(uint32_t) +
  460. bitcodeSize / sizeof(uint32_t) + ((bitcodeSize % 4) ? 1 : 0);
  461. InitBitcodeHeader(header.BitcodeHeader, dxilVersion, bitcodeSize);
  462. }
  463. inline const char *GetDxilBitcodeData(const DxilProgramHeader *pHeader) {
  464. const DxilBitcodeHeader *pBCHdr = &(pHeader->BitcodeHeader);
  465. return (const char *)pBCHdr + pBCHdr->BitcodeOffset;
  466. }
  467. inline uint32_t GetDxilBitcodeSize(const DxilProgramHeader *pHeader) {
  468. return pHeader->BitcodeHeader.BitcodeSize;
  469. }
  470. /// Extract the shader type from the program version value.
  471. inline DXIL::ShaderKind GetVersionShaderType(uint32_t programVersion) {
  472. return (DXIL::ShaderKind)((programVersion & 0xffff0000) >> 16);
  473. }
  474. inline uint32_t GetVersionMajor(uint32_t programVersion) {
  475. return (programVersion & 0xf0) >> 4;
  476. }
  477. inline uint32_t GetVersionMinor(uint32_t programVersion) {
  478. return (programVersion & 0xf);
  479. }
  480. inline uint32_t EncodeVersion(DXIL::ShaderKind shaderType, uint32_t major,
  481. uint32_t minor) {
  482. return ((unsigned)shaderType << 16) | (major << 4) | minor;
  483. }
  484. inline bool IsDxilShaderDebugNameValid(const DxilPartHeader *pPart) {
  485. if (pPart->PartFourCC != DFCC_ShaderDebugName) return false;
  486. if (pPart->PartSize < MinDxilShaderDebugNameSize) return false;
  487. const DxilShaderDebugName *pDebugNameContent = reinterpret_cast<const DxilShaderDebugName *>(GetDxilPartData(pPart));
  488. uint16_t ExpectedSize = sizeof(DxilShaderDebugName) + pDebugNameContent->NameLength + 1;
  489. if (ExpectedSize & 0x3) {
  490. ExpectedSize += 0x4;
  491. ExpectedSize &= ~(0x3);
  492. }
  493. if (pPart->PartSize != ExpectedSize) return false;
  494. return true;
  495. }
  496. inline bool GetDxilShaderDebugName(const DxilPartHeader *pDebugNamePart,
  497. const char **ppUtf8Name, _Out_opt_ uint16_t *pUtf8NameLen) {
  498. *ppUtf8Name = nullptr;
  499. if (!IsDxilShaderDebugNameValid(pDebugNamePart)) {
  500. return false;
  501. }
  502. const DxilShaderDebugName *pDebugNameContent = reinterpret_cast<const DxilShaderDebugName *>(GetDxilPartData(pDebugNamePart));
  503. if (pUtf8NameLen) {
  504. *pUtf8NameLen = pDebugNameContent->NameLength;
  505. }
  506. *ppUtf8Name = (const char *)(pDebugNameContent + 1);
  507. return true;
  508. }
  509. enum class SerializeDxilFlags : uint32_t {
  510. None = 0, // No flags defined.
  511. IncludeDebugInfoPart = 1 << 0, // Include the debug info part in the container.
  512. IncludeDebugNamePart = 1 << 1, // Include the debug name part in the container.
  513. DebugNameDependOnSource = 1 << 2, // Make the debug name depend on source (and not just final module).
  514. StripReflectionFromDxilPart = 1 << 3, // Strip Reflection info from DXIL part.
  515. IncludeReflectionPart = 1 << 4, // Include reflection in STAT part.
  516. StripRootSignature = 1 << 5, // Strip Root Signature from main shader container.
  517. };
  518. inline SerializeDxilFlags& operator |=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
  519. l = static_cast<SerializeDxilFlags>(static_cast<int>(l) | static_cast<int>(r));
  520. return l;
  521. }
  522. inline SerializeDxilFlags& operator &=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
  523. l = static_cast<SerializeDxilFlags>(static_cast<int>(l) & static_cast<int>(r));
  524. return l;
  525. }
  526. inline int operator&(SerializeDxilFlags l, SerializeDxilFlags r) {
  527. return static_cast<int>(l) & static_cast<int>(r);
  528. }
  529. inline SerializeDxilFlags operator~(SerializeDxilFlags l) {
  530. return static_cast<SerializeDxilFlags>(~static_cast<uint32_t>(l));
  531. }
  532. void CreateDxcContainerReflection(IDxcContainerReflection **ppResult);
  533. // Converts uint32_t partKind to char array object.
  534. inline char * PartKindToCharArray(uint32_t partKind, _Out_writes_(5) char* pText) {
  535. pText[0] = (char)((partKind & 0x000000FF) >> 0);
  536. pText[1] = (char)((partKind & 0x0000FF00) >> 8);
  537. pText[2] = (char)((partKind & 0x00FF0000) >> 16);
  538. pText[3] = (char)((partKind & 0xFF000000) >> 24);
  539. pText[4] = '\0';
  540. return pText;
  541. }
  542. inline size_t GetOffsetTableSize(uint32_t partCount) {
  543. return sizeof(uint32_t) * partCount;
  544. }
  545. // Compute total size of the dxil container from parts information
  546. inline size_t GetDxilContainerSizeFromParts(uint32_t partCount, uint32_t partsSize) {
  547. return partsSize + (uint32_t)sizeof(DxilContainerHeader) +
  548. GetOffsetTableSize(partCount) +
  549. (uint32_t)sizeof(DxilPartHeader) * partCount;
  550. }
  551. } // namespace hlsl
  552. #endif // __DXC_CONTAINER__