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