DX12Shader.h 15 KB

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