Files
XCEngine/docs/api/XCEngine/RHI/D3D12/D3D12DescriptorSet/D3D12DescriptorSet.md

3.2 KiB
Raw Blame History

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 真正需要的绑定形式。

生命周期

  1. D3D12DescriptorHeap 调用 Initialize
  2. 通过 UpdateUpdateSamplerWriteConstant 写入内容
  3. 在命令列表绑定阶段由 D3D12CommandList 消费
  4. 销毁时调用 Shutdown()

当前实现的真实行为

绑定索引分配

  • 初始化时会复制 layout
  • 只为当前 heap 类型真正可承载的绑定分配 descriptor index
  • 分配顺序不是“按声明原顺序平铺全部绑定”,而是按类型分组:
    • SRV
    • UAV
    • Sampler
  • 每组内部再按 binding 升序排列
  • CBV 不占用 descriptor heap 槽位

常量缓冲策略

  • WriteConstant 只改写 CPU 侧字节缓存,并标记 dirty
  • UploadConstantBuffer 才会真正创建或更新 GPU 侧 upload buffer
  • upload buffer 按 256 字节对齐,这是 D3D12 常量缓冲视图的基本约束
  • 每个 CBV binding 都可能拥有一块独立的 D3D12Buffer

Bind / Unbind 的真实语义

  • Bind 当前是空实现
  • Unbind 当前也是空实现
  • 真正的绑定动作发生在 D3D12CommandList::SetGraphicsDescriptorSets() / SetComputeDescriptorSets()

也就是说,D3D12DescriptorSet 更像“绑定数据容器”,而不是一个会自己把内容推到 GPU pipeline 的主动对象。

线程语义

没有内部锁。更安全的假设是:

  • 更新描述符与写常量发生在提交前、单线程阶段
  • 绑定后不要同时从其他线程修改同一个 set

当前限制

  • Update() 只处理 CBV_SRV_UAV heap 路径
  • UpdateSampler() 只处理 sampler heap 路径
  • Bind() / Unbind() 仍是 no-op
  • 常量缓冲上传是惰性的,只有命令列表绑定阶段显式触发时才会真正落到 GPU 资源

重点公共方法

相关文档