renderer_d3d12.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. /*
  2. * Copyright 2011-2019 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #ifndef BGFX_RENDERER_D3D12_H_HEADER_GUARD
  6. #define BGFX_RENDERER_D3D12_H_HEADER_GUARD
  7. #define USE_D3D12_DYNAMIC_LIB BX_PLATFORM_WINDOWS
  8. #include <sal.h>
  9. #if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
  10. # include <d3d12.h>
  11. #else
  12. # if !BGFX_CONFIG_DEBUG
  13. # define D3DCOMPILE_NO_DEBUG 1
  14. # endif // !BGFX_CONFIG_DEBUG
  15. # include <d3d12_x.h>
  16. #endif // BX_PLATFORM_XBOXONE
  17. #if defined(__MINGW32__) // BK - temp workaround for MinGW until I nuke d3dx12 usage.
  18. extern "C++" {
  19. __extension__ template<typename Ty>
  20. const GUID& __mingw_uuidof();
  21. template<>
  22. const GUID& __mingw_uuidof<ID3D12Device>()
  23. {
  24. static const GUID IID_ID3D12Device0 = { 0x189819f1, 0x1db6, 0x4b57, { 0xbe, 0x54, 0x18, 0x21, 0x33, 0x9b, 0x85, 0xf7 } };
  25. return IID_ID3D12Device0;
  26. }
  27. }
  28. #endif // defined(__MINGW32__)
  29. BX_PRAGMA_DIAGNOSTIC_PUSH();
  30. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wmissing-field-initializers");
  31. #if BX_PLATFORM_XBOXONE
  32. # include <d3dx12_x.h>
  33. #else
  34. # include <d3dx12.h>
  35. #endif // BX_PLATFORM_XBOXONE
  36. BX_PRAGMA_DIAGNOSTIC_POP();
  37. #ifndef D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
  38. # define D3D12_TEXTURE_DATA_PITCH_ALIGNMENT 1024
  39. #endif // D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
  40. #include "renderer.h"
  41. #include "renderer_d3d.h"
  42. #include "shader_dxbc.h"
  43. #include "debug_renderdoc.h"
  44. #include "nvapi.h"
  45. #include "dxgi.h"
  46. #if BGFX_CONFIG_DEBUG_PIX
  47. # if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
  48. typedef struct PIXEventsThreadInfo* (WINAPI* PFN_PIX_GET_THREAD_INFO)();
  49. typedef uint64_t (WINAPI* PFN_PIX_EVENTS_REPLACE_BLOCK)(bool _getEarliestTime);
  50. extern PFN_PIX_GET_THREAD_INFO bgfx_PIXGetThreadInfo;
  51. extern PFN_PIX_EVENTS_REPLACE_BLOCK bgfx_PIXEventsReplaceBlock;
  52. # define PIXGetThreadInfo bgfx_PIXGetThreadInfo
  53. # define PIXEventsReplaceBlock bgfx_PIXEventsReplaceBlock
  54. # else
  55. extern "C" struct PIXEventsThreadInfo* WINAPI bgfx_PIXGetThreadInfo();
  56. extern "C" uint64_t WINAPI bgfx_PIXEventsReplaceBlock(bool _getEarliestTime);
  57. # endif // BX_PLATFORM_WINDOWS
  58. # include <pix3.h>
  59. # define _PIX3_BEGINEVENT(_commandList, _color, _name) PIXBeginEvent(_commandList, _color, _name)
  60. # define _PIX3_SETMARKER(_commandList, _color, _name) PIXSetMarker(_commandList, _color, _name)
  61. # define _PIX3_ENDEVENT(_commandList) PIXEndEvent(_commandList)
  62. # define PIX3_BEGINEVENT(_commandList, _color, _name) _PIX3_BEGINEVENT(_commandList, _color, _name)
  63. # define PIX3_SETMARKER(_commandList, _color, _name) _PIX3_SETMARKER(_commandList, _color, _name)
  64. # define PIX3_ENDEVENT(_commandList) _PIX3_ENDEVENT(_commandList)
  65. #else
  66. # define PIX3_BEGINEVENT(_commandList, _color, _name) BX_UNUSED(_commandList, _color, _name)
  67. # define PIX3_SETMARKER(_commandList, _color, _name) BX_UNUSED(_commandList, _color, _name)
  68. # define PIX3_ENDEVENT(_commandList) BX_UNUSED(_commandList)
  69. #endif // BGFX_CONFIG_DEBUG_PIX
  70. namespace bgfx { namespace d3d12
  71. {
  72. typedef HRESULT (WINAPI* PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(uint32_t _numFeatures, const IID* _iids, void* _configurationStructs, uint32_t* _configurationStructSizes);
  73. struct Rdt
  74. {
  75. enum Enum
  76. {
  77. Sampler,
  78. SRV,
  79. CBV,
  80. UAV,
  81. Count
  82. };
  83. };
  84. class ScratchBufferD3D12
  85. {
  86. public:
  87. ScratchBufferD3D12()
  88. {
  89. }
  90. ~ScratchBufferD3D12()
  91. {
  92. }
  93. void create(uint32_t _size, uint32_t _maxDescriptors);
  94. void destroy();
  95. void reset(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle);
  96. void allocEmpty(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle);
  97. void* allocCbv(D3D12_GPU_VIRTUAL_ADDRESS& _gpuAddress, uint32_t _size);
  98. void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint8_t _mip = 0);
  99. void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct BufferD3D12& _buffer);
  100. void allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint8_t _mip = 0);
  101. void allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct BufferD3D12& _buffer);
  102. ID3D12DescriptorHeap* getHeap()
  103. {
  104. return m_heap;
  105. }
  106. private:
  107. ID3D12DescriptorHeap* m_heap;
  108. ID3D12Resource* m_upload;
  109. D3D12_GPU_VIRTUAL_ADDRESS m_gpuVA;
  110. D3D12_CPU_DESCRIPTOR_HANDLE m_cpuHandle;
  111. D3D12_GPU_DESCRIPTOR_HANDLE m_gpuHandle;
  112. uint32_t m_incrementSize;
  113. uint8_t* m_data;
  114. uint32_t m_size;
  115. uint32_t m_pos;
  116. };
  117. class DescriptorAllocatorD3D12
  118. {
  119. public:
  120. DescriptorAllocatorD3D12()
  121. : m_numDescriptorsPerBlock(1)
  122. {
  123. }
  124. ~DescriptorAllocatorD3D12()
  125. {
  126. }
  127. void create(D3D12_DESCRIPTOR_HEAP_TYPE _type, uint16_t _maxDescriptors, uint16_t _numDescriptorsPerBlock = 1);
  128. void destroy();
  129. uint16_t alloc(ID3D12Resource* _ptr, const D3D12_SHADER_RESOURCE_VIEW_DESC* _desc);
  130. uint16_t alloc(const uint32_t* _flags, uint32_t _num, const float _palette[][4]);
  131. void free(uint16_t _handle);
  132. void reset();
  133. D3D12_GPU_DESCRIPTOR_HANDLE get(uint16_t _handle);
  134. ID3D12DescriptorHeap* getHeap()
  135. {
  136. return m_heap;
  137. }
  138. private:
  139. ID3D12DescriptorHeap* m_heap;
  140. bx::HandleAlloc* m_handleAlloc;
  141. D3D12_CPU_DESCRIPTOR_HANDLE m_cpuHandle;
  142. D3D12_GPU_DESCRIPTOR_HANDLE m_gpuHandle;
  143. uint32_t m_incrementSize;
  144. uint16_t m_numDescriptorsPerBlock;
  145. };
  146. struct BufferD3D12
  147. {
  148. BufferD3D12()
  149. : m_ptr(NULL)
  150. , m_state(D3D12_RESOURCE_STATE_COMMON)
  151. , m_size(0)
  152. , m_flags(BGFX_BUFFER_NONE)
  153. , m_dynamic(false)
  154. {
  155. }
  156. void create(uint32_t _size, void* _data, uint16_t _flags, bool _vertex, uint32_t _stride = 0);
  157. void update(ID3D12GraphicsCommandList* _commandList, uint32_t _offset, uint32_t _size, void* _data, bool _discard = false);
  158. void destroy();
  159. D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
  160. D3D12_SHADER_RESOURCE_VIEW_DESC m_srvd;
  161. D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
  162. ID3D12Resource* m_ptr;
  163. D3D12_GPU_VIRTUAL_ADDRESS m_gpuVA;
  164. D3D12_RESOURCE_STATES m_state;
  165. uint32_t m_size;
  166. uint16_t m_flags;
  167. bool m_dynamic;
  168. };
  169. struct VertexBufferD3D12 : public BufferD3D12
  170. {
  171. void create(uint32_t _size, void* _data, VertexDeclHandle _declHandle, uint16_t _flags);
  172. VertexDeclHandle m_decl;
  173. };
  174. struct ShaderD3D12
  175. {
  176. ShaderD3D12()
  177. : m_code(NULL)
  178. , m_constantBuffer(NULL)
  179. , m_hash(0)
  180. , m_numUniforms(0)
  181. , m_numPredefined(0)
  182. {
  183. }
  184. void create(const Memory* _mem);
  185. void destroy()
  186. {
  187. if (NULL != m_constantBuffer)
  188. {
  189. UniformBuffer::destroy(m_constantBuffer);
  190. m_constantBuffer = NULL;
  191. }
  192. m_numPredefined = 0;
  193. if (NULL != m_code)
  194. {
  195. release(m_code);
  196. m_code = NULL;
  197. m_hash = 0;
  198. }
  199. }
  200. const Memory* m_code;
  201. UniformBuffer* m_constantBuffer;
  202. PredefinedUniform m_predefined[PredefinedUniform::Count];
  203. uint16_t m_attrMask[Attrib::Count];
  204. uint32_t m_hash;
  205. uint16_t m_numUniforms;
  206. uint16_t m_size;
  207. uint8_t m_numPredefined;
  208. };
  209. struct ProgramD3D12
  210. {
  211. ProgramD3D12()
  212. : m_vsh(NULL)
  213. , m_fsh(NULL)
  214. {
  215. }
  216. void create(const ShaderD3D12* _vsh, const ShaderD3D12* _fsh)
  217. {
  218. BX_CHECK(NULL != _vsh->m_code, "Vertex shader doesn't exist.");
  219. m_vsh = _vsh;
  220. bx::memCopy(&m_predefined[0], _vsh->m_predefined, _vsh->m_numPredefined*sizeof(PredefinedUniform));
  221. m_numPredefined = _vsh->m_numPredefined;
  222. if (NULL != _fsh)
  223. {
  224. BX_CHECK(NULL != _fsh->m_code, "Fragment shader doesn't exist.");
  225. m_fsh = _fsh;
  226. bx::memCopy(&m_predefined[m_numPredefined], _fsh->m_predefined, _fsh->m_numPredefined*sizeof(PredefinedUniform));
  227. m_numPredefined += _fsh->m_numPredefined;
  228. }
  229. }
  230. void destroy()
  231. {
  232. m_numPredefined = 0;
  233. m_vsh = NULL;
  234. m_fsh = NULL;
  235. }
  236. const ShaderD3D12* m_vsh;
  237. const ShaderD3D12* m_fsh;
  238. PredefinedUniform m_predefined[PredefinedUniform::Count * 2];
  239. uint8_t m_numPredefined;
  240. };
  241. struct TextureD3D12
  242. {
  243. enum Enum
  244. {
  245. Texture2D,
  246. Texture3D,
  247. TextureCube,
  248. };
  249. TextureD3D12()
  250. : m_ptr(NULL)
  251. , m_directAccessPtr(NULL)
  252. , m_state(D3D12_RESOURCE_STATE_COMMON)
  253. , m_numMips(0)
  254. {
  255. bx::memSet(&m_srvd, 0, sizeof(m_srvd) );
  256. bx::memSet(&m_uavd, 0, sizeof(m_uavd) );
  257. }
  258. void* create(const Memory* _mem, uint64_t _flags, uint8_t _skip);
  259. void destroy();
  260. void update(ID3D12GraphicsCommandList* _commandList, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem);
  261. void resolve(uint8_t _resolve) const;
  262. D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, D3D12_RESOURCE_STATES _state);
  263. D3D12_SHADER_RESOURCE_VIEW_DESC m_srvd;
  264. D3D12_UNORDERED_ACCESS_VIEW_DESC m_uavd;
  265. ID3D12Resource* m_ptr;
  266. void* m_directAccessPtr;
  267. D3D12_RESOURCE_STATES m_state;
  268. uint64_t m_flags;
  269. uint32_t m_width;
  270. uint32_t m_height;
  271. uint32_t m_depth;
  272. uint16_t m_samplerIdx;
  273. uint8_t m_type;
  274. uint8_t m_requestedFormat;
  275. uint8_t m_textureFormat;
  276. uint8_t m_numMips;
  277. };
  278. struct FrameBufferD3D12
  279. {
  280. FrameBufferD3D12()
  281. : m_swapChain(NULL)
  282. , m_nwh(NULL)
  283. , m_width(0)
  284. , m_height(0)
  285. , m_denseIdx(UINT16_MAX)
  286. , m_num(0)
  287. , m_numTh(0)
  288. , m_state(D3D12_RESOURCE_STATE_PRESENT)
  289. , m_needPresent(false)
  290. {
  291. m_depth.idx = bgfx::kInvalidHandle;
  292. }
  293. void create(uint8_t _num, const Attachment* _attachment);
  294. void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat);
  295. uint16_t destroy();
  296. HRESULT present(uint32_t _syncInterval, uint32_t _flags);
  297. void preReset();
  298. void postReset();
  299. void resolve();
  300. void clear(ID3D12GraphicsCommandList* _commandList, const Clear& _clear, const float _palette[][4], const D3D12_RECT* _rect = NULL, uint32_t _num = 0);
  301. D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, uint8_t _idx, D3D12_RESOURCE_STATES _state);
  302. TextureHandle m_texture[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
  303. TextureHandle m_depth;
  304. Dxgi::SwapChainI* m_swapChain;
  305. void* m_nwh;
  306. uint32_t m_width;
  307. uint32_t m_height;
  308. uint16_t m_denseIdx;
  309. uint8_t m_num;
  310. uint8_t m_numTh;
  311. Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
  312. D3D12_RESOURCE_STATES m_state;
  313. bool m_needPresent;
  314. };
  315. struct CommandQueueD3D12
  316. {
  317. CommandQueueD3D12()
  318. : m_currentFence(0)
  319. , m_completedFence(0)
  320. , m_control(BX_COUNTOF(m_commandList) )
  321. {
  322. BX_STATIC_ASSERT(BX_COUNTOF(m_commandList) == BX_COUNTOF(m_release) );
  323. }
  324. void init(ID3D12Device* _device);
  325. void shutdown();
  326. ID3D12GraphicsCommandList* alloc();
  327. uint64_t kick();
  328. void finish(uint64_t _waitFence = UINT64_MAX, bool _finishAll = false);
  329. bool tryFinish(uint64_t _waitFence);
  330. void release(ID3D12Resource* _ptr);
  331. bool consume(uint32_t _ms = INFINITE);
  332. struct CommandList
  333. {
  334. ID3D12GraphicsCommandList* m_commandList;
  335. ID3D12CommandAllocator* m_commandAllocator;
  336. HANDLE m_event;
  337. };
  338. ID3D12CommandQueue* m_commandQueue;
  339. uint64_t m_currentFence;
  340. uint64_t m_completedFence;
  341. ID3D12Fence* m_fence;
  342. CommandList m_commandList[256];
  343. typedef stl::vector<ID3D12Resource*> ResourceArray;
  344. ResourceArray m_release[256];
  345. bx::RingBufferControl m_control;
  346. };
  347. struct BatchD3D12
  348. {
  349. enum Enum
  350. {
  351. Draw,
  352. DrawIndexed,
  353. Count
  354. };
  355. BatchD3D12()
  356. : m_currIndirect(0)
  357. , m_maxDrawPerBatch(0)
  358. , m_minIndirect(0)
  359. , m_flushPerBatch(0)
  360. {
  361. bx::memSet(m_num, 0, sizeof(m_num) );
  362. }
  363. ~BatchD3D12()
  364. {
  365. }
  366. void create(uint32_t _maxDrawPerBatch);
  367. void destroy();
  368. template<typename Ty>
  369. Ty& getCmd(Enum _type);
  370. uint32_t draw(ID3D12GraphicsCommandList* _commandList, D3D12_GPU_VIRTUAL_ADDRESS _cbv, const RenderDraw& _draw);
  371. void flush(ID3D12GraphicsCommandList* _commandList, Enum _type);
  372. void flush(ID3D12GraphicsCommandList* _commandList, bool _clean = false);
  373. void begin();
  374. void end(ID3D12GraphicsCommandList* _commandList);
  375. void setSeqMode(bool _enabled)
  376. {
  377. m_flushPerBatch = _enabled ? 1 : m_maxDrawPerBatch;
  378. }
  379. void setIndirectMode(bool _enabled)
  380. {
  381. m_minIndirect = _enabled ? 64 : UINT32_MAX;
  382. }
  383. ID3D12CommandSignature* m_commandSignature[Count];
  384. uint32_t m_num[Count];
  385. void* m_cmds[Count];
  386. struct DrawIndirectCommand
  387. {
  388. D3D12_VERTEX_BUFFER_VIEW vbv[BGFX_CONFIG_MAX_VERTEX_STREAMS + 1 /* instanced buffer */];
  389. D3D12_GPU_VIRTUAL_ADDRESS cbv;
  390. D3D12_DRAW_ARGUMENTS args;
  391. };
  392. struct DrawIndexedIndirectCommand
  393. {
  394. D3D12_VERTEX_BUFFER_VIEW vbv[BGFX_CONFIG_MAX_VERTEX_STREAMS + 1 /* instanced buffer */];
  395. D3D12_INDEX_BUFFER_VIEW ibv;
  396. D3D12_GPU_VIRTUAL_ADDRESS cbv;
  397. D3D12_DRAW_INDEXED_ARGUMENTS args;
  398. };
  399. struct Stats
  400. {
  401. uint32_t m_numImmediate[Count];
  402. uint32_t m_numIndirect[Count];
  403. };
  404. BufferD3D12 m_indirect[32];
  405. uint32_t m_currIndirect;
  406. DrawIndexedIndirectCommand m_current;
  407. Stats m_stats;
  408. uint32_t m_maxDrawPerBatch;
  409. uint32_t m_minIndirect;
  410. uint32_t m_flushPerBatch;
  411. };
  412. struct TimerQueryD3D12
  413. {
  414. TimerQueryD3D12()
  415. : m_control(BX_COUNTOF(m_query) )
  416. {
  417. }
  418. void init();
  419. void shutdown();
  420. uint32_t begin(uint32_t _resultIdx);
  421. void end(uint32_t _idx);
  422. bool update();
  423. struct Query
  424. {
  425. uint32_t m_resultIdx;
  426. bool m_ready;
  427. uint64_t m_fence;
  428. };
  429. struct Result
  430. {
  431. void reset()
  432. {
  433. m_begin = 0;
  434. m_end = 0;
  435. m_pending = 0;
  436. }
  437. uint64_t m_begin;
  438. uint64_t m_end;
  439. uint32_t m_pending;
  440. };
  441. uint64_t m_frequency;
  442. Result m_result[BGFX_CONFIG_MAX_VIEWS+1];
  443. Query m_query[BGFX_CONFIG_MAX_VIEWS*4];
  444. ID3D12Resource* m_readback;
  445. ID3D12QueryHeap* m_queryHeap;
  446. uint64_t* m_queryResult;
  447. bx::RingBufferControl m_control;
  448. };
  449. struct OcclusionQueryD3D12
  450. {
  451. OcclusionQueryD3D12()
  452. : m_control(BX_COUNTOF(m_handle) )
  453. {
  454. }
  455. void init();
  456. void shutdown();
  457. void begin(ID3D12GraphicsCommandList* _commandList, Frame* _render, OcclusionQueryHandle _handle);
  458. void end(ID3D12GraphicsCommandList* _commandList);
  459. void invalidate(OcclusionQueryHandle _handle);
  460. ID3D12Resource* m_readback;
  461. ID3D12QueryHeap* m_queryHeap;
  462. OcclusionQueryHandle m_handle[BGFX_CONFIG_MAX_OCCLUSION_QUERIES];
  463. uint64_t* m_result;
  464. bx::RingBufferControl m_control;
  465. };
  466. } /* namespace d3d12 */ } // namespace bgfx
  467. #endif // BGFX_RENDERER_D3D12_H_HEADER_GUARD