4.9 KiB
OpenGLEnums
命名空间: XCEngine::RHI
类型: header
头文件: XCEngine/RHI/OpenGL/OpenGLEnums.h
描述: OpenGL 后端的头文件内联映射工具集,负责把跨后端 RHI 枚举和 OpenGL 专用枚举转换成底层 GLenum / GLbitfield / 格式组合。
概览
OpenGLEnums.h 不是“普通的常量头文件”,而是 OpenGL RHI 行为的核心翻译层之一。很多看似分散在 OpenGLTexture、OpenGLBuffer、OpenGLPipelineState、OpenGLRenderTargetView、OpenGLDepthStencilView 里的行为,最终都依赖这里的内联函数完成跨后端语义到 OpenGL 枚举的落地。
从商业引擎的设计角度看,这种集中式映射层非常重要,因为它能把:
- 跨后端统一语义
- 后端特有枚举
- 近似映射和能力退化
明确地放在一个地方管理,而不是散落在每个资源类和命令类里。
映射类别
当前头文件里的内联函数主要覆盖以下几组语义:
- 图元与拓扑:
PrimitiveTopology、PrimitiveType - 深度/模板与混合:
ComparisonFunc、StencilOp、BlendFactor、BlendOp - 纹理与格式:
OpenGLTextureType、OpenGLFormat - Buffer 与顶点输入:
OpenGLBufferType、VertexAttributeType - 渲染目标:
RenderTargetType - 采样与光栅状态:
SamplerWrapMode、SamplerFilter、TextureAddressMode、FilterMode、CullMode、FrontFace、FillMode - 清除与 attachment:
ToOpenGLClearBuffer()、ToOpenGLDepthAttachment()、ToOpenGLStencilAttachment()、ToOpenGLDepthStencilAttachment()、ToOpenGLColorAttachment()
设计意义
这层映射的价值不只是“少写几个 switch”。更关键的是它明确了 OpenGL 后端当前的真实能力边界:
- 哪些枚举能一一对应落地
- 哪些枚举只是近似模拟
- 哪些跨后端概念在 OpenGL 里只能退化表达
这对 API 文档尤其重要,因为用户看到统一 RHI 接口时,很容易默认不同后端的表达能力是完全对称的。OpenGLEnums.h 恰好就是把这种对称性打破并说明白的地方。
需要特别注意的映射
Buffer 角色并不总是“一一对等”
OpenGLBufferType::ShaderBindingTable 当前被映射到 GL_SHADER_STORAGE_BUFFER。这说明 OpenGL 后端保留了统一命名,但实际落地是“最接近的通用存储缓冲表达”,而不是真正的硬件光追 SBT 模型。
OpenGLFormat 只实现了部分格式
ToOpenGLFormat() 当前只显式处理:
R8RG8RG32FRGBA8RGBA16FRGBA32FDepth24Stencil8Depth32F
CompressedDXT1 和 CompressedDXT5 不在当前分支中,最终会落入默认值 GL_RGBA8 / GL_RGBA / GL_UNSIGNED_BYTE。也就是说,相关枚举虽然存在,但当前通用纹理初始化路径并没有实现压缩纹理上传语义。
过滤模式存在能力退化
FilterMode::Anisotropic、FilterMode::ComparisonLinear、FilterMode::ComparisonAnisotropic 等模式,在当前映射里会退化成普通 GL_LINEAR 或 GL_NEAREST。这意味着仅靠这层函数并不能表达完整的各向异性采样或比较采样状态,还需要 sampler 对象和额外参数共同参与。
attachment helper 很直接,但语义后果很大
ToOpenGLDepthAttachment()固定返回GL_DEPTH_ATTACHMENTToOpenGLStencilAttachment()固定返回GL_STENCIL_ATTACHMENTToOpenGLDepthStencilAttachment()固定返回GL_DEPTH_STENCIL_ATTACHMENTToOpenGLColorAttachment(index)返回GL_COLOR_ATTACHMENT0 + index
这类 helper 很薄,但它们直接决定了 framebuffer / view 文档里很多“当前行为为什么是这样”的结论。例如 OpenGLDepthStencilView 当前初始化路径使用的是 ToOpenGLDepthAttachment(),这就是它为何更偏向深度附件而不是完整 depth-stencil attachment 落地的直接来源。
清除位掩码是引擎自定义协议
ToOpenGLClearBuffer(uint32_t buffers) 当前把:
1映射到GL_COLOR_BUFFER_BIT2映射到GL_DEPTH_BUFFER_BIT4映射到GL_STENCIL_BUFFER_BIT
这说明这里不是直接接受 OpenGL 原始位掩码,而是在消费引擎内部约定的自定义 bit mask。
当前实现的整体特点
- 全部是
inline头文件函数,没有独立 cpp 和运行时状态。 - 映射函数本身不做能力探测、不做错误检查。
- 很多地方采用“合理默认值 + 退化映射”策略,而不是追求完全语义对等。
对商业级引擎来说,这种做法是务实且常见的,但前提是文档必须把退化点讲透,否则上层会误把它当成“已经完整支持”。