feat(d3d12): 实现交换链与渲染表面管理

- 新增 d3d12_surface 类,管理交换链和渲染目标
- 实现三重缓冲后台缓冲区管理
- 添加视口和裁剪矩形配置
- 修复 GraphicsPlatformInterface.h 循环包含问题
- 添加完整的中文 Doxygen 注释
- 更新 D3D12 学习 Wiki,添加交换链章节
This commit is contained in:
SpecialX
2026-03-31 11:12:11 +08:00
parent b6c0211d6a
commit 95d8893182
14 changed files with 840 additions and 27 deletions

View File

@@ -489,9 +489,124 @@ void allocate() {
} // 自动解锁
```
## 8. 渲染表面与窗口
## 8. 交换链Swap Chain
### 8.1 render_surface 结构
### 8.1 什么是交换链?
交换链是 DXGI 提供的机制,用于管理前后缓冲区的交换,实现流畅的画面显示。
```
┌─────────────────────────────────────────────────────────────┐
│ 交换链工作原理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 后台缓冲 │ │ 后台缓冲 │ │ 后台缓冲 │ │
│ │ 0 │ │ 1 │ │ 2 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └─────────────┼─────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Present() │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ 前台缓冲 │ ───► 显示器 │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
### 8.2 三重缓冲
项目使用三重缓冲(`frame_buffer_count = 3`
| 特性 | 说明 |
|------|------|
| **减少撕裂** | 前台缓冲独立于后台缓冲,避免部分更新 |
| **提高并行性** | CPU 可提前录制多帧命令 |
| **平滑帧率** | 缓冲区平滑帧时间波动 |
### 8.3 d3d12_surface 类
```cpp
class d3d12_surface
{
public:
// 创建交换链
void create_swap_chain(IDXGIFactory7* factory,
ID3D12CommandQueue* cmd_queue,
DXGI_FORMAT format);
// 呈现当前帧
void present() const;
// 调整大小
void resize();
// 获取当前后台缓冲区
ID3D12Resource* back_buffer() const;
descriptor_handle rtv() const;
private:
IDXGISwapChain4* _swap_chain;
render_target_data _render_target_data[frame_buffer_count];
D3D12_VIEWPORT _viewport;
D3D12_RECT _scissor_rect;
};
```
### 8.4 交换链创建流程
```cpp
void create_swap_chain(...)
{
// 1. 配置描述
DXGI_SWAP_CHAIN_DESC1 desc{};
desc.BufferCount = frame_buffer_count;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.Width = window.width();
desc.Height = window.height();
desc.SampleDesc.Count = 1; // 禁用 MSAA
// 2. 创建交换链
factory->CreateSwapChainForHwnd(cmd_queue, hwnd, &desc, ...);
// 3. 禁用 Alt+Enter由应用处理
factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
// 4. 创建渲染目标视图
for(u32 i = 0; i < frame_buffer_count; ++i)
{
_swap_chain->GetBuffer(i, &resource);
device->CreateRenderTargetView(resource, &desc, rtv.cpu);
}
}
```
### 8.5 视口与裁剪矩形
```cpp
// 视口:定义光栅化区域
D3D12_VIEWPORT viewport{
.TopLeftX = 0.0f,
.TopLeftY = 0.0f,
.Width = (float)width,
.Height = (float)height,
.MinDepth = 0.0f,
.MaxDepth = 1.0f
};
// 裁剪矩形:定义像素输出区域
D3D12_RECT scissor_rect{0, 0, width, height};
```
## 9. 渲染表面与窗口
### 9.1 render_surface 结构
```cpp
struct render_surface {
@@ -500,7 +615,7 @@ struct render_surface {
};
```
### 8.2 多窗口支持
### 9.2 多窗口支持
TestRenderer 测试展示了多窗口渲染:
@@ -513,7 +628,7 @@ for (u32 i{0}; i < _countof(_surfaces); ++i) {
}
```
### 8.3 全屏切换
### 9.3 全屏切换
通过 `WM_SYSCHAR` 消息处理 Alt+Enter
@@ -523,42 +638,42 @@ if (wparam == VK_RETURN && (HIWORD(lparam) & KF_ALTDOWN)) {
}
```
## 9. 后续学习路径
## 10. 后续学习路径
### 9.1 基础阶段
### 10.1 基础阶段
- [x] 完成设备创建和适配器枚举
- [x] 创建命令队列和命令列表
- [x] 描述符堆管理
- [ ] 实现交换链和后台缓冲区
- [x] 实现交换链和后台缓冲区
- [ ] 渲染第一个三角形
### 9.2 进阶阶段
### 10.2 进阶阶段
- [ ] 根签名和管线状态对象
- [ ] 资源屏障和同步
- [ ] 常量缓冲区和着色器资源
### 9.3 高级阶段
### 10.3 高级阶段
- [ ] 多线程渲染
- [ ] 资源绑定策略
- [ ] 动态资源管理
- [ ] 性能优化
## 10. 参考资源
## 11. 参考资源
### 10.1 官方文档
### 11.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)
### 10.2 推荐书籍
### 11.2 推荐书籍
- 《Introduction to 3D Game Programming with DirectX 12》
- 《Real-Time 3D Rendering with DirectX and HLSL》
### 10.3 项目相关文档
### 11.3 项目相关文档
- [Graphics渲染架构分析](./Graphics渲染架构分析.md)
- [项目约定规范](./项目约定规范.md)