Create ISceneManager interface and fix GetSceneManager return type

- Created ISceneManager interface with Editor需要的 SceneManager 方法
- SceneManager now implements ISceneManager
- IEditorContext::GetSceneManager() now returns ISceneManager& instead of void*
- Removed SceneManager::GetSceneManagerConcrete() method
- Updated HierarchyPanel and InspectorPanel to use ISceneManager interface
This commit is contained in:
2026-03-25 16:39:15 +08:00
parent 48d9e0a7d2
commit 605d086bcc
8 changed files with 193 additions and 194 deletions

View File

@@ -0,0 +1,144 @@
# 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 接口,行为会与预期不符**

View File

@@ -1,174 +0,0 @@
# RHI 模块严重问题PipelineState 与 Shader 关系设计混乱
## 问题严重程度
**严重级别**: 🔴 架构级缺陷Critical
## 问题定位
根据核心设计理念:
> - **求同存异**:优先提取 API 共性作为核心抽象
> - **核心约束原则**:面向 D3D12/Vulkan 设计,参考 Unity RHI
当前设计存在一个**根本性的架构缺陷**。
## 问题详述
### `RHIDevice::CreatePipelineState()` 接口设计错误
```cpp
// engine/include/XCEngine/RHI/RHIDevice.h:41
virtual RHIPipelineState* CreatePipelineState(const GraphicsPipelineDesc& desc) = 0;
```
### `GraphicsPipelineDesc` 缺少 Shader 字段
```cpp
// engine/include/XCEngine/RHI/RHITypes.h:309-320
struct GraphicsPipelineDesc {
InputLayoutDesc inputLayout;
RasterizerDesc rasterizerState;
BlendDesc blendState;
DepthStencilStateDesc depthStencilState;
uint32_t topologyType = 0;
uint32_t renderTargetCount = 1;
uint32_t renderTargetFormats[8] = { 0 };
uint32_t depthStencilFormat = 0;
uint32_t sampleCount = 1;
// ❌ 缺少 Shader 字段!
};
```
## 导致的严重后果
### 1. D3D12 PSO 创建后立即无效
```cpp
// engine/src/RHI/D3D12/D3D12Device.cpp:434-444
RHIPipelineState* D3D12Device::CreatePipelineState(const GraphicsPipelineDesc& desc) {
auto* pso = new D3D12PipelineState(m_device.Get());
pso->SetInputLayout(desc.inputLayout);
// ... 设置各种状态
return pso; // ❌ 此时 m_vsBytecode 和 m_psBytecode 都是空的!
}
```
当调用 `EnsureValid()` 时:
```cpp
// engine/src/RHI/D3D12/D3D12PipelineState.cpp:143-146
bool D3D12PipelineState::CreateD3D12PSO() {
if (!m_vsBytecode.pShaderBytecode || !m_psBytecode.pShaderBytecode) {
return false; // ❌ 直接失败!
}
// ...
}
```
### 2. 后端行为不一致,违反"求同存异"原则
| 后端 | `CreatePipelineState()` 返回后 `IsValid()` |
|------|------------------------------------------|
| D3D12 | `false` (需要额外设置 shader) |
| OpenGL | `true` (OpenGL 不需要预编译 PSO) |
这完全违反了核心设计原则。
### 3. 运行时状态污染
Shader 通过 `SetShaderBytecodes()` 在运行时注入:
```cpp
// 需要外部代码手动调用
pso->SetShaderBytecodes(vsBytecode, psBytecode); // ❌ 语义混乱
pso->EnsureValid(); // ❌ 现在才能创建真正的 D3D12 PSO
```
## 设计根源分析
### 参考 Unity RHI 的正确做法
Unity 的 `PipelineState`**Shader + RenderState** 的不可变组合:
- 创建时必须提供完整的 shader 和 state
- 创建后不可修改
- `IsValid()` 的语义是确定的
### 当前设计的错误假设
把 Shader 和 PipelineState 分离,试图让 PSO 成为"可配置的 render state 容器",但这与 D3D12/Vulkan 的 PSO 概念完全冲突——在这些 API 中,**PSO 是 shader + state 的编译后不可变对象**。
## 影响范围
1. **无法正确实现 SRP**:上层渲染管线无法可靠地预编译 PSO
2. **资源管理混乱**PSO 何时真正创建?何时可以释放?语义不明确
3. **测试困难**:后端行为不一致,单元测试无法统一编写
4. **扩展性差**:未来添加 Vulkan 后端会遇到同样的问题
## 建议修复方案
### 方案 A在 `GraphicsPipelineDesc` 中添加 Shader 字段
```cpp
struct GraphicsPipelineDesc {
// ... 现有字段
RHIShader* vertexShader = nullptr;
RHIShader* pixelShader = nullptr;
RHIShader* geometryShader = nullptr;
RHIShader* hullShader = nullptr;
RHIShader* domainShader = nullptr;
};
```
### 方案 B创建专用的 ShaderProgram 类型
```cpp
struct ShaderProgramDesc {
RHIShader* vertexShader = nullptr;
RHIShader* pixelShader = nullptr;
// ...
};
struct GraphicsPipelineDesc {
ShaderProgramDesc shaders; // 包含所有 shader
InputLayoutDesc inputLayout;
RasterizerDesc rasterizerState;
BlendDesc blendState;
DepthStencilStateDesc depthStencilState;
// ...
};
```
### 方案 C分离 PSO 创建接口
```cpp
// 独立的 Compute PSO 创建
RHIPipelineState* CreateComputePipelineState(RHIShader* computeShader);
// Graphics PSO 创建时必须提供 shader
RHIPipelineState* CreateGraphicsPipelineState(
const GraphicsPipelineDesc& desc,
RHIShader* vertexShader,
RHIShader* pixelShader
);
```
## 相关文件
- `engine/include/XCEngine/RHI/RHIDevice.h`
- `engine/include/XCEngine/RHI/RHITypes.h`
- `engine/include/XCEngine/RHI/RHIPipelineState.h`
- `engine/src/RHI/D3D12/D3D12Device.cpp`
- `engine/src/RHI/D3D12/D3D12PipelineState.cpp`
- `engine/src/RHI/OpenGL/OpenGLDevice.cpp`
## 总结
**`GraphicsPipelineDesc` 缺少 Shader 字段** 导致:
1. 抽象层无法正确表达 D3D12/Vulkan 的 PSO 概念
2. 后端行为不一致,违反"求同存异"
3. PSO 生命周期管理语义混乱
这是整个 RHI 模块**最严重的架构级缺陷**,应该优先修复。