Files
XCEngine/docs/api/XCEngine/RHI/OpenGL/OpenGLBuffer/OpenGLBuffer.md

88 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_BUFFER`
- `Index` -> `GL_ELEMENT_ARRAY_BUFFER`
- `Uniform` -> `GL_UNIFORM_BUFFER`
- `CopyRead` -> `GL_COPY_READ_BUFFER`
- `CopyWrite` -> `GL_COPY_WRITE_BUFFER`
- `AtomicCounter` -> `GL_ATOMIC_COUNTER_BUFFER`
- `DispatchIndirect` -> `GL_DISPATCH_INDIRECT_BUFFER`
- `DrawIndirect` -> `GL_DRAW_INDIRECT_BUFFER`
- `ShaderBindingTable` -> `GL_SHADER_STORAGE_BUFFER`
最后这一项尤其值得注意: `ShaderBindingTable` 在当前 OpenGL 后端并不对应真正的硬件光追 SBT而是退化映射到了 `GL_SHADER_STORAGE_BUFFER`。这正是商业级跨后端抽象里常见的做法: 保留统一语义名,但允许某些后端落到“最接近、但不完全等价”的实现。
## 生命周期
- [OpenGLBuffer()](Constructor.md) 构造空对象。
- [Initialize](Initialize.md) / [InitializeVertexBuffer](InitializeVertexBuffer.md) / [InitializeIndexBuffer](InitializeIndexBuffer.md) 生成原生 buffer 并上传初始数据。
- [Bind](Bind.md)、[BindBase](BindBase.md)、[Map](Map.md)、[SetData](SetData.md) 在使用阶段操作该 buffer。
- [Shutdown](Shutdown.md) 删除原生 buffer。
- [~OpenGLBuffer()](Destructor.md) 析构时自动调用 `Shutdown()`
## 当前实现的真实行为
- [Initialize](Initialize.md) 当前始终返回 `true`,没有显式错误处理或状态回滚。
- `m_isIndexBuffer` 会在初始化时根据 `OpenGLBufferType::Index` 设置,但当前没有公开 getter也没有在其他逻辑里继续参与行为。
- `m_bufferType``m_stride``m_name``m_state` 都不会在初始化时自动推导,需要调用方自行设置。
- [Map](Map.md) 固定使用 `GL_WRITE_ONLY`,不支持读映射、持久映射或显式 map flag。
- [Unmap](Unmap.md) 会调用 `glUnmapBuffer()`,但忽略它的返回值。
- [SetData](SetData.md) 只有在“整块覆盖且大小等于原始 `m_size`”时才走 `glBufferData()`,否则走 `glBufferSubData()`,不会做越界检查,也不会更新 `m_size`
- 单测 `tests/RHI/OpenGL/unit/test_buffer.cpp` 主要覆盖初始化、绑定和写映射路径,没有覆盖复杂错误场景。
## 使用建议
- 如果你的调用逻辑依赖 RHI 侧的 `BufferType``stride``state`,请显式设置,不要假设 `Initialize()` 会自动填好。
- 如果需要把同一个 buffer 绑定到 indexed target使用 [BindBase](BindBase.md) 时要明确传入正确的 OpenGL target函数不会帮你从 `m_type` 推断。
- 当前不要把 `ShaderBindingTable` 视为真正的 OpenGL ray tracing SBT 支持。
## 关键方法
- [Initialize](Initialize.md)
- [Bind](Bind.md)
- [BindBase](BindBase.md)
- [Map](Map.md)
- [SetData](SetData.md)
- [Shutdown](Shutdown.md)
## 相关文档
- [OpenGL](../OpenGL.md)
- [OpenGLEnums](../OpenGLEnums/OpenGLEnums.md)
- [OpenGLCommandList](../OpenGLCommandList/OpenGLCommandList.md)
- [OpenGLVertexArray](../OpenGLVertexArray/OpenGLVertexArray.md)