feat: implement command queue with multi-frame buffering
D3D12 Core: - Add d3d12_command class for command queue management - Support Direct/Compute/Copy command queue types - Implement multi-frame buffering (frame_buffer_count=3) - Add begin_frame/end_frame rendering cycle - Add NAME_D3D12_OBJECT_INDEXED macro Platform Interface: - Add render function pointer to platform_interface - Implement render() in Renderer Documentation: - Add changelog for command queue implementation - Update D3D12 Wiki with multi-frame buffering section - Mark command queue task as completed
This commit is contained in:
135
docs/changelogs/2026-03/20260326-d3d12-command-queue.md
Normal file
135
docs/changelogs/2026-03/20260326-d3d12-command-queue.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# 变更记录:命令队列与多帧缓冲
|
||||
|
||||
**提交日期**: 2026-03-26
|
||||
**提交哈希**: `26e18bd`
|
||||
**变更类型**: 功能实现
|
||||
|
||||
---
|
||||
|
||||
## 变更概述
|
||||
|
||||
本次提交实现了 D3D12 命令队列管理类 `d3d12_command`,支持多帧缓冲渲染架构,实现了 CPU-GPU 并行渲染的基础设施。
|
||||
|
||||
## 修改文件
|
||||
|
||||
### Engine/Graphics/Direct3D12/
|
||||
|
||||
| 文件 | 变更说明 |
|
||||
|------|----------|
|
||||
| `D3D12Core.cpp` | 添加 `d3d12_command` 类,实现命令队列和命令列表管理 |
|
||||
| `D3D12Core.h` | 添加 `render()` 函数声明 |
|
||||
| `D3D12CommonHeader.h` | 添加 `frame_buffer_count` 常量和 `NAME_D3D12_OBJECT_INDEXED` 宏 |
|
||||
|
||||
### Engine/Graphics/
|
||||
|
||||
| 文件 | 变更说明 |
|
||||
|------|----------|
|
||||
| `GraphicsPlatformInterface.h` | 添加 `render` 函数指针 |
|
||||
| `Renderer.h` | 添加 `render()` 函数声明 |
|
||||
| `Renderer.cpp` | 实现 `render()` 函数 |
|
||||
|
||||
---
|
||||
|
||||
## 技术要点
|
||||
|
||||
### 1. 多帧缓冲架构
|
||||
|
||||
```cpp
|
||||
constexpr u32 frame_buffer_count{ 3 };
|
||||
```
|
||||
|
||||
采用三重缓冲设计,允许 CPU 提前录制命令,GPU 异步执行,最大化硬件利用率。
|
||||
|
||||
### 2. d3d12_command 类
|
||||
|
||||
```cpp
|
||||
class d3d12_command
|
||||
{
|
||||
// 创建命令队列(支持 Direct/Compute/Copy 三种类型)
|
||||
// 为每帧创建独立的命令分配器
|
||||
// 创建命令列表
|
||||
|
||||
void begin_frame(); // 等待帧完成,重置分配器和命令列表
|
||||
void end_frame(); // 关闭命令列表,提交执行
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 帧索引轮转机制
|
||||
|
||||
```cpp
|
||||
_frame_index = (_frame_index + 1) % frame_buffer_count;
|
||||
```
|
||||
|
||||
环形缓冲区管理帧资源,确保 CPU 不会超前 GPU 超过 3 帧。
|
||||
|
||||
### 4. command_frame 结构
|
||||
|
||||
```cpp
|
||||
struct command_frame
|
||||
{
|
||||
ID3D12CommandAllocator* cmd_allocator{ nullptr };
|
||||
void wait(); // 等待 GPU 完成该帧
|
||||
void release(); // 释放资源
|
||||
};
|
||||
```
|
||||
|
||||
每帧独立的命令分配器,避免 GPU 执行期间重置冲突。
|
||||
|
||||
### 5. 命名调试宏
|
||||
|
||||
```cpp
|
||||
#define NAME_D3D12_OBJECT_INDEXED(obj, n, name) \
|
||||
obj->SetName(full_name); ...
|
||||
```
|
||||
|
||||
支持为多个同类对象设置带索引的调试名称。
|
||||
|
||||
---
|
||||
|
||||
## 渲染流程
|
||||
|
||||
```
|
||||
render()
|
||||
│
|
||||
├─► begin_frame()
|
||||
│ ├─► 等待当前帧 GPU 完成
|
||||
│ ├─► 重置命令分配器
|
||||
│ └─► 重置命令列表
|
||||
│
|
||||
└─► end_frame()
|
||||
├─► 关闭命令列表
|
||||
├─► 提交命令列表执行
|
||||
└─► 递增帧索引
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 设计原理
|
||||
|
||||
### 为什么需要多帧缓冲?
|
||||
|
||||
1. **CPU-GPU 并行性**: 单缓冲模式下 CPU 必须等待 GPU 完成,多帧缓冲允许 CPU 提前录制 N 帧
|
||||
2. **命令分配器冲突解决**: D3D12 中命令分配器在 GPU 执行期间不能被重置,每帧独立分配器解决此问题
|
||||
3. **帧时序稳定性**: 缓冲 N 帧可平滑帧率波动
|
||||
|
||||
### 命令列表创建后立即关闭
|
||||
|
||||
```cpp
|
||||
DXCall(_cmd_list->Close());
|
||||
```
|
||||
|
||||
新创建的命令列表处于"录制打开"状态,立即关闭使其进入可提交状态,这是一种防御性编程。
|
||||
|
||||
---
|
||||
|
||||
## 后续工作
|
||||
|
||||
- [ ] 实现 Fence 同步机制
|
||||
- [ ] 实现交换链
|
||||
- [ ] 实现描述符堆
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12学习Wiki](../wiki/D3D12学习Wiki.md)
|
||||
@@ -16,6 +16,7 @@ changelogs/
|
||||
|
||||
| 日期 | 提交 | 变更内容 |
|
||||
|------|------|----------|
|
||||
| 2026-03-26 | [命令队列与多帧缓冲](./2026-03/20260326-d3d12-command-queue.md) | D3D12 命令队列和多帧渲染架构 |
|
||||
| 2026-03-26 | [D3D12设备初始化](./2026-03/20260326-d3d12-device-init.md) | D3D12 设备创建与调试层实现 |
|
||||
| 2026-03-26 | [Graphics模块](./2026-03/20260326-d3d12-foundation.md) | Graphics 模块与 D3D12 后端框架 |
|
||||
| 2026-03-19 | [DX12初始框架](./2026-03/20260326-dx12-initial.md) | 初始 DX12 基础框架 |
|
||||
|
||||
@@ -164,6 +164,7 @@ Microsoft::WRL::ComPtr<ID3D12Device8> device;
|
||||
void get_platform_interface(platform_interface& pi) {
|
||||
pi.initialize = core::initialize;
|
||||
pi.shutdown = core::shutdown;
|
||||
pi.render = core::render;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -172,9 +173,47 @@ void get_platform_interface(platform_interface& pi) {
|
||||
- 各后端独立开发和测试
|
||||
- 上层代码与具体 API 解耦
|
||||
|
||||
## 6. 渲染表面与窗口
|
||||
## 6. 命令队列与多帧缓冲
|
||||
|
||||
### 6.1 render_surface 结构
|
||||
### 6.1 d3d12_command 类
|
||||
|
||||
项目实现了命令队列管理类,支持多帧缓冲渲染:
|
||||
|
||||
```cpp
|
||||
class d3d12_command
|
||||
{
|
||||
void begin_frame(); // 等待帧完成,重置分配器和命令列表
|
||||
void end_frame(); // 关闭命令列表,提交执行
|
||||
private:
|
||||
ID3D12CommandQueue* _cmd_queue;
|
||||
ID3D12GraphicsCommandList6* _cmd_list;
|
||||
command_frame _cmd_frames[frame_buffer_count];
|
||||
u32 _frame_index;
|
||||
};
|
||||
```
|
||||
|
||||
### 6.2 多帧缓冲原理
|
||||
|
||||
```cpp
|
||||
constexpr u32 frame_buffer_count{ 3 };
|
||||
```
|
||||
|
||||
采用三重缓冲设计:
|
||||
- CPU 提前录制命令
|
||||
- GPU 异步执行
|
||||
- 最大化硬件利用率
|
||||
|
||||
### 6.3 帧索引轮转
|
||||
|
||||
```cpp
|
||||
_frame_index = (_frame_index + 1) % frame_buffer_count;
|
||||
```
|
||||
|
||||
环形缓冲区管理帧资源,确保 CPU 不会超前 GPU 超过 3 帧。
|
||||
|
||||
## 7. 渲染表面与窗口
|
||||
|
||||
### 7.1 render_surface 结构
|
||||
|
||||
```cpp
|
||||
struct render_surface {
|
||||
@@ -183,7 +222,7 @@ struct render_surface {
|
||||
};
|
||||
```
|
||||
|
||||
### 6.2 多窗口支持
|
||||
### 7.2 多窗口支持
|
||||
|
||||
TestRenderer 测试展示了多窗口渲染:
|
||||
|
||||
@@ -196,7 +235,7 @@ for (u32 i{0}; i < _countof(_surfaces); ++i) {
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 全屏切换
|
||||
### 7.3 全屏切换
|
||||
|
||||
通过 `WM_SYSCHAR` 消息处理 Alt+Enter:
|
||||
|
||||
@@ -206,42 +245,42 @@ if (wparam == VK_RETURN && (HIWORD(lparam) & KF_ALTDOWN)) {
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 后续学习路径
|
||||
## 8. 后续学习路径
|
||||
|
||||
### 7.1 基础阶段
|
||||
### 8.1 基础阶段
|
||||
|
||||
- [x] 完成设备创建和适配器枚举
|
||||
- [ ] 创建命令队列和命令列表
|
||||
- [x] 创建命令队列和命令列表
|
||||
- [ ] 实现交换链和后台缓冲区
|
||||
- [ ] 渲染第一个三角形
|
||||
|
||||
### 7.2 进阶阶段
|
||||
### 8.2 进阶阶段
|
||||
|
||||
- [ ] 描述符堆管理
|
||||
- [ ] 根签名和管线状态对象
|
||||
- [ ] 资源屏障和同步
|
||||
- [ ] 常量缓冲区和着色器资源
|
||||
|
||||
### 7.3 高级阶段
|
||||
### 8.3 高级阶段
|
||||
|
||||
- [ ] 多线程渲染
|
||||
- [ ] 资源绑定策略
|
||||
- [ ] 动态资源管理
|
||||
- [ ] 性能优化
|
||||
|
||||
## 8. 参考资源
|
||||
## 9. 参考资源
|
||||
|
||||
### 8.1 官方文档
|
||||
### 9.1 官方文档
|
||||
|
||||
- [Microsoft D3D12 文档](https://docs.microsoft.com/en-us/windows/win32/direct3d12/direct3d-12-graphics)
|
||||
- [DXGI 文档](https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dx-graphics-dxgi)
|
||||
|
||||
### 8.2 推荐书籍
|
||||
### 9.2 推荐书籍
|
||||
|
||||
- 《Introduction to 3D Game Programming with DirectX 12》
|
||||
- 《Real-Time 3D Rendering with DirectX and HLSL》
|
||||
|
||||
### 8.3 项目相关文档
|
||||
### 9.3 项目相关文档
|
||||
|
||||
- [Graphics渲染架构分析](./Graphics渲染架构分析.md)
|
||||
- [项目约定规范](./项目约定规范.md)
|
||||
|
||||
Reference in New Issue
Block a user