1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-11 13:10:58 +00:00

Add descriptor heap pooling to D3D12.

(cherry picked from commit f7fd65923a)
This commit is contained in:
Lukas Rahmann
2025-05-30 10:58:38 +02:00
committed by Thaddeus Crews
parent 11e6e4afef
commit acab46d09e
2 changed files with 355 additions and 84 deletions

View File

@@ -30,6 +30,7 @@
#pragma once
#include "core/templates/a_hash_map.h"
#include "core/templates/hash_map.h"
#include "core/templates/paged_allocator.h"
#include "core/templates/self_list.h"
@@ -133,38 +134,107 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
RenderingShaderContainerFormatD3D12 shader_container_format;
String pipeline_cache_id;
class DescriptorsHeap {
class CPUDescriptorsHeapPool;
struct CPUDescriptorsHeapHandle {
ID3D12DescriptorHeap *heap = nullptr;
CPUDescriptorsHeapPool *pool = nullptr;
uint32_t offset = 0;
uint32_t base_offset = 0;
uint32_t count = 0;
uint32_t nonce = 0;
uint32_t global_offset() const { return offset + base_offset; }
};
class CPUDescriptorsHeapPool {
Mutex mutex;
struct FreeBlockInfo {
ID3D12DescriptorHeap *heap = nullptr;
uint32_t global_offset = 0; // Global offset in an address space shared by all the heaps.
uint32_t base_offset = 0; // The offset inside the space of this heap.
uint32_t size = 0;
uint32_t nonce = 0;
};
struct FreeBlockSortIndexSort {
_FORCE_INLINE_ bool operator()(const uint32_t &p_l, const uint32_t &p_r) const {
return p_l > p_r;
}
};
typedef RBMap<uint32_t, FreeBlockInfo> OffsetTableType;
typedef RBMap<uint32_t, List<uint32_t>, FreeBlockSortIndexSort> SizeTableType;
OffsetTableType free_blocks_by_offset;
SizeTableType free_blocks_by_size;
uint32_t current_offset = 0;
uint32_t current_nonce = 0;
void add_to_size_map(const FreeBlockInfo &p_block);
void remove_from_size_map(const FreeBlockInfo &p_block);
void verify();
public:
Error allocate(ID3D12Device *p_device, const D3D12_DESCRIPTOR_HEAP_DESC &p_desc, CPUDescriptorsHeapHandle &r_result);
Error release(const CPUDescriptorsHeapHandle &p_result);
};
class CPUDescriptorsHeapPools {
CPUDescriptorsHeapPool pools[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
public:
Error allocate(ID3D12Device *p_device, const D3D12_DESCRIPTOR_HEAP_DESC &p_desc, CPUDescriptorsHeapHandle &r_result);
};
struct CPUDescriptorsHeapWalker {
uint32_t handle_size = 0;
uint32_t handle_count = 0;
D3D12_CPU_DESCRIPTOR_HANDLE first_cpu_handle = {};
uint32_t handle_index = 0;
D3D12_CPU_DESCRIPTOR_HANDLE get_curr_cpu_handle();
_FORCE_INLINE_ void rewind() { handle_index = 0; }
void advance(uint32_t p_count = 1);
uint32_t get_current_handle_index() const { return handle_index; }
uint32_t get_free_handles() { return handle_count - handle_index; }
bool is_at_eof() { return handle_index == handle_count; }
};
struct GPUDescriptorsHeapWalker : CPUDescriptorsHeapWalker {
D3D12_GPU_DESCRIPTOR_HANDLE first_gpu_handle = {};
D3D12_GPU_DESCRIPTOR_HANDLE get_curr_gpu_handle();
};
class CPUDescriptorsHeap {
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
CPUDescriptorsHeapHandle handle;
uint32_t handle_size = 0;
public:
CPUDescriptorsHeap() = default;
Error allocate(RenderingDeviceDriverD3D12 *p_driver, D3D12_DESCRIPTOR_HEAP_TYPE p_type, uint32_t p_descriptor_count);
uint32_t get_descriptor_count() const { return desc.NumDescriptors; }
~CPUDescriptorsHeap();
CPUDescriptorsHeapWalker make_walker() const;
};
class GPUDescriptorsHeap {
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
ComPtr<ID3D12DescriptorHeap> heap;
uint32_t handle_size = 0;
public:
class Walker { // Texas Ranger.
friend class DescriptorsHeap;
uint32_t handle_size = 0;
uint32_t handle_count = 0;
D3D12_CPU_DESCRIPTOR_HANDLE first_cpu_handle = {};
D3D12_GPU_DESCRIPTOR_HANDLE first_gpu_handle = {};
uint32_t handle_index = 0;
public:
D3D12_CPU_DESCRIPTOR_HANDLE get_curr_cpu_handle();
D3D12_GPU_DESCRIPTOR_HANDLE get_curr_gpu_handle();
_FORCE_INLINE_ void rewind() { handle_index = 0; }
void advance(uint32_t p_count = 1);
uint32_t get_current_handle_index() const { return handle_index; }
uint32_t get_free_handles() { return handle_count - handle_index; }
bool is_at_eof() { return handle_index == handle_count; }
};
Error allocate(ID3D12Device *m_device, D3D12_DESCRIPTOR_HEAP_TYPE m_type, uint32_t m_descriptor_count, bool p_for_gpu);
Error allocate(RenderingDeviceDriverD3D12 *p_device, D3D12_DESCRIPTOR_HEAP_TYPE p_type, uint32_t p_descriptor_count);
uint32_t get_descriptor_count() const { return desc.NumDescriptors; }
ID3D12DescriptorHeap *get_heap() const { return heap.Get(); }
Walker make_walker() const;
GPUDescriptorsHeapWalker make_walker() const;
};
CPUDescriptorsHeapPools cpu_descriptor_pool;
struct {
ComPtr<ID3D12CommandSignature> draw;
ComPtr<ID3D12CommandSignature> draw_indexed;
@@ -498,8 +568,8 @@ private:
bool is_screen = false;
Size2i size;
TightLocalVector<uint32_t> attachments_handle_inds; // RTV heap index for color; DSV heap index for DSV.
DescriptorsHeap rtv_heap;
DescriptorsHeap dsv_heap; // Used only if not for screen and some depth-stencil attachments.
CPUDescriptorsHeap rtv_heap;
CPUDescriptorsHeap dsv_heap; // Used only for depth-stencil attachments.
TightLocalVector<TextureID> attachments; // Color and depth-stencil. Used if not screen.
TextureID vrs_attachment;
@@ -609,8 +679,8 @@ private:
struct UniformSetInfo {
struct {
DescriptorsHeap resources;
DescriptorsHeap samplers;
CPUDescriptorsHeap resources;
CPUDescriptorsHeap samplers;
} desc_heaps;
struct StateRequirement {
@@ -842,16 +912,16 @@ public:
private:
struct FrameInfo {
struct {
DescriptorsHeap resources;
DescriptorsHeap samplers;
DescriptorsHeap aux;
DescriptorsHeap rtv;
GPUDescriptorsHeap resources;
GPUDescriptorsHeap samplers;
CPUDescriptorsHeap aux;
CPUDescriptorsHeap rtv;
} desc_heaps;
struct {
DescriptorsHeap::Walker resources;
DescriptorsHeap::Walker samplers;
DescriptorsHeap::Walker aux;
DescriptorsHeap::Walker rtv;
GPUDescriptorsHeapWalker resources;
GPUDescriptorsHeapWalker samplers;
CPUDescriptorsHeapWalker aux;
CPUDescriptorsHeapWalker rtv;
} desc_heap_walkers;
struct {
bool resources = false;