Add Vulkan quad integration path

This commit is contained in:
2026-03-27 13:52:56 +08:00
parent 4b21b5d3d1
commit 727b6ca249
23 changed files with 1574 additions and 39 deletions

View File

@@ -8,6 +8,7 @@
#include "XCEngine/RHI/RHIEnums.h"
#include <cmath>
#include <string>
namespace XCEngine {
@@ -245,6 +246,162 @@ inline VkSampleCountFlagBits ToVulkanSampleCount(uint32_t sampleCount) {
}
}
inline VkDescriptorType ToVulkanDescriptorType(DescriptorType type) {
switch (type) {
case DescriptorType::CBV:
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case DescriptorType::SRV:
return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
case DescriptorType::UAV:
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
case DescriptorType::Sampler:
return VK_DESCRIPTOR_TYPE_SAMPLER;
default:
return VK_DESCRIPTOR_TYPE_MAX_ENUM;
}
}
inline VkShaderStageFlags ToVulkanShaderStageFlags(uint32_t visibility) {
switch (static_cast<ShaderVisibility>(visibility)) {
case ShaderVisibility::Vertex:
return VK_SHADER_STAGE_VERTEX_BIT;
case ShaderVisibility::Geometry:
return VK_SHADER_STAGE_GEOMETRY_BIT;
case ShaderVisibility::Pixel:
return VK_SHADER_STAGE_FRAGMENT_BIT;
case ShaderVisibility::Amplification:
case ShaderVisibility::Mesh:
case ShaderVisibility::Hull:
case ShaderVisibility::Domain:
case ShaderVisibility::All:
default:
return VK_SHADER_STAGE_ALL_GRAPHICS;
}
}
inline VkFilter ToVulkanMinFilter(FilterMode filter) {
switch (filter) {
case FilterMode::Point:
case FilterMode::ComparisonPoint:
case FilterMode::MinimumPoint:
case FilterMode::MaximumPoint:
return VK_FILTER_NEAREST;
default:
return VK_FILTER_LINEAR;
}
}
inline VkFilter ToVulkanMagFilter(FilterMode filter) {
switch (filter) {
case FilterMode::Point:
case FilterMode::ComparisonPoint:
case FilterMode::MinimumPoint:
case FilterMode::MaximumPoint:
return VK_FILTER_NEAREST;
default:
return VK_FILTER_LINEAR;
}
}
inline VkSamplerMipmapMode ToVulkanSamplerMipmapMode(FilterMode filter) {
switch (filter) {
case FilterMode::Point:
case FilterMode::ComparisonPoint:
case FilterMode::MinimumPoint:
case FilterMode::MaximumPoint:
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
default:
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
}
}
inline bool UsesVulkanSamplerAnisotropy(FilterMode filter) {
return filter == FilterMode::Anisotropic ||
filter == FilterMode::ComparisonAnisotropic ||
filter == FilterMode::MinimumAnisotropic ||
filter == FilterMode::MaximumAnisotropic;
}
inline bool UsesVulkanComparisonSampling(FilterMode filter) {
return filter == FilterMode::ComparisonPoint ||
filter == FilterMode::ComparisonLinear ||
filter == FilterMode::ComparisonAnisotropic;
}
inline VkSamplerAddressMode ToVulkanSamplerAddressMode(TextureAddressMode mode) {
switch (mode) {
case TextureAddressMode::Wrap:
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case TextureAddressMode::Mirror:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case TextureAddressMode::Clamp:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case TextureAddressMode::Border:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case TextureAddressMode::MirrorOnce:
return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
default:
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
}
}
inline VkBorderColor ToVulkanBorderColor(float r, float g, float b, float a) {
const bool opaqueBlack = std::fabs(r) < 0.0001f &&
std::fabs(g) < 0.0001f &&
std::fabs(b) < 0.0001f &&
std::fabs(a - 1.0f) < 0.0001f;
if (opaqueBlack) {
return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
}
const bool opaqueWhite = std::fabs(r - 1.0f) < 0.0001f &&
std::fabs(g - 1.0f) < 0.0001f &&
std::fabs(b - 1.0f) < 0.0001f &&
std::fabs(a - 1.0f) < 0.0001f;
if (opaqueWhite) {
return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
}
return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
}
inline VkImageViewType ToVulkanImageViewType(ResourceViewDimension dimension, TextureType textureType) {
switch (dimension) {
case ResourceViewDimension::Texture1D:
return VK_IMAGE_VIEW_TYPE_1D;
case ResourceViewDimension::Texture1DArray:
return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
case ResourceViewDimension::Texture2DArray:
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
case ResourceViewDimension::Texture3D:
return VK_IMAGE_VIEW_TYPE_3D;
case ResourceViewDimension::TextureCube:
return VK_IMAGE_VIEW_TYPE_CUBE;
case ResourceViewDimension::TextureCubeArray:
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
case ResourceViewDimension::Texture2D:
case ResourceViewDimension::Unknown:
default:
break;
}
switch (textureType) {
case TextureType::Texture1D:
return VK_IMAGE_VIEW_TYPE_1D;
case TextureType::Texture2DArray:
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
case TextureType::Texture3D:
return VK_IMAGE_VIEW_TYPE_3D;
case TextureType::TextureCube:
return VK_IMAGE_VIEW_TYPE_CUBE;
case TextureType::TextureCubeArray:
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
case TextureType::Texture2D:
default:
return VK_IMAGE_VIEW_TYPE_2D;
}
}
inline uint32_t ResolveVulkanApiMajor(uint32_t apiVersion) {
return VK_API_VERSION_MAJOR(apiVersion);
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include "XCEngine/RHI/RHIDescriptorPool.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
#include <vector>
namespace XCEngine {
namespace RHI {
class VulkanDescriptorSet;
class VulkanDescriptorPool : public RHIDescriptorPool {
public:
VulkanDescriptorPool() = default;
~VulkanDescriptorPool() override;
bool Initialize(VkDevice device, const DescriptorPoolDesc& desc);
bool Initialize(const DescriptorPoolDesc& desc) override;
void Shutdown() override;
void* GetNativeHandle() override { return m_descriptorPool; }
uint32_t GetDescriptorCount() const override { return m_descriptorCount; }
DescriptorHeapType GetType() const override { return m_type; }
RHIDescriptorSet* AllocateSet(const DescriptorSetLayoutDesc& layout) override;
void FreeSet(RHIDescriptorSet* set) override;
VkDevice GetDevice() const { return m_device; }
VkDescriptorPool GetDescriptorPool() const { return m_descriptorPool; }
private:
VkDevice m_device = VK_NULL_HANDLE;
VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
DescriptorHeapType m_type = DescriptorHeapType::CBV_SRV_UAV;
uint32_t m_descriptorCount = 0;
std::vector<VulkanDescriptorSet*> m_allocatedSets;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,63 @@
#pragma once
#include "XCEngine/RHI/RHIDescriptorSet.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
#include <unordered_map>
#include <vector>
namespace XCEngine {
namespace RHI {
class VulkanDescriptorPool;
class VulkanDescriptorSet : public RHIDescriptorSet {
public:
VulkanDescriptorSet() = default;
~VulkanDescriptorSet() override;
bool Initialize(
VkDevice device,
VulkanDescriptorPool* pool,
VkDescriptorSetLayout layout,
VkDescriptorSet descriptorSet,
const DescriptorSetLayoutDesc& desc);
void Shutdown() override;
void Bind() override;
void Unbind() override;
void Update(uint32_t offset, RHIResourceView* view) override;
void UpdateSampler(uint32_t offset, RHISampler* sampler) override;
void WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset = 0) override;
uint32_t GetBindingCount() const override { return static_cast<uint32_t>(m_bindings.size()); }
const DescriptorSetLayoutBinding* GetBindings() const override {
return m_bindings.empty() ? nullptr : m_bindings.data();
}
void* GetConstantBufferData() override {
return m_constantBufferData.empty() ? nullptr : m_constantBufferData.data();
}
size_t GetConstantBufferSize() const override { return m_constantBufferData.size(); }
bool IsConstantDirty() const override { return m_constantDirty; }
void MarkConstantClean() override { m_constantDirty = false; }
VkDescriptorSet GetDescriptorSet() const { return m_descriptorSet; }
VkDescriptorSetLayout GetDescriptorSetLayout() const { return m_descriptorSetLayout; }
private:
const DescriptorSetLayoutBinding* FindBinding(uint32_t binding) const;
VkDevice m_device = VK_NULL_HANDLE;
VulkanDescriptorPool* m_pool = nullptr;
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE;
std::vector<DescriptorSetLayoutBinding> m_bindings;
std::unordered_map<uint32_t, uint32_t> m_bindingToIndex;
std::vector<uint8_t> m_constantBufferData;
bool m_constantDirty = false;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,40 @@
#pragma once
#include "XCEngine/RHI/RHIPipelineLayout.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
#include <vector>
namespace XCEngine {
namespace RHI {
class VulkanPipelineLayout : public RHIPipelineLayout {
public:
VulkanPipelineLayout() = default;
~VulkanPipelineLayout() override;
bool Initialize(VkDevice device, const RHIPipelineLayoutDesc& desc);
bool Initialize(const RHIPipelineLayoutDesc& desc) override;
void Shutdown() override;
void* GetNativeHandle() override { return m_pipelineLayout; }
VkPipelineLayout GetPipelineLayout() const { return m_pipelineLayout; }
const RHIPipelineLayoutDesc& GetDesc() const { return m_desc; }
bool UsesSetLayouts() const { return m_desc.setLayoutCount > 0 && m_desc.setLayouts != nullptr; }
private:
void PrepareExplicitLayouts(const RHIPipelineLayoutDesc& desc);
void PrepareFlatLayouts(const RHIPipelineLayoutDesc& desc);
bool CreateNativeSetLayouts();
VkDevice m_device = VK_NULL_HANDLE;
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
RHIPipelineLayoutDesc m_desc = {};
std::vector<DescriptorSetLayoutDesc> m_setLayouts;
std::vector<std::vector<DescriptorSetLayoutBinding>> m_setLayoutBindings;
std::vector<VkDescriptorSetLayout> m_nativeSetLayouts;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -51,6 +51,7 @@ private:
VkPipeline m_pipeline = VK_NULL_HANDLE;
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
VkRenderPass m_renderPass = VK_NULL_HANDLE;
bool m_ownsPipelineLayout = false;
InputLayoutDesc m_inputLayoutDesc = {};
RasterizerDesc m_rasterizerDesc = {};
BlendDesc m_blendDesc = {};

View File

@@ -15,6 +15,7 @@ public:
~VulkanResourceView() override;
bool InitializeAsRenderTarget(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
bool InitializeAsShaderResource(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
bool InitializeAsVertexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc);
bool InitializeAsIndexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc);

View File

@@ -0,0 +1,31 @@
#pragma once
#include "XCEngine/RHI/RHISampler.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
namespace XCEngine {
namespace RHI {
class VulkanSampler : public RHISampler {
public:
VulkanSampler() = default;
~VulkanSampler() override;
bool Initialize(VkDevice device, const SamplerDesc& desc);
void Shutdown() override;
void Bind(unsigned int unit) override;
void Unbind(unsigned int unit) override;
void* GetNativeHandle() override { return m_sampler != VK_NULL_HANDLE ? &m_sampler : nullptr; }
unsigned int GetID() override { return 0; }
VkSampler GetSampler() const { return m_sampler; }
private:
VkDevice m_device = VK_NULL_HANDLE;
VkSampler m_sampler = VK_NULL_HANDLE;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -20,13 +20,23 @@ public:
uint32_t height,
Format format,
VkFormat vkFormat);
bool InitializeOwnedImage(
VkDevice device,
VkImage image,
VkDeviceMemory memory,
uint32_t width,
uint32_t height,
uint32_t mipLevels,
Format format,
TextureType textureType,
VkFormat vkFormat);
void Shutdown() override;
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 GetMipLevels() const override { return 1; }
uint32_t GetMipLevels() const override { return m_mipLevels; }
Format GetFormat() const override { return m_format; }
TextureType GetTextureType() const override { return m_textureType; }
@@ -39,17 +49,21 @@ public:
void SetName(const std::string& name) override { m_name = name; }
VkImage GetImage() const { return m_image; }
VkDeviceMemory GetMemory() const { return m_memory; }
VkFormat GetVkFormat() const { return m_vkFormat; }
private:
VkDevice m_device = VK_NULL_HANDLE;
VkImage m_image = VK_NULL_HANDLE;
VkDeviceMemory m_memory = VK_NULL_HANDLE;
uint32_t m_width = 0;
uint32_t m_height = 0;
uint32_t m_mipLevels = 1;
Format m_format = Format::Unknown;
TextureType m_textureType = TextureType::Texture2D;
ResourceStates m_state = ResourceStates::Common;
VkFormat m_vkFormat = VK_FORMAT_UNDEFINED;
bool m_ownsImage = false;
std::string m_name;
};