chore: sync workspace state
This commit is contained in:
364
docs/used/C#脚本系统_Editor前置缺口.md
Normal file
364
docs/used/C#脚本系统_Editor前置缺口.md
Normal file
@@ -0,0 +1,364 @@
|
||||
# C#脚本系统 Editor 前置缺口
|
||||
|
||||
## 1. 目的
|
||||
|
||||
本文档只记录 **C# 脚本系统接入 editor 时需要补齐的 editor 侧缺口**。
|
||||
|
||||
这些内容 **不是脚本模块第一阶段的实现范围**。
|
||||
第一阶段仍以:
|
||||
|
||||
- 运行时闭环
|
||||
- 单元测试闭环
|
||||
- 最小场景级验证
|
||||
|
||||
为主。
|
||||
|
||||
本文档的作用是防止后续把 editor 集成需求误混到第一阶段里。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前策略
|
||||
|
||||
当前策略明确如下:
|
||||
|
||||
- 脚本系统第一阶段先不依赖 editor
|
||||
- editor 只作为后续集成目标
|
||||
- editor 相关工作拆分为独立 issue
|
||||
|
||||
因此,下面所有条目均属于:
|
||||
|
||||
- 后续阶段工作
|
||||
- 或 editor / runtime 边界层工作
|
||||
|
||||
---
|
||||
|
||||
## 3. Issue 列表
|
||||
|
||||
## E-001 Play / Simulate 工作流尚未落地
|
||||
|
||||
### 现状
|
||||
|
||||
editor 当前已经定义了相关事件,但完整的 Play / Simulate 切换链路仍未形成统一工作流。
|
||||
|
||||
### 影响
|
||||
|
||||
没有这条链路,脚本系统无法在 editor 中以接近 Unity 的方式运行:
|
||||
|
||||
- 无法从编辑态切换到运行态
|
||||
- 无法创建运行时场景副本
|
||||
- 无法触发脚本运行时启动与停止
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- `EditorMode` 状态机
|
||||
- `Edit / Play / Simulate` 三态切换
|
||||
- 菜单栏或工具栏中的 Play / Stop / Pause 控件
|
||||
- 对应的事件派发和恢复流程
|
||||
|
||||
### 优先级
|
||||
|
||||
高,但属于 editor 集成阶段,不属于脚本第一阶段
|
||||
|
||||
---
|
||||
|
||||
## E-002 editor 场景与 runtime 场景切换控制未封装
|
||||
|
||||
### 现状
|
||||
|
||||
当前 scene 管理具备快照能力,但 editor 还没有一套完整的“运行时场景副本控制器”。
|
||||
|
||||
### 影响
|
||||
|
||||
没有这一层,脚本一旦接入 editor,会直接面临以下风险:
|
||||
|
||||
- Play 过程污染编辑场景
|
||||
- Stop 后无法恢复编辑态
|
||||
- 运行时对象状态和 editor 面板状态错乱
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- editor 场景与 runtime 场景的明确所有权
|
||||
- Play 前复制
|
||||
- Stop 后恢复
|
||||
- 运行时期间禁用部分编辑操作
|
||||
- 选中对象和层级面板的状态同步策略
|
||||
|
||||
### 优先级
|
||||
|
||||
高
|
||||
|
||||
---
|
||||
|
||||
## E-003 Inspector 缺少 `ScriptComponent` 作者化 UI
|
||||
|
||||
### 现状
|
||||
|
||||
当前 editor Inspector 还没有脚本组件专用 UI。
|
||||
|
||||
### 影响
|
||||
|
||||
即使底层脚本系统完成,用户也无法在 editor 中完成以下基础操作:
|
||||
|
||||
- 添加脚本组件
|
||||
- 删除脚本组件
|
||||
- 选择脚本类
|
||||
- 查看脚本类名
|
||||
- 调整脚本组件顺序
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- Add Component 菜单中的 `ScriptComponent`
|
||||
- 已挂载脚本组件列表
|
||||
- 脚本类选择器
|
||||
- 脚本丢失 / 类不存在 / 程序集未加载的错误态显示
|
||||
|
||||
### 优先级
|
||||
|
||||
高
|
||||
|
||||
---
|
||||
|
||||
## E-004 Inspector 缺少脚本字段编辑能力
|
||||
|
||||
### 现状
|
||||
|
||||
当前 editor 没有基于脚本字段元数据的动态 Inspector。
|
||||
|
||||
### 影响
|
||||
|
||||
无法实现 Unity 风格脚本工作流中最关键的一环:
|
||||
|
||||
- 在 Inspector 中编辑脚本字段
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- 字段元数据缓存到 editor 层
|
||||
- 基础类型字段绘制
|
||||
- `Vector2/3/4` 字段绘制
|
||||
- `bool` / `string` / 数值类型编辑
|
||||
- 字段值回写 `ScriptComponent` 的字段缓存
|
||||
|
||||
### 优先级
|
||||
|
||||
高
|
||||
|
||||
---
|
||||
|
||||
## E-005 C# 项目与程序集管理缺失
|
||||
|
||||
### 现状
|
||||
|
||||
`Project` 面板目前已经有 `Assets/Scripts` 目录概念,但没有正式的 C# 项目管理机制。
|
||||
|
||||
### 影响
|
||||
|
||||
用户无法在 editor 中稳定地管理脚本编译输入和输出:
|
||||
|
||||
- 没有 `GameScripts.csproj`
|
||||
- 没有 `ScriptCore` 引用管理
|
||||
- 没有程序集输出路径约定
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- 项目初始化时创建脚本工程模板
|
||||
- 脚本程序集输出目录规范
|
||||
- `ScriptCore` 引用自动配置
|
||||
- 脚本工程文件缺失时的恢复策略
|
||||
|
||||
### 优先级
|
||||
|
||||
中到高
|
||||
|
||||
---
|
||||
|
||||
## E-006 editor 内缺少脚本编译触发入口
|
||||
|
||||
### 现状
|
||||
|
||||
当前 editor 没有“编译脚本”入口,也没有编译状态反馈。
|
||||
|
||||
### 影响
|
||||
|
||||
后续即使 Inspector 可选择脚本,用户也无法在 editor 中完成闭环:
|
||||
|
||||
- 修改脚本
|
||||
- 编译程序集
|
||||
- 重新加载类列表
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- 手动编译按钮
|
||||
- 后续可扩展到自动编译或文件监听
|
||||
- 编译状态显示
|
||||
- 成功/失败结果通知
|
||||
|
||||
### 优先级
|
||||
|
||||
中到高
|
||||
|
||||
---
|
||||
|
||||
## E-007 Console 面板缺少脚本编译错误与运行时异常接入
|
||||
|
||||
### 现状
|
||||
|
||||
当前 Console 还没有专门的脚本编译/加载/执行错误通路。
|
||||
|
||||
### 影响
|
||||
|
||||
脚本系统接入 editor 后,最基本的错误反馈都会缺失:
|
||||
|
||||
- 编译错误
|
||||
- 程序集加载失败
|
||||
- 类发现失败
|
||||
- 运行时异常
|
||||
- 栈信息显示
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- 编译器 stdout/stderr 采集
|
||||
- 程序集加载错误显示
|
||||
- 托管异常栈转发到 Console
|
||||
- 错误级别区分
|
||||
- 后续可扩展到点击跳转文件/行号
|
||||
|
||||
### 优先级
|
||||
|
||||
高
|
||||
|
||||
---
|
||||
|
||||
## E-008 脚本类数据库与类缓存刷新机制缺失
|
||||
|
||||
### 现状
|
||||
|
||||
editor 还没有“当前项目有哪些可挂载脚本类”的缓存层。
|
||||
|
||||
### 影响
|
||||
|
||||
没有这一层,Inspector 无法稳定实现:
|
||||
|
||||
- 类下拉列表
|
||||
- 类是否可挂载的判断
|
||||
- 类丢失提示
|
||||
- 程序集重载后的刷新
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- 脚本程序集扫描结果缓存
|
||||
- 全限定类名列表
|
||||
- 类状态标记
|
||||
- reload 后缓存刷新
|
||||
|
||||
### 优先级
|
||||
|
||||
中
|
||||
|
||||
---
|
||||
|
||||
## E-009 对象引用字段的 editor 交互控件缺失
|
||||
|
||||
### 现状
|
||||
|
||||
后续脚本字段一旦支持 `GameObject` / 组件引用,editor 目前没有相应控件。
|
||||
|
||||
### 影响
|
||||
|
||||
对象引用字段虽然不属于脚本第一阶段必需项,但属于后续可用性的关键能力。
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- 场景对象选择器
|
||||
- 层级面板拖拽赋值
|
||||
- 失效引用显示
|
||||
- 类型校验
|
||||
|
||||
### 优先级
|
||||
|
||||
中
|
||||
|
||||
---
|
||||
|
||||
## E-010 脚本程序集重载的 editor UX 缺失
|
||||
|
||||
### 现状
|
||||
|
||||
editor 当前没有定义“脚本重载时如何影响当前状态”的用户体验规则。
|
||||
|
||||
### 影响
|
||||
|
||||
后续一旦接入脚本编译与重载,会出现一系列状态问题:
|
||||
|
||||
- 当前选中对象是否刷新
|
||||
- Inspector 是否保留编辑状态
|
||||
- Play 中是否允许重载
|
||||
- 重载失败如何回退
|
||||
|
||||
### 需要补齐
|
||||
|
||||
- Edit 模式重载策略
|
||||
- Play 模式重载策略
|
||||
- 失败回退策略
|
||||
- 用户提示文案与状态反馈
|
||||
|
||||
### 优先级
|
||||
|
||||
中
|
||||
|
||||
---
|
||||
|
||||
## 4. 与 editor 集成直接相关的推荐顺序
|
||||
|
||||
建议的 editor 集成顺序如下:
|
||||
|
||||
1. `E-001` Play / Simulate 工作流
|
||||
2. `E-002` runtime scene 切换控制
|
||||
3. `E-003` `ScriptComponent` 作者化 UI
|
||||
4. `E-004` 脚本字段 Inspector
|
||||
5. `E-007` Console 错误接入
|
||||
6. `E-005` C# 项目与程序集管理
|
||||
7. `E-006` 脚本编译入口
|
||||
8. `E-008` 类数据库刷新
|
||||
9. `E-009` 对象引用字段控件
|
||||
10. `E-010` 程序集重载 UX
|
||||
|
||||
这个顺序的核心原则是:
|
||||
|
||||
- 先让脚本能在 editor 中“跑起来”
|
||||
- 再让脚本能在 editor 中“被作者化”
|
||||
- 最后再补自动化体验与重载体验
|
||||
|
||||
---
|
||||
|
||||
## 5. 关联但不归 editor 的前置项
|
||||
|
||||
以下事项不是 editor issue,但会直接影响后续 editor 集成质量:
|
||||
|
||||
- `GameObject UUID` 持久化
|
||||
- 运行时生命周期规范化
|
||||
- `Start` 一次性语义
|
||||
- `SetActive` 驱动 `OnEnable/OnDisable`
|
||||
- 场景递归更新
|
||||
- `ScriptComponent` 字段缓存与序列化
|
||||
|
||||
这些工作应当在脚本第一阶段或 editor 集成前置阶段优先完成。
|
||||
|
||||
---
|
||||
|
||||
## 6. 结论
|
||||
|
||||
脚本系统第一阶段不应被 editor 当前进度绑定。
|
||||
|
||||
正确的推进方式是:
|
||||
|
||||
- 先做运行时与单测闭环
|
||||
- 再按本文档逐项补 editor 集成能力
|
||||
|
||||
这样可以避免脚本模块在早期同时背负:
|
||||
|
||||
- 运行时实现风险
|
||||
- editor 工作流风险
|
||||
- UI 设计风险
|
||||
- 重载体验风险
|
||||
|
||||
从而把复杂度拆开,逐步落地。
|
||||
1612
docs/used/D3D12后端测试设计.md
Normal file
1612
docs/used/D3D12后端测试设计.md
Normal file
File diff suppressed because it is too large
Load Diff
940
docs/used/Editor设计与实现.md
Normal file
940
docs/used/Editor设计与实现.md
Normal file
@@ -0,0 +1,940 @@
|
||||
# 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 架构问题)*
|
||||
1186
docs/used/OpenGL后端测试设计.md
Normal file
1186
docs/used/OpenGL后端测试设计.md
Normal file
File diff suppressed because it is too large
Load Diff
410
docs/used/OpenGL测试实施计划.md
Normal file
410
docs/used/OpenGL测试实施计划.md
Normal file
@@ -0,0 +1,410 @@
|
||||
# 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/`
|
||||
144
docs/used/RHI_OpenGL_State_Not_Applied.md
Normal file
144
docs/used/RHI_OpenGL_State_Not_Applied.md
Normal 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 接口,行为会与预期不符**
|
||||
1069
docs/used/RHI抽象层设计与实现.md
Normal file
1069
docs/used/RHI抽象层设计与实现.md
Normal file
File diff suppressed because it is too large
Load Diff
120
docs/used/Renderer模块_EditorViewport缺少RenderSurface接入层3.27.md
Normal file
120
docs/used/Renderer模块_EditorViewport缺少RenderSurface接入层3.27.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Renderer模块 EditorViewport缺少RenderSurface接入层
|
||||
|
||||
## 1. 问题定义
|
||||
|
||||
当前 editor 已经有:
|
||||
|
||||
- `GameViewPanel`
|
||||
- `SceneViewPanel`
|
||||
|
||||
但二者目前仍然是空面板,尚未形成真正的 viewport 渲染宿主。
|
||||
|
||||
这意味着 Renderer 即使在 runtime 侧建立起来,editor 侧也还没有标准方式去承接:
|
||||
|
||||
- 离屏 color/depth 输出
|
||||
- viewport resize
|
||||
- 渲染结果贴到 ImGui 面板
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前现状
|
||||
|
||||
当前 `GameViewPanel::Render()` 与 `SceneViewPanel::Render()` 仅创建面板窗口,本身没有:
|
||||
|
||||
- 离屏渲染目标
|
||||
- 渲染尺寸管理
|
||||
- RHI / Renderer 级渲染输出对象
|
||||
- 纹理到 ImGui 的桥接
|
||||
|
||||
也就是说,editor 当前只有“面板外壳”,还没有“渲染宿主层”。
|
||||
|
||||
---
|
||||
|
||||
## 3. 为什么这不应该反向污染 Renderer 设计
|
||||
|
||||
这个问题很容易走偏成下面这种错误路线:
|
||||
|
||||
- 先把 renderer 直接写进 editor 面板逻辑
|
||||
- `SceneView` 一套渲染逻辑
|
||||
- `GameView` 一套渲染逻辑
|
||||
- runtime 又一套渲染逻辑
|
||||
|
||||
这会导致:
|
||||
|
||||
- 渲染逻辑重复
|
||||
- editor 与 runtime 耦合
|
||||
- 后续 C# SRP 难以统一接管
|
||||
|
||||
因此正确思路不是“先让面板自己画”,而是:
|
||||
|
||||
1. Renderer 模块先支持统一的 `RenderSurface`
|
||||
2. editor viewport 只作为 `RenderSurface` 的宿主与展示层
|
||||
|
||||
---
|
||||
|
||||
## 4. 建议方案
|
||||
|
||||
### 4.1 先在 Renderer 模块建立 `RenderSurface`
|
||||
|
||||
`RenderSurface` 应统一描述:
|
||||
|
||||
- swapchain 输出
|
||||
- 离屏 color / depth 目标
|
||||
- viewport 尺寸
|
||||
- resize 行为
|
||||
|
||||
### 4.2 editor 侧建立 viewport host 层
|
||||
|
||||
editor 侧后续应新增一层专门承接:
|
||||
|
||||
- 面板尺寸变化
|
||||
- 请求 Renderer 重建或 resize `RenderSurface`
|
||||
- 把结果纹理显示到 ImGui
|
||||
|
||||
而不是把渲染实现直接塞进面板类。
|
||||
|
||||
### 4.3 `SceneView` 与 `GameView` 应共享同一套 Renderer 输出机制
|
||||
|
||||
区别只在于:
|
||||
|
||||
- `GameView` 使用 runtime camera
|
||||
- `SceneView` 使用 editor 自有 camera / gizmo / overlay
|
||||
|
||||
但底层渲染输出机制应一致。
|
||||
|
||||
---
|
||||
|
||||
## 5. 与未来 Unity 风格演进的关系
|
||||
|
||||
未来如果要做接近 Unity 的 editor 与 SRP 体系,这一层非常关键。
|
||||
|
||||
因为 Unity 的:
|
||||
|
||||
- Game 视图
|
||||
- Scene 视图
|
||||
- Camera 预览
|
||||
|
||||
本质上都不是复制多套渲染器,而是在同一渲染体系上挂不同宿主与附加绘制。
|
||||
|
||||
XCEngine 也应遵循同样思路。
|
||||
|
||||
---
|
||||
|
||||
## 6. 验收标准
|
||||
|
||||
完成后至少应满足:
|
||||
|
||||
1. Renderer 能输出到离屏 `RenderSurface`
|
||||
2. `GameView` 能显示 renderer 的离屏结果
|
||||
3. `SceneView` 能显示 renderer 的离屏结果
|
||||
4. viewport resize 不需要复制新的渲染逻辑
|
||||
5. runtime 与 editor 共用同一套渲染宿主接口
|
||||
|
||||
---
|
||||
|
||||
## 7. 优先级
|
||||
|
||||
中到高。
|
||||
|
||||
它不是 Renderer v0 的第一步实现内容,但必须在 renderer 基础链路稳定后尽快接上,否则 editor 渲染体系会被迫走临时方案。
|
||||
|
||||
146
docs/used/Renderer模块_Material与Shader资产模型暂不满足SRP演进需求.md
Normal file
146
docs/used/Renderer模块_Material与Shader资产模型暂不满足SRP演进需求.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Renderer模块 Material与Shader资产模型暂不满足SRP演进需求
|
||||
|
||||
## 1. 问题定义
|
||||
|
||||
当前资源层已经具备:
|
||||
|
||||
- `Material`
|
||||
- `Shader`
|
||||
- `Texture`
|
||||
|
||||
但现有模型仍然偏“最小资源容器”,尚不足以直接承接未来 Unity 风格 Renderer / SRP 的完整需求。
|
||||
|
||||
当前最典型的问题是:
|
||||
|
||||
- `Shader` 更像“单个 stage shader 资源”
|
||||
- `Material` 更像“shader 引用 + 属性包”
|
||||
- 资产层缺少 pass / tag / render state / render queue 语义
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前现状
|
||||
|
||||
从现有实现看:
|
||||
|
||||
### `Shader`
|
||||
|
||||
当前 `Shader` 资源主要描述:
|
||||
|
||||
- shader type
|
||||
- shader language
|
||||
- source / compiled binary
|
||||
- uniforms / attributes
|
||||
|
||||
这更接近“单个 shader stage 对象”,而不是面向渲染管线选择的 shader asset。
|
||||
|
||||
### `Material`
|
||||
|
||||
当前 `Material` 资源主要描述:
|
||||
|
||||
- 一个 `Shader` 引用
|
||||
- 属性表
|
||||
- 纹理绑定表
|
||||
|
||||
当前 `MaterialLoader` 也只解析最基础的 `"shader"` 字段。
|
||||
|
||||
---
|
||||
|
||||
## 3. 为什么这会影响未来 Renderer / SRP
|
||||
|
||||
在未来的 Unity 风格渲染体系中,Renderer / SRP 至少需要下列能力:
|
||||
|
||||
- 根据 shader pass/tag 选择绘制路径
|
||||
- 区分 opaque / transparent / shadow caster / depth only 等 pass
|
||||
- 用 render queue 控制排序层级
|
||||
- 用 render state 描述 cull / blend / ztest / zwrite
|
||||
- 为后续 keyword / variant 留空间
|
||||
|
||||
如果材质 / shader 资产模型长期停留在当前结构,会导致:
|
||||
|
||||
- 内建 forward 渲染可以临时跑起来
|
||||
- 但未来一旦上 SRP,就必须大规模重构资源资产模型
|
||||
|
||||
这会影响:
|
||||
|
||||
- Renderer
|
||||
- Material 资源格式
|
||||
- Shader 导入格式
|
||||
- editor 材质面板
|
||||
- 未来 C# SRP 的 pass 选择逻辑
|
||||
|
||||
---
|
||||
|
||||
## 4. 建议方向
|
||||
|
||||
### 4.1 不要让 `Shader` 永远停留在“单 stage 资源”
|
||||
|
||||
后续建议演进到更面向渲染管线的概念,例如:
|
||||
|
||||
- `ShaderAsset`
|
||||
- `ShaderPass`
|
||||
- 每个 pass 包含 vertex / fragment 等 stage 组合
|
||||
- 每个 pass 具备 tag 与 render state 描述
|
||||
|
||||
### 4.2 `Material` 应逐步获得 renderer 需要的元数据
|
||||
|
||||
后续建议补充:
|
||||
|
||||
- render queue
|
||||
- pass 相关 tag / override
|
||||
- render state override
|
||||
- shader keyword / variant 预留位
|
||||
|
||||
### 4.3 第一阶段可以先不一次性做全
|
||||
|
||||
但即使第一阶段只做 `UnlitTexture` / `SimpleLit`,也建议:
|
||||
|
||||
- 不把格式彻底写死成只有 `"shader"` 这一个入口
|
||||
- 为 future pass/tag 结构预留升级路径
|
||||
|
||||
换句话说:
|
||||
|
||||
- 当前阶段可以简化实现
|
||||
- 但不能封死演进路线
|
||||
|
||||
---
|
||||
|
||||
## 5. 与 Unity 风格的关系
|
||||
|
||||
未来如果要在 C# 层做接近 Unity 的 SRP,shader pass 选择是核心能力之一。
|
||||
|
||||
例如:
|
||||
|
||||
- `ShaderTagId`
|
||||
- `DrawingSettings`
|
||||
- `FilteringSettings`
|
||||
- renderer list / pass filtering
|
||||
|
||||
这些能力都要求材质与 shader 资产层至少能表达“pass/tag/state”。
|
||||
|
||||
因此,这个问题虽然不一定是 Renderer v0 第一周就要全量解决,但必须在设计阶段明确记录。
|
||||
|
||||
---
|
||||
|
||||
## 6. 建议验收标准
|
||||
|
||||
进入下一阶段时,至少应达到以下其中一档:
|
||||
|
||||
### 档位 A:最小可演进
|
||||
|
||||
- 明确存在“shader pass”概念
|
||||
- 材质资产格式有升级空间
|
||||
- 内建 pipeline 能按 pass 选择绘制
|
||||
|
||||
### 档位 B:更接近 SRP
|
||||
|
||||
- 具备 `pass + tag + render state + queue`
|
||||
- 为 future keyword / variant 留接口
|
||||
|
||||
---
|
||||
|
||||
## 7. 优先级
|
||||
|
||||
中到高。
|
||||
|
||||
它不一定阻塞 Renderer v0 的第一步落地,但如果完全忽略,未来做 C# SRP 时会出现明显返工。
|
||||
|
||||
129
docs/used/Renderer模块_Scene层缺少MeshFilter与MeshRenderer抽象3.27.md
Normal file
129
docs/used/Renderer模块_Scene层缺少MeshFilter与MeshRenderer抽象3.27.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Renderer模块 Scene层缺少MeshFilter与MeshRenderer抽象
|
||||
|
||||
## 1. 问题定义
|
||||
|
||||
当前工程已经具备:
|
||||
|
||||
- `GameObject`
|
||||
- `Component`
|
||||
- `Scene`
|
||||
- `CameraComponent`
|
||||
- `LightComponent`
|
||||
|
||||
但仍然缺少最关键的可渲染组件抽象:
|
||||
|
||||
- `MeshFilterComponent`
|
||||
- `MeshRendererComponent`
|
||||
|
||||
这会导致 Renderer 模块无法以“正式场景组件”的方式承接渲染对象。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前现状
|
||||
|
||||
从当前代码看:
|
||||
|
||||
- `GameObject` 已经支持通用组件挂载
|
||||
- `Scene` 的序列化 / 反序列化已经依赖 `ComponentFactoryRegistry`
|
||||
- `ComponentFactoryRegistry` 当前只注册了 `Camera`、`Light`、`AudioSource`、`AudioListener`
|
||||
|
||||
也就是说,场景层已经具备“扩展组件”的框架,但还没有真正承接渲染对象的组件类型。
|
||||
|
||||
---
|
||||
|
||||
## 3. 为什么这是 Renderer 阶段必须先补的缺口
|
||||
|
||||
如果没有正式的可渲染组件,Renderer 会被迫依赖以下临时做法:
|
||||
|
||||
- 在测试里手工拼 mesh/material/transform
|
||||
- 在 Renderer 内部写死资源路径或对象查找逻辑
|
||||
- 把“场景对象”和“渲染对象”分裂成两套平行系统
|
||||
|
||||
这会直接破坏后续目标:
|
||||
|
||||
- 不利于 editor Inspector 展示
|
||||
- 不利于场景序列化
|
||||
- 不利于未来 C# API 对齐 Unity
|
||||
- 不利于未来引入 `SkinnedMeshRenderer`、`SpriteRenderer` 等扩展
|
||||
|
||||
---
|
||||
|
||||
## 4. 与 Unity 风格的关系
|
||||
|
||||
如果未来要模仿 Unity 做 C# SRP,那么场景组件模型最好一开始就尽量贴近 Unity。
|
||||
|
||||
因此建议不是只加一个大而全的 `MeshRendererComponent`,而是直接采用:
|
||||
|
||||
- `MeshFilterComponent`:持有 mesh
|
||||
- `MeshRendererComponent`:持有材质和渲染状态
|
||||
|
||||
这样更容易在未来映射到:
|
||||
|
||||
- C# `MeshFilter`
|
||||
- C# `MeshRenderer`
|
||||
- Inspector 上的分离展示
|
||||
- 脚本对 mesh / material 的分别访问
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议方案
|
||||
|
||||
### 5.1 新增组件
|
||||
|
||||
#### `MeshFilterComponent`
|
||||
|
||||
最小建议字段:
|
||||
|
||||
- `ResourceHandle<Mesh> m_mesh`
|
||||
|
||||
#### `MeshRendererComponent`
|
||||
|
||||
最小建议字段:
|
||||
|
||||
- 材质数组
|
||||
- `enabled`
|
||||
- `castShadows`
|
||||
- `receiveShadows`
|
||||
- `renderLayer`
|
||||
|
||||
### 5.2 注册到 `ComponentFactoryRegistry`
|
||||
|
||||
这样场景文件才能:
|
||||
|
||||
- 正确反序列化
|
||||
- 在 editor 中按组件类型恢复
|
||||
- 为未来脚本与 Inspector 留入口
|
||||
|
||||
### 5.3 Renderer 只从组件层抽取渲染对象
|
||||
|
||||
Renderer 不应自行维护另一套“逻辑对象 -> 渲染对象”的临时注册表作为长期方案。
|
||||
|
||||
正确方式应是:
|
||||
|
||||
- `Scene`
|
||||
- `GameObject`
|
||||
- `MeshFilterComponent`
|
||||
- `MeshRendererComponent`
|
||||
|
||||
共同构成 Renderer 的输入源。
|
||||
|
||||
---
|
||||
|
||||
## 6. 验收标准
|
||||
|
||||
完成后至少应满足:
|
||||
|
||||
1. 场景可正式挂载 mesh 渲染对象
|
||||
2. `Scene` 序列化 / 反序列化可恢复对应组件
|
||||
3. Renderer 可以直接从场景中提取可渲染对象
|
||||
4. editor 后续可以直接复用同一套组件数据
|
||||
5. 后续 C# API 可以平滑映射到 Unity 风格组件模型
|
||||
|
||||
---
|
||||
|
||||
## 7. 优先级
|
||||
|
||||
高。
|
||||
|
||||
这是 Renderer 模块正式落地前必须解决的前置缺口。
|
||||
|
||||
4564
docs/used/XCEngine渲染引擎架构设计.md
Normal file
4564
docs/used/XCEngine渲染引擎架构设计.md
Normal file
File diff suppressed because it is too large
Load Diff
6025
docs/used/XCGameEngine架构设计.md
Normal file
6025
docs/used/XCGameEngine架构设计.md
Normal file
File diff suppressed because it is too large
Load Diff
1325
docs/used/仿Unity RHI架构设计.md
Normal file
1325
docs/used/仿Unity RHI架构设计.md
Normal file
File diff suppressed because it is too large
Load Diff
335
docs/used/第三阶段计划.md
Normal file
335
docs/used/第三阶段计划.md
Normal file
@@ -0,0 +1,335 @@
|
||||
# 第三阶段计划: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.1:OpenGLEnum.h - 枚举转换层**
|
||||
|
||||
实现 RHI 枚举到 OpenGL 枚举的转换:
|
||||
- `Format` → `GLenum`
|
||||
- `PrimitiveTopology` → `GLenum`
|
||||
- `BlendOp` / `BlendFactor` → `GLenum`
|
||||
- `ComparisonFunc` → `GLenum`
|
||||
- `ResourceStates` → `GLenum` (简化)
|
||||
- `ShaderType` → `GLenum`
|
||||
|
||||
**任务 3.2:OpenGLCommon.h - 公共定义**
|
||||
|
||||
- OpenGL 初始化辅助函数
|
||||
- 格式支持检测
|
||||
- 错误检查宏
|
||||
- GLAD 加载器封装
|
||||
|
||||
---
|
||||
|
||||
### 3.3.2 核心组件实现
|
||||
|
||||
**任务 3.3:OpenGLDevice - 设备实现**
|
||||
|
||||
实现 `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.4:OpenGLSwapChain - 交换链实现**
|
||||
|
||||
实现 `OpenGLSwapChain` 类:
|
||||
- GLFW 窗口管理
|
||||
- 双缓冲切换
|
||||
- 帧缓冲 resize 处理
|
||||
|
||||
**任务 3.5:OpenGLShader - 着色器实现**
|
||||
|
||||
实现 `OpenGLShader` 类:
|
||||
- GLSL 源码加载
|
||||
- `glShaderSource` + `glCompileShader`
|
||||
- 编译错误获取
|
||||
- 反射数据提取(可选)
|
||||
|
||||
**任务 3.6:OpenGLBuffer - 缓冲区实现**
|
||||
|
||||
实现 `OpenGLBuffer` 类:
|
||||
- VBO 创建与管理
|
||||
- IBO 索引缓冲
|
||||
- UBO uniform 缓冲
|
||||
- Buffer mapping
|
||||
|
||||
**任务 3.7:OpenGLTexture - 纹理实现**
|
||||
|
||||
实现 `OpenGLTexture` 类:
|
||||
- 2D 纹理创建
|
||||
- 纹理参数设置
|
||||
- Mipmap 生成
|
||||
- 纹理绑定
|
||||
|
||||
**任务 3.8:OpenGLPipelineState - 管线状态实现**
|
||||
|
||||
实现 `OpenGLPipelineState` 类:
|
||||
- VAO 管理
|
||||
- Shader Program 链接
|
||||
- 状态缓存(blend, depth, rasterizer)
|
||||
- 输入布局映射
|
||||
|
||||
**任务 3.9:OpenGLCommandList - 命令列表实现**
|
||||
|
||||
实现 `OpenGLCommandList` 类:
|
||||
- 状态缓存与批量提交
|
||||
- `glDrawArrays` / `glDrawElements` 封装
|
||||
- 视口裁剪设置
|
||||
- 渲染目标绑定
|
||||
|
||||
**任务 3.10:OpenGLFence - 同步实现**
|
||||
|
||||
实现 `OpenGLFence` 类:
|
||||
- `glFenceSync` 封装
|
||||
- CPU 等待实现
|
||||
|
||||
**任务 3.11:OpenGLDescriptorHeap - 描述符堆实现**
|
||||
|
||||
实现 `OpenGLDescriptorHeap` 类:
|
||||
- Texture Unit 数组管理
|
||||
- 简化版描述符绑定
|
||||
|
||||
---
|
||||
|
||||
### 3.3.3 视图实现
|
||||
|
||||
**任务 3.12:OpenGLRenderTargetView - 渲染目标视图**
|
||||
|
||||
- Framebuffer 对象管理
|
||||
- 颜色附件绑定
|
||||
|
||||
**任务 3.13:OpenGLDepthStencilView - 深度模板视图**
|
||||
|
||||
- Depth/stencil buffer 管理
|
||||
- FBO 深度附件
|
||||
|
||||
**任务 3.14:OpenGLShaderResourceView - 着色器资源视图**
|
||||
|
||||
- 纹理视图绑定到 Texture Unit
|
||||
|
||||
**任务 3.15:OpenGLUnorderedAccessView - 无序访问视图**
|
||||
|
||||
- SSBO 管理
|
||||
|
||||
**任务 3.16:OpenGLConstantBufferView - 常量缓冲区视图**
|
||||
|
||||
- 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 后端
|
||||
829
docs/used/第二阶段计划.md
Normal file
829
docs/used/第二阶段计划.md
Normal file
@@ -0,0 +1,829 @@
|
||||
# 第二阶段计划: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.1:Enums.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.2:RHISystem.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.3:RHIDevice.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.4:CommandQueue.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.5:CommandList.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.7:Resource.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.8:ResourceView.h - 资源视图基类接口**
|
||||
|
||||
```cpp
|
||||
class IResourceView {
|
||||
public:
|
||||
virtual ~IResourceView() = default;
|
||||
virtual void* GetNativeHandle() const = 0;
|
||||
virtual IResource* GetResource() const = 0;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3.3 D3D12 后端实现
|
||||
|
||||
**任务 2.9:D3D12Common.h - 公共定义**
|
||||
|
||||
D3D12相关的公共定义和辅助函数:
|
||||
- 格式转换映射
|
||||
- 描述符大小计算
|
||||
- 资源状态转换
|
||||
- 辅助工具函数
|
||||
|
||||
**任务 2.10:D3D12Device - 设备实现**
|
||||
|
||||
实现 `D3D12Device` 类:
|
||||
- ID3D12Device 封装
|
||||
- IDXGIFactory 创建与管理
|
||||
- 所有资源创建接口实现
|
||||
- 适配器信息查询
|
||||
- 功能级别支持检测
|
||||
- 内存信息查询
|
||||
- 设备移除与恢复处理
|
||||
|
||||
**任务 2.11:D3D12CommandQueue - 命令队列实现**
|
||||
|
||||
实现 `D3D12CommandQueue` 类:
|
||||
- ID3D12CommandQueue 封装
|
||||
- 命令列表执行
|
||||
- 围栏同步
|
||||
- 时间戳频率查询
|
||||
|
||||
**任务 2.12:D3D12CommandList - 命令列表实现**
|
||||
|
||||
实现 `D3D12CommandList` 类:
|
||||
- ID3D12GraphicsCommandList 封装
|
||||
- 所有渲染命令实现
|
||||
- 状态追踪与验证
|
||||
- 资源追踪
|
||||
|
||||
**任务 2.13:D3D12CommandAllocator - 命令分配器实现**
|
||||
|
||||
实现 `D3D12CommandAllocator` 类:
|
||||
- ID3D12CommandAllocator 封装
|
||||
- 重置管理
|
||||
|
||||
**任务 2.14:D3D12Fence - 围栏实现**
|
||||
|
||||
实现 `D3D12Fence` 类:
|
||||
- ID3D12Fence 封装
|
||||
- CPU/GPU同步
|
||||
- 事件句柄管理
|
||||
|
||||
**任务 2.15:D3D12DescriptorHeap - 描述符堆实现**
|
||||
|
||||
实现 `D3D12DescriptorHeap` 类:
|
||||
- ID3D12DescriptorHeap 封装
|
||||
- CPU/GPU描述符句柄管理
|
||||
- 描述符分配/释放
|
||||
- 堆增量大小计算
|
||||
|
||||
**任务 2.16:D3D12RootSignature - 根签名实现**
|
||||
|
||||
实现 `D3D12RootSignature` 类:
|
||||
- ID3D12RootSignature 封装
|
||||
- 根参数配置
|
||||
- 描述符表布局
|
||||
- 静态采样器
|
||||
|
||||
**任务 2.17:D3D12PipelineState - 管线状态实现**
|
||||
|
||||
实现 `D3D12PipelineState` 类:
|
||||
- ID3D12PipelineState 封装
|
||||
- 图形管线描述构建
|
||||
- 计算管线描述构建
|
||||
- 混合状态
|
||||
- 深度模板状态
|
||||
- 输入布局
|
||||
- 顶点/像素着色器绑定
|
||||
|
||||
**任务 2.18:D3D12Sampler - 采样器实现**
|
||||
|
||||
实现 `D3D12Sampler` 类:
|
||||
- D3D12_SAMPLER_DESC 封装
|
||||
- 静态采样器支持
|
||||
|
||||
**任务 2.19:D3D12QueryHeap - 查询堆实现**
|
||||
|
||||
实现 `D3D12QueryHeap` 类:
|
||||
- ID3D12QueryHeap 封装
|
||||
- 时间戳查询
|
||||
- 遮挡查询
|
||||
- 流水线统计
|
||||
|
||||
**任务 2.20:D3D12SwapChain - 交换链实现**
|
||||
|
||||
实现 `D3D12SwapChain` 类:
|
||||
- IDXGISwapChain3 封装
|
||||
- 帧缓冲管理
|
||||
- 呈现模式配置
|
||||
- 完整屏幕支持
|
||||
|
||||
**任务 2.21:D3D12Texture - 纹理实现**
|
||||
|
||||
实现 `D3D12Texture` 类:
|
||||
- ID3D12Resource 封装
|
||||
- 纹理描述
|
||||
- 子资源管理
|
||||
- 视图创建(SRV, RTV, DSV, UAV)
|
||||
- 状态管理
|
||||
|
||||
**任务 2.22:D3D12Buffer - 缓冲区实现**
|
||||
|
||||
实现 `D3D12Buffer` 类:
|
||||
- ID3D12Resource 封装
|
||||
- 缓冲区描述
|
||||
- 视图创建(SRV, CBV, UAV)
|
||||
- 上传堆管理
|
||||
- 默认堆管理
|
||||
|
||||
**任务 2.23:D3D12Shader - 着色器实现**
|
||||
|
||||
实现 `D3D12Shader` 类:
|
||||
- 着色器字节码管理
|
||||
- 反射数据提取
|
||||
- 输入布局构建
|
||||
|
||||
**任务 2.24:D3D12RenderTargetView - 渲染目标视图实现**
|
||||
|
||||
实现 `D3D12RenderTargetView` 类:
|
||||
- ID3D12RenderTargetView 封装
|
||||
- 描述符创建与管理
|
||||
|
||||
**任务 2.25:D3D12DepthStencilView - 深度模板视图实现**
|
||||
|
||||
实现 `D3D12DepthStencilView` 类:
|
||||
- ID3D12DepthStencilView 封装
|
||||
- 描述符创建与管理
|
||||
|
||||
**任务 2.26:D3D12ShaderResourceView - 着色器资源视图实现**
|
||||
|
||||
实现 `D3D12ShaderResourceView` 类:
|
||||
- ID3D12ShaderResourceView 封装
|
||||
- 描述符创建与管理
|
||||
|
||||
**任务 2.27:D3D12UnorderedAccessView - 无序访问视图实现**
|
||||
|
||||
实现 `D3D12UnorderedAccessView` 类:
|
||||
- ID3D12UnorderedAccessView 封装
|
||||
- 描述符创建与管理
|
||||
|
||||
**任务 2.28:D3D12ConstantBufferView - 常量缓冲区视图实现**
|
||||
|
||||
实现 `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提交绘制命令
|
||||
Reference in New Issue
Block a user