Files
DX12/docs/changelogs/2026-03/20260326-d3d12-command-queue.md
SpecialX 7da17ccadd 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
2026-03-27 12:31:12 +08:00

136 lines
3.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 变更记录:命令队列与多帧缓冲
**提交日期**: 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)