4.5 KiB
4.5 KiB
OpenGLBuffer
命名空间: XCEngine::RHI
类型: class
头文件: XCEngine/RHI/OpenGL/OpenGLBuffer.h
描述: OpenGL 后端的通用缓冲区封装,负责创建原生 buffer 对象,并在引擎侧缓存一部分跨后端元数据。
概览
OpenGLBuffer 是 OpenGL RHI 里最基础的资源包装之一。它做的事情其实很直接:
- 按指定
OpenGLBufferType创建一个 OpenGL buffer - 记录大小、动态标记和目标类型
- 提供绑定、映射、更新数据等常见入口
- 额外缓存
BufferType、stride、name、state这类跨后端元数据
从商业引擎的设计视角看,这种“原生对象 + 少量 RHI 元数据”的组合非常常见。原因是底层驱动对象本身只知道“这是一块 buffer”,但上层渲染框架还需要知道它被当作顶点缓冲、索引缓冲、常量缓冲还是别的什么角色来使用。
设计背景
现代显式 API 往往把“资源本体”和“如何使用它”拆得更细。例如 D3D12/Vulkan 里 buffer 的用途、状态和 view 往往由更多配套对象共同表达。OpenGL 则更多依赖“把同一个 buffer 绑定到不同 target”来体现用途。
OpenGLBuffer 的策略是:
- 用
OpenGLBufferType决定当前 buffer 的主要 OpenGL 绑定目标。 - 用
BufferType、stride、state等字段补充跨后端语义。
这样做的好处是接口统一,上层代码比较容易跨后端复用;代价是调用方必须清楚地区分“OpenGL 原生目标”和“RHI 语义元数据”不是同一个概念。
OpenGLBufferType 与绑定目标
当前枚举和 ToOpenGL(OpenGLBufferType) 的映射关系如下:
Vertex->GL_ARRAY_BUFFERIndex->GL_ELEMENT_ARRAY_BUFFERUniform->GL_UNIFORM_BUFFERCopyRead->GL_COPY_READ_BUFFERCopyWrite->GL_COPY_WRITE_BUFFERAtomicCounter->GL_ATOMIC_COUNTER_BUFFERDispatchIndirect->GL_DISPATCH_INDIRECT_BUFFERDrawIndirect->GL_DRAW_INDIRECT_BUFFERShaderBindingTable->GL_SHADER_STORAGE_BUFFER
最后这一项尤其值得注意: ShaderBindingTable 在当前 OpenGL 后端并不对应真正的硬件光追 SBT,而是退化映射到了 GL_SHADER_STORAGE_BUFFER。这正是商业级跨后端抽象里常见的做法: 保留统一语义名,但允许某些后端落到“最接近、但不完全等价”的实现。
生命周期
- OpenGLBuffer() 构造空对象。
- Initialize / InitializeVertexBuffer / InitializeIndexBuffer 生成原生 buffer 并上传初始数据。
- Bind、BindBase、Map、SetData 在使用阶段操作该 buffer。
- Shutdown 删除原生 buffer。
- ~OpenGLBuffer() 析构时自动调用
Shutdown()。
当前实现的真实行为
- Initialize 当前始终返回
true,没有显式错误处理或状态回滚。 m_isIndexBuffer会在初始化时根据OpenGLBufferType::Index设置,但当前没有公开 getter,也没有在其他逻辑里继续参与行为。m_bufferType、m_stride、m_name、m_state都不会在初始化时自动推导,需要调用方自行设置。- Map 固定使用
GL_WRITE_ONLY,不支持读映射、持久映射或显式 map flag。 - Unmap 会调用
glUnmapBuffer(),但忽略它的返回值。 - SetData 只有在“整块覆盖且大小等于原始
m_size”时才走glBufferData(),否则走glBufferSubData(),不会做越界检查,也不会更新m_size。 - 单测
tests/RHI/OpenGL/unit/test_buffer.cpp主要覆盖初始化、绑定和写映射路径,没有覆盖复杂错误场景。
使用建议
- 如果你的调用逻辑依赖 RHI 侧的
BufferType、stride或state,请显式设置,不要假设Initialize()会自动填好。 - 如果需要把同一个 buffer 绑定到 indexed target,使用 BindBase 时要明确传入正确的 OpenGL target,函数不会帮你从
m_type推断。 - 当前不要把
ShaderBindingTable视为真正的 OpenGL ray tracing SBT 支持。