Add Vulkan RHI minimal backend path
This commit is contained in:
@@ -14,6 +14,10 @@
|
||||
#include "XCEngine/RHI/RHIScreenshot.h"
|
||||
#include "XCEngine/RHI/RHIEnums.h"
|
||||
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
#include "XCEngine/RHI/Vulkan/VulkanSwapChain.h"
|
||||
#endif
|
||||
|
||||
using namespace XCEngine::Debug;
|
||||
using namespace XCEngine::Containers;
|
||||
|
||||
@@ -83,7 +87,7 @@ void RHIIntegrationFixture::SetUp() {
|
||||
ASSERT_NE(mDevice, nullptr);
|
||||
|
||||
bool initResult = false;
|
||||
if (GetParam() == RHIType::D3D12) {
|
||||
if (GetParam() == RHIType::D3D12 || GetParam() == RHIType::Vulkan) {
|
||||
RHIDeviceDesc desc = {};
|
||||
desc.enableDebugLayer = false;
|
||||
desc.enableGPUValidation = false;
|
||||
@@ -132,7 +136,7 @@ void RHIIntegrationFixture::SetUp() {
|
||||
|
||||
auto* rtv = new D3D12ResourceView();
|
||||
rtv->InitializeAsRenderTarget(device, backBuffer.GetResource(), &rtvDesc, mRTVHeap, i);
|
||||
mRTVs.push_back(rtv);
|
||||
mBackBufferViews.push_back(rtv);
|
||||
}
|
||||
|
||||
mDepthStencilTexture = new D3D12Texture();
|
||||
@@ -152,26 +156,55 @@ void RHIIntegrationFixture::SetUp() {
|
||||
}
|
||||
|
||||
void RHIIntegrationFixture::BeginRender() {
|
||||
if (GetParam() == RHIType::Vulkan) {
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
auto* vulkanSwapChain = static_cast<VulkanSwapChain*>(mSwapChain);
|
||||
ASSERT_NE(vulkanSwapChain, nullptr);
|
||||
ASSERT_TRUE(vulkanSwapChain->AcquireNextImage());
|
||||
#endif
|
||||
}
|
||||
|
||||
mCurrentBackBufferIndex = mSwapChain->GetCurrentBackBufferIndex();
|
||||
Log("[TEST] BeginRender: backBufferIndex=%d", mCurrentBackBufferIndex);
|
||||
}
|
||||
|
||||
void RHIIntegrationFixture::SetRenderTargetForClear(bool includeDepthStencil) {
|
||||
if (GetParam() == RHIType::D3D12) {
|
||||
Log("[TEST] SetRenderTargetForClear: D3D12 branch, mRTVs.size=%d, index=%d",
|
||||
(int)mRTVs.size(), mCurrentBackBufferIndex);
|
||||
if (!mRTVs.empty() && mCurrentBackBufferIndex < mRTVs.size()) {
|
||||
Log("[TEST] SetRenderTargetForClear: D3D12 branch, mBackBufferViews.size=%d, index=%d",
|
||||
(int)mBackBufferViews.size(), mCurrentBackBufferIndex);
|
||||
if (!mBackBufferViews.empty() && mCurrentBackBufferIndex < mBackBufferViews.size()) {
|
||||
D3D12Texture* backBuffer = static_cast<D3D12Texture*>(mSwapChain->GetCurrentBackBuffer());
|
||||
D3D12CommandList* d3d12CmdList = static_cast<D3D12CommandList*>(mCommandList);
|
||||
Log("[TEST] SetRenderTargetForClear: calling TransitionBarrier");
|
||||
d3d12CmdList->TransitionBarrier(backBuffer->GetResource(), ResourceStates::Present, ResourceStates::RenderTarget);
|
||||
RHIResourceView* rtv = mRTVs[mCurrentBackBufferIndex];
|
||||
RHIResourceView* rtv = mBackBufferViews[mCurrentBackBufferIndex];
|
||||
Log("[TEST] SetRenderTargetForClear: calling SetRenderTargets, rtv=%p", (void*)rtv);
|
||||
mCommandList->SetRenderTargets(1, &rtv, includeDepthStencil ? mDSV : nullptr);
|
||||
Log("[TEST] SetRenderTargetForClear: done");
|
||||
} else {
|
||||
Log("[TEST] SetRenderTargetForClear: skipped - condition failed");
|
||||
}
|
||||
} else if (GetParam() == RHIType::Vulkan) {
|
||||
if (mCurrentBackBufferIndex < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t backBufferIndex = static_cast<size_t>(mCurrentBackBufferIndex);
|
||||
if (mBackBufferViews.size() <= backBufferIndex) {
|
||||
mBackBufferViews.resize(backBufferIndex + 1, nullptr);
|
||||
}
|
||||
|
||||
if (mBackBufferViews[backBufferIndex] == nullptr) {
|
||||
ResourceViewDesc viewDesc = {};
|
||||
viewDesc.dimension = ResourceViewDimension::Texture2D;
|
||||
viewDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
viewDesc.arraySize = 1;
|
||||
mBackBufferViews[backBufferIndex] = mDevice->CreateRenderTargetView(GetCurrentBackBuffer(), viewDesc);
|
||||
}
|
||||
|
||||
ASSERT_NE(mBackBufferViews[backBufferIndex], nullptr);
|
||||
RHIResourceView* rtv = mBackBufferViews[backBufferIndex];
|
||||
mCommandList->SetRenderTargets(1, &rtv, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,13 +224,17 @@ void RHIIntegrationFixture::TearDown() {
|
||||
mScreenshot = nullptr;
|
||||
}
|
||||
|
||||
if (GetParam() == RHIType::D3D12) {
|
||||
for (auto* rtv : mRTVs) {
|
||||
delete rtv;
|
||||
for (auto* backBufferView : mBackBufferViews) {
|
||||
if (backBufferView) {
|
||||
backBufferView->Shutdown();
|
||||
delete backBufferView;
|
||||
}
|
||||
mRTVs.clear();
|
||||
}
|
||||
mBackBufferViews.clear();
|
||||
|
||||
if (GetParam() == RHIType::D3D12) {
|
||||
if (mDSV) {
|
||||
mDSV->Shutdown();
|
||||
delete mDSV;
|
||||
mDSV = nullptr;
|
||||
}
|
||||
@@ -276,6 +313,8 @@ void RHIIntegrationFixture::WaitForGPU() {
|
||||
delete fence;
|
||||
}
|
||||
Sleep(100);
|
||||
} else if (GetParam() == RHIType::Vulkan) {
|
||||
mCommandQueue->WaitForIdle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
|
||||
#include "XCEngine/RHI/RHIFactory.h"
|
||||
@@ -23,6 +24,10 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
#endif
|
||||
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
#include "XCEngine/RHI/Vulkan/VulkanSwapChain.h"
|
||||
#endif
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
namespace Integration {
|
||||
@@ -62,12 +67,12 @@ private:
|
||||
RHIScreenshot* mScreenshot = nullptr;
|
||||
HWND mWindow = nullptr;
|
||||
int mCurrentBackBufferIndex = 0;
|
||||
std::vector<RHIResourceView*> mBackBufferViews;
|
||||
|
||||
#if defined(XCENGINE_SUPPORT_D3D12)
|
||||
D3D12DescriptorHeap* mRTVHeap = nullptr;
|
||||
D3D12DescriptorHeap* mDSVHeap = nullptr;
|
||||
D3D12Texture* mDepthStencilTexture = nullptr;
|
||||
std::vector<RHIResourceView*> mRTVs;
|
||||
RHIResourceView* mDSV = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -33,11 +33,16 @@ target_link_libraries(rhi_integration_minimal PRIVATE
|
||||
GTest::gtest
|
||||
)
|
||||
|
||||
if(TARGET Vulkan::Vulkan)
|
||||
target_link_libraries(rhi_integration_minimal PRIVATE Vulkan::Vulkan)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(rhi_integration_minimal PRIVATE
|
||||
UNICODE
|
||||
_UNICODE
|
||||
XCENGINE_SUPPORT_OPENGL
|
||||
XCENGINE_SUPPORT_D3D12
|
||||
XCENGINE_SUPPORT_VULKAN
|
||||
)
|
||||
|
||||
add_custom_command(TARGET rhi_integration_minimal POST_BUILD
|
||||
|
||||
@@ -20,7 +20,16 @@ protected:
|
||||
};
|
||||
|
||||
const char* GetScreenshotFilename(RHIType type) {
|
||||
return type == RHIType::D3D12 ? "minimal_d3d12.ppm" : "minimal_opengl.ppm";
|
||||
switch (type) {
|
||||
case RHIType::D3D12:
|
||||
return "minimal_d3d12.ppm";
|
||||
case RHIType::OpenGL:
|
||||
return "minimal_opengl.ppm";
|
||||
case RHIType::Vulkan:
|
||||
return "minimal_vulkan.ppm";
|
||||
default:
|
||||
return "minimal_unknown.ppm";
|
||||
}
|
||||
}
|
||||
|
||||
int GetComparisonThreshold(RHIType type) {
|
||||
@@ -94,6 +103,9 @@ TEST_P(MinimalTest, RenderClear) {
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(D3D12, MinimalTest, ::testing::Values(RHIType::D3D12));
|
||||
INSTANTIATE_TEST_SUITE_P(OpenGL, MinimalTest, ::testing::Values(RHIType::OpenGL));
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
INSTANTIATE_TEST_SUITE_P(Vulkan, MinimalTest, ::testing::Values(RHIType::Vulkan));
|
||||
#endif
|
||||
|
||||
GTEST_API_ int main(int argc, char** argv) {
|
||||
Logger::Get().Initialize();
|
||||
|
||||
@@ -6,6 +6,7 @@ find_package(GTest REQUIRED)
|
||||
|
||||
set(TEST_SOURCES
|
||||
fixtures/RHITestFixture.cpp
|
||||
test_factory.cpp
|
||||
test_device.cpp
|
||||
test_buffer.cpp
|
||||
test_texture.cpp
|
||||
@@ -30,7 +31,10 @@ set(TEST_SOURCES
|
||||
|
||||
add_executable(rhi_unit_tests ${TEST_SOURCES})
|
||||
|
||||
target_compile_definitions(rhi_unit_tests PRIVATE XCENGINE_SUPPORT_OPENGL)
|
||||
target_compile_definitions(rhi_unit_tests PRIVATE
|
||||
XCENGINE_SUPPORT_OPENGL
|
||||
XCENGINE_SUPPORT_VULKAN
|
||||
)
|
||||
|
||||
target_link_libraries(rhi_unit_tests PRIVATE
|
||||
d3d12
|
||||
@@ -42,6 +46,10 @@ target_link_libraries(rhi_unit_tests PRIVATE
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
if(TARGET Vulkan::Vulkan)
|
||||
target_link_libraries(rhi_unit_tests PRIVATE Vulkan::Vulkan)
|
||||
endif()
|
||||
|
||||
target_include_directories(rhi_unit_tests PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fixtures
|
||||
${PROJECT_ROOT_DIR}/engine/include
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
#include "XCEngine/RHI/RHIFactory.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12Device.h"
|
||||
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
#include "XCEngine/RHI/Vulkan/VulkanDevice.h"
|
||||
#endif
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST(RHIFactory, CreateD3D12Device_ReturnsValidPointer) {
|
||||
@@ -30,11 +34,29 @@ TEST(RHIFactory, CreateInvalidDevice_ReturnsNullptr) {
|
||||
}
|
||||
|
||||
TEST(RHIFactory, CreateInvalidType_ReturnsNullptr) {
|
||||
RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::Vulkan);
|
||||
RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::Metal);
|
||||
|
||||
ASSERT_EQ(device, nullptr);
|
||||
}
|
||||
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
TEST(RHIFactory, CreateVulkanDevice_ReturnsValidPointer) {
|
||||
RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::Vulkan);
|
||||
|
||||
ASSERT_NE(device, nullptr);
|
||||
|
||||
delete device;
|
||||
}
|
||||
|
||||
TEST(RHIFactory, CreateVulkanDeviceByName_ReturnsValidPointer) {
|
||||
RHIDevice* device = RHIFactory::CreateRHIDevice("Vulkan");
|
||||
|
||||
ASSERT_NE(device, nullptr);
|
||||
|
||||
delete device;
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(D3D12DeviceCreation, DirectCreation_Success) {
|
||||
D3D12Device* device = new D3D12Device();
|
||||
|
||||
@@ -42,3 +64,13 @@ TEST(D3D12DeviceCreation, DirectCreation_Success) {
|
||||
|
||||
delete device;
|
||||
}
|
||||
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
TEST(VulkanDeviceCreation, DirectCreation_Success) {
|
||||
VulkanDevice* device = new VulkanDevice();
|
||||
|
||||
ASSERT_NE(device, nullptr);
|
||||
|
||||
delete device;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user