refactor(editor): Complete architecture refactoring

- SceneManager: remove singleton, use dependency injection via EditorContext
- SelectionManager: already interface-based via ISelectionManager
- Panel: now receives IEditorContext for accessing managers
- HierarchyPanel: migrated to use IEditorContext instead of singletons
- Add ISceneManager interface and SceneManagerImpl
- EditorContextImpl: holds all editor subsystems

Architecture now follows dependency injection pattern:
Application -> EditorContext -> SceneManager/SelectionManager
EditorLayer -> Panels (receive context via SetContext)

All Manager singletons removed: EditorSceneManager::Get(), SelectionManager::Get()
This commit is contained in:
2026-03-25 15:51:27 +08:00
parent 56ec2e9b85
commit 008fb98dee
18 changed files with 1491 additions and 181 deletions

View File

@@ -0,0 +1,466 @@
# RHI 模块审查报告
## 审查范围
基于设计文档 `RHI模块总览.md` 中定义的设计理念,对当前 RHI 模块的设计和实现进行全面审查。
---
## 一、设计问题
### 1. 接口一致性问题
#### 1.1 RHIResource 基类接口过于简单
**当前实现** ([RHIResource.h](file:///d:/Xuanchi/Main/XCEngine/engine/include/XCEngine/RHI/RHIResource.h)):
```cpp
class RHIResource {
public:
virtual ~RHIResource() = default;
virtual void* GetNativeHandle() = 0;
virtual ResourceStates GetState() const = 0;
virtual void SetState(ResourceStates state) = 0;
};
```
**问题**:
- 缺少资源命名接口 (`SetName`/`GetName`)
- 缺少资源类型查询接口
- 缺少资源大小查询接口
**影响**: RHITexture 自行添加了 `SetName`/`GetName`/`GetWidth` 等方法,导致接口不统一。
**建议**: 扩展 RHIResource 基类接口:
```cpp
class RHIResource {
public:
virtual ~RHIResource() = default;
// 现有接口
virtual void* GetNativeHandle() = 0;
virtual ResourceStates GetState() const = 0;
virtual void SetState(ResourceStates state) = 0;
// 建议新增
virtual void SetName(const char* name) = 0;
virtual const char* GetName() const = 0;
virtual ResourceType GetResourceType() const = 0;
virtual uint64_t GetGpuVirtualAddress() const = 0; // 对于 Buffer
};
```
---
#### 1.2 资源生命周期管理不一致
**当前问题**:
- 所有资源使用 `Shutdown()` + `delete` 的手动管理方式
- 容易导致资源泄漏或重复释放
- 与引擎 Core 模块的智能指针体系 (`Ref`, `UniqueRef`) 不统一
**建议**:
1. 考虑使用引用计数管理 RHI 资源
2. 或者提供 RAII 包装器类
3. 至少应该提供统一的资源销毁接口(如 `RHIDevice::DestroyResource()`
---
### 2. 描述符系统设计问题
#### 2.1 描述符接口偏向 D3D12
**当前实现** ([RHIDescriptorPool.h](file:///d:/Xuanchi/Main/XCEngine/engine/include/XCEngine/RHI/RHIDescriptorPool.h)):
```cpp
struct DescriptorPoolDesc {
uint32_t maxDescriptorCount; // D3D12 风格
// ...
};
```
**问题**:
- OpenGL 没有原生的描述符池概念
- OpenGL 后端需要完全模拟,可能效率低下
- 缺少 DescriptorSetLayout 的概念
**建议**: 参考 Vulkan 的描述符系统设计:
```cpp
// 1. 先创建 DescriptorSetLayout
struct DescriptorSetLayoutDesc {
std::vector<DescriptorBinding> bindings;
};
class RHIDescriptorSetLayout { ... };
// 2. 从 Layout 创建 Pool
struct DescriptorPoolDesc {
std::vector<DescriptorPoolSize> poolSizes; // 按类型指定数量
uint32_t maxSets;
};
// 3. 从 Pool 分配 Set
class RHIDescriptorSet {
virtual void Update(uint32_t binding, RHIResource* resource) = 0;
};
```
---
#### 2.2 缺少描述符集绑定机制
**当前问题**:
- RHICommandList 直接绑定资源 (`SetVertexBuffer`, `SetTexture`)
- 缺少批量绑定描述符集的能力
**建议**: 添加描述符集绑定接口:
```cpp
virtual void BindDescriptorSet(
uint32_t setIndex,
RHIDescriptorSet* descriptorSet,
RHIPipelineLayout* layout
) = 0;
```
---
### 3. 命令列表设计问题
#### 3.1 命令列表生命周期管理
**当前问题**:
- 缺少命令列表池化管理
- 每帧可能需要重新创建命令列表
**建议**: 添加命令分配器概念:
```cpp
class RHICommandAllocator {
public:
virtual void Reset() = 0; // 重用命令列表内存
};
// Device 接口
virtual RHICommandAllocator* CreateCommandAllocator(
CommandListType type
) = 0;
```
---
#### 3.2 屏障接口不够清晰
**当前实现**:
```cpp
virtual void ResourceBarrier(
uint32_t numBarriers,
ResourceBarrierDesc* barriers
) = 0;
virtual void ExecuteBarriers() = 0; // 这个方法名容易误解
```
**问题**: `ExecuteBarriers` 方法名暗示有延迟执行,但实际行为不明确。
**建议**:
- 明确屏障是立即执行还是批量执行
- 考虑添加 `FlushBarriers()` 方法名替代 `ExecuteBarriers()`
---
### 4. 着色器系统问题
#### 4.1 编译接口职责混乱
**当前实现** ([RHIShader.h](file:///d:/Xuanchi/Main/XCEngine/engine/include/XCEngine/RHI/RHIShader.h)):
```cpp
class RHIShader {
public:
// RHIShader 自己有编译方法
virtual bool CompileFromFile(...) = 0;
virtual bool Compile(...) = 0;
};
// RHIDevice 也有编译方法
virtual RHIShader* CompileShader(const ShaderCompileDesc& desc) = 0;
```
**问题**: 编译职责分散,用户不知道该用哪个接口。
**建议**: 统一着色器创建流程:
```cpp
// 方案1: 只在 Device 中创建
class RHIDevice {
virtual RHIShader* CreateShader(const ShaderDesc& desc) = 0;
};
// 方案2: 使用 ShaderCompiler 工具类
class RHIShaderCompiler {
virtual RHIShader* CompileFromFile(...) = 0;
virtual RHIShader* CompileFromSource(...) = 0;
};
```
---
#### 4.2 缺少着色器反射接口
**当前问题**:
- 只有 `GetUniformInfos()` 方法
- 缺少完整的着色器反射(输入/输出语义、资源绑定等)
**建议**: 添加完整的着色器反射接口:
```cpp
struct ShaderReflection {
std::vector<VertexInputAttribute> vertexInputs;
std::vector<FragmentOutput> fragmentOutputs;
std::vector<ResourceBinding> resourceBindings;
std::vector<PushConstantRange> pushConstantRanges;
};
virtual ShaderReflection GetReflection() const = 0;
```
---
### 5. 管线状态对象问题
#### 5.1 缺少管线缓存
**当前问题**: 每次创建 PSO 都需要完整编译,没有缓存机制。
**建议**: 添加管线缓存接口:
```cpp
class RHIPipelineCache {
public:
virtual void Save(const char* filePath) = 0;
virtual void Load(const char* filePath) = 0;
virtual size_t GetDataSize() const = 0;
virtual void* GetData() const = 0;
};
// Device 接口
virtual RHIPipelineCache* CreatePipelineCache() = 0;
virtual RHIPipelineState* CreatePipelineState(
const PipelineStateDesc& desc,
RHIPipelineCache* cache = nullptr
) = 0;
```
---
### 6. 缺失的关键功能
#### 6.1 缺少资源别名 (Aliasing) 支持
**设计文档提到**: "求同存异"
**问题**: D3D12 和 Vulkan 都支持资源别名(多个资源共享同一块内存),但当前 RHI 没有暴露。
**建议**: 添加资源别名支持:
```cpp
struct ResourceAliasingDesc {
RHIResource* overlappingResources;
uint32_t resourceCount;
};
virtual void AliasingResources(
const ResourceAliasingDesc& desc
) = 0;
```
---
#### 6.2 缺少多队列支持
**当前问题**:
- RHICommandQueue 只支持单一类型
- 缺少多队列同步机制
**建议**: 添加跨队列同步支持:
```cpp
struct QueueSyncDesc {
RHICommandQueue* waitQueue;
RHIFence* fence;
uint64_t value;
};
virtual void QueueSubmit(
const QueueSubmitDesc& desc,
const QueueSyncDesc* waitSyncs = nullptr,
uint32_t waitSyncCount = 0,
const QueueSyncDesc* signalSyncs = nullptr,
uint32_t signalSyncCount = 0
) = 0;
```
---
#### 6.3 缺少 RenderGraph 支持
**设计文档提到**: "渲染管线层SRP/Render Graph"
**问题**: 当前 RHI 接口没有为 RenderGraph 提供必要的支持:
- 缺少资源传递机制
- 缺少自动屏障生成
- 缺少资源生命周期跟踪
**建议**: 添加 RenderGraph 友好的接口:
```cpp
struct ResourceTransition {
RHIResource* resource;
ResourceStates fromState;
ResourceStates toState;
uint32_t queueFamily; // 支持跨队列传递
};
virtual void TransitionResources(
const ResourceTransition* transitions,
uint32_t count
) = 0;
```
---
## 二、实现问题
### 1. OpenGL 后端状态管理
**问题**: OpenGL 是状态机模型,需要仔细管理状态。
**建议检查点**:
- [ ] 是否正确跟踪当前绑定的 VAO/VBO/纹理
- [ ] 是否正确跟踪当前激活的着色器程序
- [ ] 是否正确跟踪混合/深度/模板状态
- [ ] 是否有不必要的冗余状态切换
**建议**: 实现状态跟踪器:
```cpp
class OpenGLStateTracker {
public:
void BindTexture(uint32_t unit, uint32_t texture);
void BindVertexArray(uint32_t vao);
void UseProgram(uint32_t program);
// ... 避免重复绑定
};
```
---
### 2. 资源状态跟踪不一致
**问题**:
- D3D12 需要精确的资源状态跟踪
- OpenGL 没有显式的资源状态概念
- 当前实现在 OpenGL 后端如何处理状态?
**建议**:
- OpenGL 后端可以忽略资源状态(或仅用于调试)
- 或者实现软件状态跟踪用于验证
---
### 3. 内存管理缺失
**问题**:
- 缺少显式的 GPU 内存分配接口
- D3D12 有 Heap 概念OpenGL 没有
**建议**: 添加内存分配抽象:
```cpp
struct HeapDesc {
HeapType type; // Default, Upload, Readback
uint64_t size;
HeapFlags flags;
};
class RHIHeap {
public:
virtual void* Map() = 0;
virtual void Unmap() = 0;
};
// 资源创建时指定堆
struct BufferDesc {
// ...
RHIHeap* heap; // 可选
uint64_t heapOffset; // 可选
};
```
---
### 4. 错误处理机制
**当前问题**:
- 大部分方法返回 `void``bool`
- 缺少详细的错误信息
**建议**: 添加结果类型:
```cpp
template<typename T>
struct RHIResult {
T value;
RHIErrorCode error;
const char* errorMessage;
};
// 使用示例
RHIResult<RHITexture*> result = device->CreateTexture(desc);
if (result.error != RHIErrorCode::Success) {
LogError(result.errorMessage);
}
```
---
## 三、与设计理念的对比
### 设计理念 vs 实际实现
| 设计理念 | 设计文档要求 | 当前实现状态 | 问题 |
|---------|------------|------------|------|
| **求同存异** | 提取 API 共性 | ✅ 部分实现 | 描述符系统偏向 D3D12 |
| **分层抽象** | 清晰的层级结构 | ✅ 已实现 | 层级清晰 |
| **特性降级** | 能力检测和替代方案 | ⚠️ 部分实现 | RHICapabilities 存在但使用不明确 |
| **底层逃逸** | 允许访问原生 API | ✅ 已实现 | GetNativeHandle() 接口存在 |
---
## 四、优先级建议
### 高优先级(影响功能正确性)
1. **统一资源生命周期管理** - 防止内存泄漏
2. **完善错误处理机制** - 便于调试
3. **OpenGL 状态跟踪** - 避免渲染错误
### 中优先级(影响性能和可维护性)
4. **重构描述符系统** - 提高 OpenGL 效率
5. **统一着色器编译接口** - 提高易用性
6. **添加命令分配器** - 提高性能
### 低优先级(增强功能)
7. **添加管线缓存** - 加速启动
8. **添加资源别名支持** - 优化内存
9. **RenderGraph 支持** - 高级功能
---
## 五、总结
### 优点
1. ✅ 分层架构清晰,符合设计文档
2. ✅ 核心抽象接口基本完整
3. ✅ D3D12 后端实现较为完善
4. ✅ 测试覆盖较好
### 主要问题
1. ❌ 描述符系统设计偏向 D3D12OpenGL 后端效率可能受影响
2. ❌ 资源生命周期管理不一致,存在泄漏风险
3. ❌ 着色器编译接口职责混乱
4. ⚠️ 缺少部分高级功能(资源别名、多队列同步等)
### 建议
建议按照优先级逐步改进,首先解决高优先级问题,确保引擎的稳定性和正确性。

View File

@@ -0,0 +1,335 @@
# XCEngine 项目熟悉计划
## 项目概述
XCEngine 是一个正在开发中的模块化 C++ 游戏引擎,采用 RHIRender Hardware Interface抽象层设计支持 DirectX 12 和 OpenGL 4.6+ 多种渲染 API。
### 技术栈
- **语言**: C++17
- **渲染 API**: DirectX 12, OpenGL 4.6+
- **构建系统**: CMake 3.15+
- **测试框架**: Google Test
- **UI**: ImGui用于编辑器
---
## 项目结构
```
XCEngine/
├── engine/ # 核心引擎库(静态库)
│ ├── include/XCEngine/ # 头文件
│ │ ├── Audio/ # 音频系统
│ │ ├── Components/ # 组件系统
│ │ ├── Core/ # 核心基础模块
│ │ ├── Debug/ # 调试与日志
│ │ ├── Input/ # 输入模块
│ │ ├── Memory/ # 内存管理
│ │ ├── Platform/ # 平台抽象层
│ │ ├── RHI/ # 渲染硬件接口
│ │ ├── Resources/ # 资源管理
│ │ ├── Scene/ # 场景管理
│ │ └── Threading/ # 线程系统
│ ├── src/ # 实现文件
│ └── third_party/ # 第三方库
├── editor/ # 编辑器 UI 应用程序
│ └── src/ # 编辑器源代码
├── tests/ # 单元测试
│ ├── math/ # 数学库测试
│ ├── containers/ # 容器测试
│ ├── memory/ # 内存管理测试
│ ├── threading/ # 线程模块测试
│ ├── debug/ # 调试模块测试
│ ├── core/ # 核心模块测试
│ ├── Scene/ # 场景测试
│ ├── Resources/ # 资源管理测试
│ ├── Input/ # 输入模块测试
│ └── RHI/ # RHI 抽象层测试
├── mvs/ # 示例程序
│ ├── D3D12/ # DirectX 12 渲染示例
│ ├── OpenGL/ # OpenGL 渲染示例
│ ├── VolumeRenderer/ # 体积渲染器
│ ├── RenderDoc/ # RenderDoc 集成示例
│ └── ui/ # 编辑器 UI 示例
└── docs/ # 文档
├── api/ # API 文档
└── plan/ # 开发计划与架构设计
```
---
## 核心模块详解
### 1. Core核心基础
位置: `engine/include/XCEngine/Core/`
| 子模块 | 说明 |
|--------|------|
| Types.h | 基础类型别名int8, uint32 等) |
| RefCounted.h | 引用计数基类 |
| SmartPtr.h | 智能指针Ref, UniqueRef |
| Event.h | 事件系统,支持订阅/发布模式 |
| FileWriter.h | 文件写入工具 |
| Layer.h/LayerStack.h | 层级与层级栈管理 |
**Core/Math 数学库**:
- Vector2/3/4 - 向量运算
- Matrix3/4 - 矩阵运算
- Quaternion - 四元数
- Transform - 变换
- Color - 颜色
- Rect - 矩形
- Sphere/Box/Plane/Ray - 几何体
- AABB/Bounds/Frustum - 包围体
**Core/Containers 容器**:
- Array.h - 动态数组
- String.h - 字符串类
- HashMap.h - 哈希表
**Core/Asset 资源系统核心**:
- IResource.h - 资源接口基类
- ResourceTypes.h - 资源类型定义
- ResourceHandle.h - 资源句柄
- ResourceManager.h - 全局资源管理器
- ResourceCache.h - 资源缓存
- AsyncLoader.h - 异步资源加载器
**Core/IO 资源 IO 系统**:
- IResourceLoader.h - 资源加载器接口
- ResourceFileSystem.h - 资源文件系统
- FileArchive.h - 文件归档
### 2. RHI渲染硬件接口
位置: `engine/include/XCEngine/RHI/`
这是引擎的核心抽象层,借鉴 Unity SRP 架构设计。
**设计原则**:
- 求同存异:提取各 API 共同特性
- 分层抽象:核心抽象层 → 后端实现层 → 平台适配层
- 特性降级:后端不支持的特性优雅降级
**抽象接口**:
| 接口 | 说明 |
|------|------|
| RHIDevice | 渲染设备抽象 |
| RHICommandQueue | 命令队列抽象 |
| RHICommandList | 命令列表抽象 |
| RHISwapChain | 交换链抽象 |
| RHIPipelineState | 渲染管线状态抽象 |
| RHIBuffer/RHITexture | 资源抽象 |
| RHIShader | 着色器抽象 |
| RHISampler | 采样器抽象 |
| RHIFence | 同步栅栏抽象 |
| RHIDescriptorPool | 描述符池抽象 |
| RHIRenderPass | 渲染通道抽象 |
| RHIFramebuffer | 帧缓冲抽象 |
**后端实现**:
- `RHI/D3D12/` - DirectX 12 后端
- `RHI/OpenGL/` - OpenGL 4.6+ 后端
### 3. Components组件系统
位置: `engine/include/XCEngine/Components/`
采用类似 Unity 的组件架构:
| 组件 | 说明 |
|------|------|
| Component.h | 组件基类,提供生命周期管理 |
| GameObject.h | 游戏对象,支持层级结构 |
| TransformComponent.h | 变换组件 |
| AudioSourceComponent.h | 音频源组件 |
| AudioListenerComponent.h | 音频监听器组件 |
### 4. Scene场景管理
位置: `engine/include/XCEngine/Scene/`
- **Scene.h** - 场景类,管理场景内的所有游戏对象
- **SceneManager.h** - 场景管理器,处理场景切换
### 5. Audio音频系统
位置: `engine/include/XCEngine/Audio/`
| 模块 | 说明 |
|------|------|
| AudioSystem.h | 音频系统主类 |
| AudioMixer.h | 音频混音器 |
| HRTF.h | 头部相关传输函数,空间音频 |
| FFTFilter.h | 快速傅里叶变换滤波器 |
| Reverbation.h | 混响效果 |
| Equalizer.h | 音频均衡器 |
| IAudioBackend.h | 音频后端接口 |
| WindowsAudioBackend.h | Windows WASAPI 后端 |
### 6. Memory内存管理
位置: `engine/include/XCEngine/Memory/`
| 模块 | 说明 |
|------|------|
| Allocator.h | 内存分配器接口 |
| LinearAllocator.h | 线性分配器,适合帧分配 |
| PoolAllocator.h | 内存池分配器,适合固定大小对象 |
| ProxyAllocator.h | 代理分配器,跟踪内存使用统计 |
| MemoryManager.h | 全局内存管理器 |
### 7. Threading线程系统
位置: `engine/include/XCEngine/Threading/`
| 模块 | 说明 |
|------|------|
| Thread.h | 线程封装类 |
| Mutex.h | 互斥锁 |
| SpinLock.h | 自旋锁 |
| ReadWriteLock.h | 读写锁 |
| TaskSystem.h | 多线程任务系统 |
| Task.h/TaskGroup.h | 任务和任务组管理 |
### 8. Debug调试与日志
位置: `engine/include/XCEngine/Debug/`
| 模块 | 说明 |
|------|------|
| Logger.h | 分级日志系统 |
| ConsoleLogSink.h | 控制台日志输出 |
| FileLogSink.h | 文件日志输出 |
| Profiler.h | 性能分析工具 |
| RenderDocCapture.h | RenderDoc 帧捕获集成 |
### 9. Resources资源管理
位置: `engine/include/XCEngine/Resources/`
按类型分目录管理:
- **Texture/** - 纹理资源
- **Mesh/** - 网格资源
- **Shader/** - 着色器资源
- **Material/** - 材质资源
- **AudioClip/** - 音频资源
### 10. Platform平台抽象层
位置: `engine/include/XCEngine/Platform/`
跨平台抽象接口:
- IPlatform - 平台接口
- IWindow - 窗口接口
- IFileSystem - 文件系统接口
- IClock - 时钟接口
- Windows/ - Windows 平台实现
### 11. Input输入模块
位置: `engine/include/XCEngine/Input/`
- InputManager - 输入管理器
- InputModule - 输入模块基类
- InputEvent - 输入事件定义
- InputAxis - 输入轴配置
---
## 渲染架构
### 渲染流程
```
Scene → CullingSystem → RenderQueue → Renderer → GPU
↓ ↓
CullingResults CommandList
```
### 关键概念(借鉴 Unity SRP
1. **CullingResults** - 剔除结果
2. **RenderPipeline** - 渲染管线
3. **RenderQueue** - 渲染队列
4. **ScriptableRenderContext** - 渲染上下文
5. **LightManager** - 光照管理
6. **ShadowAtlas** - 阴影图集
---
## 构建与测试
### 构建项目
```bash
mkdir build && cd build
cmake .. -A x64
cmake --build . --config Debug
```
### 运行测试
```bash
cd build/tests
ctest -C Debug --output-on-failure
```
---
## 学习路径建议
### 第一阶段:核心基础
1. 阅读 `README.md` 了解项目概述
2. 学习 Core 模块Types, Event, SmartPtr
3. 学习 Math 数学库
4. 学习 Containers 容器
### 第二阶段:系统模块
1. 学习 Memory 内存管理
2. 学习 Threading 线程系统
3. 学习 Debug 日志系统
4. 学习 Platform 平台抽象
### 第三阶段:渲染系统
1. 学习 RHI 抽象层设计
2. 学习 D3D12 后端实现
3. 学习 OpenGL 后端实现
4. 学习渲染管线架构
### 第四阶段:高级功能
1. 学习 Scene 场景管理
2. 学习 Components 组件系统
3. 学习 Resources 资源管理
4. 学习 Audio 音频系统
### 第五阶段:实践
1. 运行 mvs 中的示例程序
2. 阅读测试用例理解 API 用法
3. 尝试修改或扩展现有功能
---
## 关键文件索引
| 文件 | 说明 |
|------|------|
| README.md | 项目说明文档 |
| CMakeLists.txt | 根构建配置 |
| engine/CMakeLists.txt | 引擎库构建配置 |
| docs/plan/XCEngine渲染引擎架构设计.md | 渲染架构详细设计 |
| docs/api/main.md | API 文档入口 |
---
## 注意事项
1. 项目目前仅支持 Windows 平台
2. 需要 Visual Studio 2019 或更高版本
3. D3D12 后端需要 Windows 10/11
4. OpenGL 后端需要 OpenGL 4.6+ 支持