4.5 KiB
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 3 和 7,然后显式调用:
set->Update(7, srv)
并验证只有 binding 7 被更新。
常量数据
这组接口说明当前 RHIDescriptorSet 不只是一个“引用外部 GPU 资源的句柄集合”,它还承担了一层常量数据 staging / dirty tracking 的职责。
布局信息
RHIDescriptorSet 通过以下接口暴露自身布局:
布局描述本身来自 RHITypes 中的:
DescriptorSetLayoutBindingDescriptorSetLayoutDesc
这意味着 set 的资源组织方式在创建时就已由布局确定,而不是运行时自由追加字段。
测试体现出的真实语义
tests/RHI/unit/test_descriptor_set.cpp 很能说明当前实现已经具备哪些行为:
- 可以分配空布局 set,也可以分配带 SRV / Sampler / CBV 的布局
Update()可以写入RHIResourceViewUpdateSampler()可以写入RHISamplerWriteConstant()会分配或更新常量数据,并能通过GetConstantBufferData()/GetConstantBufferSize()读取状态WriteConstant()会把 dirty 标记设为 true,MarkConstantClean()会清掉该标记- OpenGL 路径会按 binding number 执行纹理和 UBO 绑定
- D3D12 路径还存在更底层的 descriptor offset、descriptor index 和常量缓冲上传行为
这说明 RHIDescriptorSet 当前已经不是纸面抽象,而是后端资源绑定机制的真实统一入口。
设计理解
如果参考商业引擎常见做法,这样的 descriptor set 抽象有几个明显好处:
- renderer 可以用统一布局描述去组织材质和 pass 资源
- 后端可以各自把这组绑定映射到 descriptor heap、binding point 或 native layout
- 常量缓冲和资源视图能在同一对象里统一管理修改状态
代价是当前接口也背了一些实现细节:
offset/binding语义不够直观- 既有资源绑定,也有常量缓冲 staging
- 后端差异仍然会在具体行为上暴露出来
生命周期
通常流程是:
- 从 RHIDescriptorPool 分配
- 调用
Update()/UpdateSampler()/WriteConstant()填充数据 - 交给 RHICommandList 或后端绑定路径使用
- 使用结束后 Shutdown 并
delete
公共方法
- Shutdown
- Bind
- Unbind
- Update
- UpdateSampler
- WriteConstant
- GetBindingCount
- GetBindings
- GetConstantBufferData
- GetConstantBufferSize
- IsConstantDirty
- MarkConstantClean