- 修复Initialize(IDXGIFactory4*, ...)重载缺少m_backBuffers初始化的问题 - 新增test_swap_chain.cpp单元测试文件,包含6个SwapChain测试用例 - 更新unit CMakeLists.txt添加test_swap_chain.cpp和Res路径
194 lines
4.8 KiB
C++
194 lines
4.8 KiB
C++
#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());
|
|
}
|