diff --git a/docs/RHI抽象层设计与实现.md b/docs/RHI抽象层设计与实现.md index 5bb09da1..09782cd3 100644 --- a/docs/RHI抽象层设计与实现.md +++ b/docs/RHI抽象层设计与实现.md @@ -694,6 +694,72 @@ public: 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. **执行命令差异(特性降级)** + - D3D12:ExecuteCommandLists() 提交命令列表 + - OpenGL:状态机模型,无命令队列概念 + - 解决:OpenGL 空实现 + +3. **同步机制差异(特性降级)** + - D3D12:Signal/Wait/Fence 完整实现 + - OpenGL:无对等概念 + - 解决:OpenGL 空实现 + +4. **句柄类型差异(底层逃逸)** + - D3D12:ID3D12CommandQueue* + - OpenGL:无对等概念 + - 解决:GetNativeHandle() 返回 void* + + ## 6. 后端实现示例 ### 6.1 D3D12 设备实现(D3D12Device.h) ```cpp diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h b/engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h index aa78abad..ede4d599 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h @@ -3,6 +3,7 @@ #include #include +#include "../RHICommandQueue.h" #include "../RHIEnums.h" #include "D3D12Enum.h" @@ -13,26 +14,29 @@ namespace RHI { class D3D12Fence; -class D3D12CommandQueue { +class D3D12CommandQueue : public RHICommandQueue { public: D3D12CommandQueue(); - ~D3D12CommandQueue(); + ~D3D12CommandQueue() override; bool Initialize(ID3D12Device* device, CommandQueueType type = CommandQueueType::Direct); - void Shutdown(); + void Shutdown() override; - void ExecuteCommandLists(uint32_t count, ID3D12CommandList** lists); - void Signal(D3D12Fence* fence, uint64_t value); - void Signal(ID3D12Fence* fence, uint64_t value); - void Wait(D3D12Fence* fence, uint64_t value); - void Wait(ID3D12Fence* fence, uint64_t value); - uint64_t GetCompletedValue(); - void WaitForIdle(); + 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 { return m_type; } - uint64_t GetTimestampFrequency() const { return m_timestampFrequency; } + CommandQueueType GetType() const override { return m_type; } + uint64_t GetTimestampFrequency() const override { return m_timestampFrequency; } 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: ComPtr m_commandQueue; diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandQueue.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandQueue.h new file mode 100644 index 00000000..75bbeb5d --- /dev/null +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLCommandQueue.h @@ -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 diff --git a/engine/include/XCEngine/RHI/RHICommandQueue.h b/engine/include/XCEngine/RHI/RHICommandQueue.h new file mode 100644 index 00000000..ee6883db --- /dev/null +++ b/engine/include/XCEngine/RHI/RHICommandQueue.h @@ -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 diff --git a/engine/src/RHI/D3D12/D3D12CommandQueue.cpp b/engine/src/RHI/D3D12/D3D12CommandQueue.cpp index b204819a..b8afc1b7 100644 --- a/engine/src/RHI/D3D12/D3D12CommandQueue.cpp +++ b/engine/src/RHI/D3D12/D3D12CommandQueue.cpp @@ -36,13 +36,17 @@ void D3D12CommandQueue::Shutdown() { m_commandQueue.Reset(); } -void D3D12CommandQueue::ExecuteCommandLists(uint32_t count, ID3D12CommandList** lists) { +void D3D12CommandQueue::ExecuteCommandLists(uint32_t count, void** lists) { + ExecuteCommandListsInternal(count, reinterpret_cast(lists)); +} + +void D3D12CommandQueue::ExecuteCommandListsInternal(uint32_t count, ID3D12CommandList** lists) { m_commandQueue->ExecuteCommandLists(count, lists); } -void D3D12CommandQueue::Signal(D3D12Fence* fence, uint64_t value) { +void D3D12CommandQueue::Signal(RHIFence* fence, uint64_t value) { if (fence) { - m_commandQueue->Signal(fence->GetFence(), value); + m_commandQueue->Signal(static_cast(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) { - m_commandQueue->Wait(fence->GetFence(), value); + m_commandQueue->Wait(static_cast(fence)->GetFence(), value); } } diff --git a/engine/src/RHI/OpenGL/OpenGLCommandQueue.cpp b/engine/src/RHI/OpenGL/OpenGLCommandQueue.cpp new file mode 100644 index 00000000..460d1584 --- /dev/null +++ b/engine/src/RHI/OpenGL/OpenGLCommandQueue.cpp @@ -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