#pragma once #include "D3D12CommonHeaders.h" namespace XEngine::graphics::d3d12{ class descriptor_heap; struct descriptor_handle { D3D12_CPU_DESCRIPTOR_HANDLE cpu{}; D3D12_GPU_DESCRIPTOR_HANDLE gpu{}; constexpr bool is_valid() const { return cpu.ptr != 0; } constexpr bool is_shader_visible() const { return gpu.ptr != 0; } #ifdef _DEBUG private: friend class descriptor_heap; descriptor_heap* container{ nullptr }; u32 index{ u32_invalid_id }; #endif }; // descriptor_handle class descriptor_heap { public: explicit descriptor_heap(const D3D12_DESCRIPTOR_HEAP_TYPE type): _type(type){} DISABLE_COPY_AND_MOVE(descriptor_heap); ~descriptor_heap(){assert(!_heap);} bool initialize(u32 capacity, bool is_shader_visible); void release(); [[nodiscard]] descriptor_handle allocate(); void free(descriptor_handle handle); constexpr D3D12_DESCRIPTOR_HEAP_TYPE type() const { return _type; } constexpr D3D12_CPU_DESCRIPTOR_HANDLE cpu_start() const { return _cpu_start; } constexpr D3D12_GPU_DESCRIPTOR_HANDLE gpu_start() const { return _gpu_start; } constexpr ID3D12DescriptorHeap *const heap() const { return _heap; } constexpr u32 capacity() const { return _capacity; } constexpr u32 size() const { return _size; } constexpr u32 descriptor_size() const { return _descriptor_size; } constexpr bool is_shader_visible() const { return _gpu_start.ptr != 0; } private: // 一个描述符堆是一个内存块,基于他是否着色器可见,分配在系统内存还是显存 ID3D12DescriptorHeap* _heap; // CPU起始句柄(用于CPU端描述符操作) D3D12_CPU_DESCRIPTOR_HANDLE _cpu_start{}; // GPU起始句柄(仅当堆为着色器可见时有效) D3D12_GPU_DESCRIPTOR_HANDLE _gpu_start{}; // 空闲的描述符句柄 std::unique_ptr _free_handles{}; // 用于保护资源初始化的互斥锁 std::mutex _mutex; // 描述符堆的容量 u32 _capacity{0}; // 已经分配的描述符数量 u32 _size{0}; // 不同的描述符堆类型在不同的硬件上有不同的大小,所以需要记录下描述符的大小 u32 _descriptor_size{0}; const D3D12_DESCRIPTOR_HEAP_TYPE _type; }; }