Files
XCEngine/tests/RHI/D3D12/unit/test_swap_chain.cpp

194 lines
4.8 KiB
C++
Raw Normal View History

#include "fixtures/D3D12TestFixture.h"
#include "XCEngine/RHI/D3D12/D3D12SwapChain.h"
#include <windows.h>
using namespace XCEngine::RHI;
class SwapChainTestFixture : public ::testing::Test {
protected:
void SetUp() override {
HRESULT hr = D3D12CreateDevice(
nullptr,
D3D_FEATURE_LEVEL_12_0,
IID_PPV_ARGS(&mDevice)
);
if (FAILED(hr)) {
GTEST_SKIP() << "Failed to create D3D12 device";
return;
}
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
hr = mDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue));
if (FAILED(hr)) {
GTEST_SKIP() << "Failed to create command queue";
return;
}
hr = CreateDXGIFactory1(IID_PPV_ARGS(&mFactory));
if (FAILED(hr)) {
GTEST_SKIP() << "Failed to create DXGI factory";
return;
}
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpszClassName = "SwapChainTest";
RegisterClassEx(&wc);
mHWND = CreateWindowEx(
0,
"SwapChainTest",
"SwapChain Test",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
wc.hInstance,
NULL
);
if (!mHWND) {
GTEST_SKIP() << "Failed to create window";
return;
}
}
void TearDown() override {
if (mCommandQueue) {
WaitForGPU();
}
if (mHWND) {
DestroyWindow(mHWND);
}
mSwapChain.Shutdown();
mCommandQueue.Reset();
mDevice.Reset();
mFactory.Reset();
}
void WaitForGPU() {
if (!mCommandQueue || !mDevice) return;
ComPtr<ID3D12Fence> fence;
UINT64 fenceValue = 1;
HRESULT hr = mDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
if (SUCCEEDED(hr)) {
mCommandQueue->Signal(fence.Get(), fenceValue);
if (fence->GetCompletedValue() < fenceValue) {
HANDLE eventHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (eventHandle) {
fence->SetEventOnCompletion(fenceValue, eventHandle);
WaitForSingleObject(eventHandle, INFINITE);
CloseHandle(eventHandle);
}
}
}
}
Microsoft::WRL::ComPtr<ID3D12Device> mDevice;
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
Microsoft::WRL::ComPtr<IDXGIFactory4> mFactory;
HWND mHWND = nullptr;
D3D12SwapChain mSwapChain;
};
TEST_F(SwapChainTestFixture, SwapChain_Initialize_FromFactory) {
bool result = mSwapChain.Initialize(
mFactory.Get(),
mCommandQueue.Get(),
mHWND,
800,
600,
2
);
ASSERT_TRUE(result);
}
TEST_F(SwapChainTestFixture, SwapChain_GetBackBuffer_ValidIndex) {
ASSERT_TRUE(mSwapChain.Initialize(
mFactory.Get(),
mCommandQueue.Get(),
mHWND,
800,
600,
2
));
D3D12Texture* backBuffer0 = mSwapChain.GetBackBuffer(0);
ASSERT_NE(backBuffer0, nullptr);
D3D12Texture* backBuffer1 = mSwapChain.GetBackBuffer(1);
ASSERT_NE(backBuffer1, nullptr);
ID3D12Resource* resource0 = backBuffer0->GetResource();
ID3D12Resource* resource1 = backBuffer1->GetResource();
ASSERT_NE(resource0, nullptr);
ASSERT_NE(resource1, nullptr);
ASSERT_NE(resource0, resource1);
}
TEST_F(SwapChainTestFixture, SwapChain_GetBackBuffer_InvalidIndex) {
ASSERT_TRUE(mSwapChain.Initialize(
mFactory.Get(),
mCommandQueue.Get(),
mHWND,
800,
600,
2
));
D3D12Texture* backBuffer = mSwapChain.GetBackBuffer(99);
ASSERT_TRUE(backBuffer == nullptr);
}
TEST_F(SwapChainTestFixture, SwapChain_GetCurrentBackBufferIndex) {
ASSERT_TRUE(mSwapChain.Initialize(
mFactory.Get(),
mCommandQueue.Get(),
mHWND,
800,
600,
2
));
uint32_t index = mSwapChain.GetCurrentBackBufferIndex();
EXPECT_LT(index, 2u);
}
TEST_F(SwapChainTestFixture, SwapChain_Present_DoesNotCrash) {
ASSERT_TRUE(mSwapChain.Initialize(
mFactory.Get(),
mCommandQueue.Get(),
mHWND,
800,
600,
2
));
ASSERT_NO_FATAL_FAILURE(mSwapChain.Present(0, 0));
}
TEST_F(SwapChainTestFixture, SwapChain_Shutdown_Cleanup) {
ASSERT_TRUE(mSwapChain.Initialize(
mFactory.Get(),
mCommandQueue.Get(),
mHWND,
800,
600,
2
));
ASSERT_NO_FATAL_FAILURE(mSwapChain.Shutdown());
}