chore: sync workspace state

This commit is contained in:
2026-03-29 01:36:53 +08:00
parent eb5de3e3d4
commit e5cb79f3ce
4935 changed files with 35593 additions and 360696 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,940 +0,0 @@
# XCEngine Editor 设计分析与改进计划
## 1. 项目概述
### 1.1 当前状态
XCEngine Editor 是一个基于 ImGui 的 Unity 风格编辑器 UI目前具备以下基础功能
- **渲染基础**: DirectX 12 + ImGui 对接
- **面板框架**: Docking 布局系统
- **UI 主题**: Unity 风格深色主题
### 1.2 对比参考
参考项目 Fermion Boson Editor 是一个功能完整的游戏引擎编辑器,具有:
- 完整的 3D Viewport
- 场景层级系统
- 组件检查器
- 资源浏览器
- 材质编辑器
- Play/Edit/Simulate 模式切换
---
## 2. 整体架构对比
### 2.1 架构图
**Fermion 架构**:
```
Fermion::Application
└── LayerStack
├── ImGuiLayer (overlay)
└── BosonLayer (editor layer)
├── ViewportPanel (3D viewport + gizmos)
├── SceneHierarchyPanel (entity tree)
│ └── InspectorPanel (embedded, component editor)
├── ContentBrowserPanel (asset browser)
├── MaterialEditorPanel (node-based material)
├── SettingsPanel (editor settings)
├── OverlayRenderPanel (physics debug)
└── MenuBarPanel (menu bar)
```
**XCEngine 架构**:
```
UI::Application
└── Panels (独立 Panel 类)
├── MenuBar
├── HierarchyPanel
├── InspectorPanel
├── SceneViewPanel (占位符)
├── GameViewPanel (占位符)
├── ProjectPanel
└── ConsolePanel
```
### 2.2 关键差异
| 方面 | Fermion | XCEngine |
|------|---------|----------|
| Layer 系统 | Application → LayerStack → BosonLayer | Application 直接管理 Panels |
| Panel 集成 | SceneHierarchy 内嵌 InspectorPanel | 各 Panel 独立 |
| Scene 管理 | BosonLayer 持有 Scene/SceneRenderer | SceneManager 单例 |
| 渲染集成 | BosonLayer → SceneRenderer → Framebuffer | 无对接 |
| 事件系统 | Layer::onEvent 统一分发 | 各 Panel 独立处理 |
---
## 3. 各面板详细分析
### 3.1 SceneHierarchyPanel / HierarchyPanel
#### 功能对比
| 功能 | Fermion | XCEngine | 状态 |
|------|---------|----------|------|
| 树节点渲染 | ✅ `TreeNodeEx` + UUID | ✅ `TreeNodeEx` + EntityID | 完成 |
| 选中高亮 | ✅ | ✅ | 完成 |
| 展开/折叠 | ✅ 自动记忆状态 | ✅ `isOpen` 状态 | 完成 |
| 重命名 | ✅ 双击触发 | ⚠️ 有 bug | 需修复 |
| 拖拽重排 | ✅ 完整 + 循环检测 | ⚠️ 基本实现 | 需完善 |
| 右键菜单 | ✅ Create Child, Detach, Delete | ✅ Create, Rename, Delete, Copy/Paste, Duplicate | 需补充 |
| 空区域点击 | ✅ 取消选中 | ✅ 取消选中 | 完成 |
| 嵌入 Inspector | ✅ Panel 内嵌 InspectorPanel | ❌ 分离 | 架构差异 |
#### XCEngine 问题详解
**问题 1: 重命名逻辑 bug**
`HierarchyPanel.cpp` lines 106-113:
```cpp
if (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)) {
if (strlen(m_renameBuffer) > 0) {
sceneManager.RenameEntity(id, m_renameBuffer);
}
m_renaming = false;
m_renamingEntity = INVALID_ENTITY_ID;
}
```
问题:点击 InputText 外部时,`IsItemActive()` 已经变为 false此时 `IsMouseClicked(0)` 也已经错过。
**问题 2: 缺少 "Create Child" 选项**
右键菜单只有:
- Create → Empty Object, Camera, Light, Cube, Sphere, Plane
- Rename, Delete
- Copy, Paste, Duplicate
缺少 "Create Child" 选项来在选中物体下创建子物体。
**问题 3: 没有 "Detach from Parent" 选项**
无法将子物体脱离父物体,直接变为根层级。
---
### 3.2 InspectorPanel
#### 功能对比
| 功能 | Fermion (1173 行) | XCEngine (94 行) | 状态 |
|------|-------------------|------------------|------|
| 组件显示 | ✅ 模板系统 | ⚠️ 只实现 2 种组件 (Engine 有完整组件库) | 需完善 |
| 动态增删组件 | ✅ 分类菜单 | ❌ 无 | 需实现 |
| 删除组件 | ✅ 右键 Remove | ❌ 无 | 需实现 |
| Transform 编辑 | ✅ `drawVec3Control` | ⚠️ `DragFloat3` 简陋 | 需改进 |
| Mesh 编辑 | ✅ Drag-drop + popup | ⚠️ 只有 InputText | 需改进 |
| 材质预览 | ✅ 缩略图渲染 | ❌ 无 | 需实现 |
| Camera 编辑 | ✅ 完整 | ❌ 无 | 需实现 |
| Light 编辑 | ✅ D/P/S Light | ❌ 无 | 需实现 |
| Physics 编辑 | ✅ 完整 | ❌ 无 | 需实现 |
| Script 编辑 | ✅ 字段编辑 | ❌ 无 | 需实现 |
| Entity Picking | ✅ 关节连接 | ❌ 无 | 需实现 |
#### XCEngine 实现现状
`InspectorPanel.cpp` lines 44-92:
```cpp
void InspectorPanel::RenderComponent(Component* component) {
if (auto* transform = dynamic_cast<TransformComponent*>(component)) {
ImGui::DragFloat3("##Position", transform->position, 0.1f);
ImGui::DragFloat3("##Rotation", transform->rotation, 1.0f);
ImGui::DragFloat3("##Scale", transform->scale, 0.1f);
}
else if (auto* meshRenderer = dynamic_cast<MeshRendererComponent*>(component)) {
// 只有 InputText没有预览没有拖拽
}
}
```
**主要问题**:
1. Editor Inspector 面板只实现了 Transform 和 MeshRenderer 显示编辑,但 Engine 核心已有完整组件系统
2. 没有 Add Component 菜单
3. 没有 Remove Component 功能
4. 没有 CollapsingHeader 折叠
5. 布局简陋,没有缩进和对齐
---
### 3.3 ProjectPanel / ContentBrowserPanel
#### 功能对比
| 功能 | Fermion | XCEngine | 状态 |
|------|---------|----------|------|
| 布局 | ✅ 两列 (树 + 网格) | ⚠️ 只有网格 | 需补充 |
| 文件夹树 | ✅ 左侧导航树 | ❌ 无 | 需实现 |
| 缩略图 | ✅ 加载 Texture | ⚠️ 彩色方块 | 需改进 |
| 材质预览 | ✅ 缩略图渲染 | ❌ 无 | 需实现 |
| 拖拽移动 | ✅ 完整实现 | ⚠️ stubbed | 需修复 |
| 双击打开 | ✅ 打开文件夹 | ✅ 实现 | 完成 |
| 面包屑导航 | ✅ 路径按钮 | ✅ 实现 | 完成 |
| 搜索过滤 | ✅ 实现 | ✅ 实现 | 完成 |
#### XCEngine 问题详解
**问题: HandleDrop() 返回 false**
`ProjectPanel.cpp` line 294:
```cpp
bool ProjectPanel::HandleDrop(const AssetItemPtr& targetFolder) {
return false; // STUBBED OUT - 拖拽移动功能不工作
}
```
虽然 `RenderAssetItem()` 中有拖拽目标代码,但实际上 `HandleDrop()` 从未被调用,拖拽移动功能完全失效。
---
### 3.4 MenuBar
#### 功能对比
| 功能 | Fermion (271 行) | XCEngine (55 行) | 状态 |
|------|------------------|-------------------|------|
| 实现方式 | ✅ 自定义窗口边框 | ✅ `BeginMainMenuBar` | 完成 |
| 菜单项 | ✅ 实际回调 | ❌ **全部 stubbed** | 需实现 |
| 项目操作 | ✅ new/open/save | ❌ 无 | 需实现 |
| 创建菜单 | ✅ Material/Texture | ❌ 无 | 需实现 |
| 窗口控制 | ✅ 有 (已注释) | ❌ 无 | 可选 |
#### XCEngine 问题详解
**所有菜单项都是空的**:
```cpp
// MenuBar.cpp
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {} // 空
if (ImGui::MenuItem("Open Scene", "Ctrl+O")) {} // 空
if (ImGui::MenuItem("Save Scene", "Ctrl+S")) {} // 空
// ... 所有项都是空的
```
---
### 3.5 ConsolePanel
#### 功能对比
| 功能 | Fermion (84 行) | XCEngine (70 行) | 状态 |
|------|------------------|-------------------|------|
| 日志显示 | ✅ 彩色 + 前缀 | ✅ 彩色 + 前缀 | 完成 |
| 命令输入 | ✅ 底部输入框 | ❌ 无 | 需补充 |
| 命令处理 | ✅ clear/help | ❌ 无 | 需实现 |
| 自动滚动 | ✅ 新日志时滚动 | ⚠️ flag 设置但逻辑不完整 | 需改进 |
#### XCEngine 优点
- 测试按钮注入日志功能完善
- 日志级别颜色区分正确
- 基本显示功能正常
---
### 3.6 SceneViewPanel / ViewportPanel
#### 功能对比
| 功能 | Fermion (356 行) | XCEngine (54 行) | 状态 |
|------|------------------|-------------------|------|
| 3D 渲染 | ✅ Framebuffer | ❌ **只有网格** | 需重构 |
| 相机 | ✅ EditorCamera | ❌ 无 | 需实现 |
| 鼠标拾取 | ✅ readPixel | ❌ 无 | 需实现 |
| Gizmo | ✅ ImGuizmo | ❌ 无 | 需实现 |
| 工具栏 | ✅ Q/W/E/R | ❌ 无 | 需实现 |
| Play 控制 | ✅ Play/Stop/Pause/Step | ❌ 无 | 需实现 |
| 状态切换 | ✅ Edit/Play/Simulate | ❌ 无 | 需实现 |
#### XCEngine 实现现状
```cpp
// SceneViewPanel.cpp
void SceneViewPanel::RenderGrid() {
// 只画了 50px 网格背景
for (float x = 0; x < canvasSize.x; x += gridSize) {
drawList->AddLine(...);
}
// 没有任何 3D 渲染
}
```
**问题**: 完全没有任何 3D 渲染能力,只是占位符。
---
### 3.7 GameViewPanel
| 功能 | Fermion | XCEngine | 状态 |
|------|---------|----------|------|
| 游戏视图 | ✅ Framebuffer 渲染 | ❌ **纯占位符** | 需重构 |
| 状态栏 | ✅ Play/Simulate 指示 | ❌ 无 | 需实现 |
---
## 4. XCEngine 缺失的面板
XCEngine Editor 只有 7 个面板,而 Fermion 有 10 个。以下是缺失的面板:
### 4.1 SettingsPanel - 编辑器设置
**Fermion 功能**:
- Renderer Info: 相机设置、设备信息、帧时间统计
- Environment Settings: Skybox、阴影、IBL、HDR 加载、环境光强度、法线强度
- Debug Settings: 渲染模式 (Forward/Deferred Hybrid)、GBuffer 调试、深度视图、物理调试开关、无限网格、轮廓设置
- Project Settings: 项目信息、默认字体配置
**XCEngine 状态**: 无此面板
**实现建议**: 可以作为 InspectorPanel 的扩展,或者单独的设置浮窗
---
### 4.2 OverlayRenderPanel - 调试可视化
**Fermion 功能**:
```cpp
class OverlayRenderPanel {
void render(const Context &ctx) const;
void renderPhysicsColliders(); // 物理碰撞体可视化
void renderPhysics2DColliders(); // 2D 碰撞体
void renderPhysics3DColliders(); // 3D 碰撞体
void renderJoints(); // 关节连接可视化
void renderSelectedEntityOutline(); // 选中物体轮廓
};
```
**功能说明**:
- 在 Viewport 上叠加渲染物理调试信息
- 2D 碰撞体: Box、Circle、BoxSensor、CircleSensor
- 3D 碰撞体: Box、Sphere、Capsule、Mesh (三角形线框)
- 关节: RevoluteJoint (锚点圆)、DistanceJoint (锚点圆 + 线段)
- 选中物体白色轮廓
**XCEngine 状态**: 无此面板,但可以在 SceneViewPanel 完善后添加
---
### 4.3 MaterialEditorPanel - 材质编辑器
**Fermion 功能**:
- 基于 `ax::NodeEditor` (imnodes) 的节点式材质编辑器
- PBR Output 节点 (ID=1) 固定在右侧
- Texture 节点可动态创建
- 引脚连接系统 (Pin ID 约定: `nodeID*100 + pinIndex`)
- 材质预览渲染 (`MaterialPreviewRenderer`)
- 材质编译 (`compileMaterial()`)
**节点系统**:
```cpp
// PBR Output 节点输入引脚
enum PBRInputPin {
Albedo = 1, // 引脚 ID = 101
Normal = 2, // 引脚 ID = 102
Metallic = 3, // 引脚 ID = 103
Roughness = 4,// 引脚 ID = 104
AO = 5 // 引脚 ID = 105
};
// Texture 节点输出引脚
// 引脚 ID = nodeID * 100 + 1
```
**UI 布局**:
```
┌─────────────────────────────────────────────────────┐
│ [Texture Node] ──────→ [Albedo] │
│ [Texture Node] ──────→ [Normal] │
│ [Texture Node] ──────→ [PBR Output] → [Material] │
│ → [Metallic] │
│ → [Roughness] │
│ → [AO] │
└─────────────────────────────────────────────────────┘
```
**XCEngine 状态**: 无此面板,需要独立开发
**实现难度**: 高,需要 imnodes 库集成和材质编译系统
---
### 4.4 TextureConfigPanel - 纹理配置
**Fermion 功能**:
```cpp
class TextureConfigPanel {
void loadTexture(const std::filesystem::path &ftexPath);
void loadTextures(const vector<path> &ftexPaths);
void saveTexture(TextureConfigData &data);
void saveAllTextures();
struct TextureConfigData {
std::filesystem::path FtexPath;
std::string Name;
TextureAssetSpecification Spec;
bool Modified = false;
};
bool m_BatchMode = false; // 批量配置模式
TextureAssetSpecification m_BatchSpec;
};
```
**功能**:
- 批量纹理加载
- 纹理规格编辑 (格式、过滤器、Mipmaps 等)
- 保存/导出功能
**XCEngine 状态**: 无此面板ProjectPanel 只做文件浏览
---
### 4.5 AssetManagerPanel - 资源注册表
**Fermion 功能**:
```cpp
class AssetManagerPanel {
void onImGuiRender();
// 显示所有注册的资源
// 可搜索、可过滤
// Asset 类型过滤
// Load/Unload 按钮
// 显示: asset path, type, handle ID, loading status
};
```
**功能**:
- 查看所有已注册资产
- 按类型过滤 (Texture, Mesh, Material, etc.)
- 搜索功能
- 手动加载/卸载资产
- 显示资源路径、类型、句柄 ID、加载状态
**XCEngine 状态**: 无此面板ProjectPanel 只做文件系统浏览
---
## 5. 核心系统差异分析
### 5.1 Application 架构对比
**Fermion Application**:
```cpp
class Application {
std::unique_ptr<IWindow> m_window;
std::unique_ptr<ImGuiLayer> m_imGuiLayer;
std::unique_ptr<LayerStack> m_layerStack;
void pushLayer(std::unique_ptr<Layer> layer); // 在 ImGui 之前更新
void pushOverlay(std::unique_ptr<Layer> overlay); // 在 ImGui 之后更新
};
```
**XCEngine Application**:
```cpp
class Application {
HWND m_hwnd;
ID3D12Device* m_device;
// 直接管理所有 Panels
std::unique_ptr<MenuBar> m_menuBar;
std::unique_ptr<HierarchyPanel> m_hierarchyPanel;
// ...
};
```
**关键差异**:
1. Fermion 使用 Layer/Overlay 模式,事件按倒序传播
2. XCEngine 直接管理 Panels缺乏层次化设计
3. Fermion 有 ImGuiLayer 专门处理 ImGui 事件阻塞
4. XCEngine 需要手动在 Panel 内部处理焦点判断
---
### 5.2 SceneManager vs Scene/EntityManager
**XCEngine SceneManager**:
```cpp
class SceneManager {
std::unordered_map<EntityID, GameObject> m_entities;
std::vector<EntityID> m_rootEntities;
EntityID CreateEntity(name, parent);
void DeleteEntity(id);
void MoveEntity(id, newParent);
EntityID CopyEntity(id);
EntityID PasteEntity(parent);
};
```
**Fermion Scene + EntityManager**:
```cpp
class Scene {
std::unique_ptr<EntityManager> m_entityManager;
std::unique_ptr<Physics2DWorld> m_physicsWorld2D;
std::unique_ptr<Physics3DWorld> m_physicsWorld3D;
};
class EntityManager {
entt::registry m_registry; // EnTT ECS
std::unordered_map<UUID, entt::entity> m_entityMap;
};
```
**XCEngine 实际情况**:
1. ✅ 有 Scene 类和 SceneManager (见 engine/include/XCEngine/Scene/)
2. ❌ 没有物理世界集成
3. ✅ 有 Component/GameObject 系统,但非 EnTT ECS (使用 dynamic_cast)
4. ✅ EntityID 是 uint64_t 递增整数,不是 UUID
5. ❌ Editor 没有场景状态 (Edit/Play/Simulate) 切换机制
---
### 5.3 BosonUI 自定义控件
Fermion 定义了 `ui` 命名空间的自定义控件XCEngine 没有:
**Fermion ui 控件**:
```cpp
namespace ui {
// 向量编辑器 (带 XYZ 标签和 reset 按钮)
void drawVec3Control(const char* label, glm::vec3& values,
float resetValue = 0.0f, float columnWidth = 120.0f);
// 浮点数编辑器
bool drawFloatControl(const char* label, float& value,
float columnWidth = 120.0f, float speed = 0.1f);
// 复选框
void drawCheckboxControl(const char* label, bool& value, float width = 120.0f);
// 自定义 Popup 包装
bool BeginPopup(const char* name);
void EndPopup();
}
```
**XCEngine**: 直接使用原生 ImGui API没有封装
---
### 5.4 选择系统差异
**Fermion 选择 + Entity Picking**:
```cpp
// InspectorPanel 实体拾取用于关节连接
bool m_entityPickingActive = false;
Entity m_pickingTargetEntity;
// 当用户在 Viewport 点击时
void deliverPickedEntity(Entity pickedEntity) {
if (m_pickingTargetEntity.hasComponent<RevoluteJoint2DComponent>()) {
m_pickingTargetEntity.getComponent<RevoluteJoint2DComponent>()
.connectedBodyID = pickedEntity.getUUID();
}
}
```
**XCEngine SelectionManager**:
```cpp
class SelectionManager {
Event<EntityID> OnSelectionChanged;
EntityID GetSelectedEntity();
void SetSelectedEntity(EntityID entity);
};
```
**XCEngine 问题**: 没有 Entity Picking 机制,无法在编辑关节时拾取场景中的物体
---
### 5.5 资源系统对比
**Fermion 资源系统**:
```
AssetManager (抽象基类)
├── EditorAssetManager (编辑器资源管理)
│ └── importAsset() 导入资源
└── RuntimeAssetManager (运行时资源管理)
└── getAsset<T>() 获取资源
AssetRegistry (资源注册表)
AssetHandle (资源句柄)
```
**XCEngine 资源系统**:
```
ProjectManager (文件系统浏览)
└── GetCurrentItems() 返回 AssetItem 列表
AssetItem (只包含文件信息)
├── name
├── type
├── isFolder
└── fullPath
```
**XCEngine 问题**:
1. 没有真正的资源导入流程
2. 没有 AssetRegistry 资源注册表
3. 没有 AssetHandle 统一资源句柄
4. 没有资源缓存和加载/卸载管理
---
## 7. 核心问题总结
### 7.1 已完成功能
| 面板 | 完成度 | 说明 |
|------|--------|------|
| HierarchyPanel | 70% | 基本树视图、选中、重命名、复制、拖拽 |
| ProjectPanel | 60% | 文件浏览、网格显示、导航,但拖拽移动失效 |
| ConsolePanel | 60% | 日志显示,缺少命令输入 |
| MenuBar | 30% | 菜单结构存在,但所有项 stubbed |
| InspectorPanel | 20% | 只实现 Transform 和 MeshRenderer 编辑,但 Engine 核心有完整组件库 |
| SceneViewPanel | 5% | 纯占位符 |
| GameViewPanel | 5% | 纯占位符 |
### 7.2 高优先级问题
1. **MenuBar 所有菜单项 stubbed** - 无法进行任何 Scene/Project 操作
2. **Inspector 没有 Add/Remove Component** - 无法添加/删除组件
3. **SceneViewPanel 完全是占位符** - 无法预览场景
4. **Project 拖拽移动失效** - HandleDrop() 返回 false
5. **缺少 5 个重要面板** - SettingsPanel, OverlayRenderPanel, MaterialEditorPanel, TextureConfigPanel, AssetManagerPanel
### 7.3 RHI 限制
当前 RHI 模块状态:
- D3D12: PipelineState 返回 nullptr无法创建 3D 渲染 Pipeline
- OpenGL: Framebuffer、PipelineState、Shader 正常工作
**影响**: 在 RHI 重构完成前3D Viewport 无法实现。
---
## 8. 改进计划
### 8.1 第一阶段: 完善现有面板功能
**目标**: 不依赖 RHI完善 Editor UI 功能
#### 8.1.1 MenuBar 菜单功能对接
```
优先级: 高
预计工作量: 1-2 天
依赖: 无
```
**需要实现**:
- File 菜单: New Scene, Open Scene, Save Scene, Exit
- Edit 菜单: Undo, Redo (需要命令历史系统), Cut, Copy, Paste
- View 菜单: Reset Layout
- Help 菜单: About
**实现方案**:
```cpp
// MenuBar.cpp
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {
m_onNewSceneCallback(); // 通过回调连接到 BosonLayer
}
```
#### 8.1.2 Inspector Add/Remove Component
```
优先级: 高
预计工作量: 2-3 天
依赖: 组件系统完善
```
**需要实现**:
1. 添加 "Add Component" 按钮
2. 分类组件菜单 (2D, 3D, Other)
3. 右键 "Remove Component" 选项
**实现方案**:
```cpp
// InspectorPanel.cpp
void InspectorPanel::drawComponent<T>(Entity entity, UIFunction uiFunction) {
// 右键菜单
if (ImGui::BeginPopupContextItem("ComponentSettings")) {
if (ImGui::MenuItem("Remove Component"))
entity.removeComponent<T>();
ImGui::EndPopup();
}
}
// Add Component 按钮
if (ImGui::Button("Add Component")) {
ImGui::OpenPopup("AddComponentMenu");
}
// 分类显示组件列表
```
#### 8.1.3 修复 Project 拖拽移动
```
优先级: 中
预计工作量: 0.5 天
依赖: 无
```
**问题**: `HandleDrop()` 返回 false从未被调用
**修复方案**: 在双击打开文件夹时,检查是否正在拖拽,如果是则执行移动操作。
---
### 8.2 第二阶段: Inspector 组件系统完善
**目标**: 实现完整的组件编辑功能
#### 8.2.1 Inspector 组件编辑支持
Engine 核心已有完整组件系统Editor Inspector 需要添加对这些组件的编辑支持:
| 组件 | Engine 状态 | Inspector 编辑复杂度 | 说明 |
|------|------------|---------------------|------|
| TransformComponent | ✅ | 低 | 需改进 UI (drawVec3Control) |
| MeshRendererComponent | ✅ | 中 | 需添加拖拽、预览 |
| CameraComponent | ✅ | 中 | 投影、FOV、近远裁剪 |
| DirectionalLightComponent | ✅ | 低 | 颜色、强度 |
| PointLightComponent | ✅ | 低 | 颜色、强度、范围 |
| SpotLightComponent | ✅ | 中 | 颜色、强度、范围、角度 |
| Rigidbody2DComponent | ✅ | 高 | 物理引擎对接 |
| Rigidbody3DComponent | ✅ | 高 | 物理引擎对接 |
| Collider2D/3D | ✅ | 高 | 碰撞体 |
| SpriteRendererComponent | ✅ | 中 | 2D 精灵 |
| CircleRendererComponent | ✅ | 低 | 圆形渲染 |
| TextComponent | ✅ | 中 | 文本渲染 |
| ScriptComponent | ✅ | 高 | 脚本字段编辑 |
#### 8.2.2 Transform UI 改进
**当前**:
```cpp
ImGui::DragFloat3("##Position", transform->position, 0.1f);
```
**改进方案** (参考 Fermion `ui::drawVec3Control`):
- 添加 XYZ 标签
- 添加 Per-axis reset 按钮
- 统一对齐和缩进
- 添加合适的刻度 (speed)
---
### 8.3 第三阶段: 场景序列化
**目标**: 实现 Scene Save/Load
```
优先级: 中
预计工作量: 2-3 天
依赖: Scene 序列化框架 (Engine Scene 类已有基础 Serialize/Deserialize)
```
**需要实现**:
- Scene 序列化到文件 (Engine 核心已有基础)
- Scene 反序列化
- 资源路径管理
- Editor/Runtime 场景分离
---
### 8.4 第四阶段: 3D Viewport (依赖 RHI)
**目标**: 实现完整的 3D Viewport
```
优先级: 高 (但依赖 RHI)
预计工作量: 2-4 周
依赖: RHI 重构完成
```
#### 8.4.1 OpenGL Backend 优先方案
由于 D3D12 PipelineState 当前 broken可以先用 OpenGL Backend 实现 Viewport
**优势**:
- OpenGL Framebuffer 正常工作
- OpenGL PipelineState 正常工作
- Shader uniform 设置正常工作
**需要工作**:
1. EditorCamera 实现 (Orbit/Pan/Zoom)
2. SceneRenderer 中间层
3. ViewportPanel Framebuffer 渲染
4. 鼠标拾取 (readPixel from entity ID attachment)
5. ImGuizmo 集成
#### 8.4.2 实现步骤
**Step 1: EditorCamera** (3-5 天)
```cpp
class EditorCamera {
// Orbit 模式
void orbit(float deltaX, float deltaY);
void pan(float deltaX, float deltaY);
void zoom(float delta);
// FPS 模式
void moveForward(float delta);
void moveRight(float delta);
};
```
**Step 2: SceneRenderer 中间层** (1 周)
```cpp
class ViewportRenderer {
std::shared_ptr<Framebuffer> m_framebuffer;
std::shared_ptr<Scene> m_scene;
void beginScene(const EditorCamera& camera);
void submitMesh(MeshComponent& mesh, glm::mat4 transform);
void endScene();
};
```
**Step 3: ViewportPanel 集成** (3-5 天)
```cpp
void ViewportPanel::onImGuiRender() {
// 渲染到 framebuffer
m_framebuffer->bind();
m_viewportRenderer->beginScene(m_editorCamera);
// ... 提交场景物体
m_viewportRenderer->endScene();
m_framebuffer->unbind();
// 显示到 ImGui
ImGui::Image(m_framebuffer->getColorTexture(), ...);
// 鼠标拾取
int entityID = m_framebuffer->readPixel(1, pixelX, pixelY);
}
```
**Step 4: ImGuizmo 集成** (2-3 天)
```cpp
ImGuizmo::SetOrthographic(isOrthographic);
ImGuizmo::SetRect(viewportBounds);
ImGuizmo::Manipulate(
cameraView, cameraProjection,
operation, LOCAL,
glm::value_ptr(worldTransform)
);
```
---
### 8.5 第五阶段: Play/Edit 模式
**目标**: 实现场景状态切换
```
优先级: 中
预计工作量: 1-2 周
依赖: 3D Viewport + 组件系统
```
**状态机**:
```cpp
enum class SceneState { Edit, Play, Simulate };
void BosonLayer::onScenePlay() {
m_runtimeScene = Scene::copy(m_editorScene);
m_activeScene = m_runtimeScene;
m_activeScene->onRuntimeStart();
}
void BosonLayer::onSceneStop() {
m_activeScene->onRuntimeStop();
m_activeScene = m_editorScene;
}
```
---
## 9. 技术债务
### 9.1 架构问题
1. **Editor 和 Engine 使用两套不同的 GameObject/Component 系统**
- **Editor** (`editor/src/Core/GameObject.h`): 简化版,使用 `float position[3]` 数组存储变换
- **Engine** (`engine/include/XCEngine/Components/`): 完整 ECS使用 `TransformComponent` 组件
- **后果**: Editor 无法直接使用 Engine 的组件系统,需要重新实现
- **建议**: Editor 应复用 Engine 的 Components::GameObject/Scene 系统
2. **Panel 独立设计 vs Layer 组合**
- Fermion: BosonLayer 组合所有面板,共享 Context
- XCEngine: 各 Panel 独立,通过 SceneManager 单例通信
3. **SceneManager 单例 vs Scene 指针传递**
- Editor 使用简化版 SceneManager与 Engine 的 Scene 类不兼容
- 建议: 考虑使用 Context 模式传递 Scene 引用
4. **缺少 BosonUI 自定义控件封装**
- Fermion 有 ui::drawVec3Control, ui::drawFloatControl 等
- XCEngine 直接使用原生 ImGui API代码重复
### 9.2 代码质量问题
1. **注释掉的代码** - 建议清理
2. **TODO/FIXME** - 建议跟踪
3. **Magic numbers** - 建议定义常量
---
## 10. 建议实施路线
### 短期 (1-2 周)
```
□ MenuBar 菜单功能对接
□ Inspector Add/Remove Component
□ 修复 Project 拖拽移动
□ Transform UI 改进
□ Console 命令输入
```
### 中期 (1-2 月RHI 完成后)
```
□ EditorCamera 实现
□ SceneRenderer 中间层
□ ViewportPanel 3D 渲染
□ 鼠标拾取
□ ImGuizmo 集成
□ Play/Edit/Simulate 模式
```
### 长期
```
□ 完整的 Inspector 组件编辑界面 (Engine 核心组件已有)
□ 场景序列化
□ 资源导入系统
□ 材质编辑器
□ 动画编辑器
□ OverlayRenderPanel (物理调试可视化)
□ TextureConfigPanel (纹理配置)
□ AssetManagerPanel (资源注册表)
□ SettingsPanel (编辑器设置)
□ Play/Edit/Simulate 模式切换
```
---
## 11. 参考资料
- Fermion Boson Editor 源码: `参考/Fermion/Boson/`
- XCEngine Editor 源码: `editor/`
- RHI 模块: `engine/include/XCEngine/RHI/`
---
*文档生成时间: 2026-03-24*
*最后更新: 2026-03-24 (更正 Component 系统描述,补充 Editor/Engine 架构问题)*

