Add Vulkan coverage to generic RHI unit tests
This commit is contained in:
@@ -71,8 +71,18 @@ inline bool TryResolveShaderTypeFromTarget(const char* target, ShaderType& type)
|
||||
|
||||
inline VkFormat ToVulkanFormat(Format format) {
|
||||
switch (format) {
|
||||
case Format::R8_UNorm:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
case Format::R8G8_UNorm:
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
case Format::R8G8B8A8_UNorm:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case Format::R16_UInt:
|
||||
return VK_FORMAT_R16_UINT;
|
||||
case Format::R16_Float:
|
||||
return VK_FORMAT_R16_SFLOAT;
|
||||
case Format::D16_UNorm:
|
||||
return VK_FORMAT_D16_UNORM;
|
||||
case Format::D24_UNorm_S8_UInt:
|
||||
return VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
case Format::D32_Float:
|
||||
@@ -115,9 +125,19 @@ inline uint32_t GetFormatSize(Format format) {
|
||||
|
||||
inline Format ToRHIFormat(VkFormat format) {
|
||||
switch (format) {
|
||||
case VK_FORMAT_R8_UNORM:
|
||||
return Format::R8_UNorm;
|
||||
case VK_FORMAT_R8G8_UNORM:
|
||||
return Format::R8G8_UNorm;
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
return Format::R8G8B8A8_UNorm;
|
||||
case VK_FORMAT_R16_UINT:
|
||||
return Format::R16_UInt;
|
||||
case VK_FORMAT_R16_SFLOAT:
|
||||
return Format::R16_Float;
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
return Format::D16_UNorm;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
return Format::D24_UNorm_S8_UInt;
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
void Signal(uint64_t value) override { m_value = value; }
|
||||
void Wait(uint64_t value) override { if (m_value < value) m_value = value; }
|
||||
uint64_t GetCompletedValue() const override { return m_value; }
|
||||
void* GetNativeHandle() override { return nullptr; }
|
||||
void* GetNativeHandle() override { return &m_value; }
|
||||
|
||||
private:
|
||||
uint64_t m_value = 0;
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
RHIShader* GetComputeShader() const override { return m_computeShader; }
|
||||
bool HasComputeShader() const override { return m_computeShader != nullptr; }
|
||||
|
||||
bool IsValid() const override { return m_pipeline != VK_NULL_HANDLE; }
|
||||
bool IsValid() const override { return m_isConfigured; }
|
||||
void EnsureValid() override;
|
||||
|
||||
void Shutdown() override;
|
||||
@@ -70,6 +70,7 @@ private:
|
||||
uint32_t m_depthStencilFormat = 0;
|
||||
uint32_t m_sampleCount = 1;
|
||||
RHIShader* m_computeShader = nullptr;
|
||||
bool m_isConfigured = false;
|
||||
};
|
||||
|
||||
} // namespace RHI
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
VkDeviceMemory memory,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t depth,
|
||||
uint32_t mipLevels,
|
||||
Format format,
|
||||
TextureType textureType,
|
||||
@@ -35,7 +36,7 @@ public:
|
||||
|
||||
uint32_t GetWidth() const override { return m_width; }
|
||||
uint32_t GetHeight() const override { return m_height; }
|
||||
uint32_t GetDepth() const override { return 1; }
|
||||
uint32_t GetDepth() const override { return m_depth; }
|
||||
uint32_t GetMipLevels() const override { return m_mipLevels; }
|
||||
Format GetFormat() const override { return m_format; }
|
||||
TextureType GetTextureType() const override { return m_textureType; }
|
||||
@@ -60,6 +61,7 @@ private:
|
||||
VkDeviceMemory m_memory = VK_NULL_HANDLE;
|
||||
uint32_t m_width = 0;
|
||||
uint32_t m_height = 0;
|
||||
uint32_t m_depth = 1;
|
||||
uint32_t m_mipLevels = 1;
|
||||
Format m_format = Format::Unknown;
|
||||
TextureType m_textureType = TextureType::Texture2D;
|
||||
|
||||
@@ -427,8 +427,10 @@ bool VulkanDevice::CreateLogicalDevice() {
|
||||
void VulkanDevice::QueryDeviceInfo() {
|
||||
VkPhysicalDeviceProperties properties = {};
|
||||
VkPhysicalDeviceFeatures features = {};
|
||||
VkPhysicalDeviceMemoryProperties memoryProperties = {};
|
||||
vkGetPhysicalDeviceProperties(m_physicalDevice, &properties);
|
||||
vkGetPhysicalDeviceFeatures(m_physicalDevice, &features);
|
||||
vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memoryProperties);
|
||||
|
||||
m_deviceInfo.description = WidenAscii(properties.deviceName);
|
||||
m_deviceInfo.vendor = ResolveVendorName(properties.vendorID);
|
||||
@@ -439,6 +441,14 @@ void VulkanDevice::QueryDeviceInfo() {
|
||||
m_deviceInfo.vendorId = properties.vendorID;
|
||||
m_deviceInfo.deviceId = properties.deviceID;
|
||||
m_deviceInfo.isSoftware = properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU;
|
||||
for (uint32_t heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; ++heapIndex) {
|
||||
const VkMemoryHeap& heap = memoryProperties.memoryHeaps[heapIndex];
|
||||
if ((heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0) {
|
||||
m_deviceInfo.dedicatedVideoMemory += heap.size;
|
||||
} else {
|
||||
m_deviceInfo.sharedSystemMemory += heap.size;
|
||||
}
|
||||
}
|
||||
|
||||
m_capabilities.bSupportsGeometryShaders = features.geometryShader == VK_TRUE;
|
||||
m_capabilities.bSupportsTessellation = features.tessellationShader == VK_TRUE;
|
||||
@@ -580,6 +590,7 @@ RHITexture* VulkanDevice::CreateTexture(const TextureDesc& desc) {
|
||||
memory,
|
||||
desc.width,
|
||||
desc.height,
|
||||
desc.depth > 0 ? desc.depth : 1u,
|
||||
imageInfo.mipLevels,
|
||||
format,
|
||||
static_cast<TextureType>(desc.textureType),
|
||||
|
||||
@@ -66,6 +66,7 @@ bool VulkanPipelineState::Initialize(VulkanDevice* device, const GraphicsPipelin
|
||||
const bool hasVertexShader = HasShaderPayload(desc.vertexShader);
|
||||
const bool hasFragmentShader = HasShaderPayload(desc.fragmentShader);
|
||||
if (!hasVertexShader && !hasFragmentShader) {
|
||||
m_isConfigured = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -79,6 +80,7 @@ bool VulkanPipelineState::Initialize(VulkanDevice* device, const GraphicsPipelin
|
||||
return false;
|
||||
}
|
||||
|
||||
m_isConfigured = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -362,6 +364,9 @@ void VulkanPipelineState::SetComputeShader(RHIShader* shader) {
|
||||
m_pipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
m_computeShader = shader;
|
||||
if (m_computeShader != nullptr && m_pipelineLayout != VK_NULL_HANDLE) {
|
||||
m_isConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
PipelineStateHash VulkanPipelineState::GetHash() const {
|
||||
@@ -425,6 +430,7 @@ void VulkanPipelineState::Shutdown() {
|
||||
m_device = VK_NULL_HANDLE;
|
||||
m_ownsPipelineLayout = false;
|
||||
m_computeShader = nullptr;
|
||||
m_isConfigured = false;
|
||||
}
|
||||
|
||||
} // namespace RHI
|
||||
|
||||
@@ -18,6 +18,7 @@ bool VulkanTexture::InitializeSwapChainImage(
|
||||
m_image = image;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_depth = 1;
|
||||
m_mipLevels = 1;
|
||||
m_format = format;
|
||||
m_vkFormat = vkFormat;
|
||||
@@ -33,6 +34,7 @@ bool VulkanTexture::InitializeOwnedImage(
|
||||
VkDeviceMemory memory,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t depth,
|
||||
uint32_t mipLevels,
|
||||
Format format,
|
||||
TextureType textureType,
|
||||
@@ -46,6 +48,7 @@ bool VulkanTexture::InitializeOwnedImage(
|
||||
m_memory = memory;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_depth = depth > 0 ? depth : 1u;
|
||||
m_mipLevels = mipLevels;
|
||||
m_format = format;
|
||||
m_vkFormat = vkFormat;
|
||||
@@ -69,6 +72,7 @@ void VulkanTexture::Shutdown() {
|
||||
m_device = VK_NULL_HANDLE;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_depth = 1;
|
||||
m_mipLevels = 1;
|
||||
m_format = Format::Unknown;
|
||||
m_vkFormat = VK_FORMAT_UNDEFINED;
|
||||
|
||||
@@ -8,12 +8,18 @@
|
||||
#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12CommandList.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
#include "XCEngine/RHI/Vulkan/VulkanDevice.h"
|
||||
#endif
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(D3D12, RHITestFixture, ::testing::Values(RHIType::D3D12));
|
||||
INSTANTIATE_TEST_SUITE_P(OpenGL, RHITestFixture, ::testing::Values(RHIType::OpenGL));
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
INSTANTIATE_TEST_SUITE_P(Vulkan, RHITestFixture, ::testing::Values(RHIType::Vulkan));
|
||||
#endif
|
||||
|
||||
void RHITestFixture::SetUpTestSuite() {
|
||||
}
|
||||
@@ -36,7 +42,7 @@ void RHITestFixture::SetUp() {
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
|
||||
bool initResult = false;
|
||||
if (GetParam() == RHIType::D3D12) {
|
||||
if (GetParam() == RHIType::D3D12 || GetParam() == RHIType::Vulkan) {
|
||||
RHIDeviceDesc desc = {};
|
||||
desc.enableDebugLayer = false;
|
||||
initResult = mDevice->Initialize(desc);
|
||||
@@ -66,14 +72,19 @@ void RHITestFixture::SetUp() {
|
||||
}
|
||||
|
||||
void RHITestFixture::WaitForGPU() {
|
||||
if (mDevice == nullptr || mCommandQueue == nullptr || mFence == nullptr) {
|
||||
if (mDevice == nullptr || mCommandQueue == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetParam() == RHIType::D3D12) {
|
||||
if (mFence == nullptr) {
|
||||
return;
|
||||
}
|
||||
mFenceValue++;
|
||||
mCommandQueue->Signal(mFence, mFenceValue);
|
||||
mFence->Wait(mFenceValue);
|
||||
} else {
|
||||
mCommandQueue->WaitForIdle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h"
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
#include "XCEngine/RHI/Vulkan/VulkanPipelineLayout.h"
|
||||
#endif
|
||||
#include "XCEngine/RHI/RHIPipelineLayout.h"
|
||||
#include "XCEngine/RHI/RHIDescriptorSet.h"
|
||||
|
||||
@@ -181,6 +184,10 @@ TEST_P(RHITestFixture, PipelineLayout_DeepCopiesSetLayoutsAndInfersCounts) {
|
||||
const RHIPipelineLayoutDesc* storedDesc = nullptr;
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
storedDesc = &static_cast<D3D12PipelineLayout*>(layout)->GetDesc();
|
||||
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||
} else if (GetBackendType() == RHIType::Vulkan) {
|
||||
storedDesc = &static_cast<VulkanPipelineLayout*>(layout)->GetDesc();
|
||||
#endif
|
||||
} else {
|
||||
storedDesc = &static_cast<OpenGLPipelineLayout*>(layout)->GetDesc();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
#include "fixtures/RHITestFixture.h"
|
||||
#include "XCEngine/RHI/RHIShader.h"
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
|
||||
using namespace XCEngine::RHI;
|
||||
|
||||
namespace {
|
||||
|
||||
std::wstring ResolveShaderPath(const wchar_t* relativePath) {
|
||||
wchar_t exePath[MAX_PATH] = {};
|
||||
const DWORD length = GetModuleFileNameW(nullptr, exePath, MAX_PATH);
|
||||
std::filesystem::path rootPath = length > 0 ? std::filesystem::path(exePath).parent_path() : std::filesystem::current_path();
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
rootPath = rootPath.parent_path();
|
||||
}
|
||||
return (rootPath / relativePath).wstring();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_P(RHITestFixture, Shader_Compile_EmptyDesc_ReturnsNullptr) {
|
||||
ShaderCompileDesc desc = {};
|
||||
RHIShader* shader = GetDevice()->CreateShader(desc);
|
||||
@@ -13,7 +28,7 @@ TEST_P(RHITestFixture, Shader_Compile_EmptyDesc_ReturnsNullptr) {
|
||||
TEST_P(RHITestFixture, Shader_Compile_ValidVertexShader) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl");
|
||||
desc.entryPoint = L"MainVS";
|
||||
desc.profile = L"vs_5_0";
|
||||
} else {
|
||||
@@ -36,7 +51,7 @@ TEST_P(RHITestFixture, Shader_Compile_ValidVertexShader) {
|
||||
TEST_P(RHITestFixture, Shader_Compile_ValidFragmentShader) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl");
|
||||
desc.entryPoint = L"MainPS";
|
||||
desc.profile = L"ps_5_0";
|
||||
} else {
|
||||
@@ -59,7 +74,7 @@ TEST_P(RHITestFixture, Shader_Compile_ValidFragmentShader) {
|
||||
TEST_P(RHITestFixture, Shader_GetType_VertexShader) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl");
|
||||
desc.entryPoint = L"MainVS";
|
||||
desc.profile = L"vs_5_0";
|
||||
} else {
|
||||
@@ -80,7 +95,7 @@ TEST_P(RHITestFixture, Shader_GetType_VertexShader) {
|
||||
TEST_P(RHITestFixture, Shader_GetType_FragmentShader) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl");
|
||||
desc.entryPoint = L"MainPS";
|
||||
desc.profile = L"ps_5_0";
|
||||
} else {
|
||||
@@ -101,7 +116,7 @@ TEST_P(RHITestFixture, Shader_GetType_FragmentShader) {
|
||||
TEST_P(RHITestFixture, Shader_GetNativeHandle_ValidShader) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl");
|
||||
desc.entryPoint = L"MainVS";
|
||||
desc.profile = L"vs_5_0";
|
||||
} else {
|
||||
@@ -123,7 +138,7 @@ TEST_P(RHITestFixture, Shader_GetNativeHandle_ValidShader) {
|
||||
TEST_P(RHITestFixture, Shader_Shutdown_Invalidates) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl");
|
||||
desc.entryPoint = L"MainVS";
|
||||
desc.profile = L"vs_5_0";
|
||||
} else {
|
||||
@@ -145,11 +160,15 @@ TEST_P(RHITestFixture, Shader_Shutdown_Invalidates) {
|
||||
TEST_P(RHITestFixture, Shader_Compile_FromFile_ReturnsValidShader) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/quad.hlsl");
|
||||
desc.entryPoint = L"MainVS";
|
||||
desc.profile = L"vs_5_0";
|
||||
} else if (GetBackendType() == RHIType::Vulkan) {
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/integration/triangle/Res/Shader/triangle_vulkan.vert");
|
||||
desc.entryPoint = L"main";
|
||||
desc.profile = L"vs";
|
||||
} else {
|
||||
desc.fileName = L"tests/RHI/OpenGL/integration/triangle/Res/Shader/triangle.vert";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/OpenGL/integration/triangle/Res/Shader/triangle.vert");
|
||||
desc.entryPoint = L"main";
|
||||
desc.profile = L"vs_4_30";
|
||||
}
|
||||
@@ -165,11 +184,11 @@ TEST_P(RHITestFixture, Shader_Compile_FromFile_ReturnsValidShader) {
|
||||
TEST_P(RHITestFixture, Shader_Compile_MissingFile_ReturnsNullptr) {
|
||||
ShaderCompileDesc desc = {};
|
||||
if (GetBackendType() == RHIType::D3D12) {
|
||||
desc.fileName = L"tests/RHI/D3D12/integration/quad/Res/Shader/does_not_exist.hlsl";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/D3D12/integration/quad/Res/Shader/does_not_exist.hlsl");
|
||||
desc.entryPoint = L"MainVS";
|
||||
desc.profile = L"vs_5_0";
|
||||
} else {
|
||||
desc.fileName = L"tests/RHI/OpenGL/integration/triangle/Res/Shader/does_not_exist.vert";
|
||||
desc.fileName = ResolveShaderPath(L"tests/RHI/OpenGL/integration/triangle/Res/Shader/does_not_exist.vert");
|
||||
desc.entryPoint = L"main";
|
||||
desc.profile = L"vs_4_30";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user