DX12Shader.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #pragma once
  2. #include "Array.h"
  3. #include "DX12Buffer.h"
  4. struct ID3D12Device5;
  5. struct ID3D12GraphicsCommandList;
  6. struct D3D12_INPUT_ELEMENT_DESC;
  7. struct D3D12_ROOT_PARAMETER1;
  8. struct D3D12_CONSTANT_BUFFER_VIEW_DESC;
  9. struct ID3D12StateObjectProperties;
  10. namespace Framework
  11. {
  12. class Texture;
  13. class DX12TLAS;
  14. class DX12SamplerState;
  15. enum DX12ShaderRegister
  16. {
  17. DX12_SHADER_REGISTER_B_CONST_BUFFER = 0,
  18. DX12_SHADER_REGISTER_T_SHADER_RESOURCE = 1,
  19. DX12_SHADER_REGISTER_U_UNORDERED_ACCESS = 2,
  20. DX12_SHADER_REGISTER_S_SAMPLER = 3,
  21. };
  22. enum DX12DescriptorHeapType
  23. {
  24. GLOBAL_DESCRIPTOR_HEAP = 0,
  25. TEXTURE_DESCRIPTOR_HEAP = 1,
  26. SAMPLER_DESCRIPTOR_HEAP = 2,
  27. __DESCRIPTOR_HEAP_TYPE_COUNT__
  28. };
  29. struct DX12ShaderRegisterUsage
  30. {
  31. DX12ShaderRegister registerType;
  32. DX12DescriptorHeapType descriptorHeapType;
  33. int registerIndex;
  34. int spaceIndex;
  35. int descriptorHeapIndex;
  36. int bindingTableIndex;
  37. bool array;
  38. int arraySize;
  39. };
  40. class DX12ShaderHeap;
  41. class DX12ShaderSignature : public ReferenceCounter
  42. {
  43. private:
  44. ID3D12RootSignature* signature;
  45. Array<DX12ShaderRegisterUsage*> descriptorHeapBindings;
  46. Array<DX12ShaderRegisterUsage*> bindingTableBindings;
  47. bool changed;
  48. int shaderBindingTableParamCount;
  49. bool useGlobalDescriptorHeap;
  50. bool useTextureDescriptorHeap;
  51. bool useSamplerDescriptorHeap;
  52. public:
  53. DLLEXPORT DX12ShaderSignature();
  54. DLLEXPORT ~DX12ShaderSignature();
  55. /**
  56. * for each datastructure with : register(...) in the shader code,
  57. * either this function or addRegisterUsageLinkedToDescriptorHeap must
  58. * be called to link the register usage to the shader binding table or
  59. * descriptor heap.
  60. *
  61. * \param registerType the register type e.g.
  62. * DX12_SHADER_REGISTER_B_CONST_BUFFER for : register(b0)
  63. * \param registerIndex the register index e.g. 1 for : register(b1)
  64. * \param spaceIndex the optional space index e.g. 3 for : register(b1,
  65. * space3)
  66. * \return pointer to the offset in the shader binding table where this
  67. * parameter needs to be placed. This pointer is only valid after the
  68. * call to createSignature() and should be used to fill the shader
  69. * binding table with the correct GPU addresses of the resources.
  70. */
  71. DLLEXPORT int* addRegisterUsageLinkedToShaderBindingTable(
  72. DX12ShaderRegister registerType,
  73. int registerIndex,
  74. int spaceIndex = 0);
  75. /**
  76. * for each datastructure with : register(...) in the shader code,
  77. * either this function or addRegisterUsageLinkedToDescriptorHeap must
  78. * be called to link the register usage to the shader binding table or
  79. * descriptor heap.
  80. * For optimal performance the registers that are linked to the
  81. * descriptor heaps should be consecutive and use consecutive descriptor
  82. * heap spaces. Example: register(b3), register(b4), register(b5) linked
  83. * to descriptor heap index 2, 3, 4.
  84. *
  85. * \param descriptorHeapIndex the index in the descriptor heap witch
  86. * contains the resource for this register usage
  87. * \param registerType the register type e.g.
  88. * DX12_SHADER_REGISTER_B_CONST_BUFFER for : register(b0)
  89. * \param registerIndex the register index e.g. 1 for : register(b1)
  90. * \param spaceIndex the optional space index e.g. 3 for : register(b1,
  91. * space3)
  92. * \param array used to specify if the register referes to an array in
  93. * hlsl
  94. * \param arraySize the size of the array if array is true or -1 if the
  95. * size is unknown (unbound array)
  96. */
  97. DLLEXPORT void addRegisterUsageLinkedToDescriptorHeap(
  98. int descriptorHeapIndex,
  99. DX12ShaderRegister registerType,
  100. int registerIndex,
  101. int spaceIndex = 0,
  102. DX12DescriptorHeapType descriptorHeapType = GLOBAL_DESCRIPTOR_HEAP,
  103. bool array = false,
  104. int arraySize = -1);
  105. /**
  106. * Creates the root signature.
  107. */
  108. DLLEXPORT void createSignature(ID3D12Device5* zDevice,
  109. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfnD3D12SerializeRootSignature);
  110. DLLEXPORT ID3D12RootSignature* zSignature() const;
  111. DLLEXPORT const Array<DX12ShaderRegisterUsage*>&
  112. getDescriptorHeapBindings() const;
  113. DLLEXPORT int gerShaderBindingTableParamCount() const;
  114. DLLEXPORT bool doesUseGlobalDescriptorHeap() const;
  115. DLLEXPORT bool doesUseTextureDescriptorHeap() const;
  116. DLLEXPORT bool doesUseSamplerDescriptorHeap() const;
  117. };
  118. enum DX12ShaderFunctionType
  119. {
  120. DX12_SHADER_FUNCTION_TYPE_RAY_GEN,
  121. DX12_SHADER_FUNCTION_TYPE_INTERSECTION,
  122. DX12_SHADER_FUNCTION_TYPE_ANY_HIT,
  123. DX12_SHADER_FUNCTION_TYPE_CLOSEST_HIT,
  124. DX12_SHADER_FUNCTION_TYPE_MISS,
  125. DX12_SHADER_FUNCTION_TYPE_CALLABLE,
  126. };
  127. class DX12ShaderFunction : public ReferenceCounter
  128. {
  129. private:
  130. Text functionName;
  131. DX12ShaderSignature* signature;
  132. D3D12_EXPORT_DESC* exportDesc;
  133. DX12ShaderFunctionType functionType;
  134. public:
  135. DLLEXPORT DX12ShaderFunction(const Text& functionName,
  136. DX12ShaderSignature* signature,
  137. DX12ShaderFunctionType functionType);
  138. DLLEXPORT ~DX12ShaderFunction();
  139. DLLEXPORT const Text& getFunctionName() const;
  140. DLLEXPORT DX12ShaderSignature* zSignature() const;
  141. DLLEXPORT D3D12_EXPORT_DESC* zExportDesc() const;
  142. DLLEXPORT DX12ShaderFunctionType getFunctionType() const;
  143. };
  144. class DX12Shader : public ReferenceCounter
  145. {
  146. private:
  147. RCArray<DX12ShaderFunction> functions;
  148. const unsigned char* shaderBytes;
  149. int shaderBytesSize;
  150. D3D12_DXIL_LIBRARY_DESC* libraryDesc;
  151. public:
  152. DLLEXPORT DX12Shader(
  153. const unsigned char* shaderBytes, int shaderBytesSize);
  154. DLLEXPORT ~DX12Shader();
  155. DLLEXPORT void addFunction(DX12ShaderFunction* function);
  156. DLLEXPORT int getShaderBytesSize() const;
  157. DLLEXPORT const unsigned char* getShaderBytes() const;
  158. DLLEXPORT const RCArray<DX12ShaderFunction>& getFunctions() const;
  159. DLLEXPORT D3D12_DXIL_LIBRARY_DESC* zLibraryDesc() const;
  160. };
  161. class DX12ShaderHitGroup : public ReferenceCounter
  162. {
  163. private:
  164. Text name;
  165. DX12ShaderFunction* closestHitShaderFunction;
  166. DX12ShaderFunction* anyHitShaderFunction;
  167. DX12ShaderFunction* intersectionShaderFunction;
  168. int payloadSize;
  169. int attributeSize;
  170. D3D12_HIT_GROUP_DESC* hitGroupDesc;
  171. public:
  172. DLLEXPORT DX12ShaderHitGroup(const Text name);
  173. DLLEXPORT ~DX12ShaderHitGroup();
  174. DLLEXPORT void setClosestHitShaderFunction(
  175. DX12ShaderFunction* zClosestHitShaderFunction);
  176. DLLEXPORT void setAnyHitShaderFunction(
  177. DX12ShaderFunction* zAnyHitShaderFunction);
  178. DLLEXPORT void setIntersectionShaderFunction(
  179. DX12ShaderFunction* zIntersectionShaderFunction);
  180. DLLEXPORT void setPayloadSize(int payloadSize);
  181. DLLEXPORT void setAttributeSize(int attributeSize);
  182. DLLEXPORT const Text& getName() const;
  183. DLLEXPORT DX12ShaderFunction* zClosestHitShaderFunction() const;
  184. DLLEXPORT DX12ShaderFunction* zAnyHitShaderFunction() const;
  185. DLLEXPORT DX12ShaderFunction* zIntersectionShaderFunction() const;
  186. DLLEXPORT int getPayloadSize() const;
  187. DLLEXPORT int getAttributeSize() const;
  188. DLLEXPORT D3D12_HIT_GROUP_DESC* zHitGroupDesc() const;
  189. DLLEXPORT DX12ShaderSignature* zSignature() const;
  190. };
  191. class DX12ShaderBindingTable;
  192. class DX12GlobalDescriptorHeap;
  193. class DX12Pipeline : public ReferenceCounter
  194. {
  195. private:
  196. RCArray<DX12Shader> shaders;
  197. RCArray<DX12ShaderHitGroup> hitGroups;
  198. Array<const DX12ShaderFunction*> functionsWithoutHitGroups;
  199. ID3D12RootSignature* emptyGlobalRootSignature;
  200. ID3D12RootSignature* emptyLocalRootSignature;
  201. ID3D12StateObject* pipelineState;
  202. int maxRecursionDepth;
  203. public:
  204. DLLEXPORT DX12Pipeline();
  205. DLLEXPORT ~DX12Pipeline();
  206. DLLEXPORT void addShader(DX12Shader* shader);
  207. DLLEXPORT void addHitGroup(DX12ShaderHitGroup* hitGroup);
  208. DLLEXPORT void setMaxRecursionDepth(int maxRecursionDepth);
  209. DLLEXPORT void createPipelineState(ID3D12Device5* zDevice,
  210. PFN_D3D12_SERIALIZE_ROOT_SIGNATURE pfnD3D12SerializeRootSignature);
  211. DLLEXPORT ID3D12StateObject* zPipelineState() const;
  212. DLLEXPORT DX12ShaderBindingTable* createShaderBindingTable();
  213. DLLEXPORT DX12GlobalDescriptorHeap* createGlobalDescriptorHeap(
  214. DX12DescriptorHeapType type);
  215. DLLEXPORT const RCArray<DX12Shader>& getShaders() const;
  216. DLLEXPORT const Array<const DX12ShaderFunction*>&
  217. getFunctionsWithoutHitGroups() const;
  218. DLLEXPORT const RCArray<DX12ShaderHitGroup>& getHitGroups() const;
  219. }; // namespace Framework
  220. struct DX12ShaderRegisterInput
  221. {
  222. DX12ShaderRegister registerType;
  223. ReferenceCounter*
  224. inputResource; // Can be Texture*, DXBuffer*, or DX12TLAS*
  225. };
  226. class DX12GlobalDescriptorHeap : public ReferenceCounter
  227. {
  228. private:
  229. DX12Pipeline* pipeline;
  230. ID3D12DescriptorHeap* descriptorHeap;
  231. Array<DX12ShaderRegisterInput*> registerInputs;
  232. int lastDescriptorHeapSize;
  233. ID3D12Device5* zDevice;
  234. DX12DescriptorHeapType type;
  235. bool heapChanged;
  236. public:
  237. DX12GlobalDescriptorHeap(
  238. DX12Pipeline* pipeline, DX12DescriptorHeapType type);
  239. ~DX12GlobalDescriptorHeap();
  240. private:
  241. DLLEXPORT void addInput(
  242. DX12ShaderRegister type, ReferenceCounter* inputResource);
  243. public:
  244. DLLEXPORT void addTextureInput(
  245. DX12ShaderRegister type, Texture* zTexture);
  246. DLLEXPORT void updateTextureInput(
  247. int heapIndex, DX12ShaderRegister type, Texture* zTexture);
  248. DLLEXPORT void addBufferInput(
  249. DX12ShaderRegister type, DXBuffer* zBuffer);
  250. DLLEXPORT void addTLASInput(DX12ShaderRegister type, DX12TLAS* zTLAS);
  251. DLLEXPORT void updateTLASInput(
  252. int heapIndex, DX12ShaderRegister type, DX12TLAS* zTLAS);
  253. DLLEXPORT void addSamplerInput(DX12SamplerState* zSampler);
  254. DLLEXPORT void updateDescriptorHeap(ID3D12Device5* zDevice);
  255. DLLEXPORT DX12Pipeline* zPipeline() const;
  256. DLLEXPORT ID3D12DescriptorHeap* zDescriptorHeap() const;
  257. DLLEXPORT void setHeapChanged(bool changed);
  258. DLLEXPORT bool wasHeapChanged() const;
  259. };
  260. class DX12ShaderBindingTable : public ReferenceCounter
  261. {
  262. private:
  263. DX12Pipeline* pipeline;
  264. DX12Buffer* shaderBindingTableBuffer;
  265. DX12GlobalDescriptorHeap* globalDescriptorHeap;
  266. DX12GlobalDescriptorHeap* textureDescriptorHeap;
  267. DX12GlobalDescriptorHeap* samplerDescriptorHeap;
  268. int rayGenRecordSize;
  269. int rayGenCount;
  270. int missRecordSize;
  271. int missCount;
  272. int callableRecordSize;
  273. int callableCount;
  274. int hitGroupRecordSize;
  275. int hitGroupCount;
  276. char* tableBuffer;
  277. int tableBufferSize;
  278. Array<char*> tempBuffers;
  279. int nextHitGroupOffset;
  280. ID3D12StateObjectProperties* stateObjectProperties;
  281. public:
  282. DLLEXPORT DX12ShaderBindingTable(DX12Pipeline* pipeline);
  283. DLLEXPORT ~DX12ShaderBindingTable();
  284. DLLEXPORT void setGlobalDescriptorHeap(
  285. DX12GlobalDescriptorHeap* zGlobalDescriptorHeap);
  286. DLLEXPORT void setTextureDescriptorHeap(
  287. DX12GlobalDescriptorHeap* zTextureDescriptorHeap);
  288. DLLEXPORT void setSamplerDescriptorHeap(
  289. DX12GlobalDescriptorHeap* zSamplerDescriptorHeap);
  290. DLLEXPORT void startUpdate();
  291. private:
  292. DLLEXPORT void set(int index, void* data, int size);
  293. public:
  294. /**
  295. * sets inputs for shader outside of any hit groups for the current
  296. * update of the shader binding table.
  297. *
  298. * \param zFunction the sample shader function for which the inputs are
  299. * set. The function must be part of the pipeline.
  300. * \param offsetPointer pointer for the offset in the shader binding
  301. * table witch was obtained by adding the register usage to the
  302. * segnature of the shader function by calling
  303. * DX12ShaderSignature::addRegisterUsageLinkedToShaderBindingTable.
  304. * \param gpuAddress the parameter to be placed in the shader binding
  305. * table for this input. This is usually the GPU address of a buffer or
  306. * texture.
  307. */
  308. DLLEXPORT void setShaderInput(DX12ShaderFunction* zFunction,
  309. int* offsetPointer,
  310. __int64 gpuAddress);
  311. /**
  312. * adds a hit group to the current update of the shader binding table.
  313. * each hit group mus be readded for each update of the shader binding
  314. * table.
  315. *
  316. * \param zHitGroup the hit group to be added. The hit group must be
  317. * part of the pipeline.
  318. * \param lastIndex the index of the hit group when it was added at the
  319. * last frame
  320. * \return the index of the hit group in the shader binding table. This
  321. * index can be used to set the inputs for this hit group by calling
  322. * setHitGroupShaderInput.
  323. */
  324. DLLEXPORT int addHitGroup(
  325. DX12ShaderHitGroup* zHitGroup, int lastIndex = -1);
  326. /**
  327. * sets a specific input for a previously added hitgroup.
  328. *
  329. * \param hitGroupOffset the hit group offset returned by addHitGroup
  330. * for the hit group for which the input is set.
  331. * \param offsetPointer pointer for the offset in the shader binding
  332. * table witch was obtained by adding the register usage to the
  333. * segnature of the shader function by calling
  334. * DX12ShaderSignature::addRegisterUsageLinkedToShaderBindingTable.
  335. * \param gpuAddress the parameter to be placed in the shader binding
  336. * table for this input. This is usually the GPU address of a buffer or
  337. * texture.
  338. */
  339. DLLEXPORT void setHitGroupShaderInput(
  340. int hitGroupOffset, int* offsetPointer, __int64 gpuAddress);
  341. DLLEXPORT void endUpdate(
  342. ID3D12Device5* zDevice, DX12CommandQueue* zQueue);
  343. DLLEXPORT void fillDispatchRaysDesc(
  344. D3D12_DISPATCH_RAYS_DESC* dispatchRaysDesc);
  345. DLLEXPORT DX12Pipeline* zPipeline() const;
  346. };
  347. } // namespace Framework