File diff suppressed because it is too large Load Diff

View File

@@ -1,410 +0,0 @@
# OpenGL 测试实施计划
## 1. 概述
本文档是 `docs/OpenGL后端测试设计.md` 的实施细化计划,基于设计文档中的 5 阶段实现优先级,结合 D3D12 测试经验54 个测试)制定。
### 1.1 目标
- 搭建完整的 OpenGL 后端测试框架
- 实现与 D3D12 对齐的 54+ 个测试用例
- 确保 CI 环境可用
- 支持无头渲染headless测试
### 1.2 测试组件总览
| # | 组件 | 测试数量 | 文件 | 优先级 |
|---|------|:--------:|------|:------:|
| 1 | OpenGLDevice | 6 | test_device.cpp | Phase 1 |
| 2 | OpenGLBuffer | 6 | test_buffer.cpp | Phase 1 |
| 3 | OpenGLFence | 5 | test_fence.cpp | Phase 1 |
| 4 | OpenGLTexture | 5 | test_texture.cpp | Phase 2 |
| 5 | OpenGLSampler | 4 | test_sampler.cpp | Phase 2 |
| 6 | OpenGLShader | 4 | test_shader.cpp | Phase 3 |
| 7 | OpenGLPipelineState | 3 | test_pipeline_state.cpp | Phase 3 |
| 8 | OpenGLVertexArray | 4 | test_vertex_array.cpp | Phase 3 |
| 9 | OpenGLCommandList | 8 | test_command_list.cpp | Phase 4 |
| 10 | OpenGLRenderTargetView | 4 | test_render_target_view.cpp | Phase 4 |
| 11 | OpenGLDepthStencilView | 4 | test_depth_stencil_view.cpp | Phase 4 |
| 12 | OpenGLSwapChain | 3 | test_swap_chain.cpp | Phase 5 |
| **总计** | | **56** | | |
---
## 2. 实施阶段
### Phase 1: 核心基础设施(约 1 天)
#### 2.1 创建目录结构
```
tests/RHI/OpenGL/
├── CMakeLists.txt
├── fixtures/
│ ├── OpenGLTestFixture.h
│ └── OpenGLTestFixture.cpp
└── Res/
├── Shader/
├── Texture/
└── Data/
```
#### 2.2 实现测试夹具
**OpenGLTestFixture** 是所有测试的基础:
| 功能 | 描述 |
|------|------|
| `SetUpTestSuite()` | 创建隐藏 GLFW 窗口和 GL 上下文 |
| `TearDownTestSuite()` | 销毁窗口,终止 GLFW |
| `SetUp()` | 确保上下文激活,清除 GL 错误 |
| `TearDown()` | 重置 GL 状态,检查泄漏 |
| `CheckGLError()` | 检查并报告 GL 错误 |
**GL 错误检查宏**
```cpp
#define GL_CLEAR_ERRORS() do { while (glGetError() != GL_NO_ERROR); } while(0)
#define GL_CHECK(call) do { call; ASSERT_TRUE(CheckGLError(__FILE__, __LINE__)); } while(0)
#define GL_EXPECT_SUCCESS(call) do { call; EXPECT_EQ(glGetError(), GL_NO_ERROR); } while(0)
```
#### 2.3 OpenGLDevice 测试6 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `CreateRenderWindow_ValidParams` | 窗口创建成功 |
| `CreateRenderWindow_DebugMode` | 调试模式创建 |
| `InitializeWithExistingWindow` | 现有窗口初始化 |
| `GetDeviceInfo_ReturnsValid` | 供应商/渲染器/版本信息 |
| `SwapBuffers_NoErrors` | 交换缓冲区无错误 |
| `PollEvents_ReturnsTrue` | 事件轮询正常 |
#### 2.4 OpenGLBuffer 测试6 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_VertexBuffer` | 顶点缓冲创建 |
| `Initialize_IndexBuffer` | 索引缓冲创建 |
| `Initialize_UniformBuffer` | Uniform 缓冲创建 |
| `Initialize_Dynamic` | 动态缓冲创建 |
| `Bind_Unbind` | 缓冲绑定/解绑 |
| `Map_Unmap` | 数据映射操作 |
#### 2.5 OpenGLFence 测试5 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_Unsignaled` | 未 signaled 状态创建 |
| `Initialize_Signaled` | signaled 状态创建 |
| `Signal_SetsValue` | Signal 设置值 |
| `Wait_Blocks` | Wait 阻塞等待 |
| `IsSignaled_ReturnsState` | signaled 状态查询 |
#### 2.6 验证步骤
```bash
# 构建
cmake --build build --config Debug
# 运行测试
./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.Device*:OpenGLTestFixture.Buffer*:OpenGLTestFixture.Fence*
# 预期结果
[==========] 17 tests from OpenGLTestFixture
[ PASSED ] 17 tests
```
---
### Phase 2: 资源管理(约 1 天)
#### 2.7 OpenGLTexture 测试5 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_2DTexture` | 2D 纹理创建 |
| `Initialize_CubeMap` | 立方体纹理创建 |
| `Bind_Unbind` | 纹理绑定/解绑 |
| `GenerateMipmap` | Mipmap 生成 |
| `SetFiltering_SetWrapping` | 过滤/环绕参数 |
#### 2.8 OpenGLSampler 测试4 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_Default` | 默认采样器创建 |
| `Initialize_Custom` | 自定义采样器创建 |
| `Bind_Unbind` | 采样器绑定/解绑 |
| `GetID_ReturnsValid` | 采样器 ID 有效 |
#### 2.9 验证步骤
```bash
# 运行资源管理测试
./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.Texture*:OpenGLTestFixture.Sampler*
# 预期结果
[==========] 9 tests from OpenGLTestFixture
[ PASSED ] 9 tests
```
---
### Phase 3: 渲染管线(约 1.5 天)
#### 2.10 OpenGLShader 测试4 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Compile_VertexFragment` | 顶点和片段着色器编译 |
| `Compile_WithGeometry` | 几何着色器编译 |
| `Compile_InvalidSource` | 无效源码编译失败 |
| `SetUniforms` | Uniform 设置 (int/float/vec3/mat4) |
#### 2.11 OpenGLPipelineState 测试3 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `SetDepthStencilState` | 深度/模板状态设置 |
| `SetBlendState` | 混合状态设置 |
| `SetViewport_SetScissor` | 视口/裁剪矩形 |
#### 2.12 OpenGLVertexArray 测试4 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_CreatesVAO` | VAO 创建 |
| `AddVertexBuffer` | 顶点缓冲添加 |
| `SetIndexBuffer` | 索引缓冲设置 |
| `Bind_Unbind` | VAO 绑定/解绑 |
#### 2.13 验证步骤
```bash
# 运行渲染管线测试
./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.Shader*:OpenGLTestFixture.PipelineState*:OpenGLTestFixture.VertexArray*
# 预期结果
[==========] 11 tests from OpenGLTestFixture
[ PASSED ] 11 tests
```
---
### Phase 4: 命令与视图(约 1.5 天)
#### 2.14 OpenGLCommandList 测试8 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Clear_ColorBuffer` | 清除颜色缓冲 |
| `Clear_DepthStencil` | 清除深度/模板 |
| `SetVertexBuffer` | 设置顶点缓冲 |
| `SetIndexBuffer` | 设置索引缓冲 |
| `Draw_Triangles` | 绘制三角形 |
| `DrawIndexed_Indices` | 索引绘制 |
| `DrawInstanced` | 实例化绘制 |
| `Dispatch_ComputeShader` | 计算着色器分发 |
#### 2.15 OpenGLRenderTargetView 测试4 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_Texture2D` | 2D 纹理 RTV 创建 |
| `Initialize_Default` | 默认帧缓冲 RTV |
| `Bind_Unbind` | RTV 绑定/解绑 |
| `Clear_Color` | 清除颜色 |
#### 2.16 OpenGLDepthStencilView 测试4 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_Texture2D` | 2D 纹理 DSV 创建 |
| `Initialize_DepthOnly` | 仅深度 DSV |
| `Bind_Unbind` | DSV 绑定/解绑 |
| `ClearDepthStencil` | 清除深度/模板 |
#### 2.17 验证步骤
```bash
# 运行命令与视图测试
./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.CommandList*:OpenGLTestFixture.RenderTargetView*:OpenGLTestFixture.DepthStencilView*
# 预期结果
[==========] 16 tests from OpenGLTestFixture
[ PASSED ] 16 tests
```
---
### Phase 5: 窗口管理(约 0.5 天)
#### 2.18 OpenGLSwapChain 测试3 个)
| 测试用例 | 验证内容 |
|----------|----------|
| `Initialize_Window` | 交换链初始化 |
| `Present_VSync` | 垂直同步显示 |
| `Resize_ChangesSize` | 调整大小 |
#### 2.19 验证步骤
```bash
# 运行窗口管理测试
./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.SwapChain*
# 预期结果
[==========] 3 tests from OpenGLTestFixture
[ PASSED ] 3 tests
```
---
## 3. 完整验证
### 3.1 运行所有测试
```bash
# 完整测试
cmake --build build --config Debug
ctest --test-dir build -C Debug --output-on-failure
# 预期结果
[==========] 56 tests from 1 test suite.
[ PASSED ] 56 tests
```
### 3.2 测试分类统计
| 分类 | 数量 | 占比 |
|------|:----:|:----:|
| 初始化测试 | 18 | 32% |
| 绑定/解绑测试 | 10 | 18% |
| 数据操作测试 | 8 | 14% |
| 状态设置测试 | 10 | 18% |
| 绘制/执行测试 | 10 | 18% |
---
## 4. CI 配置
### 4.1 GitHub Actions
```yaml
# .github/workflows/opengl-tests.yml
name: OpenGL Tests
on: [push, pull_request]
jobs:
test:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Configure
run: cmake -B build -S . -G "Visual Studio 17 2022"
- name: Build
run: cmake --build build --config Debug
- name: Run Tests
run: ctest --test-dir build -C Debug --output-on-failure
```
### 4.2 Linux CI可选
Linux 下需要配置 Mesa 软件渲染:
```yaml
- name: Run Tests
env:
MESA_GL_VERSION_OVERRIDE: 4.6
MESA_GALLIUM_DRIVER: llvmpipe
run: ctest --test-dir build -C Debug --output-on-failure
```
---
## 5. 任务清单
### 阶段 1基础设施
- [ ] 1.1 创建 `tests/RHI/OpenGL/CMakeLists.txt`
- [ ] 1.2 创建 `tests/RHI/OpenGL/fixtures/OpenGLTestFixture.h`
- [ ] 1.3 创建 `tests/RHI/OpenGL/fixtures/OpenGLTestFixture.cpp`
- [ ] 1.4 实现 `test_device.cpp`6 个测试)
- [ ] 1.5 实现 `test_buffer.cpp`6 个测试)
- [ ] 1.6 实现 `test_fence.cpp`5 个测试)
- [ ] 1.7 构建验证17 个测试)
### 阶段 2资源管理
- [ ] 2.1 实现 `test_texture.cpp`5 个测试)
- [ ] 2.2 实现 `test_sampler.cpp`4 个测试)
- [ ] 2.3 构建验证9 个测试)
### 阶段 3渲染管线
- [ ] 3.1 实现 `test_shader.cpp`4 个测试)
- [ ] 3.2 实现 `test_pipeline_state.cpp`3 个测试)
- [ ] 3.3 实现 `test_vertex_array.cpp`4 个测试)
- [ ] 3.4 构建验证11 个测试)
### 阶段 4命令与视图
- [ ] 4.1 实现 `test_command_list.cpp`8 个测试)
- [ ] 4.2 实现 `test_render_target_view.cpp`4 个测试)
- [ ] 4.3 实现 `test_depth_stencil_view.cpp`4 个测试)
- [ ] 4.4 构建验证16 个测试)
### 阶段 5窗口管理
- [ ] 5.1 实现 `test_swap_chain.cpp`3 个测试)
- [ ] 5.2 完整测试验证56 个测试)
- [ ] 5.3 提交并推送
---
## 6. 关键注意事项
### 6.1 窗口依赖
- OpenGL 必须有 GLFW 窗口上下文
- 使用 `GLFW_VISIBLE = GLFW_FALSE` 创建隐藏窗口
- 每个测试前 `glfwMakeContextCurrent()`
### 6.2 GL 状态污染
- OpenGL 状态是全局的,必须隔离
- `TearDown()` 中重置所有 GL 状态
- 测试结束后 `glBindBuffer(..., 0)`
### 6.3 错误检查
- 使用 `GL_CHECK()` 宏验证每个 GL 调用
- 测试开始时 `GL_CLEAR_ERRORS()`
- 捕获 GL 错误并转换为测试失败
### 6.4 与 D3D12 对齐
- 保持相同的测试数量级54+
- 使用相同的 TEST_F 宏
- 遵循相同的命名约定
---
## 7. 后续工作
- [ ] 资源泄漏检测工具
- [ ] 性能基准测试
- [ ] 截图对比测试
- [ ] Linux CI 配置
- [ ] macOS 支持
---
**文档版本**1.0
**创建日期**2026年3月17日
**基于文档**`docs/OpenGL后端测试设计.md``tests/RHI/D3D12/`

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,556 @@
# Renderer模块设计与实现
## 1. 背景
XCEngine 当前已经完成了较为可用的 RHI 抽象层,且已经具备:
- `Scene + GameObject + Component` 基础场景模型
- `CameraComponent` / `LightComponent` 等基础组件
- `Mesh` / `Material` / `Texture` / `Shader` 等资源类型
- D3D12 / OpenGL 双后端 RHI 抽象与测试体系
下一阶段不应该继续封闭式打磨 RHI而应该在 RHI 之上正式建立 **Renderer 模块**
这里的 Renderer 模块不是“最终形态的 SRP”而是
- 先建立一层 **原生渲染运行时**
- 先让场景对象能够以正式渲染链路被绘制
- 同时在设计上预留未来 **C# Scriptable Render PipelineSRP** 的接入点
也就是说,当前阶段的正确目标不是直接实现 Unity 的 URP/HDRP而是先建立一套 **与 Unity 渲染架构方向一致的原生基础层**,后续让 C# SRP 驱动它。
---
## 2. 设计目标
Renderer 模块的目标分为两层:
### 2.1 当前阶段目标
先完成一套最小但完整的原生渲染链路:
-`Scene` 中提取可渲染对象
- 通过 `Camera` 构建视图与投影数据
- 通过 `Material` / `Mesh` / `Texture` 构建 GPU 绘制数据
- 在 RHI 之上完成正式的 frame 渲染
- 支持 swapchain 输出与离屏输出
- 建立独立于 editor 的渲染宿主模型
### 2.2 面向未来 C# SRP 的目标
当前阶段的实现必须为后续演进预留稳定边界:
- 未来允许用 C# 定义 `RenderPipelineAsset` / `RenderPipeline`
- 未来允许用 C# 组织 render pass
- 未来允许 editor `SceneView` / `GameView` 通过同一套 renderer 输出
- 未来允许 C# 脚本控制 camera 渲染、pass 排序、目标输出与 command buffer
因此,当前阶段的原生 Renderer 不能做成一个写死的“大一统内建渲染函数”,而应该一开始就具备“可被上层 pipeline 驱动”的结构。
---
## 3. 与 Unity 渲染架构的对应关系
当前建议的路线与 Unity 的总体方向是对齐的,但要注意分层位置。
### 3.1 推荐分层
```text
Scene / Components / Resources
Renderer 模块(原生渲染运行时)
未来 C# SRP 层(脚本化渲染管线)
RHI 抽象层
D3D12 / OpenGL / Vulkan 后端
```
### 3.2 各层职责
#### Scene / Components / Resources
负责描述“要渲染什么”,例如:
- 场景对象
- 相机
- 灯光
- 网格
- 材质
- 贴图
这一层不应该直接持有后端 API 对象。
#### Renderer 模块(本阶段核心)
负责描述“如何从场景变成 draw call”例如
- 渲染对象抽取
- 可见性裁剪
- GPU 资源缓存
- camera frame 数据组织
- render target / depth target 管理
- render pass 调度
- 内建前向管线
这一层是未来 C# SRP 的原生支撑层。
#### 未来 C# SRP 层
负责描述“以脚本方式控制渲染流程”,例如:
- `RenderPipelineAsset`
- `RenderPipeline`
- `ScriptableRenderContext`
- `CommandBuffer`
- `RenderPassEvent`
- pass 注入与重排
这一层不应该直接绕过 Renderer 模块去操作后端 API。
#### RHI 抽象层
负责统一 GPU 接口与资源对象,是渲染系统的执行后端,而不是场景渲染逻辑本身。
### 3.3 与 Unity 的概念映射
| Unity 概念 | XCEngine 当前/规划对应 |
|---|---|
| `Camera` | `CameraComponent` |
| `Light` | `LightComponent` |
| `MeshFilter` | 计划新增 `MeshFilterComponent` |
| `MeshRenderer` | 计划新增 `MeshRendererComponent` |
| `RenderPipelineAsset` | 未来 Renderer 模块上的 pipeline asset 抽象 |
| `RenderPipeline` | 未来 Renderer 模块上的 pipeline 实例抽象 |
| `ScriptableRenderContext` | 未来 Renderer 模块对脚本暴露的原生 render context |
| `CommandBuffer` | 未来 Renderer 模块对脚本暴露的命令缓冲抽象 |
| `GraphicsDevice` / native render backend | 当前 RHI + 后端实现 |
结论是:
- **方向上符合 Unity 渲染架构**
- **当前阶段实现的应是 Unity 渲染体系中的原生底座**
- **而不是直接跳到最终的脚本化 SRP**
---
## 4. 核心设计原则
### 4.1 先建立原生渲染运行时,再开放脚本化管线
如果现在直接做 C# SRP而原生 Renderer 边界还不存在,后续会出现:
- C# API 直接耦合 RHI
- editor viewport 与 runtime camera 逻辑混杂
- 资源对象与 GPU 对象生命周期混乱
因此必须先收敛原生 Renderer 模块。
### 4.2 Scene 层只描述逻辑对象,不持有后端对象
`GameObject``Component``Mesh``Material` 等对象只能描述逻辑与资源,不应该直接持有 D3D12/OpenGL 私有对象。
GPU 对象应由 Renderer 内部缓存层负责创建和复用。
### 4.3 editor 只是渲染宿主,不是渲染逻辑本体
`GameView` / `SceneView` 最终只是 Renderer 的输出宿主。
Renderer 本身必须先支持:
- 输出到 swapchain
- 输出到离屏纹理
然后 editor 再把离屏纹理接进 ImGui 面板。
### 4.4 为未来 SRP 预留 pipeline 抽象
即使第一阶段先做内建前向渲染,也不应该把逻辑写死成单一 `SceneRenderer::DrawEverything()`
应该从一开始就保留:
- `RenderPipeline`
- `RenderPipelineAsset`
- `RenderContext`
- camera 列表驱动
- pass 分阶段执行
这样未来 C# 只是在这个原生结构上做绑定,而不是重做一遍架构。
### 4.5 测试体系与渲染层分离
`tests/RHI/` 继续只验证 RHI。
Renderer 模块应建立自己的测试体系:
- `tests/Rendering/unit/`
- `tests/Rendering/integration/`
这样职责边界才清晰。
---
## 5. 模块划分建议
建议新增 `Rendering` 模块,作为场景与 RHI 之间的正式中间层。
### 5.1 推荐目录结构
```text
engine/
├── include/XCEngine/Rendering/
│ ├── RenderSurface.h
│ ├── RenderContext.h
│ ├── RenderPipeline.h
│ ├── RenderPipelineAsset.h
│ ├── SceneRenderer.h
│ ├── RenderSceneExtractor.h
│ ├── RenderCameraData.h
│ ├── VisibleRenderObject.h
│ ├── RenderResourceCache.h
│ └── Pipelines/
│ └── BuiltinForwardPipeline.h
└── src/Rendering/
├── RenderSurface.cpp
├── SceneRenderer.cpp
├── RenderSceneExtractor.cpp
├── RenderResourceCache.cpp
└── Pipelines/
└── BuiltinForwardPipeline.cpp
```
### 5.2 组件层建议
为了尽可能对齐 Unity而不是做一个临时过渡方案建议直接采用
- `MeshFilterComponent`
- `MeshRendererComponent`
其中:
#### `MeshFilterComponent`
负责“这个对象使用哪一个 mesh”
- `ResourceHandle<Mesh>`
#### `MeshRendererComponent`
负责“这个对象如何被渲染”:
- 材质数组
- cast shadow / receive shadow
- render queue / layer / enable 状态
- 未来可扩展 light probe / motion vector / static batching 标记
这样做的好处是:
- 更贴近 Unity 的对象模型
- 更容易映射未来 C# API
- 更容易在 editor Inspector 中呈现
- 更容易为 `SkinnedMeshRenderer``SpriteRenderer` 等后续组件扩展留位置
### 5.3 Renderer 内部运行时对象
#### `RenderSurface`
统一表示渲染输出目标:
- 交换链输出
- 离屏 color/depth 输出
- editor viewport 输出
#### `RenderSceneExtractor`
负责从 `Scene` 中提取本帧可渲染对象:
- mesh
- material
- transform
- bounds
- render state
#### `RenderResourceCache`
负责把资源模块对象转成 GPU 可用对象:
- mesh -> vertex/index buffer
- texture -> RHI texture / resource view
- material -> descriptor set / uniform buffer / pipeline key
- shader pass -> pipeline state
#### `RenderContext`
作为原生渲染执行上下文,未来用于承接脚本化 pipeline 的调度。
它应封装:
- 当前 frame 的 command list
- render target 设置
- clear / draw / submit
- camera 相关渲染上下文
#### `RenderPipeline`
用于抽象具体渲染流程。
第一阶段只有一个原生内建实现:
- `BuiltinForwardPipeline`
未来再开放:
- native 可切换 pipeline
- C# 绑定的 scriptable pipeline
---
## 6. 第一阶段实现边界
第一阶段只做最小可用链路,不做“大而全”。
### 6.1 第一阶段要做
- `Rendering` 模块骨架
- `MeshFilterComponent` / `MeshRendererComponent`
- `RenderSurface`
- `RenderSceneExtractor`
- `RenderResourceCache`
- `SceneRenderer`
- `BuiltinForwardPipeline`
- 单 camera
- 单方向的 opaque forward 渲染
- 深度测试与深度写入
- 交换链输出
- 离屏输出
### 6.2 第一阶段先不做
- 阴影
- 后处理
- 延迟渲染
- 完整 PBR
- render graph
- C# SRP 真正落地
- editor viewport 完整交互
- 多 camera 叠加
### 6.3 第一阶段材质能力建议
建议先支持两档:
1. `UnlitTexture`
2. `SimpleLit`
其中:
- `UnlitTexture` 用于先打通最小链路
- `SimpleLit` 用于验证灯光、法线与材质基础通路
---
## 7. 面向未来 C# SRP 的预留设计
虽然第一阶段先做原生内建渲染,但必须提前约束下面这些方向。
### 7.1 先定义 pipeline 边界,再定义内建实现
正确顺序应当是:
1. 先定义 `RenderPipeline` 抽象
2. 再实现 `BuiltinForwardPipeline`
3. 后续 C# SRP 只是在这个边界上做脚本绑定
而不是:
1. 先写死一个 `SceneRenderer`
2. 以后再强行拆成 pipeline
第二种方式后续返工会很大。
### 7.2 Renderer 模块应向未来脚本层暴露的概念
当前阶段不一定全部实现,但结构上要留位置:
- `RenderPipelineAsset`
- `RenderPipeline`
- `RenderContext`
- `CullingResults`
- `DrawingSettings`
- `FilteringSettings`
- `ShaderTag`
- `CommandBuffer`
- `RendererList`
这些概念不一定要立刻与 Unity 一字不差,但应该在职责上能对应上。
### 7.3 材质与 Shader 资产模型不能停留在“单 shader 文件 + 属性包”
未来做 SRP 时shader pass 选择、render queue、tag、render state 都是必要能力。
因此当前阶段即使先不全量实现,也不能把资产模型彻底锁死在过于简单的结构上。
这一点单独列为 issue。
---
## 8. 分阶段推进建议
### 阶段 ARenderer v0 骨架
目标:
- 建立 `Rendering` 模块
- 建立 `MeshFilterComponent` / `MeshRendererComponent`
- 建立 `RenderSurface`
- 建立 `BuiltinForwardPipeline`
验收:
- 可以通过 Renderer 正式绘制一个 textured quad 场景
- 输出到 swapchain
- 输出到离屏 RT
### 阶段 B真实资源场景接入
目标:
- 接入 mesh / texture / material 资源模块
- 跑通 `backpack` 这样的真实模型场景
验收:
- 真实 obj 资源经资源模块导入后可通过 Renderer 正式绘制
- D3D12 / OpenGL 双后端结果一致
### 阶段 C基础光照
目标:
- 接入 `LightComponent`
- 跑通最基础的单方向光前向渲染
验收:
- `sphere` / `backpack` 存在正确基础明暗
- 材质参数与法线链路可验证
### 阶段 Dpipeline 抽象显式化
目标:
- 把内建前向渲染切到 `RenderPipeline` 抽象之下
- 支持 camera 列表驱动
- 为未来 C# SRP 绑定准备原生接口
验收:
- 原生内建 pipeline 通过统一接口驱动
- renderer 不再依赖单一路径写死执行
### 阶段 Eeditor viewport 接入
目标:
- `SceneView` / `GameView` 使用 Renderer 的离屏输出
验收:
- editor 面板只是渲染宿主
- 不额外复制一套渲染逻辑
### 阶段 FC# SRP 桥接
目标:
- 在既有 Renderer 模块基础上绑定脚本化 pipeline
验收:
- C# 可以控制 camera 渲染流程
- 原生 Renderer 继续负责底层资源、上下文与执行
---
## 9. 测试体系建议
Renderer 模块需要独立测试体系。
### 9.1 单元测试
建议放在:
- `tests/Rendering/unit/`
测试内容:
- render object 抽取
- material 参数打包
- pipeline key 构建
- GPU cache 命中与失效
- render surface 创建与 resize
### 9.2 集成测试
建议放在:
- `tests/Rendering/integration/`
建议场景:
1. `textured_quad_scene`
2. `backpack_scene`
3. `lit_sphere_scene`
仍然维持当前 RHI 抽象测试的好习惯:
- 一场景一张 `GT.ppm`
- D3D12 / OpenGL 都与同一张 GT 比对
### 9.3 与 RHI 测试的关系
`tests/RHI/` 继续用于验证:
- API 抽象正确性
- 后端行为一致性
- 资源 / 命令 /格式映射等底层问题
`tests/Rendering/` 则验证:
- 场景渲染链路
- 组件与资源到渲染结果的闭环
---
## 10. 当前已识别的不适配问题
以下问题不适合直接塞进本设计文档正文实现里,而应该独立跟踪:
1. `Scene / Components` 层还没有 `MeshFilter / MeshRenderer` 抽象
2. `Editor` 还没有 viewport 的离屏渲染宿主接入层
3. `Material / Shader` 资产模型还不足以支撑未来 SRP 的 pass/tag 语义
对应 issue
- `docs/issues/Renderer模块_Scene层缺少MeshFilter与MeshRenderer抽象.md`
- `docs/issues/Renderer模块_EditorViewport缺少RenderSurface接入层.md`
- `docs/issues/Renderer模块_Material与Shader资产模型暂不满足SRP演进需求.md`
---
## 11. 结论
当前 Renderer 阶段的正确方向是:
- 在 RHI 之上建立 **原生渲染运行时**
- 用它先承接基础前向渲染
- 同时提前为未来 **C# SRP** 留出清晰接口
因此,下一阶段的 Renderer 规划如果按本文执行,是与 Unity 渲染架构方向相容的,而且比“先做一个临时内建 renderer后面再拆”更稳。
一句话概括:
- **现在做的是 Unity 式渲染体系的原生底座**
- **以后在这个底座之上接 C# SRP**

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,335 +0,0 @@
# 第三阶段计划OpenGL 后端实现
> **目标**:实现 OpenGL 后端,完成 RHI 跨平台图形抽象
> **阶段**:第三阶段
> **前置依赖**:第二阶段 RHI 抽象层与 D3D12 后端
---
## 3.1 阶段目标
在已有 RHI 抽象层和 D3D12 后端的基础上,实现 OpenGL 后端:
- 复用现有抽象接口
- 对接 OpenGL (GLFW + GLAD)
- 支持最小渲染系统验证
---
## 3.2 目录结构
```
engine/include/XCEngine/RHI/OpenGL/
├── OpenGLCommon.h # OpenGL 公共定义与辅助函数
├── OpenGLEnum.h # RHI 枚举 → OpenGL 枚举转换层
├── OpenGLDevice.h # 设备初始化
├── OpenGLDevice.cpp
├── OpenGLSwapChain.h # 交换链GLFW 窗口)
├── OpenGLSwapChain.cpp
├── OpenGLCommandList.h # 命令列表封装
├── OpenGLCommandList.cpp
├── OpenGLBuffer.h # VBO/IBO/UBO 管理
├── OpenGLBuffer.cpp
├── OpenGLTexture.h # 纹理管理
├── OpenGLTexture.cpp
├── OpenGLShader.h # GLSL 着色器
├── OpenGLShader.cpp
├── OpenGLPipelineState.h # VAO + Program + State
├── OpenGLPipelineState.cpp
├── OpenGLRenderTarget.h # FBO + RTV
├── OpenGLRenderTarget.cpp
├── OpenGLDepthStencil.h # 深度模板
├── OpenGLDepthStencil.cpp
├── OpenGLDescriptorHeap.h # Texture Unit 模拟
├── OpenGLDescriptorHeap.cpp
├── OpenGLFence.h # 同步
├── OpenGLFence.cpp
├── OpenGLQueryHeap.h # 查询堆
├── OpenGLQueryHeap.cpp
├── OpenGLRootSignature.h # 简化实现
├── OpenGLRootSignature.cpp
├── OpenGLSampler.h # 采样器
├── OpenGLSampler.cpp
├── OpenGLResourceView.h # 视图基类
├── OpenGLResourceView.cpp
└── OpenGLRenderTargetView.h # 渲染目标视图
├── OpenGLRenderTargetView.cpp
├── OpenGLDepthStencilView.h
├── OpenGLDepthStencilView.cpp
├── OpenGLShaderResourceView.h
├── OpenGLShaderResourceView.cpp
├── OpenGLUnorderedAccessView.h
├── OpenGLUnorderedAccessView.cpp
├── OpenGLConstantBufferView.h
└── OpenGLConstantBufferView.cpp
```
---
## 3.3 任务拆分
### 3.3.1 基础准备
**任务 3.1OpenGLEnum.h - 枚举转换层**
实现 RHI 枚举到 OpenGL 枚举的转换:
- `Format``GLenum`
- `PrimitiveTopology``GLenum`
- `BlendOp` / `BlendFactor``GLenum`
- `ComparisonFunc``GLenum`
- `ResourceStates``GLenum` (简化)
- `ShaderType``GLenum`
**任务 3.2OpenGLCommon.h - 公共定义**
- OpenGL 初始化辅助函数
- 格式支持检测
- 错误检查宏
- GLAD 加载器封装
---
### 3.3.2 核心组件实现
**任务 3.3OpenGLDevice - 设备实现**
实现 `OpenGLDevice` 类:
- GLFW 窗口创建
- GLAD 初始化
- OpenGL 上下文配置
- 设备信息查询
```cpp
class OpenGLDevice : public IRHIDevice {
public:
bool Initialize(void* windowHandle, bool enableDebug = false);
GLFWwindow* GetWindow() const { return m_window; }
// IRHIDevice 实现...
private:
GLFWwindow* m_window;
HGLRC m_glContext;
};
```
**任务 3.4OpenGLSwapChain - 交换链实现**
实现 `OpenGLSwapChain` 类:
- GLFW 窗口管理
- 双缓冲切换
- 帧缓冲 resize 处理
**任务 3.5OpenGLShader - 着色器实现**
实现 `OpenGLShader` 类:
- GLSL 源码加载
- `glShaderSource` + `glCompileShader`
- 编译错误获取
- 反射数据提取(可选)
**任务 3.6OpenGLBuffer - 缓冲区实现**
实现 `OpenGLBuffer` 类:
- VBO 创建与管理
- IBO 索引缓冲
- UBO uniform 缓冲
- Buffer mapping
**任务 3.7OpenGLTexture - 纹理实现**
实现 `OpenGLTexture` 类:
- 2D 纹理创建
- 纹理参数设置
- Mipmap 生成
- 纹理绑定
**任务 3.8OpenGLPipelineState - 管线状态实现**
实现 `OpenGLPipelineState` 类:
- VAO 管理
- Shader Program 链接
- 状态缓存blend, depth, rasterizer
- 输入布局映射
**任务 3.9OpenGLCommandList - 命令列表实现**
实现 `OpenGLCommandList` 类:
- 状态缓存与批量提交
- `glDrawArrays` / `glDrawElements` 封装
- 视口裁剪设置
- 渲染目标绑定
**任务 3.10OpenGLFence - 同步实现**
实现 `OpenGLFence` 类:
- `glFenceSync` 封装
- CPU 等待实现
**任务 3.11OpenGLDescriptorHeap - 描述符堆实现**
实现 `OpenGLDescriptorHeap` 类:
- Texture Unit 数组管理
- 简化版描述符绑定
---
### 3.3.3 视图实现
**任务 3.12OpenGLRenderTargetView - 渲染目标视图**
- Framebuffer 对象管理
- 颜色附件绑定
**任务 3.13OpenGLDepthStencilView - 深度模板视图**
- Depth/stencil buffer 管理
- FBO 深度附件
**任务 3.14OpenGLShaderResourceView - 着色器资源视图**
- 纹理视图绑定到 Texture Unit
**任务 3.15OpenGLUnorderedAccessView - 无序访问视图**
- SSBO 管理
**任务 3.16OpenGLConstantBufferView - 常量缓冲区视图**
- UBO 绑定
---
## 3.4 D3D12 与 OpenGL 关键差异
| D3D12 组件 | OpenGL 对应 | 差异说明 |
|------------|-------------|----------|
| `ID3D12Device` | `OpenGLDevice` | GLFW + GLAD 初始化 |
| `ID3D12CommandQueue` | 简化 | OpenGL 无需显式命令队列 |
| `ID3D12CommandList` | `OpenGLCommandList` | 封装立即模式渲染 |
| `ID3D12DescriptorHeap` | `OpenGLDescriptorHeap` | 使用 Texture Unit 模拟 |
| `ID3D12PipelineState` | `OpenGLPipelineState` | VAO + Program + State |
| `ID3D12RootSignature` | 简化 | 使用 uniform binding |
| `ID3D12Fence` | `OpenGLFence` | glFenceSync |
| `ID3D12SwapChain` | `OpenGLSwapChain` | GLFW 窗口管理 |
| `ID3D12Buffer` | `OpenGLBuffer` | VBO/IBO/UBO |
| `ID3D12Texture` | `OpenGLTexture` | GL 纹理对象 |
| `ID3D12Shader` | `OpenGLShader` | GLSL 编译 |
| `ID3D12QueryHeap` | `OpenGLQueryHeap` | GL 查询对象 |
---
## 3.5 实现顺序
```
阶段 3.1: 基础准备 (1天)
├── 3.1.1 OpenGLEnum.h (枚举转换)
└── 3.1.2 OpenGLCommon.h (公共定义)
阶段 3.2: 核心组件 (4天)
├── 3.2.1 OpenGLDevice
├── 3.2.2 OpenGLSwapChain
├── 3.2.3 OpenGLShader
├── 3.2.4 OpenGLBuffer
├── 3.2.5 OpenGLTexture
├── 3.2.6 OpenGLPipelineState
└── 3.2.7 OpenGLCommandList
阶段 3.3: 辅助组件 (2天)
├── 3.3.1 OpenGLFence
├── 3.3.2 OpenGLDescriptorHeap
├── 3.3.3 OpenGLQueryHeap
├── 3.3.4 OpenGLSampler
└── 3.3.5 OpenGLRootSignature
阶段 3.4: 视图实现 (1天)
├── 3.4.1 OpenGLRenderTargetView
├── 3.4.2 OpenGLDepthStencilView
├── 3.4.3 OpenGLShaderResourceView
├── 3.4.4 OpenGLUnorderedAccessView
└── 3.4.5 OpenGLConstantBufferView
阶段 3.5: 集成测试 (1天)
├── 窗口创建与渲染循环
├── 简单模型渲染测试
└── 与 mvs/OpenGL 功能对比验证
```
---
## 3.6 关键技术点
### 3.6.1 状态管理
OpenGL 是状态机模式:
-`OpenGLCommandList` 中缓存当前状态
- 绘制前检查状态变化,仅调用变化的 GL 函数
- 避免冗余状态设置
### 3.6.2 资源绑定
D3D12: Descriptor Heap + Root Signature
OpenGL: Texture Unit + Uniform Location
```cpp
// OpenGL 方式
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(location, slot);
```
### 3.6.3 着色器编译
```cpp
// GLSL 编译
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, nullptr);
glCompileShader(vertexShader);
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
```
### 3.6.4 VAO 管理
```cpp
// Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
```
### 3.6.5 帧缓冲
```cpp
// Framebuffer Object
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthID, 0);
```
---
## 3.7 验收标准
1. **编译通过**:所有头文件和实现文件能够无错误编译
2. **接口完整**:所有 RHI 抽象接口都有 OpenGL 实现
3. **功能验证**
- 能够创建 GLFW 窗口并初始化 OpenGL 上下文
- 能够渲染简单的几何体
- 能够加载和显示纹理
- 能够呈现到屏幕
4. **功能对比**:与现有 mvs/OpenGL 功能一致
---
## 3.8 后续阶段依赖
- 第四阶段渲染管线RenderPipeline需要 RHI 多后端支持
- 材质系统需要统一的 Shader 接口
- 跨平台渲染验证需要 OpenGL 后端

