3.2 KiB
3.2 KiB
D3D12DescriptorSet
命名空间: XCEngine::RHI
类型: class
头文件: XCEngine/RHI/D3D12/D3D12DescriptorSet.h
描述: D3D12 后端对“descriptor set”抽象的适配层,负责把 layout 绑定映射到 descriptor heap 槽位与 root CBV 上传逻辑。
概览
严格来说,D3D12 并没有 Vulkan 式的原生 descriptor set。D3D12DescriptorSet 的价值在于给跨后端 RHI 提供一个统一的“成组绑定”接口,然后在 D3D12 侧分解成:
- descriptor heap 中的 SRV / UAV / Sampler 段
- root signature 中的 CBV root parameter
- 每个常量绑定独立维护的 upload buffer
这就是它和商业引擎底层“绑定组抽象”的典型相似点:上层继续按 set 思维写代码,后端负责把它拆成 D3D12 真正需要的绑定形式。
生命周期
- 由
D3D12DescriptorHeap调用Initialize - 通过
Update、UpdateSampler、WriteConstant写入内容 - 在命令列表绑定阶段由
D3D12CommandList消费 - 销毁时调用
Shutdown()
当前实现的真实行为
绑定索引分配
- 初始化时会复制 layout
- 只为当前 heap 类型真正可承载的绑定分配 descriptor index
- 分配顺序不是“按声明原顺序平铺全部绑定”,而是按类型分组:
SRVUAVSampler
- 每组内部再按
binding升序排列 CBV不占用 descriptor heap 槽位
常量缓冲策略
WriteConstant只改写 CPU 侧字节缓存,并标记 dirtyUploadConstantBuffer才会真正创建或更新 GPU 侧 upload buffer- upload buffer 按 256 字节对齐,这是 D3D12 常量缓冲视图的基本约束
- 每个
CBVbinding 都可能拥有一块独立的D3D12Buffer
Bind / Unbind 的真实语义
Bind当前是空实现Unbind当前也是空实现- 真正的绑定动作发生在
D3D12CommandList::SetGraphicsDescriptorSets()/SetComputeDescriptorSets()
也就是说,D3D12DescriptorSet 更像“绑定数据容器”,而不是一个会自己把内容推到 GPU pipeline 的主动对象。
线程语义
没有内部锁。更安全的假设是:
- 更新描述符与写常量发生在提交前、单线程阶段
- 绑定后不要同时从其他线程修改同一个 set
当前限制
Update()只处理CBV_SRV_UAVheap 路径UpdateSampler()只处理 sampler heap 路径Bind()/Unbind()仍是 no-op- 常量缓冲上传是惰性的,只有命令列表绑定阶段显式触发时才会真正落到 GPU 资源