Files
XCEngine/docs/api/XCEngine/RHI/RHIDescriptorSet/RHIDescriptorSet.md
2026-03-29 01:36:53 +08:00

4.5 KiB
Raw Blame History

RHIDescriptorSet

命名空间: XCEngine::RHI

类型: class (abstract)

头文件: XCEngine/RHI/RHIDescriptorSet.h

描述: 资源绑定集合对象,负责把 resource view、sampler 和常量数据组织成一组可绑定描述。

角色概述

RHIDescriptorSet 是当前抽象层里对“一组资源绑定”的统一表达。它通常不直接独立创建,而是从 RHIDescriptorPool 中分配出来。

它承担三类职责:

  • 管理布局绑定信息
  • 持有或引用 view / sampler 绑定
  • 维护常量缓冲区的 CPU 侧写入状态

当前接口语义

生命周期与绑定

这说明 descriptor set 在当前抽象里不是单纯静态数据对象,而是允许直接参与绑定/解绑流程。

资源更新

这两个接口分别用于写入资源视图和 sampler。

需要特别注意的是,Update(uint32_t offset, ...) 参数名虽然叫 offset,但从当前测试特别是 OpenGL 路径来看它的现实语义更接近“binding number”而不是“布局数组中的第几个元素”。

例如测试会定义 binding 37,然后显式调用:

  • set->Update(7, srv)

并验证只有 binding 7 被更新。

常量数据

这组接口说明当前 RHIDescriptorSet 不只是一个“引用外部 GPU 资源的句柄集合”,它还承担了一层常量数据 staging / dirty tracking 的职责。

布局信息

RHIDescriptorSet 通过以下接口暴露自身布局:

布局描述本身来自 RHITypes 中的:

  • DescriptorSetLayoutBinding
  • DescriptorSetLayoutDesc

这意味着 set 的资源组织方式在创建时就已由布局确定,而不是运行时自由追加字段。

测试体现出的真实语义

tests/RHI/unit/test_descriptor_set.cpp 很能说明当前实现已经具备哪些行为:

  • 可以分配空布局 set也可以分配带 SRV / Sampler / CBV 的布局
  • Update() 可以写入 RHIResourceView
  • UpdateSampler() 可以写入 RHISampler
  • WriteConstant() 会分配或更新常量数据,并能通过 GetConstantBufferData() / GetConstantBufferSize() 读取状态
  • WriteConstant() 会把 dirty 标记设为 trueMarkConstantClean() 会清掉该标记
  • OpenGL 路径会按 binding number 执行纹理和 UBO 绑定
  • D3D12 路径还存在更底层的 descriptor offset、descriptor index 和常量缓冲上传行为

这说明 RHIDescriptorSet 当前已经不是纸面抽象,而是后端资源绑定机制的真实统一入口。

设计理解

如果参考商业引擎常见做法,这样的 descriptor set 抽象有几个明显好处:

  • renderer 可以用统一布局描述去组织材质和 pass 资源
  • 后端可以各自把这组绑定映射到 descriptor heap、binding point 或 native layout
  • 常量缓冲和资源视图能在同一对象里统一管理修改状态

代价是当前接口也背了一些实现细节:

  • offset / binding 语义不够直观
  • 既有资源绑定,也有常量缓冲 staging
  • 后端差异仍然会在具体行为上暴露出来

生命周期

通常流程是:

  1. RHIDescriptorPool 分配
  2. 调用 Update() / UpdateSampler() / WriteConstant() 填充数据
  3. 交给 RHICommandList 或后端绑定路径使用
  4. 使用结束后 Shutdowndelete

公共方法

相关文档