144 lines
3.9 KiB
Markdown
144 lines
3.9 KiB
Markdown
|
|
# RHI 模块严重问题:OpenGL 后端 RHI 状态不生效
|
|||
|
|
|
|||
|
|
## 问题严重程度
|
|||
|
|
|
|||
|
|
**严重级别**: 🔴 Critical Bug
|
|||
|
|
|
|||
|
|
## 问题定位
|
|||
|
|
|
|||
|
|
`OpenGLPipelineState` 维护了两套状态系统,但它们之间没有关联。
|
|||
|
|
|
|||
|
|
### 两套状态系统
|
|||
|
|
|
|||
|
|
**RHI 抽象层状态** (`OpenGLPipelineState.h:131-133`):
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
RasterizerDesc m_rasterizerDesc;
|
|||
|
|
BlendDesc m_blendDesc;
|
|||
|
|
DepthStencilStateDesc m_depthStencilDesc;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**OpenGL 特定状态** (`OpenGLPipelineState.h:141-143`):
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
OpenGLDepthStencilState m_glDepthStencilState;
|
|||
|
|
OpenGLBlendState m_glBlendState;
|
|||
|
|
OpenGLRasterizerState m_glRasterizerState;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 问题详述
|
|||
|
|
|
|||
|
|
### RHI 接口设置的状态只存储不生效
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// OpenGLPipelineState.cpp:19-21
|
|||
|
|
void OpenGLPipelineState::SetRasterizerState(const RasterizerDesc& state) {
|
|||
|
|
m_rasterizerDesc = state; // ❌ 只存储到 m_rasterizerDesc
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void OpenGLPipelineState::SetBlendState(const BlendDesc& state) {
|
|||
|
|
m_blendDesc = state; // ❌ 只存储到 m_blendDesc
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void OpenGLPipelineState::SetDepthStencilState(const DepthStencilStateDesc& state) {
|
|||
|
|
m_depthStencilDesc = state; // ❌ 只存储到 m_depthStencilDesc
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Apply() 使用的是另一套状态
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// OpenGLPipelineState.cpp:133-149
|
|||
|
|
void OpenGLPipelineState::ApplyRasterizer() {
|
|||
|
|
if (m_glRasterizerState.cullFaceEnable) { // ✅ 使用的是 m_glRasterizerState
|
|||
|
|
glEnable(GL_CULL_FACE);
|
|||
|
|
glCullFace(static_cast<GLenum>(m_glRasterizerState.cullFace));
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void OpenGLPipelineState::ApplyBlend() {
|
|||
|
|
if (m_glBlendState.blendEnable) { // ✅ 使用的是 m_glBlendState
|
|||
|
|
glEnable(GL_BLEND);
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void OpenGLPipelineState::ApplyDepthStencil() {
|
|||
|
|
if (m_glDepthStencilState.depthTestEnable) { // ✅ 使用的是 m_glDepthStencilState
|
|||
|
|
glEnable(GL_DEPTH_TEST);
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 导致的后果
|
|||
|
|
|
|||
|
|
**通过 RHI 抽象层设置的状态完全不会生效!**
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// 上层代码
|
|||
|
|
RasterizerDesc raster;
|
|||
|
|
raster.cullMode = 2; // 设置剔除模式
|
|||
|
|
pso->SetRasterizerState(raster); // 通过 RHI 接口设置
|
|||
|
|
|
|||
|
|
// 实际渲染时
|
|||
|
|
pso->Bind(); // 调用 ApplyRasterizer()
|
|||
|
|
// ❌ m_glRasterizerState.cullMode 仍然是默认值,不是设置的值!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 对比 D3D12 后端
|
|||
|
|
|
|||
|
|
D3D12 后端正确地在 `CreateD3D12PSO()` 中使用了 RHI 状态:
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// D3D12PipelineState.cpp:157-161
|
|||
|
|
desc.RasterizerState.FillMode = static_cast<D3D12_FILL_MODE>(m_rasterizerDesc.fillMode);
|
|||
|
|
desc.RasterizerState.CullMode = static_cast<D3D12_CULL_MODE>(m_rasterizerDesc.cullMode);
|
|||
|
|
// ✅ 直接使用 m_rasterizerDesc
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 根本原因
|
|||
|
|
|
|||
|
|
OpenGL 后端有两个 `SetRasterizerState` 重载:
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// RHI 接口 - 只存储
|
|||
|
|
void SetRasterizerState(const RasterizerDesc& state);
|
|||
|
|
|
|||
|
|
// OpenGL 特定接口 - 会生效
|
|||
|
|
void SetRasterizerState(const OpenGLRasterizerState& state);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
RHI 接口的实现缺少状态转换逻辑。
|
|||
|
|
|
|||
|
|
## 修复方案
|
|||
|
|
|
|||
|
|
在 `SetRasterizerState(const RasterizerDesc& state)` 中添加转换逻辑:
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
void OpenGLPipelineState::SetRasterizerState(const RasterizerDesc& state) {
|
|||
|
|
m_rasterizerDesc = state;
|
|||
|
|
|
|||
|
|
// 转换到 OpenGL 状态
|
|||
|
|
m_glRasterizerState.cullFaceEnable = (state.cullMode != 0); // CullMode::None
|
|||
|
|
m_glRasterizerState.cullFace = static_cast<CullMode>(state.cullMode);
|
|||
|
|
m_glRasterizerState.frontFace = static_cast<FrontFace>(state.frontFace);
|
|||
|
|
m_glRasterizerState.polygonMode = static_cast<FillMode>(state.fillMode);
|
|||
|
|
m_glRasterizerState.depthClipEnable = state.depthClipEnable;
|
|||
|
|
// ... 其他字段
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
同样需要修复 `SetBlendState` 和 `SetDepthStencilState`。
|
|||
|
|
|
|||
|
|
## 相关文件
|
|||
|
|
|
|||
|
|
- `engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h`
|
|||
|
|
- `engine/src/RHI/OpenGL/OpenGLPipelineState.cpp`
|
|||
|
|
|
|||
|
|
## 影响范围
|
|||
|
|
|
|||
|
|
1. **所有通过 RHI 抽象层设置的状态都不会生效**
|
|||
|
|
2. **OpenGL 集成测试能工作是因为使用了 OpenGL 特定 API**
|
|||
|
|
3. **上层代码如果使用 RHI 接口,行为会与预期不符**
|