From 354b6a5cfc36d3c40bc0f2de6486ce4a27117383 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 17 Mar 2026 18:05:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(RHI):=20=E5=AE=9E=E7=8E=B0=20RHISwapChain?= =?UTF-8?q?=20=E6=8A=BD=E8=B1=A1=E5=9F=BA=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/RHI抽象层设计与实现.md | 58 +++++++++++++++++++ .../XCEngine/RHI/D3D12/D3D12SwapChain.h | 24 +++++--- .../XCEngine/RHI/OpenGL/OpenGLSwapChain.h | 24 +++++--- engine/include/XCEngine/RHI/RHISwapChain.h | 31 ++++++++++ engine/src/RHI/D3D12/D3D12SwapChain.cpp | 14 +++++ engine/src/RHI/OpenGL/OpenGLSwapChain.cpp | 29 ++++++++++ 6 files changed, 163 insertions(+), 17 deletions(-) create mode 100644 engine/include/XCEngine/RHI/RHISwapChain.h diff --git a/docs/RHI抽象层设计与实现.md b/docs/RHI抽象层设计与实现.md index 7d77a3b9..d8571bd5 100644 --- a/docs/RHI抽象层设计与实现.md +++ b/docs/RHI抽象层设计与实现.md @@ -838,6 +838,64 @@ public: - 解决:统一 SetRenderTargets 接口 +### 5.13 交换链(RHISwapChain)抽象设计 + +#### 5.13.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化参数差异 | 求同存异 | 统一 Desc,后端各自处理 | +| 窗口管理差异 | 特性降级 | OpenGL 有,D3D12 无 | +| 呈现方式差异 | 求同存异 | 统一 Present 接口 | + +#### 5.13.2 现有实现对比 + +| 功能 | D3D12SwapChain | OpenGLSwapChain | 处理方案 | +|------|----------------|------------------|----------| +| 初始化 | factory/queue/hwnd | window | 统一 Initialize(Desc) | +| 后缓冲 | GetBackBuffer() | 无 | 通过 GetCurrentBackBuffer | +| 显示 | Present(sync, flags) | Present() | 统一 Present() | +| 调整大小 | Resize(w, h) | Resize(w, h) | 统一 | +| 窗口事件 | 无 | ShouldClose/PollEvents | OpenGL 实现 | + +#### 5.13.3 抽象接口定义 + +```cpp +class RHISwapChain { +public: + virtual ~RHISwapChain() = default; + + virtual void Shutdown() = 0; + + virtual uint32_t GetCurrentBackBufferIndex() const = 0; + virtual RHITexture* GetCurrentBackBuffer() = 0; + virtual void Present(uint32_t syncInterval = 1, uint32_t flags = 0) = 0; + virtual void Resize(uint32_t width, uint32_t height) = 0; + + virtual bool ShouldClose() const = 0; + virtual void SetShouldClose(bool shouldClose) = 0; + virtual void PollEvents() = 0; +}; +``` + +#### 5.13.4 差异处理策略 + +1. **初始化参数差异(求同存异)** + - D3D12:factory + commandQueue + hwnd + - OpenGL:window + - 解决:Device 的 CreateSwapChain() 统一接收 SwapChainDesc + +2. **窗口管理差异(特性降级)** + - OpenGL:ShouldClose/PollEvents + - D3D12:无 + - 解决:OpenGL 实现具体功能,D3D12 空实现 + +3. **呈现方式差异(求同存异)** + - D3D12:Present(syncInterval, flags) + - OpenGL:Present() / SwapBuffers() + - 解决:统一 Present(syncInterval, flags) + + ## 6. 后端实现示例 ### 6.1 D3D12 设备实现(D3D12Device.h) ```cpp diff --git a/engine/include/XCEngine/RHI/D3D12/D3D12SwapChain.h b/engine/include/XCEngine/RHI/D3D12/D3D12SwapChain.h index 661c5fda..aaee598e 100644 --- a/engine/include/XCEngine/RHI/D3D12/D3D12SwapChain.h +++ b/engine/include/XCEngine/RHI/D3D12/D3D12SwapChain.h @@ -5,6 +5,7 @@ #include #include +#include "../RHISwapChain.h" #include "D3D12Enum.h" #include "D3D12Texture.h" @@ -13,22 +14,27 @@ using Microsoft::WRL::ComPtr; namespace XCEngine { namespace RHI { -class D3D12SwapChain { +class D3D12SwapChain : public RHISwapChain { public: D3D12SwapChain(); - ~D3D12SwapChain(); + ~D3D12SwapChain() override; bool Initialize(IDXGIFactory4* factory, ID3D12CommandQueue* commandQueue, HWND windowHandle, uint32_t width, uint32_t height, uint32_t bufferCount = 2); bool Initialize(IDXGISwapChain* swapChain, uint32_t width, uint32_t height); - void Shutdown(); + void Shutdown() override; - uint32_t GetCurrentBackBufferIndex() const; + uint32_t GetCurrentBackBufferIndex() const override; + RHITexture* GetCurrentBackBuffer() override; D3D12Texture* GetBackBuffer(uint32_t index) const; - void Present(uint32_t syncInterval, uint32_t flags); - void Resize(uint32_t width, uint32_t height); - void SetFullscreen(bool fullscreen); - bool IsFullscreen() const; - void* GetNativeHandle() const; + void Present(uint32_t syncInterval = 1, uint32_t flags = 0) override; + void Resize(uint32_t width, uint32_t height) override; + void SetFullscreen(bool fullscreen) override; + bool IsFullscreen() const override; + void* GetNativeHandle() override; + + bool ShouldClose() const override; + void SetShouldClose(bool shouldClose) override; + void PollEvents() override; IDXGISwapChain3* GetSwapChain() const { return m_swapChain.Get(); } diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h index fe8240e2..c3c70a2e 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h @@ -3,6 +3,8 @@ #include #include +#include "../RHISwapChain.h" + namespace XCEngine { namespace RHI { @@ -20,20 +22,22 @@ enum class SurfaceFormat { BGRA8 }; -class OpenGLSwapChain { +class OpenGLSwapChain : public RHISwapChain { public: OpenGLSwapChain(); - ~OpenGLSwapChain(); + ~OpenGLSwapChain() override; bool Initialize(GLFWwindow* window, bool vsync = true); bool Initialize(GLFWwindow* window, int width, int height, PresentMode mode = PresentMode::VSync); - void Shutdown(); + void Shutdown() override; - void Present(); + void Present(uint32_t syncInterval = 1, uint32_t flags = 0) override; void SwapBuffers(); - void Resize(int width, int height); + void Resize(uint32_t width, uint32_t height) override; void SetVSync(bool enabled); bool IsVSync() const { return m_vsync; } + void SetFullscreen(bool fullscreen) override; + bool IsFullscreen() const override; void SetFramebufferSize(int width, int height); int GetWidth() const { return m_width; } @@ -43,9 +47,13 @@ public: GLFWwindow* GetWindow() const { return m_window; } - bool ShouldClose() const; - void SetShouldClose(bool shouldClose); - void PollEvents(); + bool ShouldClose() const override; + void SetShouldClose(bool shouldClose) override; + void PollEvents() override; + + uint32_t GetCurrentBackBufferIndex() const override; + RHITexture* GetCurrentBackBuffer() override; + void* GetNativeHandle() override; private: GLFWwindow* m_window; diff --git a/engine/include/XCEngine/RHI/RHISwapChain.h b/engine/include/XCEngine/RHI/RHISwapChain.h new file mode 100644 index 00000000..a53fa800 --- /dev/null +++ b/engine/include/XCEngine/RHI/RHISwapChain.h @@ -0,0 +1,31 @@ +#pragma once + +#include "RHITypes.h" + +namespace XCEngine { +namespace RHI { + +class RHITexture; + +class RHISwapChain { +public: + virtual ~RHISwapChain() = default; + + virtual void Shutdown() = 0; + + virtual uint32_t GetCurrentBackBufferIndex() const = 0; + virtual RHITexture* GetCurrentBackBuffer() = 0; + virtual void Present(uint32_t syncInterval = 1, uint32_t flags = 0) = 0; + virtual void Resize(uint32_t width, uint32_t height) = 0; + virtual void SetFullscreen(bool fullscreen) = 0; + virtual bool IsFullscreen() const = 0; + + virtual bool ShouldClose() const = 0; + virtual void SetShouldClose(bool shouldClose) = 0; + virtual void PollEvents() = 0; + + virtual void* GetNativeHandle() = 0; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/src/RHI/D3D12/D3D12SwapChain.cpp b/engine/src/RHI/D3D12/D3D12SwapChain.cpp index cc63399f..f5c0302f 100644 --- a/engine/src/RHI/D3D12/D3D12SwapChain.cpp +++ b/engine/src/RHI/D3D12/D3D12SwapChain.cpp @@ -105,5 +105,19 @@ void* D3D12SwapChain::GetNativeHandle() const { return reinterpret_cast(m_swapChain.Get()); } +RHITexture* D3D12SwapChain::GetCurrentBackBuffer() { + return GetBackBuffer(GetCurrentBackBufferIndex()); +} + +bool D3D12SwapChain::ShouldClose() const { + return false; +} + +void D3D12SwapChain::SetShouldClose(bool shouldClose) { +} + +void D3D12SwapChain::PollEvents() { +} + } // namespace RHI } // namespace XCEngine diff --git a/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp b/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp index 1f94c9e7..d7e2e831 100644 --- a/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp +++ b/engine/src/RHI/OpenGL/OpenGLSwapChain.cpp @@ -116,5 +116,34 @@ void OpenGLSwapChain::PollEvents() { glfwPollEvents(); } +void OpenGLSwapChain::Present(uint32_t syncInterval, uint32_t flags) { + if (m_window) { + glfwSwapBuffers(m_window); + } +} + +void OpenGLSwapChain::Resize(uint32_t width, uint32_t height) { + Resize(static_cast(width), static_cast(height)); +} + +void OpenGLSwapChain::SetFullscreen(bool fullscreen) { +} + +bool OpenGLSwapChain::IsFullscreen() const { + return false; +} + +uint32_t OpenGLSwapChain::GetCurrentBackBufferIndex() const { + return 0; +} + +RHITexture* OpenGLSwapChain::GetCurrentBackBuffer() { + return nullptr; +} + +void* OpenGLSwapChain::GetNativeHandle() { + return nullptr; +} + } // namespace RHI } // namespace XCEngine