4.0 KiB
4.0 KiB
OpenGLDescriptorSet
命名空间: XCEngine::RHI
类型: class
头文件: XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h
描述: OpenGL 后端对 RHI descriptor set 抽象的适配层,负责缓存纹理、采样器和常量数据,并在绑定阶段把它们映射到 OpenGL 的全局 binding point。
概述
OpenGL 没有 Vulkan / D3D12 那样原生的 descriptor set 对象,只有全局的 texture unit、sampler slot、UBO binding point 和 image unit。OpenGLDescriptorSet 的职责,就是把引擎上层仍然使用的“按 set / binding 组织资源”工作流,翻译成 OpenGL 能接受的状态切换。
这类设计在商业引擎里很常见: 上层继续按材质、pass、set 来组织资源,后端再根据平台差异落成真正的绑定命令。这样做的好处是:
- 渲染层不需要为 OpenGL 单独改写一套资源绑定模型。
- 同一份 shader / material 代码更容易在 D3D12、Vulkan、OpenGL 之间复用。
OpenGLCommandList可以在 draw / dispatch 前统一消费RHIDescriptorSet。
生命周期
- 由
OpenGLDescriptorPool分配对象,并调用Initialize复制 layout。 - 通过
Update、UpdateSampler、WriteConstant写入资源。 - 图形或计算命令通过
BindWithPipelineLayout把当前 set 映射到实际 GL binding point。 - 销毁前调用
Shutdown释放 texture unit 和内部 UBO。
当前实现的真实行为
layout 与资源分配
- 初始化时会深拷贝
DescriptorSetLayoutDesc。 - 只有
SRV、UAV、Sampler会向OpenGLTextureUnitAllocator申请 unit。 CBV不占用 texture unit,而是共用一个懒上传的 UBO。Initialize()的count参数当前没有被使用,实际以layout.bindingCount为准。
常量缓冲策略
WriteConstant把数据写进一个共享的std::vector<uint8_t>。- 首次绑定前,如果 dirty,则会创建一个单独的
GL_UNIFORM_BUFFER并整块上传。 - 当前实现里所有
CBVbinding 都绑定同一个 UBO 对象。 WriteConstant()的binding参数当前不会切换到“每个 binding 一块独立常量缓冲”的模式,它只是保留了 RHI 级 API 形状。
绑定路径
Bind走“直接使用声明 binding 编号”的旧路径,更接近裸 OpenGL 资源绑定。BindWithPipelineLayout才是OpenGLCommandList::SetGraphicsDescriptorSets()/SetComputeDescriptorSets()使用的主路径。- 该主路径会借助
OpenGLPipelineLayout把set + binding映射到连续的 OpenGL binding point。
当前限制
Update()/UpdateSampler()只更新每个 binding 的第0个元素,未提供数组元素级写入接口。- 纹理绑定路径默认按
GL_TEXTURE_2D处理普通采样纹理,没有根据真实 texture target 细分。 UAV绑定固定使用glBindImageTexture(..., GL_RGBA8),当前没有从 view format 推导 image format。Unbind主要是Bind的对称清理函数,并不完整回滚BindWithPipelineLayout()的重映射结果。
线程语义
- 没有内部锁。
- 更安全的使用方式,是在拥有当前 OpenGL 上下文的线程上完成
Update*()、WriteConstant()和Bind*()。