2026-03-26 16:45:24 +08:00
|
|
|
|
# OpenGLResourceView
|
|
|
|
|
|
|
|
|
|
|
|
**命名空间**: `XCEngine::RHI`
|
|
|
|
|
|
|
|
|
|
|
|
**类型**: `class`
|
|
|
|
|
|
|
|
|
|
|
|
**头文件**: `XCEngine/RHI/OpenGL/OpenGLResourceView.h`
|
|
|
|
|
|
|
2026-03-27 23:33:59 +08:00
|
|
|
|
**描述**: OpenGL 后端统一资源视图对象,把 RHI 层的多种 view 语义映射为纹理、缓冲区、framebuffer 及其绑定元数据。
|
|
|
|
|
|
|
|
|
|
|
|
## 概览
|
|
|
|
|
|
|
|
|
|
|
|
在 D3D12 / Vulkan 里,resource view 往往会自然让人想到独立的 descriptor 或 view object。OpenGL 不是这套模型,它更多依赖:
|
|
|
|
|
|
|
|
|
|
|
|
- 纹理对象本身
|
|
|
|
|
|
- buffer 对象本身
|
|
|
|
|
|
- framebuffer 绑定关系
|
|
|
|
|
|
- texture unit / image unit / uniform buffer binding point
|
|
|
|
|
|
|
|
|
|
|
|
`OpenGLResourceView` 的职责,就是把这些分散的 OpenGL 机制整理成统一的 RHI 视图对象,让上层仍然可以用 `RenderTargetView`、`ShaderResourceView`、`ConstantBufferView` 这类抽象去表达渲染意图。
|
|
|
|
|
|
|
|
|
|
|
|
## 设计定位
|
|
|
|
|
|
|
|
|
|
|
|
它不是“单一原生句柄的薄封装”,而是一个多态视图元数据对象:
|
|
|
|
|
|
|
|
|
|
|
|
- RTV / DSV: 依赖现有 framebuffer,并缓存附件信息
|
|
|
|
|
|
- SRV: 仅保存纹理和格式信息,不立即分配纹理单元
|
|
|
|
|
|
- UAV: 分配纹理单元,并立刻绑定 image texture
|
|
|
|
|
|
- CBV: 分配 uniform buffer binding point
|
|
|
|
|
|
- VB / IB: 只保存 buffer、偏移、步长和格式
|
|
|
|
|
|
|
|
|
|
|
|
这种设计的好处是跨后端接口统一,代价是 `GetNativeHandle()` 的真实含义会随着 `ResourceViewType` 改变。
|
|
|
|
|
|
|
|
|
|
|
|
## 生命周期
|
|
|
|
|
|
|
|
|
|
|
|
- 构造时对象为空,但默认 `m_viewType` 会被初始化成 `RenderTarget`。
|
|
|
|
|
|
- 调用某个 `InitializeAs...` 方法后进入对应视图模式。
|
|
|
|
|
|
- [Shutdown](Shutdown.md) 会释放它占用的 texture unit 或 binding point,并清空缓存元数据。
|
|
|
|
|
|
- 析构时自动调用 `Shutdown()`。
|
|
|
|
|
|
|
|
|
|
|
|
## 线程语义
|
|
|
|
|
|
|
|
|
|
|
|
- 当前实现没有锁。
|
|
|
|
|
|
- 由于涉及 OpenGL 资源和绑定点分配器,应视为依赖渲染线程 / OpenGL 上下文的对象,不适合跨线程并发读写。
|
|
|
|
|
|
|
|
|
|
|
|
## 当前实现的真实行为
|
|
|
|
|
|
|
|
|
|
|
|
- RTV / DSV 不创建独立 OpenGL view object,而是引用已有 `OpenGLFramebuffer` 并缓存 `FramebufferAttachment`。
|
|
|
|
|
|
- SRV 当前只是只读纹理视图元数据,不会立即占用 texture unit。
|
|
|
|
|
|
- UAV 会直接调用 `glBindImageTexture()`,但当前绑定参数是硬编码的 `GL_RGBA8 + mip0 + layer0 + read_write`。
|
|
|
|
|
|
- CBV 通过 `OpenGLUniformBufferManager` 分配绑定点,但当前底层使用 `glBindBufferBase`,不支持范围绑定。
|
|
|
|
|
|
- VB / IB 不创建额外对象,只把 buffer 信息缓存起来供命令列表消费。
|
|
|
|
|
|
- `OpenGLCommandList` 会真实使用这些信息:
|
|
|
|
|
|
- `TransitionBarrier()` 通过 [GetTextureResource](GetTextureResource.md) 更新纹理状态
|
|
|
|
|
|
- `SetRenderTargets()` 通过 framebuffer attachment 重新组装 FBO
|
|
|
|
|
|
- `SetVertexBuffers()` / `SetIndexBuffer()` 读取偏移、步长和格式
|
|
|
|
|
|
|
|
|
|
|
|
## 为什么这样设计
|
|
|
|
|
|
|
|
|
|
|
|
这和商业引擎里常见的“跨后端统一资源视图层”是一致的思路:
|
|
|
|
|
|
|
|
|
|
|
|
- 上层系统可以统一讨论 SRV / UAV / RTV / DSV / CBV
|
|
|
|
|
|
- 底层后端各自用最接近自己的机制去实现
|
|
|
|
|
|
|
|
|
|
|
|
对使用者来说,重要的不是假设所有后端都拥有完全对称的 view 模型,而是清楚知道当前 OpenGL 后端真正落到了哪一层。这个页面就是为了把这种边界说清楚。
|
|
|
|
|
|
|
|
|
|
|
|
## 当前限制
|
|
|
|
|
|
|
|
|
|
|
|
- `GetNativeHandle()` 不是统一类型句柄。
|
|
|
|
|
|
- SRV 不负责即时分配 texture unit。
|
|
|
|
|
|
- UAV 的 image 绑定参数是简化实现,不足以覆盖完整 typed / layered image view 需求。
|
|
|
|
|
|
- CBV 没有实现真正的 offset/size range 绑定。
|
|
|
|
|
|
- 构造后的默认 `GetViewType()` 是 `RenderTarget`,但对象并不有效。
|
|
|
|
|
|
|
|
|
|
|
|
## 关键方法
|
|
|
|
|
|
|
|
|
|
|
|
- [InitializeAsRenderTarget](InitializeAsRenderTarget.md)
|
|
|
|
|
|
- [InitializeAsShaderResource](InitializeAsShaderResource.md)
|
|
|
|
|
|
- [InitializeAsUnorderedAccess](InitializeAsUnorderedAccess.md)
|
|
|
|
|
|
- [InitializeAsConstantBuffer](InitializeAsConstantBuffer.md)
|
|
|
|
|
|
- [IsValid](IsValid.md)
|
|
|
|
|
|
- [Shutdown](Shutdown.md)
|
2026-03-26 16:45:24 +08:00
|
|
|
|
|
|
|
|
|
|
## 相关文档
|
|
|
|
|
|
|
2026-03-27 23:33:59 +08:00
|
|
|
|
- [OpenGL](../OpenGL.md)
|
|
|
|
|
|
- [OpenGLFramebuffer](../OpenGLFramebuffer/OpenGLFramebuffer.md)
|
|
|
|
|
|
- [OpenGLTextureUnitAllocator](../OpenGLTextureUnitAllocator/OpenGLTextureUnitAllocator.md)
|
|
|
|
|
|
- [OpenGLUniformBufferManager](../OpenGLUniformBufferManager/OpenGLUniformBufferManager.md)
|