From 70571316dad9e5726575f750766239b10869eca9 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 18 Mar 2026 01:33:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(RHI):=20=E6=B7=BB=E5=8A=A0=20RHIFactory=20?= =?UTF-8?q?=E5=B7=A5=E5=8E=82=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 RHIFactory 头文件和实现,支持通过 RHIType 或字符串创建设备 - 修复 D3D12Buffer 缺失的 Map/Unmap/SetData 实现 - 添加 RHI 工厂测试用例 - 更新 CMakeLists.txt 添加新文件 --- engine/CMakeLists.txt | 28 ++------------- engine/include/XCEngine/RHI/RHIFactory.h | 20 +++++++++++ engine/src/RHI/D3D12/D3D12Buffer.cpp | 19 ++++++++++ engine/src/RHI/RHIFactory.cpp | 42 ++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/RHI/CMakeLists.txt | 43 +++++++++++++++++++++++ tests/RHI/test_factory.cpp | 44 ++++++++++++++++++++++++ 7 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 engine/include/XCEngine/RHI/RHIFactory.h create mode 100644 engine/src/RHI/RHIFactory.cpp create mode 100644 tests/RHI/CMakeLists.txt create mode 100644 tests/RHI/test_factory.cpp diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index d5a65855..f2b046f2 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -83,6 +83,7 @@ add_library(XCEngine STATIC # RHI ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/RHIEnums.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/RHIFactory.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Enum.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Device.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12CommandQueue.h @@ -125,31 +126,8 @@ add_library(XCEngine STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12QueryHeap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12UnorderedAccessView.cpp - # OpenGL RHI - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDevice.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLShader.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLBuffer.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLVertexArray.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLTexture.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLCommandList.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLSwapChain.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLFence.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLSampler.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLRenderTargetView.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDepthStencilView.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDevice.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLShader.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLBuffer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLVertexArray.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLTexture.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLPipelineState.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLCommandList.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLSwapChain.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLFence.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLSampler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLRenderTargetView.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDepthStencilView.cpp + # RHI Factory + ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/RHIFactory.cpp # Resources ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Resources/Resources.h diff --git a/engine/include/XCEngine/RHI/RHIFactory.h b/engine/include/XCEngine/RHI/RHIFactory.h new file mode 100644 index 00000000..cc4de4ab --- /dev/null +++ b/engine/include/XCEngine/RHI/RHIFactory.h @@ -0,0 +1,20 @@ +#pragma once + +#include "RHIEnums.h" +#include "RHIDevice.h" +#include + +namespace XCEngine { +namespace RHI { + +class RHIFactory { +public: + static RHIDevice* CreateRHIDevice(RHIType type); + static RHIDevice* CreateRHIDevice(const std::string& typeName); + +private: + RHIFactory() = default; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/src/RHI/D3D12/D3D12Buffer.cpp b/engine/src/RHI/D3D12/D3D12Buffer.cpp index 170a8c9d..63521eb4 100644 --- a/engine/src/RHI/D3D12/D3D12Buffer.cpp +++ b/engine/src/RHI/D3D12/D3D12Buffer.cpp @@ -155,5 +155,24 @@ void D3D12Buffer::UpdateData(const void* data, uint64_t size) { m_resource->Unmap(0, nullptr); } +void* D3D12Buffer::Map() { + D3D12_RANGE readRange = { 0, 0 }; + void* data = nullptr; + m_resource->Map(0, &readRange, &data); + return data; +} + +void D3D12Buffer::Unmap() { + m_resource->Unmap(0, nullptr); +} + +void D3D12Buffer::SetData(const void* data, size_t size, size_t offset) { + D3D12_RANGE writeRange = { offset, offset + size }; + unsigned char* pBuffer = nullptr; + m_resource->Map(0, &writeRange, reinterpret_cast(&pBuffer)); + memcpy(pBuffer + offset, data, size); + m_resource->Unmap(0, nullptr); +} + } // namespace RHI } // namespace XCEngine diff --git a/engine/src/RHI/RHIFactory.cpp b/engine/src/RHI/RHIFactory.cpp new file mode 100644 index 00000000..80106bfc --- /dev/null +++ b/engine/src/RHI/RHIFactory.cpp @@ -0,0 +1,42 @@ +#include "XCEngine/RHI/RHIFactory.h" +#include "XCEngine/RHI/D3D12/D3D12Device.h" + +namespace XCEngine { +namespace RHI { + +RHIDevice* RHIFactory::CreateRHIDevice(RHIType type) { + switch (type) { + case RHIType::D3D12: + return new D3D12Device(); + case RHIType::OpenGL: +#ifdef XCENGINE_SUPPORT_OPENGL + { + #include "XCEngine/RHI/OpenGL/OpenGLDevice.h" + return new OpenGLDevice(); + } +#else + return nullptr; +#endif + case RHIType::Vulkan: + case RHIType::Metal: + default: + return nullptr; + } +} + +RHIDevice* RHIFactory::CreateRHIDevice(const std::string& typeName) { + if (typeName == "D3D12" || typeName == "d3d12") { + return new D3D12Device(); + } else if (typeName == "OpenGL" || typeName == "opengl" || typeName == "GL") { +#ifdef XCENGINE_SUPPORT_OPENGL + #include "XCEngine/RHI/OpenGL/OpenGLDevice.h" + return new OpenGLDevice(); +#else + return nullptr; +#endif + } + return nullptr; +} + +} // namespace RHI +} // namespace XCEngine diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 282c81b8..2875fef9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -38,6 +38,7 @@ add_subdirectory(memory) add_subdirectory(threading) add_subdirectory(debug) add_subdirectory(D3D12) +add_subdirectory(RHI) add_subdirectory(RHI/D3D12) add_subdirectory(RHI/OpenGL) add_subdirectory(Resources) diff --git a/tests/RHI/CMakeLists.txt b/tests/RHI/CMakeLists.txt new file mode 100644 index 00000000..658c0623 --- /dev/null +++ b/tests/RHI/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.15) + +project(RHIEngineTests) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +get_filename_component(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../.. ABSOLUTE) + +find_package(OpenGL REQUIRED) + +include_directories(${CMAKE_SOURCE_DIR}/tests/OpenGL/package/include/) +include_directories(${PROJECT_ROOT_DIR}/engine/include) +include_directories(${PROJECT_ROOT_DIR}/engine/src) + +link_directories(${CMAKE_SOURCE_DIR}/tests/OpenGL/package/lib/) + +find_package(GTest REQUIRED) + +set(TEST_SOURCES + test_factory.cpp +) + +add_executable(rhi_engine_tests ${TEST_SOURCES}) + +target_link_libraries(rhi_engine_tests PRIVATE + opengl32 + glfw3 + d3d12 + dxgi + d3dcompiler + XCEngine + GTest::gtest + GTest::gtest_main +) + +target_include_directories(rhi_engine_tests PRIVATE + ${PROJECT_ROOT_DIR}/engine/include + ${PROJECT_ROOT_DIR}/engine/src +) + +enable_testing() +add_test(NAME RHIEngineTests COMMAND rhi_engine_tests) diff --git a/tests/RHI/test_factory.cpp b/tests/RHI/test_factory.cpp new file mode 100644 index 00000000..f6016cd8 --- /dev/null +++ b/tests/RHI/test_factory.cpp @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include "XCEngine/RHI/RHIFactory.h" +#include "XCEngine/RHI/D3D12/D3D12Device.h" + +using namespace XCEngine::RHI; + +TEST(RHIFactory, CreateD3D12Device_ReturnsValidPointer) { + RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::D3D12); + + ASSERT_NE(device, nullptr); + + delete device; +} + +TEST(RHIFactory, CreateD3D12DeviceByName_ReturnsValidPointer) { + RHIDevice* device = RHIFactory::CreateRHIDevice("D3D12"); + + ASSERT_NE(device, nullptr); + + delete device; +} + +TEST(RHIFactory, CreateInvalidDevice_ReturnsNullptr) { + RHIDevice* device = RHIFactory::CreateRHIDevice("InvalidAPI"); + + ASSERT_EQ(device, nullptr); +} + +TEST(RHIFactory, CreateInvalidType_ReturnsNullptr) { + RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::Vulkan); + + ASSERT_EQ(device, nullptr); +} + +TEST(D3D12DeviceCreation, DirectCreation_Success) { + D3D12Device* device = new D3D12Device(); + + ASSERT_NE(device, nullptr); + + delete device; +}