docs(api): document D3D12 queue and allocator behavior
This commit is contained in:
@@ -1,28 +1,19 @@
|
||||
# D3D12CommandAllocator::D3D12CommandAllocator()
|
||||
|
||||
构造对象。
|
||||
# D3D12CommandAllocator::D3D12CommandAllocator
|
||||
|
||||
```cpp
|
||||
D3D12CommandAllocator();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`,当前页面用于固定 `D3D12CommandAllocator` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
构造一个空的 D3D12 命令分配器封装对象。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandAllocator.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandAllocator object;
|
||||
}
|
||||
```
|
||||
- 构造函数仅把 `m_type` 初始化为 `CommandQueueType::Direct`。
|
||||
- `m_commandAllocator` 初始为空。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandAllocator.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [D3D12CommandAllocator](D3D12CommandAllocator.md)
|
||||
|
||||
@@ -6,31 +6,64 @@
|
||||
|
||||
**头文件**: `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`
|
||||
|
||||
**描述**: 定义 `XCEngine/RHI/D3D12` 子目录中的 `D3D12CommandAllocator` public API。
|
||||
**描述**: D3D12 后端的命令分配器薄封装,用于为命令列表提供底层命令内存。
|
||||
|
||||
## 概述
|
||||
## 概览
|
||||
|
||||
`D3D12CommandAllocator.h` 是 `XCEngine/RHI/D3D12` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。
|
||||
`D3D12CommandAllocator` 是对 `ID3D12CommandAllocator` 的直接封装。它的职责很单一:
|
||||
|
||||
## 声明概览
|
||||
- 按队列类型创建 allocator
|
||||
- 在合适时机执行 `Reset()`
|
||||
- 把原生 allocator 指针交给命令列表初始化或重置流程
|
||||
|
||||
| 声明 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `D3D12CommandAllocator` | `class` | 头文件中的公开声明。 |
|
||||
和商业引擎里更完整的 command context / frame graph 系统一样,allocator 的真正难点从来不在“创建它”,而在“何时安全地重置它”。当前类只封装了原生对象,不替你做生命周期调度。
|
||||
|
||||
## 公共方法
|
||||
## 设计定位
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [D3D12CommandAllocator()](Constructor.md) | 构造对象。 |
|
||||
| [~D3D12CommandAllocator()](Destructor.md) | 销毁对象并释放相关资源。 |
|
||||
| [Initialize](Initialize.md) | 初始化内部状态。 |
|
||||
| [Shutdown](Shutdown.md) | 关闭并清理内部状态。 |
|
||||
| [Reset](Reset.md) | 公开方法,详见头文件声明。 |
|
||||
| [IsReady](IsReady.md) | 查询当前状态。 |
|
||||
| [GetCommandAllocator](GetCommandAllocator.md) | 获取相关状态或对象。 |
|
||||
这是一个非常薄的后端包装器:
|
||||
|
||||
- 没有帧轮转系统
|
||||
- 没有 GPU in-flight 检查
|
||||
- 没有错误处理外层语义
|
||||
|
||||
因此它更像“把 D3D12 allocator 放进统一 RHI 代码结构里的一个基础零件”。
|
||||
|
||||
## 生命周期
|
||||
|
||||
- 构造后为空对象。
|
||||
- [Initialize](Initialize.md) 成功后持有 `ID3D12CommandAllocator`。
|
||||
- [Reset](Reset.md) 复位底层命令内存。
|
||||
- [Shutdown](Shutdown.md) 释放原生对象。
|
||||
- 析构时自动调用 `Shutdown()`。
|
||||
|
||||
## 线程语义
|
||||
|
||||
- 当前封装没有锁。
|
||||
- D3D12 allocator 的安全复用依赖 GPU 执行进度;当前类不负责并发或帧同步控制。
|
||||
|
||||
## 当前实现的真实行为
|
||||
|
||||
- `Initialize()` 直接按 `CommandQueueType` 创建 allocator。
|
||||
- `Reset()` 直接调用底层 `Reset()`,不检查返回值,也不检查 GPU 是否仍在使用该 allocator。
|
||||
- `IsReady()` 只判断 `m_commandAllocator != nullptr`,不代表“此刻可以安全重置或复用”。
|
||||
- `D3D12Device` 和 D3D12 集成测试都会把它作为命令列表初始化的基础对象。
|
||||
|
||||
## 当前限制
|
||||
|
||||
- 没有空指针保护的 `Reset()`。
|
||||
- 没有暴露底层 `HRESULT`。
|
||||
- 没有记录 allocator 当前是否仍被某条命令队列引用。
|
||||
|
||||
## 关键方法
|
||||
|
||||
- [Initialize](Initialize.md)
|
||||
- [Reset](Reset.md)
|
||||
- [IsReady](IsReady.md)
|
||||
- [GetCommandAllocator](GetCommandAllocator.md)
|
||||
- [Shutdown](Shutdown.md)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [当前目录](../D3D12.md) - 返回 `D3D12` 平行目录
|
||||
- [API 总索引](../../../../main.md) - 返回顶层索引
|
||||
- [D3D12](../D3D12.md)
|
||||
- [D3D12CommandList](../D3D12CommandList/D3D12CommandList.md)
|
||||
- [D3D12CommandQueue](../D3D12CommandQueue/D3D12CommandQueue.md)
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
# D3D12CommandAllocator::~D3D12CommandAllocator()
|
||||
|
||||
销毁对象并释放相关资源。
|
||||
# D3D12CommandAllocator::~D3D12CommandAllocator
|
||||
|
||||
```cpp
|
||||
~D3D12CommandAllocator();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`,当前页面用于固定 `D3D12CommandAllocator` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
销毁对象并释放内部 `ID3D12CommandAllocator` 引用。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandAllocator.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandAllocator object;
|
||||
// 对象离开作用域时会自动触发析构。
|
||||
}
|
||||
```
|
||||
- 析构函数内部调用 [Shutdown](Shutdown.md)。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandAllocator.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Shutdown](Shutdown.md)
|
||||
- [Reset](Reset.md)
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
# D3D12CommandAllocator::GetCommandAllocator
|
||||
|
||||
获取相关状态或对象。
|
||||
|
||||
```cpp
|
||||
ID3D12CommandAllocator* GetCommandAllocator() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`,当前页面用于固定 `D3D12CommandAllocator` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
返回底层原生命令分配器指针。
|
||||
|
||||
**返回:** `ID3D12CommandAllocator*` - 返回值语义详见头文件声明。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandAllocator.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandAllocator object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandAllocator::GetCommandAllocator(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 初始化成功后返回有效 `ID3D12CommandAllocator*`。
|
||||
- 否则返回 `nullptr`。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandAllocator.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [IsReady](IsReady.md)
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
# D3D12CommandAllocator::Initialize
|
||||
|
||||
初始化内部状态。
|
||||
|
||||
```cpp
|
||||
bool Initialize(ID3D12Device* device, CommandQueueType type = CommandQueueType::Direct);
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`,当前页面用于固定 `D3D12CommandAllocator` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:**
|
||||
- `device` - 参数语义详见头文件声明。
|
||||
- `type` - 参数语义详见头文件声明。
|
||||
创建一个与指定队列类型匹配的 D3D12 命令分配器。
|
||||
|
||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
||||
## 参数说明
|
||||
|
||||
**示例:**
|
||||
- `device`: D3D12 设备。
|
||||
- `type`: 队列类型,会映射到对应的 `D3D12_COMMAND_LIST_TYPE`。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandAllocator.h>
|
||||
## 返回值
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandAllocator object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandAllocator::Initialize(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- `CreateCommandAllocator()` 成功时返回 `true`。
|
||||
- 失败时返回 `false`。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 先把 `m_type` 保存为传入值。
|
||||
- 调用 `device->CreateCommandAllocator(ToD3D12(type), ...)` 创建原生对象。
|
||||
- 直接把 `SUCCEEDED(hResult)` 作为返回值。
|
||||
|
||||
## 使用建议
|
||||
|
||||
- 初始化成功只代表 allocator 创建完成,不代表它已经与某个命令列表或帧同步策略正确配套。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandAllocator.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Reset](Reset.md)
|
||||
- [GetCommandAllocator](GetCommandAllocator.md)
|
||||
|
||||
@@ -1,30 +1,23 @@
|
||||
# D3D12CommandAllocator::IsReady
|
||||
|
||||
查询当前状态。
|
||||
|
||||
```cpp
|
||||
bool IsReady() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`,当前页面用于固定 `D3D12CommandAllocator` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
检查当前对象是否已经持有底层 allocator。
|
||||
|
||||
**返回:** `bool` - 返回值语义详见头文件声明。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
- 仅返回 `m_commandAllocator != nullptr`。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandAllocator.h>
|
||||
## 重要限制
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandAllocator object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandAllocator::IsReady(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 这不表示 allocator 当前“可以安全重置”。
|
||||
- 它只说明原生对象已经创建出来,完全不覆盖 GPU in-flight 生命周期语义。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandAllocator.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Reset](Reset.md)
|
||||
- [GetCommandAllocator](GetCommandAllocator.md)
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
# D3D12CommandAllocator::Reset
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
void Reset();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`,当前页面用于固定 `D3D12CommandAllocator` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
复位底层命令分配器,以便重新录制命令。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
- 直接调用 `m_commandAllocator->Reset()`。
|
||||
- 不检查 `m_commandAllocator` 是否为空。
|
||||
- 不检查返回 `HRESULT`。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandAllocator.h>
|
||||
## 重要限制
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandAllocator object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandAllocator::Reset(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 如果 GPU 仍在执行引用该 allocator 的命令列表,D3D12 层面可能认为这次重置是非法的。
|
||||
- 当前封装没有任何 fence / frame ownership 校验。
|
||||
|
||||
## 使用建议
|
||||
|
||||
- 只有在外部同步逻辑已经确认该 allocator 不再被 GPU 使用时,才应调用该接口。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandAllocator.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [IsReady](IsReady.md)
|
||||
- [D3D12CommandQueue::WaitForPreviousFrame](../D3D12CommandQueue/WaitForPreviousFrame.md)
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
# D3D12CommandAllocator::Shutdown
|
||||
|
||||
关闭并清理内部状态。
|
||||
|
||||
```cpp
|
||||
void Shutdown();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandAllocator.h`,当前页面用于固定 `D3D12CommandAllocator` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
释放内部 `ID3D12CommandAllocator` 引用。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandAllocator.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandAllocator object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandAllocator::Shutdown(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 仅调用 `m_commandAllocator.Reset()`。
|
||||
- 不会重置 `m_type`。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandAllocator.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Destructor](Destructor.md)
|
||||
- [GetCommandAllocator](GetCommandAllocator.md)
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
# D3D12CommandQueue::D3D12CommandQueue()
|
||||
|
||||
构造对象。
|
||||
# D3D12CommandQueue::D3D12CommandQueue
|
||||
|
||||
```cpp
|
||||
D3D12CommandQueue();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
构造一个空的 D3D12 命令队列封装对象。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
}
|
||||
```
|
||||
- 构造函数会把:
|
||||
- `m_timestampFrequency` 初始化为 `0`
|
||||
- `m_type` 初始化为 `CommandQueueType::Direct`
|
||||
- `m_currentFrame` 依赖类内默认值初始化为 `0`
|
||||
- 原生命令队列、内部帧围栏和事件句柄均为空。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [D3D12CommandQueue](D3D12CommandQueue.md)
|
||||
|
||||
@@ -6,59 +6,88 @@
|
||||
|
||||
**头文件**: `XCEngine/RHI/D3D12/D3D12CommandQueue.h`
|
||||
|
||||
**描述**: D3D12 后端的命令提交队列封装,负责提交命令列表、与 fence 交互,并维护一条简化的“当前帧计数”时间线。
|
||||
**描述**: D3D12 后端的命令队列封装,负责命令提交、跨队列 fence 同步,以及一套内部帧完成跟踪机制。
|
||||
|
||||
## 概览
|
||||
|
||||
`D3D12CommandQueue` 是抽象 [`RHICommandQueue`](../../RHICommandQueue/RHICommandQueue.md) 在 D3D12 上的直接映射。它内部持有一个真实的 `ID3D12CommandQueue`,并额外维护了一个仅供队列自身使用的 `m_frameFence`。
|
||||
`D3D12CommandQueue` 一方面包装了真实的 `ID3D12CommandQueue`,另一方面又额外维护了一套“内部帧围栏”状态:
|
||||
|
||||
这类设计和商业引擎的 backend queue 很像:
|
||||
- `m_frameFence`
|
||||
- `m_currentFrame`
|
||||
- `m_frameEvent`
|
||||
|
||||
- 上层只关心“把哪些命令列表送到哪类队列”
|
||||
- 后端负责把抽象 `CommandQueueType` 翻译成 D3D12 queue type
|
||||
- 同步仍然是显式的,不会像 OpenGL 那样把提交和执行揉成同一个概念
|
||||
这让它既能承担普通的 D3D12 queue 提交职责,也能为引擎的“上一帧是否完成”逻辑提供一个简单的等待点。
|
||||
|
||||
## 设计定位
|
||||
|
||||
当前实现是一个实用型封装,不是完整的多帧调度系统:
|
||||
|
||||
- 它能提交命令列表
|
||||
- 能 signal / wait 指定 fence
|
||||
- 能跟踪每次内部提交后的帧序号
|
||||
- 也能做粗粒度的 queue idle 等待
|
||||
|
||||
但它没有:
|
||||
|
||||
- 完整的错误处理
|
||||
- 并发提交保护
|
||||
- 精细的 per-frame allocator / resource ownership 管理
|
||||
|
||||
## 生命周期
|
||||
|
||||
典型顺序是:
|
||||
|
||||
1. 构造对象
|
||||
2. 调用 [`Initialize`](Initialize.md)
|
||||
3. 反复调用 [`ExecuteCommandLists`](ExecuteCommandLists.md)、[`Signal`](Signal.md)、[`Wait`](Wait.md)
|
||||
4. 在需要粗粒度同步时调用 [`WaitForIdle`](WaitForIdle.md)
|
||||
5. 销毁前调用 `Shutdown()`
|
||||
|
||||
## 当前实现的真实行为
|
||||
|
||||
- `Initialize()` 会创建真实的 `ID3D12CommandQueue`
|
||||
- 同时会创建一条 `m_frameFence` 和一个 Win32 event,用于 `WaitForPreviousFrame()`
|
||||
- `ExecuteCommandLists()` 提交后会把 `m_currentFrame` 加一,并用 `m_frameFence` signal 这个值
|
||||
- [`GetCompletedValue`](GetCompletedValue.md) 返回的是 `m_frameFence` 的完成值,不是某个外部 fence 的值
|
||||
- [`WaitForIdle`](WaitForIdle.md) 当前不是复用 `m_frameFence`,而是临时创建一个 fence 后轮询等待,这属于可用但不够成熟的实现
|
||||
- 构造后为空对象。
|
||||
- [Initialize](Initialize.md) 成功后会创建:
|
||||
- `ID3D12CommandQueue`
|
||||
- 一条内部帧围栏 `m_frameFence`
|
||||
- 一个 Win32 event `m_frameEvent`
|
||||
- [Shutdown](Shutdown.md) 释放这些内部资源。
|
||||
- 析构时自动调用 `Shutdown()`。
|
||||
|
||||
## 线程语义
|
||||
|
||||
队列对象本身没有做额外并发保护。更合理的假设是:
|
||||
- 底层 D3D12 queue 可以支持多线程提交,但当前包装器没有锁。
|
||||
- 尤其是 `m_currentFrame` 和内部帧围栏的维护不是并发安全协议,应该把这个类视为单拥有者队列封装。
|
||||
|
||||
- 一条队列由渲染线程或提交线程顺序驱动
|
||||
- 外部若要并发 signal / wait / submit,需要自行加锁或做任务级调度
|
||||
## 当前实现的真实行为
|
||||
|
||||
- [ExecuteCommandListsInternal](ExecuteCommandListsInternal.md) 每次提交后都会:
|
||||
- `m_currentFrame++`
|
||||
- 用队列 signal 内部 `m_frameFence`
|
||||
- [GetCompletedValue](GetCompletedValue.md) 返回的是内部帧围栏的完成值,不是任意用户 fence 的完成值。
|
||||
- [WaitForPreviousFrame](WaitForPreviousFrame.md) 只等待内部帧围栏推进到当前 `m_currentFrame`。
|
||||
- [WaitForIdle](WaitForIdle.md) 每次都会临时创建一个新 fence,然后通过 `Sleep(1)` 轮询等待,没有使用 event。
|
||||
- [Signal](Signal.md) / [Wait](Wait.md) 既支持 `RHIFence*`,也支持 `ID3D12Fence*`,但都依赖队列已初始化。
|
||||
- `ExecuteCommandLists(void** lists)` 不会压缩空指针条目;如果调用方传入带空洞的数组,当前实现会把同样长度的数组继续传给 D3D12。
|
||||
|
||||
## 为什么这样设计
|
||||
|
||||
这套设计很像很多引擎里的“最小可用 D3D12 队列层”:
|
||||
|
||||
- 提供统一 RHI queue 接口
|
||||
- 再额外塞入一套简单的 frame completion 跟踪
|
||||
|
||||
这样可以快速支撑测试、样例和基础渲染循环,但离商业级多帧资源调度系统还有明显距离。文档里必须把“内部帧围栏”和“用户 fence”区分开,否则上层很容易把两者混为一谈。
|
||||
|
||||
## 当前限制
|
||||
|
||||
- `WaitForIdle()` 采用临时 fence + `Sleep(1)` 轮询,适合调试和初始化路径,不适合高频帧间同步
|
||||
- `GetCompletedValue()` 只反映内部帧 fence 的状态,不等同于 GPU 全局时间线
|
||||
- 多数方法没有 `m_commandQueue` 空指针保护。
|
||||
- `WaitForIdle()` 是临时 fence + busy-wait 的粗实现。
|
||||
- `ExecuteCommandLists()` 不检查命令列表是否已关闭,也不剔除空项。
|
||||
- 初始化中途失败时不会在函数内立刻回滚已创建的对象,通常依赖后续 `Shutdown()` / 析构统一清理。
|
||||
|
||||
## 重点公共方法
|
||||
## 关键方法
|
||||
|
||||
- [Initialize](Initialize.md)
|
||||
- [ExecuteCommandLists](ExecuteCommandLists.md)
|
||||
- [ExecuteCommandListsInternal](ExecuteCommandListsInternal.md)
|
||||
- [Signal](Signal.md)
|
||||
- [Wait](Wait.md)
|
||||
- [GetCompletedValue](GetCompletedValue.md)
|
||||
- [WaitForPreviousFrame](WaitForPreviousFrame.md)
|
||||
- [WaitForIdle](WaitForIdle.md)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12](../D3D12.md)
|
||||
- [D3D12Device](../D3D12Device/D3D12Device.md)
|
||||
- [D3D12Fence](../D3D12Fence/D3D12Fence.md)
|
||||
- [D3D12CommandAllocator](../D3D12CommandAllocator/D3D12CommandAllocator.md)
|
||||
- [D3D12CommandList](../D3D12CommandList/D3D12CommandList.md)
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
# D3D12CommandQueue::~D3D12CommandQueue()
|
||||
|
||||
销毁对象并释放相关资源。
|
||||
# D3D12CommandQueue::~D3D12CommandQueue
|
||||
|
||||
```cpp
|
||||
~D3D12CommandQueue() override;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
销毁对象并释放内部命令队列、帧围栏和事件句柄。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 对象离开作用域时会自动触发析构。
|
||||
}
|
||||
```
|
||||
- 析构函数内部调用 [Shutdown](Shutdown.md)。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Shutdown](Shutdown.md)
|
||||
- [Initialize](Initialize.md)
|
||||
|
||||
@@ -6,24 +6,28 @@ void ExecuteCommandLists(uint32_t count, void** lists) override;
|
||||
|
||||
## 作用
|
||||
|
||||
把一组抽象命令列表提交到当前 D3D12 队列。
|
||||
提交一组 RHI 命令列表到当前 D3D12 队列。
|
||||
|
||||
## 前置条件
|
||||
## 参数说明
|
||||
|
||||
- 队列已经初始化
|
||||
- `lists` 指向的是可提交的 `RHICommandList` 实例
|
||||
- `count`: 命令列表数量。
|
||||
- `lists`: `RHICommandList*` 指针数组,以 `void**` 形式传入。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 当 `count == 0` 或 `lists == nullptr` 时直接返回
|
||||
- 把每个 `RHICommandList` 的 `GetNativeHandle()` 转成 `ID3D12CommandList*`
|
||||
- 调用内部 `ExecuteCommandListsInternal()`
|
||||
- `ExecuteCommandListsInternal()` 提交后会:
|
||||
- `m_currentFrame++`
|
||||
- 对 `m_frameFence` signal 当前帧值
|
||||
- 当 `count == 0` 或 `lists == nullptr` 时直接返回。
|
||||
- 创建一个 `std::vector<ID3D12CommandList*>`。
|
||||
- 对每个非空 `lists[i]`:
|
||||
- 转成 `RHICommandList*`
|
||||
- 通过 `GetNativeHandle()` 取到底层命令列表指针
|
||||
- 然后调用 [ExecuteCommandListsInternal](ExecuteCommandListsInternal.md)。
|
||||
|
||||
## 重要限制
|
||||
|
||||
- 当前实现不会压缩空指针条目;如果 `lists[i]` 为 `nullptr`,对应位置仍会以空值保留在提交数组里。
|
||||
- 它不负责关闭命令列表,也不验证命令列表是否处于可执行状态。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12CommandQueue](D3D12CommandQueue.md)
|
||||
- [GetCompletedValue](GetCompletedValue.md)
|
||||
- [WaitForIdle](WaitForIdle.md)
|
||||
- [ExecuteCommandListsInternal](ExecuteCommandListsInternal.md)
|
||||
- [GetCurrentFrame](GetCurrentFrame.md)
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
# D3D12CommandQueue::ExecuteCommandListsInternal
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
void ExecuteCommandListsInternal(uint32_t count, ID3D12CommandList** lists);
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:**
|
||||
- `count` - 参数语义详见头文件声明。
|
||||
- `lists` - 参数语义详见头文件声明。
|
||||
直接向底层 `ID3D12CommandQueue` 提交原生命令列表,并推进内部帧计数。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 参数说明
|
||||
|
||||
**示例:**
|
||||
- `count`: 原生命令列表数量。
|
||||
- `lists`: `ID3D12CommandList*` 数组。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
## 当前实现行为
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::ExecuteCommandListsInternal(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 如果队列未初始化、`count == 0` 或 `lists == nullptr`,直接返回。
|
||||
- 调用 `m_commandQueue->ExecuteCommandLists(count, lists)`。
|
||||
- 然后 `m_currentFrame++`。
|
||||
- 如果内部帧围栏存在,再调用 `m_commandQueue->Signal(m_frameFence.Get(), m_currentFrame)`。
|
||||
|
||||
## 设计说明
|
||||
|
||||
- 这里的 `m_currentFrame` 不是 swap chain back buffer index。
|
||||
- 它更像“本队列完成了多少次内部提交”的单调计数器。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [GetCurrentFrame](GetCurrentFrame.md)
|
||||
- [WaitForPreviousFrame](WaitForPreviousFrame.md)
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
# D3D12CommandQueue::GetCommandQueue
|
||||
|
||||
获取相关状态或对象。
|
||||
|
||||
```cpp
|
||||
ID3D12CommandQueue* GetCommandQueue() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
返回底层原生命令队列指针。
|
||||
|
||||
**返回:** `ID3D12CommandQueue*` - 返回值语义详见头文件声明。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::GetCommandQueue(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 初始化成功后返回有效 `ID3D12CommandQueue*`。
|
||||
- 否则返回 `nullptr`。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [GetNativeHandle](GetNativeHandle.md)
|
||||
- [Initialize](Initialize.md)
|
||||
|
||||
@@ -6,18 +6,18 @@ uint64_t GetCompletedValue() override;
|
||||
|
||||
## 作用
|
||||
|
||||
查询队列内部帧 fence 当前已经完成到哪一帧。
|
||||
返回当前内部帧围栏的完成值。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 若 `m_frameFence` 存在,则返回其 `GetCompletedValue()`
|
||||
- 否则返回 `0`
|
||||
- 如果 `m_frameFence` 有效,返回 `m_frameFence->GetCompletedValue()`。
|
||||
- 否则返回 `0`。
|
||||
|
||||
## 注意事项
|
||||
## 重要区别
|
||||
|
||||
这不是对“所有提交过的外部 fence”的统一查询;它只反映队列自身维护的那条帧时间线。
|
||||
- 这里返回的是队列自己的内部 frame fence 状态,不是调用方自定义 fence 的状态。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [ExecuteCommandLists](ExecuteCommandLists.md)
|
||||
- [WaitForIdle](WaitForIdle.md)
|
||||
- [GetCurrentFrame](GetCurrentFrame.md)
|
||||
- [WaitForPreviousFrame](WaitForPreviousFrame.md)
|
||||
|
||||
@@ -1,30 +1,23 @@
|
||||
# D3D12CommandQueue::GetCurrentFrame
|
||||
|
||||
获取相关状态或对象。
|
||||
|
||||
```cpp
|
||||
uint64_t GetCurrentFrame() const;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
返回该队列的内部提交帧计数。
|
||||
|
||||
**返回:** `uint64_t` - 返回值语义详见头文件声明。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
- 初始值为 `0`。
|
||||
- 每次调用 [ExecuteCommandListsInternal](ExecuteCommandListsInternal.md) 成功走到提交路径后都会递增 `1`。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
## 使用建议
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::GetCurrentFrame(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 它表示“本队列提交次数计数”,不等于 swap chain 的 back buffer index,也不等于全局渲染帧号。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [GetCompletedValue](GetCompletedValue.md)
|
||||
- [WaitForPreviousFrame](WaitForPreviousFrame.md)
|
||||
|
||||
@@ -1,30 +1,18 @@
|
||||
# D3D12CommandQueue::GetNativeHandle
|
||||
|
||||
获取相关状态或对象。
|
||||
|
||||
```cpp
|
||||
void* GetNativeHandle() override;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
以统一接口形式暴露底层 `ID3D12CommandQueue*`。
|
||||
|
||||
**返回:** `void*` - 返回值语义详见头文件声明。
|
||||
## 返回值
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::GetNativeHandle(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 直接返回 `m_commandQueue.Get()`。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [GetCommandQueue](GetCommandQueue.md)
|
||||
- [Initialize](Initialize.md)
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
# D3D12CommandQueue::GetTimestampFrequency
|
||||
|
||||
获取相关状态或对象。
|
||||
|
||||
```cpp
|
||||
uint64_t GetTimestampFrequency() const override;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
返回命令队列的时间戳频率。
|
||||
|
||||
**返回:** `uint64_t` - 返回值语义详见头文件声明。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::GetTimestampFrequency(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 初始化成功后通过 `m_commandQueue->GetTimestampFrequency(&m_timestampFrequency)` 缓存该值。
|
||||
- 此接口仅返回缓存值,不会再次查询底层队列。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [GetType](GetType.md)
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
# D3D12CommandQueue::GetType
|
||||
|
||||
获取相关状态或对象。
|
||||
|
||||
```cpp
|
||||
CommandQueueType GetType() const override;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
返回该队列记录的逻辑类型。
|
||||
|
||||
**返回:** `CommandQueueType` - 返回值语义详见头文件声明。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::GetType(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 直接返回缓存的 `m_type`。
|
||||
- 构造默认值是 `Direct`,初始化成功后会更新为实际传入类型。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [GetTimestampFrequency](GetTimestampFrequency.md)
|
||||
|
||||
@@ -6,23 +6,32 @@ bool Initialize(ID3D12Device* device, CommandQueueType type = CommandQueueType::
|
||||
|
||||
## 作用
|
||||
|
||||
创建原生 D3D12 队列对象和队列自身使用的帧 fence。
|
||||
创建底层 D3D12 命令队列,并初始化内部帧同步对象。
|
||||
|
||||
## 参数说明
|
||||
|
||||
- `device`: D3D12 设备。
|
||||
- `type`: 队列类型。
|
||||
|
||||
## 返回值
|
||||
|
||||
- 命令队列、内部帧围栏和事件都创建成功时返回 `true`。
|
||||
- 任一步骤失败时返回 `false`。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 把 `CommandQueueType` 转成 `D3D12_COMMAND_QUEUE_DESC.Type`
|
||||
- 创建 `ID3D12CommandQueue`
|
||||
- 创建一只初始值为 `0` 的 `m_frameFence`
|
||||
- 创建 Win32 event 保存到 `m_frameEvent`
|
||||
- 缓存队列类型和 timestamp frequency
|
||||
- 构造 `D3D12_COMMAND_QUEUE_DESC` 并调用 `CreateCommandQueue()`。
|
||||
- 随后创建内部 `m_frameFence`。
|
||||
- 再创建自动重置的 Win32 event `m_frameEvent`。
|
||||
- 把 `m_type` 保存为传入值。
|
||||
- 调用 `GetTimestampFrequency()` 并缓存到 `m_timestampFrequency`。
|
||||
|
||||
## 失败路径
|
||||
## 重要限制
|
||||
|
||||
- 创建原生队列失败返回 `false`
|
||||
- 创建 `m_frameFence` 失败返回 `false`
|
||||
- 创建 event 失败返回 `false`
|
||||
- 如果创建队列成功、但后续创建 fence 或 event 失败,函数会直接返回 `false`,不会在函数内部立即回收前面已创建的对象。
|
||||
- 当前实现没有检查 `GetTimestampFrequency()` 的返回值。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12CommandQueue](D3D12CommandQueue.md)
|
||||
- [ExecuteCommandLists](ExecuteCommandLists.md)
|
||||
- [WaitForPreviousFrame](WaitForPreviousFrame.md)
|
||||
- [GetTimestampFrequency](GetTimestampFrequency.md)
|
||||
|
||||
@@ -1,30 +1,25 @@
|
||||
# D3D12CommandQueue::Shutdown
|
||||
|
||||
关闭并清理内部状态。
|
||||
|
||||
```cpp
|
||||
void Shutdown() override;
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
释放内部命令队列、帧围栏和事件句柄。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
- 如果 `m_frameEvent` 非空,调用 `CloseHandle()` 并清空句柄。
|
||||
- 调用 `m_frameFence.Reset()`。
|
||||
- 调用 `m_commandQueue.Reset()`。
|
||||
- 不会重置 `m_timestampFrequency`、`m_currentFrame` 或 `m_type`。
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
## 使用建议
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::Shutdown(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- `Shutdown()` 后不应继续调用 [Signal](Signal.md)、[Wait](Wait.md)、[WaitForIdle](WaitForIdle.md) 等依赖底层队列的方法。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [Destructor](Destructor.md)
|
||||
- [GetCommandQueue](GetCommandQueue.md)
|
||||
|
||||
@@ -2,23 +2,35 @@
|
||||
|
||||
```cpp
|
||||
void Signal(RHIFence* fence, uint64_t value) override;
|
||||
void Signal(ID3D12Fence* fence, uint64_t value);
|
||||
```
|
||||
|
||||
## 作用
|
||||
|
||||
让当前队列对指定 fence signal 一个值。
|
||||
让当前队列在执行进度推进到指定位置后 signal 某个 fence 值。
|
||||
|
||||
## 参数说明
|
||||
|
||||
- `fence`: 目标 fence,可以是 `RHIFence*` 或原生 `ID3D12Fence*`。
|
||||
- `value`: 要写入的 fence 值。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 若 `fence == nullptr`,直接返回
|
||||
- 把抽象 `RHIFence` 转成 `D3D12Fence`
|
||||
- 调用原生 `ID3D12CommandQueue::Signal(...)`
|
||||
### `Signal(RHIFence* fence, uint64_t value)`
|
||||
|
||||
## 注意事项
|
||||
- 如果 `fence` 非空,把它转成 `D3D12Fence*`。
|
||||
- 然后取出底层 `ID3D12Fence*`,调用 `m_commandQueue->Signal(...)`。
|
||||
|
||||
这里使用的是调用方传入的 fence,不是队列自己的 `m_frameFence`。
|
||||
### `Signal(ID3D12Fence* fence, uint64_t value)`
|
||||
|
||||
- 如果 `fence` 非空,直接调用 `m_commandQueue->Signal(fence, value)`。
|
||||
|
||||
## 重要限制
|
||||
|
||||
- 这两个重载都没有检查 `m_commandQueue` 是否为空。
|
||||
- 与 [D3D12Fence::Signal](../D3D12Fence/Signal.md) 不同,这里表达的是“由 GPU 队列 signal fence”。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [D3D12CommandQueue](D3D12CommandQueue.md)
|
||||
- [Wait](Wait.md)
|
||||
- [D3D12Fence::Signal](../D3D12Fence/Signal.md)
|
||||
|
||||
@@ -2,23 +2,35 @@
|
||||
|
||||
```cpp
|
||||
void Wait(RHIFence* fence, uint64_t value) override;
|
||||
void Wait(ID3D12Fence* fence, uint64_t value);
|
||||
```
|
||||
|
||||
## 作用
|
||||
|
||||
让当前队列等待指定 fence 达到目标值。
|
||||
让当前队列等待指定 fence 到达目标值。
|
||||
|
||||
## 参数说明
|
||||
|
||||
- `fence`: 目标 fence,可以是 `RHIFence*` 或原生 `ID3D12Fence*`。
|
||||
- `value`: 目标 fence 值。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 若 `fence == nullptr`,直接返回
|
||||
- 把 `RHIFence` 转成 `D3D12Fence`
|
||||
- 调用原生 `ID3D12CommandQueue::Wait(...)`
|
||||
### `Wait(RHIFence* fence, uint64_t value)`
|
||||
|
||||
- 如果 `fence` 非空,将其转为 `D3D12Fence*`。
|
||||
- 然后调用 `m_commandQueue->Wait(nativeFence, value)`。
|
||||
|
||||
### `Wait(ID3D12Fence* fence, uint64_t value)`
|
||||
|
||||
- 如果 `fence` 非空,直接调用底层队列的 `Wait()`。
|
||||
|
||||
## 设计说明
|
||||
|
||||
这是一条 GPU 侧队列等待路径,不是 CPU 阻塞等待。它的语义更接近 D3D12 原生 queue dependency,而不是 `WaitForIdle()` 那种“CPU 等 GPU”。
|
||||
- 这是 GPU 队列级等待,不会阻塞 CPU 线程。
|
||||
- 如果你要阻塞 CPU 等待 fence,应使用 [D3D12Fence::Wait](../D3D12Fence/Wait.md)。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Signal](Signal.md)
|
||||
- [WaitForIdle](WaitForIdle.md)
|
||||
- [D3D12Fence::Wait](../D3D12Fence/Wait.md)
|
||||
|
||||
@@ -6,20 +6,24 @@ void WaitForIdle() override;
|
||||
|
||||
## 作用
|
||||
|
||||
阻塞 CPU,直到当前队列在调用点之前提交的工作全部完成。
|
||||
阻塞 CPU,直到当前队列上的工作全部完成。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 从队列反查 `ID3D12Device`
|
||||
- 临时创建一只 fence
|
||||
- 对该 fence signal `1`
|
||||
- 通过 `while (fence->GetCompletedValue() < 1) { Sleep(1); }` 轮询等待
|
||||
- 先通过 `m_commandQueue->GetDevice()` 反查设备。
|
||||
- 临时创建一个新的 `ID3D12Fence`。
|
||||
- 让当前队列 signal 该 fence 到值 `1`。
|
||||
- 然后循环查询 `fence->GetCompletedValue()`:
|
||||
- 未达到 `1` 时执行 `Sleep(1)`
|
||||
- 完成后释放临时 fence 和设备引用。
|
||||
|
||||
## 设计说明
|
||||
## 重要限制
|
||||
|
||||
这是一条简单、稳定、易懂的空闲等待路径,适合初始化、销毁和测试代码,但并不适合高频帧循环。更成熟的实现通常会复用长期存在的 fence,并用事件等待代替忙轮询。
|
||||
- 当前实现没有使用 event,而是 `Sleep(1)` busy-wait。
|
||||
- 这是一种简单但较粗糙的 idle 等待实现。
|
||||
- 也没有显式检查 `m_commandQueue` 是否为空。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [ExecuteCommandLists](ExecuteCommandLists.md)
|
||||
- [WaitForPreviousFrame](WaitForPreviousFrame.md)
|
||||
- [GetCompletedValue](GetCompletedValue.md)
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
# D3D12CommandQueue::WaitForPreviousFrame
|
||||
|
||||
公开方法,详见头文件声明。
|
||||
|
||||
```cpp
|
||||
void WaitForPreviousFrame();
|
||||
```
|
||||
|
||||
该方法声明于 `XCEngine/RHI/D3D12/D3D12CommandQueue.h`,当前页面用于固定 `D3D12CommandQueue` 类目录下的方法级 canonical 路径。
|
||||
## 作用
|
||||
|
||||
**参数:** 无。
|
||||
等待该队列内部“最近一次提交帧”完成。
|
||||
|
||||
**返回:** `void` - 无返回值。
|
||||
## 当前实现行为
|
||||
|
||||
**示例:**
|
||||
- 仅当 `m_currentFrame > 0` 且 `m_frameFence` 有效时才进入等待路径。
|
||||
- 如果 `m_frameFence->GetCompletedValue() < m_currentFrame`:
|
||||
- 调用 `m_frameFence->SetEventOnCompletion(m_currentFrame, m_frameEvent)`
|
||||
- 调用 `WaitForSingleObject(m_frameEvent, INFINITE)`
|
||||
|
||||
```cpp
|
||||
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
|
||||
## 设计说明
|
||||
|
||||
void Example() {
|
||||
XCEngine::RHI::D3D12CommandQueue object;
|
||||
// 根据上下文补齐参数后调用 D3D12CommandQueue::WaitForPreviousFrame(...)。
|
||||
(void)object;
|
||||
}
|
||||
```
|
||||
- 这里等待的是队列内部 frame fence,而不是 swap chain back buffer fence。
|
||||
- 它适合作为“上一轮本队列提交是否完成”的简单同步点。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [返回类总览](D3D12CommandQueue.md)
|
||||
- [返回模块目录](../D3D12.md)
|
||||
- [GetCurrentFrame](GetCurrentFrame.md)
|
||||
- [GetCompletedValue](GetCompletedValue.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# API 文档重构状态
|
||||
|
||||
**生成时间**: `2026-03-27 23:48:52`
|
||||
**生成时间**: `2026-03-27 23:56:05`
|
||||
|
||||
**来源**: `docs/api/_tools/audit_api_docs.py`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user