View File

@@ -1,829 +0,0 @@
# 第二阶段计划RHI 渲染硬件抽象层
> **目标**构建跨平台的渲染硬件抽象层支持多后端D3D12、Vulkan等
> **阶段**:第二阶段
> **前置依赖**:第一阶段核心基础层(数学库、内存管理、线程系统)
---
## 2.1 阶段目标
实现完整的RHI抽象层提供
- 统一的图形API抽象接口
- D3D12后端完整实现
- 资源管理(纹理、缓冲区)
- 命令流提交机制
- 同步与同步原语
---
## 2.2 目录结构
```
engine/include/XCEngine/RHI/ # 渲染硬件抽象层公开API
├── Enums.h # 枚举定义(独立编号,跨平台)
├── Types.h # 通用类型定义
├── RHISystem.h # RHI 系统入口
├── RHIDevice.h # 抽象设备接口
├── Resource.h # 资源基类接口
├── ResourceView.h # 资源视图基类接口
├── RenderTargetView.h # 渲染目标视图接口
├── DepthStencilView.h # 深度模板视图接口
├── ShaderResourceView.h # 着色器资源视图接口
├── UnorderedAccessView.h # 无序访问视图接口
├── ConstantBufferView.h # 常量缓冲区视图接口
├── CommandQueue.h # 命令队列
├── CommandList.h # 命令列表
├── CommandAllocator.h # 命令分配器
├── Fence.h # 同步围栏
├── DescriptorHeap.h # 描述符堆
├── QueryHeap.h # 查询堆
├── RootSignature.h # 根签名
├── PipelineState.h # 管线状态
├── Sampler.h # 采样器
├── SwapChain.h # 交换链
├── Texture.h # 纹理资源
├── Buffer.h # 缓冲区资源
├── Shader.h # 着色器
└── D3D12/ # D3D12 后端实现
├── D3D12Enum.h # 枚举转换层RHI→D3D12
├── D3D12Device.h
├── D3D12Device.cpp
├── D3D12CommandList.h
├── D3D12CommandList.cpp
├── D3D12CommandQueue.h
├── D3D12CommandQueue.cpp
├── D3D12CommandAllocator.h
├── D3D12CommandAllocator.cpp
├── D3D12Fence.h
├── D3D12Fence.cpp
├── D3D12DescriptorHeap.h
├── D3D12DescriptorHeap.cpp
├── D3D12QueryHeap.h
├── D3D12QueryHeap.cpp
├── D3D12RootSignature.h
├── D3D12RootSignature.cpp
├── D3D12PipelineState.h
├── D3D12PipelineState.cpp
├── D3D12Sampler.h
├── D3D12Sampler.cpp
├── D3D12SwapChain.h
├── D3D12SwapChain.cpp
├── D3D12Texture.h
├── D3D12Texture.cpp
├── D3D12Buffer.h
├── D3D12Buffer.cpp
├── D3D12Shader.h
├── D3D12Shader.cpp
├── D3D12RenderTargetView.h
├── D3D12RenderTargetView.cpp
├── D3D12DepthStencilView.h
├── D3D12DepthStencilView.cpp
├── D3D12ShaderResourceView.h
├── D3D12ShaderResourceView.cpp
├── D3D12UnorderedAccessView.h
├── D3D12UnorderedAccessView.cpp
├── D3D12ConstantBufferView.h
├── D3D12ConstantBufferView.cpp
└── D3D12Common.h # 公共定义
```
---
## 2.3 任务拆分
### 2.3.1 基础枚举与类型定义
**任务 2.1Enums.h - 枚举定义**
定义所有渲染相关的枚举类型:
- `Format` - 像素格式
- `ResourceStates` - 资源状态
- `ShaderType` - 着色器类型
- `PrimitiveTopology` - 图元拓扑
- `CullMode` / `FillMode` - 剔除/填充模式
- `BlendOp` / `BlendFactor` - 混合操作/因子
- `ComparisonFunc` - 比较函数
- `StencilOp` - 模板操作
- `TextureType` - 纹理类型
- `BufferType` - 缓冲区类型
- `QueryType` - 查询类型
- `DescriptorType` - 描述符类型
- `PipelineType` - 管线类型
- `CommandQueueType` - 命令队列类型
- `LoadAction` / `StoreAction` - 渲染目标加载/存储操作
- `PresentFlags` - 呈现标志
- `IndirectDrawArguments` - 间接绘制参数
- `IndirectDispatchArguments` - 间接调度参数
**任务 2.1.2:类型定义 - Types.h**
定义通用结构体不依赖特定图形API
- `Viewport` - 视口
- `Rect` - 矩形区域
- `Color` - 颜色
- `ClearValue` - 清空值
- `ShaderCompileDesc` - 着色器编译描述
- `ShaderCompileResult` - 着色器编译结果
- `ShaderCompileMacro` - 着色器宏定义
- `InputElementDesc` - 输入元素描述
- `InputLayoutDesc` - 输入布局描述
- `VertexBufferBinding` - 顶点缓冲区绑定
- `TextureCopyLocation` - 纹理复制位置
- `DescriptorHandle` - 描述符句柄(通用类型)
- `GPUDescriptorHandle` - GPU描述符句柄
- `CPUDescriptorHandle` - CPU描述符句柄
- `ResourceBarrierDesc` - 资源屏障描述
- `SubresourceRange` - 子资源范围
- `TextureDesc` - 纹理描述
- `BufferDesc` - 缓冲区描述
- `RenderTargetDesc` - 渲染目标描述
- `DepthStencilDesc` - 深度模板描述
- `DescriptorHeapDesc` - 描述符堆描述
- `CommandQueueDesc` - 命令队列描述
- `CommandListDesc` - 命令列表描述
- `CommandAllocatorDesc` - 命令分配器描述
- `FenceDesc` - 围栏描述
- `QueryHeapDesc` - 查询堆描述
- `RootSignatureDesc` - 根签名描述
- `SamplerDesc` - 采样器描述
- `PipelineStateDesc` - 管线状态描述
- `SwapChainDesc` - 交换链描述
- `BlendStateDesc` - 混合状态描述
- `DepthStencilStateDesc` - 深度模板状态描述
- `RasterizerStateDesc` - 光栅化状态描述
- `ShaderBytecode` - 着色器字节码
- `ShaderBindingInfo` - 着色器绑定信息
- `RenderTargetViewDesc` - 渲染目标视图描述
- `DepthStencilViewDesc` - 深度模板视图描述
- `ShaderResourceViewDesc` - 着色器资源视图描述
- `UnorderedAccessViewDesc` - 无序访问视图描述
- `ConstantBufferViewDesc` - 常量缓冲区视图描述
- `FormatSupport` - 格式支持信息
### 2.3.2 核心接口定义
**任务 2.2RHISystem.h - RHI系统入口**
```cpp
struct RHISystemConfig {
void* nativeWindowHandle = nullptr; // HWND on Windows
uint32_t width = 1280;
uint32_t height = 720;
bool fullscreen = false;
uint32_t backBufferCount = 2;
bool enableDebugLayer = false;
bool enableGBV = false;
};
class RHISystem {
public:
static RHISystem& Get();
bool Initialize(const RHISystemConfig& config);
void Shutdown();
IRHIDevice* GetDevice();
ISwapChain* GetSwapChain();
void BeginFrame();
void EndFrame();
// 窗口管理
void Resize(uint32_t width, uint32_t height);
void SetFullscreen(bool fullscreen);
bool IsFullscreen() const;
private:
std::unique_ptr<IRHIDevice> m_device;
std::unique_ptr<ISwapChain> m_swapChain;
};
```
**任务 2.3RHIDevice.h - 抽象设备接口**
```cpp
struct DeviceInfo {
String deviceName;
String driverVersion;
uint64_t dedicatedVideoMemory;
uint64_t dedicatedSystemMemory;
uint64_t sharedSystemMemory;
uint32_t vendorId;
uint32_t deviceId;
bool supportsRaytracing;
bool supportsMeshShaders;
bool supportsSamplerFeedback;
};
class IRHIDevice {
public:
virtual ~IRHIDevice() = default;
// 资源创建
virtual ICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) = 0;
virtual ICommandList* CreateCommandList(const CommandListDesc& desc) = 0;
virtual ICommandAllocator* CreateCommandAllocator(const CommandAllocatorDesc& desc) = 0;
virtual IFence* CreateFence(const FenceDesc& desc) = 0;
virtual IDescriptorHeap* CreateDescriptorHeap(const DescriptorHeapDesc& desc) = 0;
virtual IQueryHeap* CreateQueryHeap(const QueryHeapDesc& desc) = 0;
virtual IRootSignature* CreateRootSignature(const RootSignatureDesc& desc) = 0;
virtual IPipelineState* CreatePipelineState(const PipelineStateDesc& desc) = 0;
virtual ISampler* CreateSampler(const SamplerDesc& desc) = 0;
virtual ITexture* CreateTexture(const TextureDesc& desc) = 0;
virtual IBuffer* CreateBuffer(const BufferDesc& desc) = 0;
virtual ISwapChain* CreateSwapChain(const SwapChainDesc& desc) = 0;
// 视图创建
virtual IRenderTargetView* CreateRenderTargetView(IResource* resource, const RenderTargetViewDesc& desc) = 0;
virtual IDepthStencilView* CreateDepthStencilView(IResource* resource, const DepthStencilViewDesc& desc) = 0;
virtual IShaderResourceView* CreateShaderResourceView(IResource* resource, const ShaderResourceViewDesc& desc) = 0;
virtual IUnorderedAccessView* CreateUnorderedAccessView(IResource* resource, const UnorderedAccessViewDesc& desc) = 0;
virtual IConstantBufferView* CreateConstantBufferView(IResource* resource, const ConstantBufferViewDesc& desc) = 0;
// 着色器编译
virtual IShader* CompileShader(const ShaderCompileDesc& desc) = 0;
// 查询
virtual void GetDeviceInfo(DeviceInfo& info) const = 0;
virtual FormatSupport GetFormatSupport(Format format) const = 0;
};
```
**任务 2.4CommandQueue.h - 命令队列接口**
```cpp
class ICommandQueue {
public:
virtual ~ICommandQueue() = default;
virtual void ExecuteCommandLists(uint32_t count, ICommandList** lists) = 0;
virtual void Signal(IFence* fence, uint64_t value) = 0;
virtual void Wait(IFence* fence, uint64_t value) = 0;
virtual uint64_t GetCompletedValue() = 0;
virtual void WaitForIdle() = 0;
virtual CommandQueueType GetType() const = 0;
virtual uint64_t GetTimestampFrequency() const = 0;
};
```
**任务 2.5CommandList.h - 命令列表接口**
```cpp
class ICommandList {
public:
virtual ~ICommandList() = default;
// 状态转换
virtual void TransitionBarrier(uint32_t count, const ResourceBarrierDesc* barriers) = 0;
virtual void UAVBarrier(IResource* resource = nullptr) = 0;
virtual void AliasBarrier(IResource* before, IResource* after) = 0;
// 渲染状态
virtual void SetPipelineState(IPipelineState* pso) = 0;
virtual void SetRootSignature(IRootSignature* signature) = 0;
virtual void SetViewport(const Viewport& viewport) = 0;
virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0;
virtual void SetScissorRect(const Rect& rect) = 0;
virtual void SetScissorRects(uint32_t count, const Rect* rects) = 0;
virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0;
virtual void SetRenderTargets(uint32_t count, IResource** renderTargets, IResource* depthStencil) = 0;
// 绑定
virtual void SetVertexBuffer(uint32_t slot, IBuffer* buffer, uint32_t offset, uint32_t stride) = 0;
virtual void SetVertexBuffers(uint32_t startSlot, uint32_t count, const VertexBufferBinding* bindings) = 0;
virtual void SetIndexBuffer(IBuffer* buffer, uint32_t offset, Format indexFormat) = 0;
virtual void SetConstantBuffer(uint32_t rootParameterIndex, IBuffer* buffer, uint32_t offset, uint32_t size) = 0;
virtual void SetShaderResource(uint32_t rootParameterIndex, IResource* resource) = 0;
virtual void SetUnorderedAccess(uint32_t rootParameterIndex, IResource* resource) = 0;
virtual void SetDescriptorHeap(IDescriptorHeap* heap) = 0;
virtual void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, GPUDescriptorHandle baseHandle) = 0;
virtual void SetComputeDescriptorTable(uint32_t rootParameterIndex, GPUDescriptorHandle baseHandle) = 0;
// 渲染状态设置
virtual void SetStencilRef(uint8_t stencilRef) = 0;
virtual void SetBlendFactor(const float blendFactor[4]) = 0;
virtual void SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp) = 0;
// 绘制
virtual void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) = 0;
virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) = 0;
virtual void DrawInstancedIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0;
virtual void DrawIndexedInstancedIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0;
// 清空
virtual void ClearRenderTargetView(IResource* renderTarget, const float color[4]) = 0;
virtual void ClearDepthStencilView(IResource* depthStencil, uint32_t clearFlags, float depth, uint8_t stencil) = 0;
virtual void ClearUnorderedAccessView(IResource* unorderedAccess, const float values[4]) = 0;
// 复制
virtual void CopyResource(IResource* dst, IResource* src) = 0;
virtual void CopyBuffer(IBuffer* dst, uint64_t dstOffset, IBuffer* src, uint64_t srcOffset, uint64_t size) = 0;
virtual void CopyTexture(ITexture* dst, const TextureCopyLocation& dstLocation, ITexture* src, const TextureCopyLocation& srcLocation) = 0;
// 查询
virtual void BeginQuery(IQueryHeap* queryHeap, QueryType type, uint32_t index) = 0;
virtual void EndQuery(IQueryHeap* queryHeap, QueryType type, uint32_t index) = 0;
virtual void ResolveQuery(IQueryHeap* queryHeap, QueryType type, uint32_t startIndex, uint32_t count, IBuffer* resultBuffer, uint64_t resultOffset) = 0;
// 提交
virtual void Close() = 0;
virtual void Reset(ICommandAllocator* allocator) = 0;
// 计算着色器
virtual void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) = 0;
virtual void DispatchIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0;
// Bundle (用于命令复用)
virtual void ExecuteBundle(ICommandList* bundle) = 0;
};
```
**任务 2.6:其他核心接口**
- `Resource.h` - 资源基类接口(所有资源的共同基类)
- `ResourceView.h` - 资源视图基类接口
- `RenderTargetView.h` - 渲染目标视图接口
- `DepthStencilView.h` - 深度模板视图接口
- `ShaderResourceView.h` - 着色器资源视图接口
- `UnorderedAccessView.h` - 无序访问视图接口
- `ConstantBufferView.h` - 常量缓冲区视图接口
- `CommandAllocator.h` - 命令分配器接口
```cpp
class ICommandAllocator {
public:
virtual ~ICommandAllocator() = default;
virtual void Reset() = 0;
virtual bool IsReady() const = 0;
};
```
- `Fence.h` - 同步围栏接口
```cpp
class IFence {
public:
virtual ~IFence() = default;
virtual void Signal(uint64_t value) = 0;
virtual void Wait(uint64_t value) = 0;
virtual uint64_t GetCompletedValue() = 0;
virtual void* GetEventHandle() = 0;
};
```
- `DescriptorHeap.h` - 描述符堆接口
```cpp
class IDescriptorHeap {
public:
virtual ~IDescriptorHeap() = default;
virtual CPUDescriptorHandle GetCPUDescriptorHandle(uint32_t index) = 0;
virtual GPUDescriptorHandle GetGPUDescriptorHandle(uint32_t index) = 0;
virtual uint32_t GetDescriptorCount() const = 0;
virtual DescriptorType GetType() const = 0;
};
```
- `QueryHeap.h` - 查询堆接口
```cpp
class IQueryHeap {
public:
virtual ~IQueryHeap() = default;
virtual void* GetNativeHandle() const = 0;
virtual QueryType GetType() const = 0;
virtual uint32_t GetCount() const = 0;
};
```
- `RootSignature.h` - 根签名接口
```cpp
class IRootSignature {
public:
virtual ~IRootSignature() = default;
virtual void* GetNativeHandle() const = 0;
virtual uint32_t GetParameterCount() const = 0;
};
```
- `PipelineState.h` - 管线状态接口
```cpp
class IPipelineState {
public:
virtual ~IPipelineState() = default;
virtual void* GetNativeHandle() const = 0;
virtual PipelineType GetType() const = 0;
};
```
- `Sampler.h` - 采样器接口
```cpp
class ISampler {
public:
virtual ~ISampler() = default;
virtual void* GetNativeHandle() const = 0;
};
```
- `SwapChain.h` - 交换链接口
```cpp
class ISwapChain {
public:
virtual ~ISwapChain() = default;
virtual uint32_t GetCurrentBackBufferIndex() = 0;
virtual IResource* GetBackBuffer(uint32_t index) = 0;
virtual void Present(uint32_t syncInterval, PresentFlags flags) = 0;
virtual void Resize(uint32_t width, uint32_t height) = 0;
virtual void SetFullscreen(bool fullscreen) = 0;
virtual bool IsFullscreen() const = 0;
virtual void* GetNativeHandle() const = 0;
};
```
- `Texture.h` - 纹理资源接口
```cpp
class ITexture : public IResource {
public:
virtual uint32_t GetWidth() const = 0;
virtual uint32_t GetHeight() const = 0;
virtual uint32_t GetDepth() const = 0;
virtual uint32_t GetMipLevels() const = 0;
virtual uint32_t GetArraySize() const = 0;
virtual Format GetFormat() const = 0;
virtual TextureType GetTextureType() const = 0;
virtual IShaderResourceView* GetOrCreateSRV() = 0;
virtual IRenderTargetView* GetOrCreateRTV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0;
virtual IDepthStencilView* GetOrCreateDSV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0;
virtual IUnorderedAccessView* GetOrCreateUAV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0;
};
```
- `Buffer.h` - 缓冲区资源接口
```cpp
class IBuffer : public IResource {
public:
virtual uint64_t GetSize() const = 0;
virtual uint32_t GetStride() const = 0;
virtual BufferType GetBufferType() const = 0;
virtual IConstantBufferView* GetOrCreateCBV() = 0;
virtual IShaderResourceView* GetOrCreateSRV() = 0;
virtual IUnorderedAccessView* GetOrCreateUAV() = 0;
};
```
- `Shader.h` - 着色器接口
```cpp
class IShader {
public:
virtual ~IShader() = default;
virtual const void* GetBytecode() const = 0;
virtual size_t GetBytecodeSize() const = 0;
virtual ShaderType GetType() const = 0;
virtual const InputLayoutDesc& GetInputLayout() const = 0;
virtual const ShaderBindingInfo& GetBindingInfo() const = 0;
};
```
- `RenderTarget.h` - 渲染目标接口
```cpp
class IRenderTarget {
public:
virtual ~IRenderTarget() = default;
virtual ITexture* GetTexture() = 0;
virtual IRenderTargetView* GetRTV() = 0;
virtual uint32_t GetWidth() const = 0;
virtual uint32_t GetHeight() const = 0;
virtual Format GetFormat() const = 0;
};
```
- `DepthStencil.h` - 深度模板接口
```cpp
class IDepthStencil {
public:
virtual ~IDepthStencil() = default;
virtual ITexture* GetTexture() = 0;
virtual IDepthStencilView* GetDSV() = 0;
virtual IShaderResourceView* GetSRV() = 0;
virtual uint32_t GetWidth() const = 0;
virtual uint32_t GetHeight() const = 0;
virtual Format GetFormat() const = 0;
};
```
**任务 2.7Resource.h - 资源基类接口**
```cpp
class IResource {
public:
virtual ~IResource() = default;
virtual void* GetNativeHandle() const = 0;
virtual ResourceStates GetState() const = 0;
virtual void SetState(ResourceStates state) = 0;
virtual uint64_t GetGPUAddress() const = 0;
virtual size_t GetSize() const = 0;
virtual const String& GetName() const = 0;
virtual void SetName(const String& name) = 0;
};
```
**任务 2.8ResourceView.h - 资源视图基类接口**
```cpp
class IResourceView {
public:
virtual ~IResourceView() = default;
virtual void* GetNativeHandle() const = 0;
virtual IResource* GetResource() const = 0;
};
```
---
### 2.3.3 D3D12 后端实现
**任务 2.9D3D12Common.h - 公共定义**
D3D12相关的公共定义和辅助函数
- 格式转换映射
- 描述符大小计算
- 资源状态转换
- 辅助工具函数
**任务 2.10D3D12Device - 设备实现**
实现 `D3D12Device` 类:
- ID3D12Device 封装
- IDXGIFactory 创建与管理
- 所有资源创建接口实现
- 适配器信息查询
- 功能级别支持检测
- 内存信息查询
- 设备移除与恢复处理
**任务 2.11D3D12CommandQueue - 命令队列实现**
实现 `D3D12CommandQueue` 类:
- ID3D12CommandQueue 封装
- 命令列表执行
- 围栏同步
- 时间戳频率查询
**任务 2.12D3D12CommandList - 命令列表实现**
实现 `D3D12CommandList` 类:
- ID3D12GraphicsCommandList 封装
- 所有渲染命令实现
- 状态追踪与验证
- 资源追踪
**任务 2.13D3D12CommandAllocator - 命令分配器实现**
实现 `D3D12CommandAllocator` 类:
- ID3D12CommandAllocator 封装
- 重置管理
**任务 2.14D3D12Fence - 围栏实现**
实现 `D3D12Fence` 类:
- ID3D12Fence 封装
- CPU/GPU同步
- 事件句柄管理
**任务 2.15D3D12DescriptorHeap - 描述符堆实现**
实现 `D3D12DescriptorHeap` 类:
- ID3D12DescriptorHeap 封装
- CPU/GPU描述符句柄管理
- 描述符分配/释放
- 堆增量大小计算
**任务 2.16D3D12RootSignature - 根签名实现**
实现 `D3D12RootSignature` 类:
- ID3D12RootSignature 封装
- 根参数配置
- 描述符表布局
- 静态采样器
**任务 2.17D3D12PipelineState - 管线状态实现**
实现 `D3D12PipelineState` 类:
- ID3D12PipelineState 封装
- 图形管线描述构建
- 计算管线描述构建
- 混合状态
- 深度模板状态
- 输入布局
- 顶点/像素着色器绑定
**任务 2.18D3D12Sampler - 采样器实现**
实现 `D3D12Sampler` 类:
- D3D12_SAMPLER_DESC 封装
- 静态采样器支持
**任务 2.19D3D12QueryHeap - 查询堆实现**
实现 `D3D12QueryHeap` 类:
- ID3D12QueryHeap 封装
- 时间戳查询
- 遮挡查询
- 流水线统计
**任务 2.20D3D12SwapChain - 交换链实现**
实现 `D3D12SwapChain` 类:
- IDXGISwapChain3 封装
- 帧缓冲管理
- 呈现模式配置
- 完整屏幕支持
**任务 2.21D3D12Texture - 纹理实现**
实现 `D3D12Texture` 类:
- ID3D12Resource 封装
- 纹理描述
- 子资源管理
- 视图创建SRV, RTV, DSV, UAV
- 状态管理
**任务 2.22D3D12Buffer - 缓冲区实现**
实现 `D3D12Buffer` 类:
- ID3D12Resource 封装
- 缓冲区描述
- 视图创建SRV, CBV, UAV
- 上传堆管理
- 默认堆管理
**任务 2.23D3D12Shader - 着色器实现**
实现 `D3D12Shader` 类:
- 着色器字节码管理
- 反射数据提取
- 输入布局构建
**任务 2.24D3D12RenderTargetView - 渲染目标视图实现**
实现 `D3D12RenderTargetView` 类:
- ID3D12RenderTargetView 封装
- 描述符创建与管理
**任务 2.25D3D12DepthStencilView - 深度模板视图实现**
实现 `D3D12DepthStencilView` 类:
- ID3D12DepthStencilView 封装
- 描述符创建与管理
**任务 2.26D3D12ShaderResourceView - 着色器资源视图实现**
实现 `D3D12ShaderResourceView` 类:
- ID3D12ShaderResourceView 封装
- 描述符创建与管理
**任务 2.27D3D12UnorderedAccessView - 无序访问视图实现**
实现 `D3D12UnorderedAccessView` 类:
- ID3D12UnorderedAccessView 封装
- 描述符创建与管理
**任务 2.28D3D12ConstantBufferView - 常量缓冲区视图实现**
实现 `D3D12ConstantBufferView` 类:
- ID3D12ConstantBufferView 封装
- 描述符创建与管理
---
## 2.4 实现顺序
```
阶段 2.1: 基础枚举与类型 (1天)
├── 2.1.1 Enums.h [已完成]
│ └── RHI枚举定义独立编号
├── 2.1.2 Types.h (通用类型定义)
└── 2.1.3 D3D12Enum.h [已完成]
└── 枚举转换层RHI→D3D12
阶段 2.2: 核心接口定义 (3天)
├── 2.2.1 RHISystem.h
├── 2.2.2 RHIDevice.h
├── 2.2.3 Resource.h (资源基类)
├── 2.2.4 ResourceView.h (视图基类)
├── 2.2.5 CommandQueue.h
├── 2.2.6 CommandList.h
└── 2.2.7 其他接口文件
阶段 2.3: D3D12 后端实现 (7天)
├── 2.3.1 D3D12Common.h
├── 2.3.2 D3D12Device
├── 2.3.3 D3D12Resource / D3D12Texture / D3D12Buffer
├── 2.3.4 D3D12CommandQueue
├── 2.3.5 D3D12CommandList
├── 2.3.6 D3D12CommandAllocator
├── 2.3.7 D3D12Fence
├── 2.3.8 D3D12DescriptorHeap
├── 2.3.9 D3D12RootSignature
├── 2.3.10 D3D12PipelineState
├── 2.3.11 D3D12Sampler
├── 2.3.12 D3D12QueryHeap
├── 2.3.13 D3D12SwapChain
├── 2.3.14 D3D12Shader
├── 2.3.15 D3D12RenderTargetView
├── 2.3.16 D3D12DepthStencilView
├── 2.3.17 D3D12ShaderResourceView
├── 2.3.18 D3D12UnorderedAccessView
└── 2.3.19 D3D12ConstantBufferView
阶段 2.4: 集成测试 (1天)
├── 窗口创建与交换链关联
├── 渲染循环基本框架
└── 简单的清屏测试
```
---
## 2.5 验收标准
1. **编译通过**:所有头文件和实现文件能够无错误编译
2. **接口完整**所有定义的接口都有D3D12实现
3. **功能验证**
- 能够创建窗口并初始化D3D12设备
- 能够创建命令队列和命令列表
- 能够执行基本的渲染命令(清屏)
- 能够处理窗口消息和呈现
4. **代码质量**
- 遵循编码规范
- 必要的注释和文档
- 错误处理完善
---
## 2.6 关键技术点
### 2.6.1 资源状态管理
D3D12要求严格的状态管理
- 资源必须处于正确的状态才能使用
- 状态转换通过 `TransitionBarrier`
- 常用状态:`D3D12_RESOURCE_STATE_GENERIC_READ`, `D3D12_RESOURCE_STATE_RENDER_TARGET`, `D3D12_RESOURCE_STATE_DEPTH_WRITE`
### 2.6.2 描述符管理
- 描述符堆类型CBV/SRV/UAV, Sampler, RTV, DSV
- GPU可见描述符堆用于渲染
- CPU可见描述符堆用于描述符拷贝
- 描述符递增大小计算
### 2.6.3 根签名设计
- 根参数类型:根常量、根描述符、根描述符表
- 描述符表:描述符数组
- 静态采样器:不可变的采样器配置
### 2.6.4 管线状态对象
- 图形管线:混合、深度、模板、光栅化、输入布局、顶点/像素/几何/ Hull/Domain着色器
- 计算管线根签名、CS着色器
### 2.6.5 视图接口设计
- 每种视图类型(RTV/DSV/SRV/UAV/CBV)都有独立接口
- 视图持有对底层资源的引用
- 视图描述符确定资源的解释方式
### 2.6.6 着色器编译
- 使用D3DCompiler API或dxc编译HLSL
- 支持着色器反射获取输入布局和资源绑定信息
- 支持着色器宏定义和include处理
### 2.6.7 跨平台抽象设计原则
- 所有接口使用抽象类型不暴露D3D12特定类型
- GPUDescriptorHandle/CPUDescriptorHandle 作为通用句柄类型
- 资源状态使用统一的ResourceStates枚举
- 创建描述符结构体独立于特定API
- RHI枚举使用独立编号通过转换层转换为特定API枚举
### 2.6.8 枚举转换层
RHI枚举使用独立编号与任何图形API无关通过转换层转换为特定API
```cpp
// RHI枚举独立编号
enum class FillMode { Wireframe, Solid };
// D3D12转换层
inline D3D12_FILL_MODE ToD3D12(FillMode mode) {
switch (mode) {
case FillMode::Wireframe: return D3D12_FILL_MODE_WIREFRAME;
case FillMode::Solid: return D3D12_FILL_MODE_SOLID;
}
}
```
---
## 2.7 后续阶段依赖
- 第三阶段渲染管线RenderPipeline需要RHI作为基础
- 材质系统需要RHI的Shader和PipelineState
- 场景渲染需要CommandList提交绘制命令