feat(RHI): 实现 RHIDevice 抽象基类
This commit is contained in:
@@ -589,7 +589,80 @@ public:
|
||||
- OpenGL:GLsync
|
||||
- 解决:GetNativeHandle() 返回 void*
|
||||
|
||||
### 5.10 根签名 vs OpenGL 资源绑定
|
||||
### 5.10 设备(RHIDevice)抽象设计
|
||||
|
||||
#### 5.10.1 设计理念对应
|
||||
|
||||
| 差异点 | 设计理念 | 处理方案 |
|
||||
|--------|---------|---------|
|
||||
| 初始化参数差异 | 求同存异 | 统一 Initialize 接口,后端各自处理 |
|
||||
| 工厂方法差异 | 特性降级 | D3D12 实现,OpenGL 返回 nullptr |
|
||||
| 窗口管理差异 | 特性降级 | OpenGL 有,D3D12 通过 SwapChain 处理 |
|
||||
| 适配器枚举差异 | 特性降级 | D3D12 实现,OpenGL 空实现 |
|
||||
| 底层设备类型差异 | 底层逃逸 | 统一返回 void* |
|
||||
|
||||
#### 5.10.2 现有实现对比
|
||||
|
||||
| 功能 | D3D12Device | OpenGLDevice | 处理方案 |
|
||||
|------|--------------|---------------|----------|
|
||||
| 初始化 | Initialize(debugLayer) | CreateRenderWindow/InitializeWithExistingWindow | 统一 Initialize |
|
||||
| 关闭 | Shutdown() | Shutdown() | 统一 |
|
||||
| 获取设备 | GetDevice() | 无 | GetNativeHandle 统一 |
|
||||
| 适配器信息 | GetAdapterInfo() | GetDeviceInfo() | 统一 GetDeviceInfo |
|
||||
| 工厂方法 | CreateBuffer/Texture/Shader... | 无 | OpenGL 返回 nullptr |
|
||||
| 窗口管理 | 通过 SwapChain | GetWindow/SwapBuffers/PollEvents | OpenGL 有,D3D12 无 |
|
||||
|
||||
#### 5.10.3 抽象接口定义
|
||||
|
||||
```cpp
|
||||
class RHIDevice {
|
||||
public:
|
||||
virtual ~RHIDevice() = default;
|
||||
|
||||
virtual bool Initialize(const RHIDeviceDesc& desc) = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
virtual const RHIDeviceInfo& GetDeviceInfo() const = 0;
|
||||
virtual const RHICapabilities& GetCapabilities() const = 0;
|
||||
|
||||
virtual RHIBuffer* CreateBuffer(const BufferDesc& desc) = 0;
|
||||
virtual RHITexture* CreateTexture(const TextureDesc& desc) = 0;
|
||||
virtual RHIShader* CompileShader(const ShaderCompileDesc& desc) = 0;
|
||||
virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0;
|
||||
virtual RHIFence* CreateFence(const FenceDesc& desc) = 0;
|
||||
|
||||
virtual void* GetNativeDevice() = 0;
|
||||
|
||||
virtual void* GetNativeHandle() const = 0;
|
||||
};
|
||||
```
|
||||
|
||||
#### 5.10.4 差异处理策略
|
||||
|
||||
1. **初始化参数差异(求同存异)**
|
||||
- D3D12:`Initialize(enableDebugLayer)`
|
||||
- OpenGL:`CreateRenderWindow` / `InitializeWithExistingWindow`
|
||||
- 解决:统一 `Initialize(const RHIDeviceDesc& desc)` 接口,Desc 中包含窗口参数
|
||||
|
||||
2. **工厂方法差异(特性降级)**
|
||||
- D3D12:有完整的工厂方法
|
||||
- OpenGL:资源直接用 glGen* 创建,没有工厂方法
|
||||
- 解决:OpenGL 后端返回 nullptr,上层需直接创建 OpenGL 资源
|
||||
|
||||
3. **窗口管理差异(特性降级)**
|
||||
- OpenGL:直接管理窗口,有 GetWindow/SwapBuffers/PollEvents
|
||||
- D3D12:通过 SwapChain 处理
|
||||
- 解决:OpenGL 提供窗口管理接口,D3D12 空实现
|
||||
|
||||
4. **适配器枚举差异(特性降级)**
|
||||
- D3D12:支持 EnumerateAdapters
|
||||
- OpenGL:无此概念
|
||||
- 解决:D3D12 实现具体功能,OpenGL 返回空
|
||||
|
||||
5. **底层设备类型差异(底层逃逸)**
|
||||
- D3D12:ID3D12Device*
|
||||
- OpenGL:无对等概念
|
||||
- 解决:GetNativeDevice() 返回 void*,OpenGL 返回 nullptr 或窗口句柄
|
||||
- **D3D12**:显式 `RootSignature` 定义资源绑定规则
|
||||
- **OpenGL**:隐式通过 `glUniformLocation`、`glBindTextureUnit` 绑定
|
||||
- **解决方案**:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../RHIDevice.h"
|
||||
#include "../RHIEnums.h"
|
||||
#include "../RHITypes.h"
|
||||
#include "D3D12Enum.h"
|
||||
@@ -44,13 +45,13 @@ struct AdapterInfo {
|
||||
bool isSoftware;
|
||||
};
|
||||
|
||||
class D3D12Device {
|
||||
class D3D12Device : public RHIDevice {
|
||||
public:
|
||||
D3D12Device();
|
||||
~D3D12Device();
|
||||
~D3D12Device() override;
|
||||
|
||||
bool Initialize(bool enableDebugLayer = false);
|
||||
void Shutdown();
|
||||
bool Initialize(const RHIDeviceDesc& desc) override;
|
||||
void Shutdown() override;
|
||||
|
||||
ID3D12Device* GetDevice() const { return m_device.Get(); }
|
||||
IDXGIFactory4* GetFactory() const { return m_factory.Get(); }
|
||||
@@ -65,20 +66,33 @@ public:
|
||||
void SetDeviceRemoved() { m_isDeviceRemoved = true; }
|
||||
bool IsDeviceRemoved() const { return m_isDeviceRemoved; }
|
||||
|
||||
// Factory methods
|
||||
D3D12CommandQueue* CreateCommandQueue(const CommandQueueDesc& desc);
|
||||
D3D12CommandList* CreateCommandList(const CommandListDesc& desc);
|
||||
RHIBuffer* CreateBuffer(const BufferDesc& desc) override;
|
||||
RHITexture* CreateTexture(const TextureDesc& desc) override;
|
||||
RHISwapChain* CreateSwapChain(const SwapChainDesc& desc) override;
|
||||
RHICommandList* CreateCommandList(const CommandListDesc& desc) override;
|
||||
RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override;
|
||||
RHIShader* CompileShader(const ShaderCompileDesc& desc) override;
|
||||
RHIPipelineState* CreatePipelineState(const PipelineStateDesc& desc) override;
|
||||
RHIFence* CreateFence(const FenceDesc& desc) override;
|
||||
RHISampler* CreateSampler(const SamplerDesc& desc) override;
|
||||
|
||||
const RHICapabilities& GetCapabilities() const override;
|
||||
const RHIDeviceInfo& GetDeviceInfo() const override;
|
||||
|
||||
void* GetNativeDevice() override;
|
||||
void* GetNativeHandle() const override;
|
||||
|
||||
bool PollEvents() override;
|
||||
void SwapBuffers() override;
|
||||
bool ShouldClose() const override;
|
||||
void SetShouldClose(bool shouldClose) override;
|
||||
|
||||
D3D12CommandQueue* CreateCommandQueueImpl(const CommandQueueDesc& desc);
|
||||
D3D12CommandList* CreateCommandListImpl(const CommandListDesc& desc);
|
||||
D3D12CommandAllocator* CreateCommandAllocator(const CommandAllocatorDesc& desc);
|
||||
D3D12Fence* CreateFence(const FenceDesc& desc);
|
||||
D3D12DescriptorHeap* CreateDescriptorHeap(const DescriptorHeapDesc& desc);
|
||||
D3D12QueryHeap* CreateQueryHeap(const QueryHeapDesc& desc);
|
||||
D3D12RootSignature* CreateRootSignature(const RootSignatureDesc& desc);
|
||||
D3D12PipelineState* CreatePipelineState(const PipelineStateDesc& desc);
|
||||
D3D12Sampler* CreateSampler(const SamplerDesc& desc);
|
||||
D3D12Texture* CreateTexture(const TextureDesc& desc);
|
||||
D3D12Buffer* CreateBuffer(const BufferDesc& desc);
|
||||
D3D12SwapChain* CreateSwapChain(const SwapChainDesc& desc);
|
||||
D3D12Shader* CompileShader(const ShaderCompileDesc& desc);
|
||||
|
||||
D3D12RenderTargetView* CreateRenderTargetView(D3D12Buffer* resource, const RenderTargetViewDesc& desc);
|
||||
D3D12DepthStencilView* CreateDepthStencilView(D3D12Buffer* resource, const DepthStencilViewDesc& desc);
|
||||
@@ -86,8 +100,6 @@ public:
|
||||
D3D12UnorderedAccessView* CreateUnorderedAccessView(D3D12Buffer* resource, const UnorderedAccessViewDesc& desc);
|
||||
D3D12ConstantBufferView* CreateConstantBufferView(D3D12Buffer* resource, const ConstantBufferViewDesc& desc);
|
||||
|
||||
void* GetNativeHandle() const;
|
||||
|
||||
private:
|
||||
bool CreateDXGIFactory(bool enableDebugLayer);
|
||||
bool CreateDevice(IDXGIAdapter1* adapter);
|
||||
@@ -98,6 +110,8 @@ private:
|
||||
ComPtr<IDXGIAdapter1> m_adapter;
|
||||
|
||||
AdapterInfo m_adapterInfo;
|
||||
RHICapabilities m_capabilities;
|
||||
RHIDeviceInfo m_deviceInfo;
|
||||
bool m_isDeviceRemoved;
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
@@ -3,37 +3,52 @@
|
||||
#include <string>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "../RHIDevice.h"
|
||||
#include "../RHICapabilities.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
struct OpenGLDeviceInfo {
|
||||
std::string vendor;
|
||||
std::string renderer;
|
||||
std::string version;
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
};
|
||||
|
||||
class OpenGLDevice {
|
||||
class OpenGLDevice : public RHIDevice {
|
||||
public:
|
||||
OpenGLDevice();
|
||||
~OpenGLDevice();
|
||||
~OpenGLDevice() override;
|
||||
|
||||
bool Initialize(const RHIDeviceDesc& desc) override;
|
||||
void Shutdown() override;
|
||||
|
||||
bool CreateRenderWindow(int width, int height, const char* title, bool enableDebug = false);
|
||||
bool InitializeWithExistingWindow(GLFWwindow* window);
|
||||
void Shutdown();
|
||||
|
||||
GLFWwindow* GetWindow() const { return m_window; }
|
||||
const OpenGLDeviceInfo& GetDeviceInfo() const { return m_deviceInfo; }
|
||||
const OpenGLDeviceInfo& GetDeviceInfoImpl() const { return m_deviceInfo; }
|
||||
|
||||
void SwapBuffers();
|
||||
bool PollEvents();
|
||||
void SetShouldClose(bool shouldClose);
|
||||
bool ShouldClose() const;
|
||||
void SwapBuffers() override;
|
||||
bool PollEvents() override;
|
||||
void SetShouldClose(bool shouldClose) override;
|
||||
bool ShouldClose() const override;
|
||||
|
||||
RHIBuffer* CreateBuffer(const BufferDesc& desc) override;
|
||||
RHITexture* CreateTexture(const TextureDesc& desc) override;
|
||||
RHISwapChain* CreateSwapChain(const SwapChainDesc& desc) override;
|
||||
RHICommandList* CreateCommandList(const CommandListDesc& desc) override;
|
||||
RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override;
|
||||
RHIShader* CompileShader(const ShaderCompileDesc& desc) override;
|
||||
RHIPipelineState* CreatePipelineState(const PipelineStateDesc& desc) override;
|
||||
RHIFence* CreateFence(const FenceDesc& desc) override;
|
||||
RHISampler* CreateSampler(const SamplerDesc& desc) override;
|
||||
|
||||
const RHICapabilities& GetCapabilities() const override;
|
||||
const RHIDeviceInfo& GetDeviceInfo() const override;
|
||||
|
||||
void* GetNativeDevice() override;
|
||||
void* GetNativeHandle() const override;
|
||||
|
||||
private:
|
||||
GLFWwindow* m_window;
|
||||
OpenGLDeviceInfo m_deviceInfo;
|
||||
RHICapabilities m_capabilities;
|
||||
RHIDeviceInfo m_deviceInfoBase;
|
||||
bool m_initialized;
|
||||
bool m_ownsWindow;
|
||||
};
|
||||
|
||||
@@ -36,24 +36,24 @@ D3D12Device::~D3D12Device() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool D3D12Device::Initialize(bool enableDebugLayer) {
|
||||
bool D3D12Device::Initialize(const RHIDeviceDesc& desc) {
|
||||
if (m_initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!CreateDXGIFactory(enableDebugLayer)) {
|
||||
if (!CreateDXGIFactory(desc.enableDebugLayer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<IDXGIAdapter1> adapter;
|
||||
int adapterIndex = 0;
|
||||
int adapterIndex = desc.adapterIndex;
|
||||
bool adapterFound = false;
|
||||
|
||||
while (m_factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
adapter->GetDesc1(&desc);
|
||||
DXGI_ADAPTER_DESC1 descAdapter;
|
||||
adapter->GetDesc1(&descAdapter);
|
||||
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||
if (descAdapter.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||
adapterIndex++;
|
||||
continue;
|
||||
}
|
||||
@@ -185,5 +185,100 @@ void* D3D12Device::GetNativeHandle() const {
|
||||
return m_device.Get();
|
||||
}
|
||||
|
||||
void* D3D12Device::GetNativeDevice() {
|
||||
return m_device.Get();
|
||||
}
|
||||
|
||||
const RHICapabilities& D3D12Device::GetCapabilities() const {
|
||||
return m_capabilities;
|
||||
}
|
||||
|
||||
const RHIDeviceInfo& D3D12Device::GetDeviceInfo() const {
|
||||
return m_deviceInfo;
|
||||
}
|
||||
|
||||
RHIBuffer* D3D12Device::CreateBuffer(const BufferDesc& desc) {
|
||||
auto* buffer = new D3D12Buffer();
|
||||
if (buffer->Initialize(m_device.Get(), desc.size, desc.stride, desc.bufferType)) {
|
||||
return buffer;
|
||||
}
|
||||
delete buffer;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc) {
|
||||
auto* texture = new D3D12Texture();
|
||||
if (texture->Initialize(m_device.Get(), desc)) {
|
||||
return texture;
|
||||
}
|
||||
delete texture;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIShader* D3D12Device::CompileShader(const ShaderCompileDesc& desc) {
|
||||
auto* shader = new D3D12Shader();
|
||||
if (shader->CompileFromFile(desc.fileName.c_str(), desc.entryPoint.c_str(), desc.profile.c_str())) {
|
||||
return shader;
|
||||
}
|
||||
delete shader;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHISampler* D3D12Device::CreateSampler(const SamplerDesc& desc) {
|
||||
auto* sampler = new D3D12Sampler();
|
||||
if (sampler->Initialize(m_device.Get(), desc)) {
|
||||
return sampler;
|
||||
}
|
||||
delete sampler;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIFence* D3D12Device::CreateFence(const FenceDesc& desc) {
|
||||
auto* fence = new D3D12Fence();
|
||||
if (fence->Initialize(m_device.Get(), desc.initialValue)) {
|
||||
return fence;
|
||||
}
|
||||
delete fence;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHISwapChain* D3D12Device::CreateSwapChain(const SwapChainDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHICommandList* D3D12Device::CreateCommandList(const CommandListDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHICommandQueue* D3D12Device::CreateCommandQueue(const CommandQueueDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIPipelineState* D3D12Device::CreatePipelineState(const PipelineStateDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool D3D12Device::PollEvents() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void D3D12Device::SwapBuffers() {
|
||||
}
|
||||
|
||||
bool D3D12Device::ShouldClose() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void D3D12Device::SetShouldClose(bool shouldClose) {
|
||||
}
|
||||
|
||||
D3D12CommandQueue* D3D12Device::CreateCommandQueueImpl(const CommandQueueDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3D12CommandList* D3D12Device::CreateCommandListImpl(const CommandListDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
|
||||
@@ -16,6 +16,23 @@ OpenGLDevice::~OpenGLDevice() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool OpenGLDevice::Initialize(const RHIDeviceDesc& desc) {
|
||||
if (m_initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (desc.windowHandle) {
|
||||
return InitializeWithExistingWindow(static_cast<GLFWwindow*>(desc.windowHandle));
|
||||
}
|
||||
|
||||
std::string titleStr = "XCEngine";
|
||||
if (!desc.appName.empty()) {
|
||||
titleStr = std::string(desc.appName.begin(), desc.appName.end());
|
||||
}
|
||||
|
||||
return CreateRenderWindow(desc.width, desc.height, titleStr.c_str(), desc.enableDebugLayer);
|
||||
}
|
||||
|
||||
bool OpenGLDevice::CreateRenderWindow(int width, int height, const char* title, bool enableDebug) {
|
||||
if (m_initialized) {
|
||||
return true;
|
||||
@@ -99,5 +116,61 @@ bool OpenGLDevice::ShouldClose() const {
|
||||
return m_window && glfwWindowShouldClose(m_window) == GLFW_TRUE;
|
||||
}
|
||||
|
||||
RHIBuffer* OpenGLDevice::CreateBuffer(const BufferDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHITexture* OpenGLDevice::CreateTexture(const TextureDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHISwapChain* OpenGLDevice::CreateSwapChain(const SwapChainDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHICommandList* OpenGLDevice::CreateCommandList(const CommandListDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHICommandQueue* OpenGLDevice::CreateCommandQueue(const CommandQueueDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIShader* OpenGLDevice::CompileShader(const ShaderCompileDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIPipelineState* OpenGLDevice::CreatePipelineState(const PipelineStateDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHIFence* OpenGLDevice::CreateFence(const FenceDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHISampler* OpenGLDevice::CreateSampler(const SamplerDesc& desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RHICapabilities& OpenGLDevice::GetCapabilities() const {
|
||||
return m_capabilities;
|
||||
}
|
||||
|
||||
const RHIDeviceInfo& OpenGLDevice::GetDeviceInfo() const {
|
||||
m_deviceInfoBase.description = L"OpenGL Device";
|
||||
m_deviceInfoBase.vendor = std::wstring(m_deviceInfo.vendor.begin(), m_deviceInfo.vendor.end());
|
||||
m_deviceInfoBase.renderer = std::wstring(m_deviceInfo.renderer.begin(), m_deviceInfo.renderer.end());
|
||||
m_deviceInfoBase.version = std::wstring(m_deviceInfo.version.begin(), m_deviceInfo.version.end());
|
||||
return m_deviceInfoBase;
|
||||
}
|
||||
|
||||
void* OpenGLDevice::GetNativeDevice() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* OpenGLDevice::GetNativeHandle() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
|
||||
Reference in New Issue
Block a user