DxilContainer.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  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 <functional>
  17. #include "dxc/HLSL/DxilConstants.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. struct DxilContainerVersion {
  34. uint16_t Major;
  35. uint16_t Minor;
  36. };
  37. /// Use this type to describe a DXIL container of parts.
  38. struct DxilContainerHeader {
  39. uint32_t HeaderFourCC;
  40. DxilContainerHash Hash;
  41. DxilContainerVersion Version;
  42. uint32_t ContainerSizeInBytes; // From start of this header
  43. uint32_t PartCount;
  44. // Structure is followed by uint32_t PartOffset[PartCount];
  45. // The offset is to a DxilPartHeader.
  46. };
  47. /// Use this type to describe the size and type of a DXIL container part.
  48. struct DxilPartHeader {
  49. uint32_t PartFourCC; // Four char code for part type.
  50. uint32_t PartSize; // Byte count for PartData.
  51. // Structure is followed by uint8_t PartData[PartSize].
  52. };
  53. #define DXIL_FOURCC(ch0, ch1, ch2, ch3) ( \
  54. (uint32_t)(uint8_t)(ch0) | (uint32_t)(uint8_t)(ch1) << 8 | \
  55. (uint32_t)(uint8_t)(ch2) << 16 | (uint32_t)(uint8_t)(ch3) << 24 \
  56. )
  57. enum DxilFourCC {
  58. DFCC_Container = DXIL_FOURCC('D', 'X', 'B', 'C'), // for back-compat with tools that look for DXBC containers
  59. DFCC_ResourceDef = DXIL_FOURCC('R', 'D', 'E', 'F'),
  60. DFCC_InputSignature = DXIL_FOURCC('I', 'S', 'G', '1'),
  61. DFCC_OutputSignature = DXIL_FOURCC('O', 'S', 'G', '1'),
  62. DFCC_PatchConstantSignature = DXIL_FOURCC('P', 'S', 'G', '1'),
  63. DFCC_ShaderStatistics = DXIL_FOURCC('S', 'T', 'A', 'T'),
  64. DFCC_ShaderDebugInfoDXIL = DXIL_FOURCC('I', 'L', 'D', 'B'),
  65. DFCC_ShaderDebugName = DXIL_FOURCC('I', 'L', 'D', 'N'),
  66. DFCC_FeatureInfo = DXIL_FOURCC('S', 'F', 'I', '0'),
  67. DFCC_PrivateData = DXIL_FOURCC('P', 'R', 'I', 'V'),
  68. DFCC_RootSignature = DXIL_FOURCC('R', 'T', 'S', '0'),
  69. DFCC_DXIL = DXIL_FOURCC('D', 'X', 'I', 'L'),
  70. DFCC_PipelineStateValidation = DXIL_FOURCC('P', 'S', 'V', '0'),
  71. };
  72. #undef DXIL_FOURCC
  73. // DFCC_FeatureInfo is a uint64_t value with these flags.
  74. static const uint64_t ShaderFeatureInfo_Doubles = 0x0001;
  75. static const uint64_t ShaderFeatureInfo_ComputeShadersPlusRawAndStructuredBuffersViaShader4X = 0x0002;
  76. static const uint64_t ShaderFeatureInfo_UAVsAtEveryStage = 0x0004;
  77. static const uint64_t ShaderFeatureInfo_64UAVs = 0x0008;
  78. static const uint64_t ShaderFeatureInfo_MinimumPrecision = 0x0010;
  79. static const uint64_t ShaderFeatureInfo_11_1_DoubleExtensions = 0x0020;
  80. static const uint64_t ShaderFeatureInfo_11_1_ShaderExtensions = 0x0040;
  81. static const uint64_t ShaderFeatureInfo_LEVEL9ComparisonFiltering = 0x0080;
  82. static const uint64_t ShaderFeatureInfo_TiledResources = 0x0100;
  83. static const uint64_t ShaderFeatureInfo_StencilRef = 0x0200;
  84. static const uint64_t ShaderFeatureInfo_InnerCoverage = 0x0400;
  85. static const uint64_t ShaderFeatureInfo_TypedUAVLoadAdditionalFormats = 0x0800;
  86. static const uint64_t ShaderFeatureInfo_ROVs = 0x1000;
  87. static const uint64_t ShaderFeatureInfo_ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer = 0x2000;
  88. static const uint64_t ShaderFeatureInfo_WaveOps = 0x4000;
  89. static const uint64_t ShaderFeatureInfo_Int64Ops = 0x8000;
  90. static const uint64_t ShaderFeatureInfo_ViewID = 0x10000;
  91. static const uint64_t ShaderFeatureInfo_Barycentrics = 0x20000;
  92. static const uint64_t ShaderFeatureInfo_NativeLowPrecision = 0x40000;
  93. static const unsigned ShaderFeatureInfoCount = 19;
  94. struct DxilShaderFeatureInfo {
  95. uint64_t FeatureFlags;
  96. };
  97. // DXIL program information.
  98. struct DxilBitcodeHeader {
  99. uint32_t DxilMagic; // ACSII "DXIL".
  100. uint32_t DxilVersion; // DXIL version.
  101. uint32_t BitcodeOffset; // Offset to LLVM bitcode (from start of header).
  102. uint32_t BitcodeSize; // Size of LLVM bitcode.
  103. };
  104. static const uint32_t DxilMagicValue = 0x4C495844; // 'DXIL'
  105. struct DxilProgramHeader {
  106. uint32_t ProgramVersion; /// Major and minor version, including type.
  107. uint32_t SizeInUint32; /// Size in uint32_t units including this header.
  108. DxilBitcodeHeader BitcodeHeader; /// Bitcode-specific header.
  109. // Followed by uint8_t[BitcodeHeader.BitcodeOffset]
  110. };
  111. struct DxilProgramSignature {
  112. uint32_t ParamCount;
  113. uint32_t ParamOffset;
  114. };
  115. enum class DxilProgramSigMinPrecision : uint32_t {
  116. Default = 0,
  117. Float16 = 1,
  118. Float2_8 = 2,
  119. Reserved = 3,
  120. SInt16 = 4,
  121. UInt16 = 5,
  122. Any16 = 0xf0,
  123. Any10 = 0xf1
  124. };
  125. // Corresponds to D3D_NAME and D3D10_SB_NAME
  126. enum class DxilProgramSigSemantic : uint32_t {
  127. Undefined = 0,
  128. Position = 1,
  129. ClipDistance = 2,
  130. CullDistance = 3,
  131. RenderTargetArrayIndex = 4,
  132. ViewPortArrayIndex = 5,
  133. VertexID = 6,
  134. PrimitiveID = 7,
  135. InstanceID = 8,
  136. IsFrontFace = 9,
  137. SampleIndex = 10,
  138. FinalQuadEdgeTessfactor = 11,
  139. FinalQuadInsideTessfactor = 12,
  140. FinalTriEdgeTessfactor = 13,
  141. FinalTriInsideTessfactor = 14,
  142. FinalLineDetailTessfactor = 15,
  143. FinalLineDensityTessfactor = 16,
  144. Barycentrics = 23,
  145. Target = 64,
  146. Depth = 65,
  147. Coverage = 66,
  148. DepthGE = 67,
  149. DepthLE = 68,
  150. StencilRef = 69,
  151. InnerCoverage = 70,
  152. };
  153. enum class DxilProgramSigCompType : uint32_t {
  154. Unknown = 0,
  155. UInt32 = 1,
  156. SInt32 = 2,
  157. Float32 = 3,
  158. UInt16 = 4,
  159. SInt16 = 5,
  160. Float16 = 6,
  161. UInt64 = 7,
  162. SInt64 = 8,
  163. Float64 = 9,
  164. };
  165. static const uint8_t DxilProgramSigMaskX = 1;
  166. static const uint8_t DxilProgramSigMaskY = 2;
  167. static const uint8_t DxilProgramSigMaskZ = 4;
  168. static const uint8_t DxilProgramSigMaskW = 8;
  169. struct DxilProgramSignatureElement {
  170. uint32_t Stream; // Stream index (parameters must appear in non-decreasing stream order)
  171. uint32_t SemanticName; // Offset to LPCSTR from start of DxilProgramSignature.
  172. uint32_t SemanticIndex; // Semantic Index
  173. DxilProgramSigSemantic SystemValue; // Semantic type. Similar to DxilSemantic::Kind, but a serialized rather than processing rep.
  174. DxilProgramSigCompType CompType; // Type of bits.
  175. uint32_t Register; // Register Index (row index)
  176. uint8_t Mask; // Mask (column allocation)
  177. union // Unconditional cases useful for validation of shader linkage.
  178. {
  179. uint8_t NeverWrites_Mask; // For an output signature, the shader the signature belongs to never
  180. // writes the masked components of the output register.
  181. uint8_t AlwaysReads_Mask; // For an input signature, the shader the signature belongs to always
  182. // reads the masked components of the input register.
  183. };
  184. uint16_t Pad;
  185. DxilProgramSigMinPrecision MinPrecision; // Minimum precision of input/output data
  186. };
  187. // Easy to get this wrong. Earlier assertions can help determine
  188. static_assert(sizeof(DxilProgramSignatureElement) == 0x20, "else DxilProgramSignatureElement is misaligned");
  189. struct DxilShaderDebugName {
  190. uint16_t Flags; // Reserved, must be set to zero.
  191. uint16_t NameLength; // Length of the debug name, without null terminator.
  192. // Followed by NameLength bytes of the UTF-8-encoded name.
  193. // Followed by a null terminator.
  194. // Followed by [0-3] zero bytes to align to a 4-byte boundary.
  195. };
  196. static const size_t MinDxilShaderDebugNameSize = sizeof(DxilShaderDebugName) + 4;
  197. #pragma pack(pop)
  198. /// Gets a part header by index.
  199. inline const DxilPartHeader *
  200. GetDxilContainerPart(const DxilContainerHeader *pHeader, uint32_t index) {
  201. const uint8_t *pLinearContainer = reinterpret_cast<const uint8_t *>(pHeader);
  202. const uint32_t *pPartOffsetTable =
  203. reinterpret_cast<const uint32_t *>(pHeader + 1);
  204. return reinterpret_cast<const DxilPartHeader *>(
  205. pLinearContainer + pPartOffsetTable[index]);
  206. }
  207. /// Gets a part header by index.
  208. inline DxilPartHeader *GetDxilContainerPart(DxilContainerHeader *pHeader,
  209. uint32_t index) {
  210. return const_cast<DxilPartHeader *>(GetDxilContainerPart(
  211. reinterpret_cast<const DxilContainerHeader *>(pHeader), index));
  212. }
  213. /// Gets the part data from the header.
  214. inline const char *GetDxilPartData(const DxilPartHeader *pPart) {
  215. return reinterpret_cast<const char *>(pPart + 1);
  216. }
  217. /// Gets the part data from the header.
  218. inline char *GetDxilPartData(DxilPartHeader *pPart) {
  219. return reinterpret_cast<char *>(pPart + 1);
  220. }
  221. /// Gets a part header by fourCC
  222. DxilPartHeader *GetDxilPartByType(DxilContainerHeader *pHeader,
  223. DxilFourCC fourCC);
  224. /// Gets a part header by fourCC
  225. const DxilPartHeader *
  226. GetDxilPartByType(const DxilContainerHeader *pHeader,
  227. DxilFourCC fourCC);
  228. /// Returns valid DxilProgramHeader. nullptr if does not exist.
  229. DxilProgramHeader *GetDxilProgramHeader(DxilContainerHeader *pHeader, DxilFourCC fourCC);
  230. /// Returns valid DxilProgramHeader. nullptr if does not exist.
  231. const DxilProgramHeader *
  232. GetDxilProgramHeader(const DxilContainerHeader *pHeader, DxilFourCC fourCC);
  233. /// Initializes container with the specified values.
  234. void InitDxilContainer(_Out_ DxilContainerHeader *pHeader, uint32_t partCount,
  235. uint32_t containerSizeInBytes);
  236. /// Checks whether pHeader claims by signature to be a DXIL container.
  237. const DxilContainerHeader *IsDxilContainerLike(const void *ptr, size_t length);
  238. /// Checks whether the DXIL container is valid and in-bounds.
  239. bool IsValidDxilContainer(const DxilContainerHeader *pHeader, size_t length);
  240. /// Use this type as a unary predicate functor.
  241. struct DxilPartIsType {
  242. uint32_t IsFourCC;
  243. DxilPartIsType(uint32_t FourCC) : IsFourCC(FourCC) { }
  244. bool operator()(const DxilPartHeader *pPart) const {
  245. return pPart->PartFourCC == IsFourCC;
  246. }
  247. };
  248. /// Use this type as an iterator over the part headers.
  249. struct DxilPartIterator : public std::iterator<std::input_iterator_tag,
  250. const DxilContainerHeader *> {
  251. const DxilContainerHeader *pHeader;
  252. uint32_t index;
  253. DxilPartIterator(const DxilContainerHeader *h, uint32_t i)
  254. : pHeader(h), index(i) {}
  255. // increment
  256. DxilPartIterator &operator++() {
  257. ++index;
  258. return *this;
  259. }
  260. DxilPartIterator operator++(int) {
  261. DxilPartIterator result(pHeader, index);
  262. ++index;
  263. return result;
  264. }
  265. // input iterator - compare and deref
  266. bool operator==(const DxilPartIterator &other) const {
  267. return index == other.index && pHeader == other.pHeader;
  268. }
  269. bool operator!=(const DxilPartIterator &other) const {
  270. return index != other.index || pHeader != other.pHeader;
  271. }
  272. const DxilPartHeader *operator*() const {
  273. return GetDxilContainerPart(pHeader, index);
  274. }
  275. };
  276. DxilPartIterator begin(const DxilContainerHeader *pHeader);
  277. DxilPartIterator end(const DxilContainerHeader *pHeader);
  278. inline bool IsValidDxilBitcodeHeader(const DxilBitcodeHeader *pHeader,
  279. uint32_t length) {
  280. return length > sizeof(DxilBitcodeHeader) &&
  281. pHeader->BitcodeOffset + pHeader->BitcodeSize >
  282. pHeader->BitcodeOffset &&
  283. length >= pHeader->BitcodeOffset + pHeader->BitcodeSize &&
  284. pHeader->DxilMagic == DxilMagicValue;
  285. }
  286. inline void InitBitcodeHeader(DxilBitcodeHeader &header,
  287. uint32_t dxilVersion,
  288. uint32_t bitcodeSize) {
  289. header.DxilMagic = DxilMagicValue;
  290. header.DxilVersion = dxilVersion;
  291. header.BitcodeOffset = sizeof(DxilBitcodeHeader);
  292. header.BitcodeSize = bitcodeSize;
  293. }
  294. inline void GetDxilProgramBitcode(const DxilProgramHeader *pHeader,
  295. const char **pBitcode,
  296. uint32_t *pBitcodeLength) {
  297. *pBitcode = reinterpret_cast<const char *>(&pHeader->BitcodeHeader) +
  298. pHeader->BitcodeHeader.BitcodeOffset;
  299. *pBitcodeLength = pHeader->BitcodeHeader.BitcodeSize;
  300. }
  301. inline bool IsValidDxilProgramHeader(const DxilProgramHeader *pHeader,
  302. uint32_t length) {
  303. return length >= sizeof(DxilProgramHeader) &&
  304. length >= (pHeader->SizeInUint32 * sizeof(uint32_t)) &&
  305. IsValidDxilBitcodeHeader(
  306. &pHeader->BitcodeHeader,
  307. length - offsetof(DxilProgramHeader, BitcodeHeader));
  308. }
  309. inline void InitProgramHeader(DxilProgramHeader &header, uint32_t shaderVersion,
  310. uint32_t dxilVersion,
  311. uint32_t bitcodeSize) {
  312. header.ProgramVersion = shaderVersion;
  313. header.SizeInUint32 =
  314. sizeof(DxilProgramHeader) / sizeof(uint32_t) +
  315. bitcodeSize / sizeof(uint32_t) + ((bitcodeSize % 4) ? 1 : 0);
  316. InitBitcodeHeader(header.BitcodeHeader, dxilVersion, bitcodeSize);
  317. }
  318. inline const char *GetDxilBitcodeData(const DxilProgramHeader *pHeader) {
  319. const DxilBitcodeHeader *pBCHdr = &(pHeader->BitcodeHeader);
  320. return (const char *)pBCHdr + pBCHdr->BitcodeOffset;
  321. }
  322. inline uint32_t GetDxilBitcodeSize(const DxilProgramHeader *pHeader) {
  323. return pHeader->BitcodeHeader.BitcodeSize;
  324. }
  325. /// Extract the shader type from the program version value.
  326. inline DXIL::ShaderKind GetVersionShaderType(uint32_t programVersion) {
  327. return (DXIL::ShaderKind)((programVersion & 0xffff0000) >> 16);
  328. }
  329. inline uint32_t GetVersionMajor(uint32_t programVersion) {
  330. return (programVersion & 0xf0) >> 4;
  331. }
  332. inline uint32_t GetVersionMinor(uint32_t programVersion) {
  333. return (programVersion & 0xf);
  334. }
  335. inline uint32_t EncodeVersion(DXIL::ShaderKind shaderType, uint32_t major,
  336. uint32_t minor) {
  337. return ((unsigned)shaderType << 16) | (major << 4) | minor;
  338. }
  339. inline bool IsDxilShaderDebugNameValid(const DxilPartHeader *pPart) {
  340. if (pPart->PartFourCC != DFCC_ShaderDebugName) return false;
  341. if (pPart->PartSize < MinDxilShaderDebugNameSize) return false;
  342. const DxilShaderDebugName *pDebugNameContent = reinterpret_cast<const DxilShaderDebugName *>(GetDxilPartData(pPart));
  343. uint16_t ExpectedSize = sizeof(DxilShaderDebugName) + pDebugNameContent->NameLength + 1;
  344. if (ExpectedSize & 0x3) {
  345. ExpectedSize += 0x4;
  346. ExpectedSize &= ~(0x3);
  347. }
  348. if (pPart->PartSize != ExpectedSize) return false;
  349. return true;
  350. }
  351. inline bool GetDxilShaderDebugName(const DxilPartHeader *pDebugNamePart,
  352. const char **ppUtf8Name, _Out_opt_ uint16_t *pUtf8NameLen) {
  353. *ppUtf8Name = nullptr;
  354. if (!IsDxilShaderDebugNameValid(pDebugNamePart)) {
  355. return false;
  356. }
  357. const DxilShaderDebugName *pDebugNameContent = reinterpret_cast<const DxilShaderDebugName *>(GetDxilPartData(pDebugNamePart));
  358. if (pUtf8NameLen) {
  359. *pUtf8NameLen = pDebugNameContent->NameLength;
  360. }
  361. *ppUtf8Name = (const char *)(pDebugNameContent + 1);
  362. return true;
  363. }
  364. class DxilPartWriter {
  365. public:
  366. virtual ~DxilPartWriter() {}
  367. virtual uint32_t size() const = 0;
  368. virtual void write(AbstractMemoryStream *pStream) = 0;
  369. };
  370. DxilPartWriter *NewProgramSignatureWriter(const DxilModule &M, DXIL::SignatureKind Kind);
  371. DxilPartWriter *NewRootSignatureWriter(const RootSignatureHandle &S);
  372. DxilPartWriter *NewFeatureInfoWriter(const DxilModule &M);
  373. DxilPartWriter *NewPSVWriter(const DxilModule &M, uint32_t PSVVersion = 0);
  374. class DxilContainerWriter : public DxilPartWriter {
  375. public:
  376. typedef std::function<void(AbstractMemoryStream*)> WriteFn;
  377. virtual ~DxilContainerWriter() {}
  378. virtual void AddPart(uint32_t FourCC, uint32_t Size, WriteFn Write) = 0;
  379. };
  380. DxilContainerWriter *NewDxilContainerWriter();
  381. enum class SerializeDxilFlags : uint32_t {
  382. None = 0, // No flags defined.
  383. IncludeDebugInfoPart = 1, // Include the debug info part in the container.
  384. IncludeDebugNamePart = 2, // Include the debug name part in the container.
  385. DebugNameDependOnSource = 4 // Make the debug name depend on source (and not just final module).
  386. };
  387. inline SerializeDxilFlags& operator |=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
  388. l = static_cast<SerializeDxilFlags>(static_cast<int>(l) | static_cast<int>(r));
  389. return l;
  390. }
  391. inline SerializeDxilFlags& operator &=(SerializeDxilFlags& l, const SerializeDxilFlags& r) {
  392. l = static_cast<SerializeDxilFlags>(static_cast<int>(l) & static_cast<int>(r));
  393. return l;
  394. }
  395. inline int operator&(SerializeDxilFlags l, SerializeDxilFlags r) {
  396. return static_cast<int>(l) & static_cast<int>(r);
  397. }
  398. inline SerializeDxilFlags operator~(SerializeDxilFlags l) {
  399. return static_cast<SerializeDxilFlags>(~static_cast<uint32_t>(l));
  400. }
  401. void SerializeDxilContainerForModule(hlsl::DxilModule *pModule,
  402. AbstractMemoryStream *pModuleBitcode,
  403. AbstractMemoryStream *pStream,
  404. SerializeDxilFlags Flags);
  405. void SerializeDxilContainerForRootSignature(hlsl::RootSignatureHandle *pRootSigHandle,
  406. AbstractMemoryStream *pStream);
  407. void CreateDxcContainerReflection(IDxcContainerReflection **ppResult);
  408. // Converts uint32_t partKind to char array object.
  409. inline char * PartKindToCharArray(uint32_t partKind, _Out_writes_(5) char* pText) {
  410. pText[0] = (char)((partKind & 0x000000FF) >> 0);
  411. pText[1] = (char)((partKind & 0x0000FF00) >> 8);
  412. pText[2] = (char)((partKind & 0x00FF0000) >> 16);
  413. pText[3] = (char)((partKind & 0xFF000000) >> 24);
  414. pText[4] = '\0';
  415. return pText;
  416. }
  417. inline size_t GetOffsetTableSize(uint32_t partCount) {
  418. return sizeof(uint32_t) * partCount;
  419. }
  420. // Compute total size of the dxil container from parts information
  421. inline size_t GetDxilContainerSizeFromParts(uint32_t partCount, uint32_t partsSize) {
  422. return partsSize + (uint32_t)sizeof(DxilContainerHeader) +
  423. GetOffsetTableSize(partCount) +
  424. (uint32_t)sizeof(DxilPartHeader) * partCount;
  425. }
  426. } // namespace hlsl
  427. #endif // __DXC_CONTAINER__