feat(RHI): 实现 RHICommandQueue 抽象基类

This commit is contained in:
2026-03-17 17:54:44 +08:00
parent 14fb51e61e
commit 4638539f17
6 changed files with 181 additions and 17 deletions

View File

@@ -694,6 +694,72 @@ public:
3. **底层逃逸**:通过 `GetNativeDevice()` 直接访问原生 API 3. **底层逃逸**:通过 `GetNativeDevice()` 直接访问原生 API
### 5.11 命令队列RHICommandQueue抽象设计
#### 5.11.1 设计理念对应
| 差异点 | 设计理念 | 处理方案 |
|--------|---------|---------|
| 初始化参数差异 | 求同存异 | 后端各自实现初始化 |
| 执行命令差异 | 特性降级 | D3D12 实现OpenGL 空实现 |
| 同步机制差异 | 特性降级 | D3D12 实现OpenGL 空实现 |
| 句柄类型差异 | 底层逃逸 | 统一返回 void* |
#### 5.11.2 现有实现对比
| 功能 | D3D12CommandQueue | OpenGL | 处理方案 |
|------|-------------------|--------|----------|
| 初始化 | Initialize(device, type) | 无 | OpenGL 空实现 |
| 执行命令 | ExecuteCommandLists() | 无 | OpenGL 空实现 |
| 信号同步 | Signal/Wait | 无 | OpenGL 空实现 |
| 空闲等待 | WaitForIdle() | 无 | OpenGL 空实现 |
| 句柄 | ID3D12CommandQueue* | 无 | GetNativeHandle |
#### 5.11.3 抽象接口定义
```cpp
class RHICommandQueue {
public:
virtual ~RHICommandQueue() = default;
virtual void Shutdown() = 0;
virtual void ExecuteCommandLists(uint32_t count, void** lists) = 0;
virtual void Signal(RHIFence* fence, uint64_t value) = 0;
virtual void Wait(RHIFence* 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;
virtual void* GetNativeHandle() = 0;
};
```
#### 5.11.4 差异处理策略
1. **初始化参数差异(求同存异)**
- D3D12需要 device + type 参数
- OpenGL无对等概念
- 解决Device 的 CreateCommandQueue() 统一接收 CommandQueueDesc
2. **执行命令差异(特性降级)**
- D3D12ExecuteCommandLists() 提交命令列表
- OpenGL状态机模型无命令队列概念
- 解决OpenGL 空实现
3. **同步机制差异(特性降级)**
- D3D12Signal/Wait/Fence 完整实现
- OpenGL无对等概念
- 解决OpenGL 空实现
4. **句柄类型差异(底层逃逸)**
- D3D12ID3D12CommandQueue*
- OpenGL无对等概念
- 解决GetNativeHandle() 返回 void*
## 6. 后端实现示例 ## 6. 后端实现示例
### 6.1 D3D12 设备实现D3D12Device.h ### 6.1 D3D12 设备实现D3D12Device.h
```cpp ```cpp

View File

