DX12Shader.h 15 KB

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