3.4 KiB
3.4 KiB
OpenGLPipelineLayout
命名空间: XCEngine::RHI
类型: class
头文件: XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h
描述: OpenGL 后端的 pipeline layout 适配对象,负责把现代 RHI 的 set + binding 资源布局翻译成 OpenGL 的全局 binding point。
概览
OpenGL 不存在真正的原生 pipeline layout,也不会像 Vulkan 那样把不同资源先按 descriptor set 分组,再按 binding 解析。它更接近这种模型:
- UBO 有自己的全局 binding 空间
- 纹理采样单元有自己的全局 binding 空间
- image unit 有自己的全局 binding 空间
- sampler object 也依赖自己的编号体系
OpenGLPipelineLayout 的职责,就是把上层更现代的 setIndex + binding 描述,压平成这些 OpenGL 能直接消费的编号。
为什么要这样设计
这是商业引擎里很典型的跨后端适配策略:
- 上层材质系统、命令列表、descriptor set 代码继续沿用统一的 set/binding 语义
- OpenGL 后端把“不存在的原生 layout 对象”降级成一份 CPU 侧翻译表
- 这样既保留了 API 设计的一致性,也避免了让整个引擎为了 OpenGL 倒退回裸 binding 编号风格
这类对象本质上不是 GPU 资源,而是“绑定规则元数据”。
当前实现的真实行为
- Initialize 总是返回
true - 存在两种工作模式:
- set-aware 模式
- flat 模式
- set-aware 模式下会深拷贝 set layout 和 binding 数组
- 同一 descriptor 类型内部,binding point 会跨 set 全局递增
- 映射分配前会按 binding 编号排序
binding.count == 0时,当前算法仍会为其预留1个槽位- flat 模式下,只有
setIndex == 0被视为有效 - GetNativeHandle 返回
this或nullptr
与其他模块的关系
- OpenGLDevice 通过
CreatePipelineLayout(...)创建它 - OpenGLCommandList 在设置 graphics/compute descriptor set 时把它传下去
- OpenGLDescriptorSet 在
BindWithPipelineLayout(...)中用它把逻辑 binding 解析成真正的 OpenGL binding point
生命周期
- OpenGLPipelineLayout() 初始化为空对象
- Initialize 构建描述缓存与映射表
- 运行时通过一系列
Has*Binding()/Get*BindingPoint()查询 - Shutdown 清空内部缓存并把对象标记为未初始化
当前限制
- 不对应 OpenGL 原生对象
- 不校验 shader 里是否真的声明了这些 binding
- 不使用 stage visibility 做裁剪
- flat 模式下的
Has*Binding()只做setIndex == 0判断,不做更严格的 binding 越界验证 GetDesc()暴露的是内部缓存引用,调用方需要注意生命周期
关键方法
- Initialize
- UsesSetLayouts
- HasConstantBufferBinding
- GetConstantBufferBindingPoint
- GetShaderResourceBindingPoint
- GetUnorderedAccessBindingPoint
- GetSamplerBindingPoint