# 变更记录:描述符堆实现 **提交日期**: 2026-03-30 **提交哈希**: `a03c544` **变更类型**: 功能实现 --- ## 变更概述 本次提交实现了 D3D12 描述符堆(Descriptor Heap)管理类,提供描述符的分配和释放功能,支持多线程安全访问。 ## 新增文件 ### Engine/Graphics/Direct3D12/ | 文件 | 说明 | |------|------| | `D3D12Resources.h` | 描述符句柄和描述符堆类定义 | | `D3D12Resource.cpp` | 描述符堆实现 | ## 修改文件 | 文件 | 变更说明 | |------|----------| | `D3D12Core.h` | 添加 `device()` 函数声明和 `release` 模板函数 | | `D3D12Core.cpp` | 添加 `device()` 函数实现 | | `D3D12CommonHeader.h` | 添加 `` 头文件 | --- ## 技术要点 ### 1. descriptor_handle 结构 ```cpp struct descriptor_handle { D3D12_CPU_DESCRIPTOR_HANDLE cpu{}; // CPU 句柄 D3D12_GPU_DESCRIPTOR_HANDLE gpu{}; // GPU 句柄(着色器可见时有效) constexpr bool is_valid() const { return cpu.ptr != 0; } constexpr bool is_shader_visible() const { return gpu.ptr != 0; } }; ``` **设计要点**: - 封装 CPU 和 GPU 双句柄 - 提供有效性检查方法 - DEBUG 模式下记录容器和索引用于调试 ### 2. descriptor_heap 类 ```cpp class descriptor_heap { public: explicit descriptor_heap(const D3D12_DESCRIPTOR_HEAP_TYPE type); bool initialize(u32 capacity, bool is_shader_visible); void release(); descriptor_handle allocate(); // 分配描述符 void free(descriptor_handle handle); // 释放描述符 // 访问器 constexpr ID3D12DescriptorHeap* heap() const; constexpr D3D12_CPU_DESCRIPTOR_HANDLE cpu_start() const; constexpr D3D12_GPU_DESCRIPTOR_HANDLE gpu_start() const; constexpr bool is_shader_visible() const; private: ID3D12DescriptorHeap* _heap; D3D12_CPU_DESCRIPTOR_HANDLE _cpu_start{}; 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; }; ``` ### 3. 描述符堆类型 | 类型 | 用途 | 着色器可见 | |------|------|------------| | `D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV` | 常量缓冲区、着色器资源、无序访问 | 可选 | | `D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER` | 采样器 | 可选 | | `D3D12_DESCRIPTOR_HEAP_TYPE_RTV` | 渲染目标视图 | 否 | | `D3D12_DESCRIPTOR_HEAP_TYPE_DSV` | 深度模板视图 | 否 | ### 4. 内存模型 ``` ┌─────────────────────────────────────────────────────┐ │ Shader-Visible 描述符堆 (GPU 显存) │ │ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ │ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │...│ │ │ │ │ │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ │ │ ↑ │ │ _cpu_start / _gpu_start │ └─────────────────────────────────────────────────────┘ _free_handles[] = [0, 1, 2, 3, 4, 5, ...] // 空闲索引池 _size = 0 // 已分配数量 ``` ### 5. 分配算法 ```cpp descriptor_handle allocate() { std::lock_guard lock(_mutex); // 线程安全 const u32 index = _free_handles[_size]; // 取空闲索引 const u32 offset = index * _descriptor_size; // 计算偏移 ++_size; // 递增已分配数量 descriptor_handle handle{}; handle.cpu.ptr = _cpu_start.ptr + offset; // CPU 句柄 if(is_shader_visible()) handle.gpu.ptr = _gpu_start.ptr + offset; // GPU 句柄 return handle; } ``` ### 6. 线程安全 ```cpp std::mutex _mutex; // 保护并发访问 // 使用 lock_guard 保护 std::lock_guard lock(_mutex); ``` 描述符堆可能被多个线程并发访问(资源创建/销毁),需要互斥锁保护。 --- ## D3D12Core 扩展 ### 新增 device() 函数 ```cpp // D3D12Core.h ID3D12Device *const device(); // D3D12Core.cpp ID3D12Device *const device() { return main_device; } ``` 提供对 D3D12 设备的访问,用于创建描述符堆等资源。 ### 新增 release 模板函数 ```cpp template constexpr void release(T*& resource) { if(resource) { resource->Release(); resource = nullptr; } } ``` 通用的 COM 对象释放模板,避免代码重复。 --- ## 使用示例 ```cpp // 创建描述符堆 descriptor_heap cbv_srv_heap{D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV}; cbv_srv_heap.initialize(100, true); // 100个描述符,着色器可见 // 分配描述符 descriptor_handle handle = cbv_srv_heap.allocate(); // 创建视图 device->CreateShaderResourceView(texture, &srvDesc, handle.cpu); // 绑定到管线 ID3D12DescriptorHeap* heaps[] = { cbv_srv_heap.heap() }; cmdList->SetDescriptorHeaps(1, heaps); cmdList->SetGraphicsRootDescriptorTable(0, handle.gpu); // 释放描述符 cbv_srv_heap.free(handle); ``` --- ## 后续工作 - [ ] 实现资源类(Texture, Buffer) - [ ] 实现交换链 - [ ] 实现渲染目标视图 --- ## 相关文档 - [D3D12学习Wiki](../wiki/D3D12学习Wiki.md)