@@ -3,6 +3,7 @@
#include <d3d12.h> #include <d3d12.h>
#include <wrl/client.h> #include <wrl/client.h>
#include "../RHICommandQueue.h"
#include "../RHIEnums.h" #include "../RHIEnums.h"
#include "D3D12Enum.h" #include "D3D12Enum.h"
@@ -13,26 +14,29 @@ namespace RHI {
class D3D12Fence; class D3D12Fence;
class D3D12CommandQueue { class D3D12CommandQueue : public RHICommandQueue {
public: public:
D3D12CommandQueue(); D3D12CommandQueue();
~D3D12CommandQueue(); ~D3D12CommandQueue() override;
bool Initialize(ID3D12Device* device, CommandQueueType type = CommandQueueType::Direct); bool Initialize(ID3D12Device* device, CommandQueueType type = CommandQueueType::Direct);
void Shutdown(); void Shutdown() override;
void ExecuteCommandLists(uint32_t count, ID3D12CommandList** lists); void ExecuteCommandLists(uint32_t count, void** lists) override;
void Signal(D3D12Fence* fence, uint64_t value); void Signal(RHIFence* fence, uint64_t value) override;
void Signal(ID3D12Fence* fence, uint64_t value); void Wait(RHIFence* fence, uint64_t value) override;
void Wait(D3D12Fence* fence, uint64_t value); uint64_t GetCompletedValue() override;
void Wait(ID3D12Fence* fence, uint64_t value); void WaitForIdle() override;
uint64_t GetCompletedValue();
void WaitForIdle();
CommandQueueType GetType() const { return m_type; } CommandQueueType GetType() const override { return m_type; }
uint64_t GetTimestampFrequency() const { return m_timestampFrequency; } uint64_t GetTimestampFrequency() const override { return m_timestampFrequency; }
ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); }
void* GetNativeHandle() override { return m_commandQueue.Get(); }
void ExecuteCommandListsInternal(uint32_t count, ID3D12CommandList** lists);
void Signal(ID3D12Fence* fence, uint64_t value);
void Wait(ID3D12Fence* fence, uint64_t value);
private: private:
ComPtr<ID3D12CommandQueue> m_commandQueue; ComPtr<ID3D12CommandQueue> m_commandQueue;

View File

@@ -0,0 +1,28 @@
#pragma once
#include "../RHICommandQueue.h"
namespace XCEngine {
namespace RHI {
class OpenGLCommandQueue : public RHICommandQueue {
public:
OpenGLCommandQueue();
~OpenGLCommandQueue() override;
void Shutdown() override;
void ExecuteCommandLists(uint32_t count, void** lists) override;
void Signal(RHIFence* fence, uint64_t value) override;
void Wait(RHIFence* fence, uint64_t value) override;
uint64_t GetCompletedValue() override;
void WaitForIdle() override;
CommandQueueType GetType() const override { return CommandQueueType::Direct; }
uint64_t GetTimestampFrequency() const override { return 0; }
void* GetNativeHandle() override { return nullptr; }
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,29 @@
#pragma once
#include "RHITypes.h"
namespace XCEngine {
namespace RHI {
class RHIFence;
class RHICommandQueue {
public:
virtual ~RHICommandQueue() = default;
virtual void Shutdown() = 0;
virtual void ExecuteCommandLists(uint32_t count, void** lists) = 0;
virtual void Signal(RHIFence* fence, uint64_t value) = 0;
virtual void Wait(RHIFence* 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;
virtual void* GetNativeHandle() = 0;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -36,13 +36,17 @@ void D3D12CommandQueue::Shutdown() {
m_commandQueue.Reset(); m_commandQueue.Reset();
} }
void D3D12CommandQueue::ExecuteCommandLists(uint32_t count, ID3D12CommandList** lists) { void D3D12CommandQueue::ExecuteCommandLists(uint32_t count, void** lists) {
ExecuteCommandListsInternal(count, reinterpret_cast<ID3D12CommandList**>(lists));
}
void D3D12CommandQueue::ExecuteCommandListsInternal(uint32_t count, ID3D12CommandList** lists) {
m_commandQueue->ExecuteCommandLists(count, lists); m_commandQueue->ExecuteCommandLists(count, lists);
} }
void D3D12CommandQueue::Signal(D3D12Fence* fence, uint64_t value) { void D3D12CommandQueue::Signal(RHIFence* fence, uint64_t value) {
if (fence) { if (fence) {
m_commandQueue->Signal(fence->GetFence(), value); m_commandQueue->Signal(static_cast<D3D12Fence*>(fence)->GetFence(), value);
} }
} }
@@ -52,9 +56,9 @@ void D3D12CommandQueue::Signal(ID3D12Fence* fence, uint64_t value) {
} }
} }
void D3D12CommandQueue::Wait(D3D12Fence* fence, uint64_t value) { void D3D12CommandQueue::Wait(RHIFence* fence, uint64_t value) {
if (fence) { if (fence) {
m_commandQueue->Wait(fence->GetFence(), value); m_commandQueue->Wait(static_cast<D3D12Fence*>(fence)->GetFence(), value);
} }
} }

View File

@@ -0,0 +1,33 @@
#include "XCEngine/RHI/OpenGL/OpenGLCommandQueue.h"
namespace XCEngine {
namespace RHI {
OpenGLCommandQueue::OpenGLCommandQueue() {
}
OpenGLCommandQueue::~OpenGLCommandQueue() {
Shutdown();
}
void OpenGLCommandQueue::Shutdown() {
}
void OpenGLCommandQueue::ExecuteCommandLists(uint32_t count, void** lists) {
}
void OpenGLCommandQueue::Signal(RHIFence* fence, uint64_t value) {
}
void OpenGLCommandQueue::Wait(RHIFence* fence, uint64_t value) {
}
uint64_t OpenGLCommandQueue::GetCompletedValue() {
return 0;
}
void OpenGLCommandQueue::WaitForIdle() {
}
} // namespace RHI
} // namespace XCEngine