#include "RHIIntegrationFixture.h" #include #include #include #include #include "XCEngine/RHI/D3D12/D3D12Device.h" #include "XCEngine/RHI/D3D12/D3D12SwapChain.h" #include "XCEngine/RHI/D3D12/D3D12Texture.h" #include "XCEngine/RHI/D3D12/D3D12CommandList.h" #include "XCEngine/RHI/RHIFence.h" #include "XCEngine/RHI/RHIScreenshot.h" #include "XCEngine/RHI/RHIEnums.h" namespace XCEngine { namespace RHI { namespace Integration { void RHIIntegrationFixture::SetUp() { WNDCLASSEXW wc = {}; wc.cbSize = sizeof(WNDCLASSEXW); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = DefWindowProcW; wc.hInstance = GetModuleHandle(nullptr); wc.lpszClassName = L"XCEngine_RHI_Integration_Test"; RegisterClassExW(&wc); const int width = 1280; const int height = 720; RECT rect = { 0, 0, width, height }; AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); mWindow = CreateWindowExW( 0, L"XCEngine_RHI_Integration_Test", L"RHI Integration Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, GetModuleHandle(nullptr), NULL ); ASSERT_NE(mWindow, nullptr); mDevice = RHIFactory::CreateRHIDevice(GetParam()); ASSERT_NE(mDevice, nullptr); bool initResult = false; if (GetParam() == RHIType::D3D12) { RHIDeviceDesc desc = {}; desc.enableDebugLayer = false; desc.enableGPUValidation = false; initResult = mDevice->Initialize(desc); } else if (GetParam() == RHIType::OpenGL) { auto* oglDevice = static_cast(mDevice); initResult = oglDevice->InitializeWithExistingWindow(mWindow); } ASSERT_TRUE(initResult); SwapChainDesc swapDesc = {}; swapDesc.windowHandle = mWindow; swapDesc.width = width; swapDesc.height = height; swapDesc.bufferCount = 2; mSwapChain = mDevice->CreateSwapChain(swapDesc); ASSERT_NE(mSwapChain, nullptr); CommandQueueDesc queueDesc = {}; queueDesc.queueType = static_cast(CommandQueueType::Direct); mCommandQueue = mDevice->CreateCommandQueue(queueDesc); ASSERT_NE(mCommandQueue, nullptr); CommandListDesc cmdDesc = {}; cmdDesc.commandListType = static_cast(CommandQueueType::Direct); mCommandList = mDevice->CreateCommandList(cmdDesc); ASSERT_NE(mCommandList, nullptr); mScreenshot = RHIScreenshot::Create(GetParam()); ASSERT_NE(mScreenshot, nullptr); ShowWindow(mWindow, SW_SHOW); UpdateWindow(mWindow); } void RHIIntegrationFixture::BeginRender() { mCurrentBackBufferIndex = mSwapChain->GetCurrentBackBufferIndex(); } void RHIIntegrationFixture::EndRender() { } void RHIIntegrationFixture::TearDown() { if (mScreenshot) { mScreenshot->Shutdown(); delete mScreenshot; mScreenshot = nullptr; } if (mCommandList) { mCommandList->Shutdown(); delete mCommandList; mCommandList = nullptr; } if (mCommandQueue) { mCommandQueue->Shutdown(); delete mCommandQueue; mCommandQueue = nullptr; } if (mSwapChain) { mSwapChain->Shutdown(); delete mSwapChain; mSwapChain = nullptr; } if (mDevice) { mDevice->Shutdown(); delete mDevice; mDevice = nullptr; } if (mWindow) { DestroyWindow(mWindow); mWindow = nullptr; } } void RHIIntegrationFixture::WaitForGPU() { if (mDevice == nullptr || mCommandQueue == nullptr) { return; } if (GetParam() == RHIType::D3D12) { FenceDesc fenceDesc = {}; fenceDesc.initialValue = 0; fenceDesc.flags = 0; auto* fence = mDevice->CreateFence(fenceDesc); if (fence) { mCommandQueue->Signal(fence, 1); fence->Wait(1); for (int i = 0; i < 100; i++) { if (fence->GetCompletedValue() >= 1) { break; } Sleep(10); } fence->Shutdown(); delete fence; } Sleep(100); } } bool RHIIntegrationFixture::TakeScreenshot(const char* filename) { if (!mScreenshot || !mDevice || !mSwapChain) { return false; } return mScreenshot->Capture(mDevice, mSwapChain, filename); } bool RHIIntegrationFixture::CompareWithGoldenTemplate(const char* outputPpm, const char* gtPpm, float threshold) { namespace fs = std::filesystem; fs::path exeDir = fs::current_path(); fs::path outputPath = exeDir / outputPpm; fs::path gtPath = exeDir / gtPpm; if (!fs::exists(outputPath)) { std::cerr << "Output file not found: " << outputPath << std::endl; return false; } if (!fs::exists(gtPath)) { std::cerr << "Golden template not found: " << gtPath << std::endl; return false; } std::string cmd = "python compare_ppm.py \"" + outputPath.string() + "\" \"" + gtPath.string() + "\" " + std::to_string(static_cast(threshold)); int result = system(cmd.c_str()); return result == 0; } } // namespace Integration } // namespace RHI } // namespace XCEngine