feat: add RHI abstraction layer unit tests
- Add RHITestFixture with RHI_BACKEND env var support for backend selection - Add unit tests for: Device, Buffer, Texture, SwapChain, CommandList, CommandQueue, Shader, Fence, Sampler - Tests can run against D3D12 or OpenGL backends via RHI_BACKEND env var - Add integration folder placeholder for future integration tests
This commit is contained in:
@@ -41,3 +41,5 @@ target_include_directories(rhi_engine_tests PRIVATE
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME RHIEngineTests COMMAND rhi_engine_tests)
|
||||
|
||||
add_subdirectory(unit)
|
||||
|
||||
25
tests/RHI/integration/README.md
Normal file
25
tests/RHI/integration/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# RHI Integration Tests
|
||||
|
||||
This folder will contain integration tests for the RHI abstraction layer.
|
||||
|
||||
Integration tests verify the interaction between multiple RHI components working together.
|
||||
|
||||
## Planned Tests
|
||||
|
||||
- Full render pipeline test (device -> swap chain -> command list -> present)
|
||||
- Multi-threaded command recording
|
||||
- Resource state transitions across multiple objects
|
||||
- Frame synchronization with fences
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Build once, run against different backends
|
||||
cmake --build build --config Debug
|
||||
|
||||
# Test D3D12 backend
|
||||
RHI_BACKEND=D3D12 ./build/tests/RHI/unit/rhi_unit_tests.exe
|
||||
|
||||
# Test OpenGL backend
|
||||
RHI_BACKEND=OpenGL ./build/tests/RHI/unit/rhi_unit_tests.exe
|
||||
```
|
||||
41
tests/RHI/unit/CMakeLists.txt
Normal file
41
tests/RHI/unit/CMakeLists.txt
Normal file
@@ -0,0 +1,41 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
get_filename_component(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ABSOLUTE)
|
||||
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
set(TEST_SOURCES
|
||||
fixtures/RHITestFixture.cpp
|
||||
test_device.cpp
|
||||
test_buffer.cpp
|
||||
test_texture.cpp
|
||||
test_swap_chain.cpp
|
||||
test_command_list.cpp
|
||||
test_command_queue.cpp
|
||||
test_shader.cpp
|
||||
test_fence.cpp
|
||||
test_sampler.cpp
|
||||
)
|
||||
|
||||
add_executable(rhi_unit_tests ${TEST_SOURCES})
|
||||
|
||||
target_link_libraries(rhi_unit_tests PRIVATE
|
||||
d3d12
|
||||
dxgi
|
||||
d3dcompiler
|
||||
opengl32
|
||||
glfw3
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(rhi_unit_tests PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/fixtures
|
||||
${PROJECT_ROOT_DIR}/engine/include
|
||||
${PROJECT_ROOT_DIR}/engine/src
|
||||
${CMAKE_SOURCE_DIR}/tests/OpenGL/package/include/
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME RHIUnitTests COMMAND rhi_unit_tests)
|
||||
47
tests/RHI/unit/fixtures/RHITestFixture.cpp
Normal file
47
tests/RHI/unit/fixtures/RHITestFixture.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "RHITestFixture.h"
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
RHIType RHITestFixture::mBackendType = RHIType::D3D12;
|
||||
|
||||
void RHITestFixture::SetUpTestSuite() {
|
||||
}
|
||||
|
||||
void RHITestFixture::TearDownTestSuite() {
|
||||
}
|
||||
|
||||
void RHITestFixture::SetUp() {
|
||||
const char* backend = std::getenv("RHI_BACKEND");
|
||||
if (backend != nullptr) {
|
||||
std::string backendStr(backend);
|
||||
if (backendStr == "OpenGL" || backendStr == "opengl") {
|
||||
mBackendType = RHIType::OpenGL;
|
||||
} else if (backendStr == "D3D12" || backendStr == "d3d12") {
|
||||
mBackendType = RHIType::D3D12;
|
||||
}
|
||||
}
|
||||
|
||||
mDevice = RHIFactory::CreateRHIDevice(mBackendType);
|
||||
ASSERT_NE(mDevice, nullptr);
|
||||
|
||||
RHIDeviceDesc desc = {};
|
||||
desc.enableDebugLayer = true;
|
||||
desc.appName = L"RHIUnitTest";
|
||||
|
||||
bool initResult = mDevice->Initialize(desc);
|
||||
ASSERT_TRUE(initResult);
|
||||
}
|
||||
|
||||
void RHITestFixture::TearDown() {
|
||||
if (mDevice != nullptr) {
|
||||
mDevice->Shutdown();
|
||||
delete mDevice;
|
||||
mDevice = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
39
tests/RHI/unit/fixtures/RHITestFixture.h
Normal file
39
tests/RHI/unit/fixtures/RHITestFixture.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
|
||||
#include "XCEngine/RHI/RHIFactory.h"
|
||||
#include "XCEngine/RHI/RHIDevice.h"
|
||||
#include "XCEngine/RHI/RHICommandQueue.h"
|
||||
#include "XCEngine/RHI/RHICommandList.h"
|
||||
#include "XCEngine/RHI/RHIBuffer.h"
|
||||
#include "XCEngine/RHI/RHITexture.h"
|
||||
#include "XCEngine/RHI/RHISwapChain.h"
|
||||
#include "XCEngine/RHI/RHIShader.h"
|
||||
#include "XCEngine/RHI/RHIFence.h"
|
||||
#include "XCEngine/RHI/RHISampler.h"
|
||||
#include "XCEngine/RHI/RHIDescriptorPool.h"
|
||||
#include "XCEngine/RHI/RHIPipelineLayout.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class RHITestFixture : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
static void SetUpTestSuite();
|
||||
static void TearDownTestSuite();
|
||||
|
||||
RHIDevice* GetDevice() { return mDevice; }
|
||||
RHIType GetBackendType() const { return mBackendType; }
|
||||
|
||||
private:
|
||||
static RHIType mBackendType;
|
||||
RHIDevice* mDevice = nullptr;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
} // namespace XCEngine
|
||||
134
tests/RHI/unit/test_buffer.cpp
Normal file
134
tests/RHI/unit/test_buffer.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHIBuffer.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_Map_Unmap) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 256;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
void* data = buffer->Map();
|
||||
ASSERT_NE(data, nullptr);
|
||||
|
||||
memset(data, 0xAB, 256);
|
||||
buffer->Unmap();
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_SetData) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 128;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
float testData[16] = {};
|
||||
buffer->SetData(testData, sizeof(testData));
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_GetSize) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 1024;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
EXPECT_EQ(buffer->GetSize(), 1024u);
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_GetStride) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 256;
|
||||
desc.stride = 16;
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
EXPECT_EQ(buffer->GetStride(), 16u);
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_SetBufferType) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 256;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
EXPECT_EQ(buffer->GetBufferType(), BufferType::Vertex);
|
||||
buffer->SetBufferType(BufferType::Index);
|
||||
EXPECT_EQ(buffer->GetBufferType(), BufferType::Index);
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_StateManagement) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 256;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
EXPECT_EQ(buffer->GetState(), ResourceStates::Common);
|
||||
buffer->SetState(ResourceStates::VertexAndConstantBuffer);
|
||||
EXPECT_EQ(buffer->GetState(), ResourceStates::VertexAndConstantBuffer);
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_Naming) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 256;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
buffer->SetName("TestBuffer");
|
||||
EXPECT_EQ(buffer->GetName(), "TestBuffer");
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Buffer_GetNativeHandle) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 256;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
|
||||
EXPECT_NE(buffer->GetNativeHandle(), nullptr);
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
228
tests/RHI/unit/test_command_list.cpp
Normal file
228
tests/RHI/unit/test_command_list.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHICommandList.h"
|
||||
#include "XCEngine/RHI/RHITexture.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_Reset_Close) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_SetPrimitiveTopology) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_SetViewport) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
Viewport vp = { 0.0f, 0.0f, 800.0f, 600.0f, 0.0f, 1.0f };
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetViewport(vp);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_SetViewports) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
Viewport viewports[2] = {
|
||||
{ 0.0f, 0.0f, 400.0f, 300.0f, 0.0f, 1.0f },
|
||||
{ 400.0f, 300.0f, 400.0f, 300.0f, 0.0f, 1.0f }
|
||||
};
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetViewports(2, viewports);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_SetScissorRect) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
Rect rect = { 0, 0, 800, 600 };
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetScissorRect(rect);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_Draw) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList);
|
||||
cmdList->Draw(3);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_DrawIndexed) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList);
|
||||
cmdList->DrawIndexed(6);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_ClearRenderTarget) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
TextureDesc texDesc = {};
|
||||
texDesc.width = 256;
|
||||
texDesc.height = 256;
|
||||
texDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
texDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(texDesc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
float color[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->ClearRenderTarget(texture->GetNativeHandle(), color);
|
||||
cmdList->Close();
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_SetDepthStencilState) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
DepthStencilState dsState = {};
|
||||
dsState.depthEnable = true;
|
||||
dsState.depthWriteMask = true;
|
||||
dsState.depthFunc = ComparisonFunc::Less;
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetDepthStencilState(dsState);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_SetBlendState) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
BlendState blendState = {};
|
||||
blendState.alphaToCoverageEnable = false;
|
||||
blendState.independentBlendEnable = false;
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetBlendState(blendState);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_SetStencilRef) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->SetStencilRef(0);
|
||||
cmdList->Close();
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandList_TransitionBarrier) {
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
TextureDesc texDesc = {};
|
||||
texDesc.width = 256;
|
||||
texDesc.height = 256;
|
||||
texDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
texDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(texDesc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->TransitionBarrier(texture->GetNativeHandle(), ResourceStates::Common, ResourceStates::RenderTarget);
|
||||
cmdList->Close();
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
109
tests/RHI/unit/test_command_queue.cpp
Normal file
109
tests/RHI/unit/test_command_queue.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHICommandQueue.h"
|
||||
#include "XCEngine/RHI/RHICommandList.h"
|
||||
#include "XCEngine/RHI/RHIFence.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, CommandQueue_ExecuteCommandLists) {
|
||||
CommandQueueDesc queueDesc = {};
|
||||
queueDesc.queueType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandQueue* queue = GetDevice()->CreateCommandQueue(queueDesc);
|
||||
ASSERT_NE(queue, nullptr);
|
||||
|
||||
CommandListDesc cmdDesc = {};
|
||||
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Reset();
|
||||
cmdList->Close();
|
||||
|
||||
void* cmdLists[] = { cmdList };
|
||||
queue->ExecuteCommandLists(1, cmdLists);
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
queue->Shutdown();
|
||||
delete queue;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandQueue_SignalWaitFence) {
|
||||
CommandQueueDesc queueDesc = {};
|
||||
queueDesc.queueType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandQueue* queue = GetDevice()->CreateCommandQueue(queueDesc);
|
||||
ASSERT_NE(queue, nullptr);
|
||||
|
||||
FenceDesc fenceDesc = {};
|
||||
fenceDesc.initialValue = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(fenceDesc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
queue->Signal(fence, 1);
|
||||
fence->Wait(1);
|
||||
|
||||
EXPECT_EQ(fence->GetCompletedValue(), 1u);
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
queue->Shutdown();
|
||||
delete queue;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandQueue_GetCompletedValue) {
|
||||
CommandQueueDesc queueDesc = {};
|
||||
queueDesc.queueType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandQueue* queue = GetDevice()->CreateCommandQueue(queueDesc);
|
||||
ASSERT_NE(queue, nullptr);
|
||||
|
||||
uint64_t completedValue = queue->GetCompletedValue();
|
||||
EXPECT_GE(completedValue, 0u);
|
||||
|
||||
queue->Shutdown();
|
||||
delete queue;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandQueue_WaitForIdle) {
|
||||
CommandQueueDesc queueDesc = {};
|
||||
queueDesc.queueType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandQueue* queue = GetDevice()->CreateCommandQueue(queueDesc);
|
||||
ASSERT_NE(queue, nullptr);
|
||||
|
||||
queue->WaitForIdle();
|
||||
|
||||
queue->Shutdown();
|
||||
delete queue;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandQueue_GetType) {
|
||||
CommandQueueDesc queueDesc = {};
|
||||
queueDesc.queueType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandQueue* queue = GetDevice()->CreateCommandQueue(queueDesc);
|
||||
ASSERT_NE(queue, nullptr);
|
||||
|
||||
EXPECT_EQ(queue->GetType(), CommandQueueType::Direct);
|
||||
|
||||
queue->Shutdown();
|
||||
delete queue;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, CommandQueue_GetTimestampFrequency) {
|
||||
CommandQueueDesc queueDesc = {};
|
||||
queueDesc.queueType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandQueue* queue = GetDevice()->CreateCommandQueue(queueDesc);
|
||||
ASSERT_NE(queue, nullptr);
|
||||
|
||||
uint64_t frequency = queue->GetTimestampFrequency();
|
||||
EXPECT_GT(frequency, 0u);
|
||||
|
||||
queue->Shutdown();
|
||||
delete queue;
|
||||
}
|
||||
122
tests/RHI/unit/test_device.cpp
Normal file
122
tests/RHI/unit/test_device.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, Device_Create_Success) {
|
||||
ASSERT_NE(GetDevice(), nullptr);
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_Initialize_Shutdown) {
|
||||
RHIDevice* device = RHIFactory::CreateRHIDevice(GetBackendType());
|
||||
ASSERT_NE(device, nullptr);
|
||||
|
||||
RHIDeviceDesc desc = {};
|
||||
desc.enableDebugLayer = true;
|
||||
bool initResult = device->Initialize(desc);
|
||||
ASSERT_TRUE(initResult);
|
||||
|
||||
device->Shutdown();
|
||||
delete device;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_GetCapabilities_ReturnsValid) {
|
||||
const auto& caps = GetDevice()->GetCapabilities();
|
||||
|
||||
EXPECT_GE(caps.maxTexture2DSize, 0u);
|
||||
EXPECT_GE(caps.maxRenderTargets, 1u);
|
||||
EXPECT_GE(caps.maxViewports, 1u);
|
||||
EXPECT_GE(caps.maxVertexAttribs, 8u);
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_GetDeviceInfo_ReturnsValid) {
|
||||
const auto& info = GetDevice()->GetDeviceInfo();
|
||||
|
||||
EXPECT_FALSE(info.vendor.empty());
|
||||
EXPECT_FALSE(info.renderer.empty());
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_CreateBuffer_ReturnsValid) {
|
||||
BufferDesc desc = {};
|
||||
desc.size = 1024;
|
||||
desc.stride = sizeof(float);
|
||||
desc.bufferType = static_cast<uint32_t>(BufferType::Vertex);
|
||||
|
||||
RHIBuffer* buffer = GetDevice()->CreateBuffer(desc);
|
||||
ASSERT_NE(buffer, nullptr);
|
||||
EXPECT_EQ(buffer->GetSize(), 1024u);
|
||||
|
||||
buffer->Shutdown();
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_CreateTexture_ReturnsValid) {
|
||||
TextureDesc desc = {};
|
||||
desc.width = 512;
|
||||
desc.height = 512;
|
||||
desc.mipLevels = 1;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
desc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(desc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
EXPECT_EQ(texture->GetWidth(), 512u);
|
||||
EXPECT_EQ(texture->GetHeight(), 512u);
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_CreateFence_ReturnsValid) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
desc.flags = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
EXPECT_EQ(fence->GetCompletedValue(), 0u);
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_CreateCommandQueue_ReturnsValid) {
|
||||
CommandQueueDesc desc = {};
|
||||
desc.queueType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandQueue* queue = GetDevice()->CreateCommandQueue(desc);
|
||||
ASSERT_NE(queue, nullptr);
|
||||
EXPECT_EQ(queue->GetType(), CommandQueueType::Direct);
|
||||
|
||||
queue->Shutdown();
|
||||
delete queue;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_CreateCommandList_ReturnsValid) {
|
||||
CommandListDesc desc = {};
|
||||
desc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||
|
||||
RHICommandList* cmdList = GetDevice()->CreateCommandList(desc);
|
||||
ASSERT_NE(cmdList, nullptr);
|
||||
|
||||
cmdList->Shutdown();
|
||||
delete cmdList;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_CreateSampler_ReturnsValid) {
|
||||
SamplerDesc desc = {};
|
||||
desc.filter = static_cast<uint32_t>(FilterMode::Linear);
|
||||
desc.addressU = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressV = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressW = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
|
||||
RHISampler* sampler = GetDevice()->CreateSampler(desc);
|
||||
ASSERT_NE(sampler, nullptr);
|
||||
|
||||
sampler->Shutdown();
|
||||
delete sampler;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Device_GetNativeDevice_ReturnsValid) {
|
||||
void* native = GetDevice()->GetNativeDevice();
|
||||
ASSERT_NE(native, nullptr);
|
||||
}
|
||||
99
tests/RHI/unit/test_fence.cpp
Normal file
99
tests/RHI/unit/test_fence.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHIFence.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, Fence_Create) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
desc.flags = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Fence_Signal) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
fence->Signal();
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Fence_SignalWithValue) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
fence->Signal(5);
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Fence_Wait) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
fence->Signal(1);
|
||||
fence->Wait(1);
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Fence_GetCompletedValue) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
EXPECT_EQ(fence->GetCompletedValue(), 0u);
|
||||
fence->Signal(1);
|
||||
EXPECT_EQ(fence->GetCompletedValue(), 1u);
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Fence_IsSignaled) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
EXPECT_FALSE(fence->IsSignaled());
|
||||
fence->Signal(1);
|
||||
EXPECT_TRUE(fence->IsSignaled());
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Fence_GetNativeHandle) {
|
||||
FenceDesc desc = {};
|
||||
desc.initialValue = 0;
|
||||
|
||||
RHIFence* fence = GetDevice()->CreateFence(desc);
|
||||
ASSERT_NE(fence, nullptr);
|
||||
|
||||
EXPECT_NE(fence->GetNativeHandle(), nullptr);
|
||||
|
||||
fence->Shutdown();
|
||||
delete fence;
|
||||
}
|
||||
77
tests/RHI/unit/test_sampler.cpp
Normal file
77
tests/RHI/unit/test_sampler.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHISampler.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, Sampler_Create) {
|
||||
SamplerDesc desc = {};
|
||||
desc.filter = static_cast<uint32_t>(FilterMode::Linear);
|
||||
desc.addressU = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressV = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressW = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.mipLodBias = 0.0f;
|
||||
desc.maxAnisotropy = 16;
|
||||
desc.comparisonFunc = static_cast<uint32_t>(ComparisonFunc::Less);
|
||||
desc.borderColorR = 0.0f;
|
||||
desc.borderColorG = 0.0f;
|
||||
desc.borderColorB = 0.0f;
|
||||
desc.borderColorA = 0.0f;
|
||||
desc.minLod = 0.0f;
|
||||
desc.maxLod = 100.0f;
|
||||
|
||||
RHISampler* sampler = GetDevice()->CreateSampler(desc);
|
||||
ASSERT_NE(sampler, nullptr);
|
||||
|
||||
sampler->Shutdown();
|
||||
delete sampler;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Sampler_Bind_Unbind) {
|
||||
SamplerDesc desc = {};
|
||||
desc.filter = static_cast<uint32_t>(FilterMode::Linear);
|
||||
desc.addressU = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressV = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressW = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
|
||||
RHISampler* sampler = GetDevice()->CreateSampler(desc);
|
||||
ASSERT_NE(sampler, nullptr);
|
||||
|
||||
sampler->Bind(0);
|
||||
sampler->Unbind(0);
|
||||
|
||||
sampler->Shutdown();
|
||||
delete sampler;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Sampler_GetID) {
|
||||
SamplerDesc desc = {};
|
||||
desc.filter = static_cast<uint32_t>(FilterMode::Linear);
|
||||
desc.addressU = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressV = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressW = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
|
||||
RHISampler* sampler = GetDevice()->CreateSampler(desc);
|
||||
ASSERT_NE(sampler, nullptr);
|
||||
|
||||
unsigned int id = sampler->GetID();
|
||||
EXPECT_GE(id, 0u);
|
||||
|
||||
sampler->Shutdown();
|
||||
delete sampler;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Sampler_GetNativeHandle) {
|
||||
SamplerDesc desc = {};
|
||||
desc.filter = static_cast<uint32_t>(FilterMode::Linear);
|
||||
desc.addressU = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressV = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
desc.addressW = static_cast<uint32_t>(TextureAddressMode::Wrap);
|
||||
|
||||
RHISampler* sampler = GetDevice()->CreateSampler(desc);
|
||||
ASSERT_NE(sampler, nullptr);
|
||||
|
||||
EXPECT_NE(sampler->GetNativeHandle(), nullptr);
|
||||
|
||||
sampler->Shutdown();
|
||||
delete sampler;
|
||||
}
|
||||
123
tests/RHI/unit/test_shader.cpp
Normal file
123
tests/RHI/unit/test_shader.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHIShader.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, Shader_Compile_FromSource) {
|
||||
const char* vertexShader = R"(
|
||||
cbuffer ConstantBuffer : register(b0)
|
||||
{
|
||||
float4x4 worldViewProj;
|
||||
}
|
||||
struct VS_INPUT {
|
||||
float3 pos : POSITION;
|
||||
};
|
||||
struct VS_OUTPUT {
|
||||
float4 pos : SV_POSITION;
|
||||
};
|
||||
VS_OUTPUT main(VS_INPUT input) {
|
||||
VS_OUTPUT output;
|
||||
output.pos = float4(input.pos, 1.0f);
|
||||
return output;
|
||||
}
|
||||
)";
|
||||
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_GetType) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
ShaderType type = shader->GetType();
|
||||
EXPECT_GE(static_cast<uint8_t>(type), static_cast<uint8_t>(ShaderType::Vertex));
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_IsValid) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
EXPECT_TRUE(shader->IsValid());
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_Bind_Unbind) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
shader->Bind();
|
||||
shader->Unbind();
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_SetInt) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
shader->SetInt("testInt", 42);
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_SetFloat) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
shader->SetFloat("testFloat", 3.14f);
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_SetVec3) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
shader->SetVec3("testVec3", 1.0f, 2.0f, 3.0f);
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_SetVec4) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
shader->SetVec4("testVec4", 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_SetMat4) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
float mat[16] = {};
|
||||
shader->SetMat4("testMat4", mat);
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Shader_GetNativeHandle) {
|
||||
RHIShader* shader = GetDevice()->CompileShader({});
|
||||
ASSERT_NE(shader, nullptr);
|
||||
|
||||
EXPECT_NE(shader->GetNativeHandle(), nullptr);
|
||||
|
||||
shader->Shutdown();
|
||||
delete shader;
|
||||
}
|
||||
110
tests/RHI/unit/test_swap_chain.cpp
Normal file
110
tests/RHI/unit/test_swap_chain.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHISwapChain.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, SwapChain_Create) {
|
||||
SwapChainDesc desc = {};
|
||||
desc.width = 800;
|
||||
desc.height = 600;
|
||||
desc.bufferCount = 2;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
desc.refreshRate = 60;
|
||||
desc.sampleCount = 1;
|
||||
desc.sampleQuality = 0;
|
||||
desc.swapEffect = 0;
|
||||
desc.flags = 0;
|
||||
|
||||
RHISwapChain* swapChain = GetDevice()->CreateSwapChain(desc);
|
||||
ASSERT_NE(swapChain, nullptr);
|
||||
|
||||
swapChain->Shutdown();
|
||||
delete swapChain;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, SwapChain_GetCurrentBackBufferIndex) {
|
||||
SwapChainDesc desc = {};
|
||||
desc.width = 800;
|
||||
desc.height = 600;
|
||||
desc.bufferCount = 2;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
|
||||
RHISwapChain* swapChain = GetDevice()->CreateSwapChain(desc);
|
||||
ASSERT_NE(swapChain, nullptr);
|
||||
|
||||
uint32_t index = swapChain->GetCurrentBackBufferIndex();
|
||||
EXPECT_LT(index, 2u);
|
||||
|
||||
swapChain->Shutdown();
|
||||
delete swapChain;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, SwapChain_GetCurrentBackBuffer) {
|
||||
SwapChainDesc desc = {};
|
||||
desc.width = 800;
|
||||
desc.height = 600;
|
||||
desc.bufferCount = 2;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
|
||||
RHISwapChain* swapChain = GetDevice()->CreateSwapChain(desc);
|
||||
ASSERT_NE(swapChain, nullptr);
|
||||
|
||||
RHITexture* backBuffer = swapChain->GetCurrentBackBuffer();
|
||||
EXPECT_NE(backBuffer, nullptr);
|
||||
|
||||
swapChain->Shutdown();
|
||||
delete swapChain;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, SwapChain_Resize) {
|
||||
SwapChainDesc desc = {};
|
||||
desc.width = 800;
|
||||
desc.height = 600;
|
||||
desc.bufferCount = 2;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
|
||||
RHISwapChain* swapChain = GetDevice()->CreateSwapChain(desc);
|
||||
ASSERT_NE(swapChain, nullptr);
|
||||
|
||||
swapChain->Resize(1024, 768);
|
||||
|
||||
swapChain->Shutdown();
|
||||
delete swapChain;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, SwapChain_FullscreenState) {
|
||||
SwapChainDesc desc = {};
|
||||
desc.width = 800;
|
||||
desc.height = 600;
|
||||
desc.bufferCount = 2;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
|
||||
RHISwapChain* swapChain = GetDevice()->CreateSwapChain(desc);
|
||||
ASSERT_NE(swapChain, nullptr);
|
||||
|
||||
EXPECT_FALSE(swapChain->IsFullscreen());
|
||||
swapChain->SetFullscreen(true);
|
||||
EXPECT_TRUE(swapChain->IsFullscreen());
|
||||
swapChain->SetFullscreen(false);
|
||||
|
||||
swapChain->Shutdown();
|
||||
delete swapChain;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, SwapChain_ShouldClose) {
|
||||
SwapChainDesc desc = {};
|
||||
desc.width = 800;
|
||||
desc.height = 600;
|
||||
desc.bufferCount = 2;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
|
||||
RHISwapChain* swapChain = GetDevice()->CreateSwapChain(desc);
|
||||
ASSERT_NE(swapChain, nullptr);
|
||||
|
||||
EXPECT_FALSE(swapChain->ShouldClose());
|
||||
swapChain->SetShouldClose(true);
|
||||
EXPECT_TRUE(swapChain->ShouldClose());
|
||||
|
||||
swapChain->Shutdown();
|
||||
delete swapChain;
|
||||
}
|
||||
103
tests/RHI/unit/test_texture.cpp
Normal file
103
tests/RHI/unit/test_texture.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHITexture.h"
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
TEST_F(RHITestFixture, Texture_Create_Texture2D) {
|
||||
TextureDesc desc = {};
|
||||
desc.width = 512;
|
||||
desc.height = 512;
|
||||
desc.depth = 1;
|
||||
desc.mipLevels = 1;
|
||||
desc.arraySize = 1;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
desc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
desc.sampleCount = 1;
|
||||
desc.sampleQuality = 0;
|
||||
desc.flags = 0;
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(desc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
EXPECT_EQ(texture->GetWidth(), 512u);
|
||||
EXPECT_EQ(texture->GetHeight(), 512u);
|
||||
EXPECT_EQ(texture->GetDepth(), 1u);
|
||||
EXPECT_EQ(texture->GetMipLevels(), 1u);
|
||||
EXPECT_EQ(texture->GetFormat(), Format::R8G8B8A8_UNorm);
|
||||
EXPECT_EQ(texture->GetTextureType(), TextureType::Texture2D);
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Texture_Create_Texture3D) {
|
||||
TextureDesc desc = {};
|
||||
desc.width = 64;
|
||||
desc.height = 64;
|
||||
desc.depth = 64;
|
||||
desc.mipLevels = 1;
|
||||
desc.format = static_cast<uint32_t>(Format::R16_Float);
|
||||
desc.textureType = static_cast<uint32_t>(TextureType::Texture3D);
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(desc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
EXPECT_EQ(texture->GetWidth(), 64u);
|
||||
EXPECT_EQ(texture->GetHeight(), 64u);
|
||||
EXPECT_EQ(texture->GetDepth(), 64u);
|
||||
EXPECT_EQ(texture->GetTextureType(), TextureType::Texture3D);
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Texture_StateManagement) {
|
||||
TextureDesc desc = {};
|
||||
desc.width = 256;
|
||||
desc.height = 256;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
desc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(desc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
EXPECT_EQ(texture->GetState(), ResourceStates::Common);
|
||||
texture->SetState(ResourceStates::RenderTarget);
|
||||
EXPECT_EQ(texture->GetState(), ResourceStates::RenderTarget);
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Texture_Naming) {
|
||||
TextureDesc desc = {};
|
||||
desc.width = 256;
|
||||
desc.height = 256;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
desc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(desc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
texture->SetName("TestTexture");
|
||||
EXPECT_EQ(texture->GetName(), "TestTexture");
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST_F(RHITestFixture, Texture_GetNativeHandle) {
|
||||
TextureDesc desc = {};
|
||||
desc.width = 256;
|
||||
desc.height = 256;
|
||||
desc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||
desc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||
|
||||
RHITexture* texture = GetDevice()->CreateTexture(desc);
|
||||
ASSERT_NE(texture, nullptr);
|
||||
|
||||
EXPECT_NE(texture->GetNativeHandle(), nullptr);
|
||||
|
||||
texture->Shutdown();
|
||||
delete texture;
|
||||
}
|
||||
Reference in New Issue
Block a user