Add Vulkan RHI minimal backend path

This commit is contained in:
2026-03-27 12:05:12 +08:00
parent 90961f01aa
commit c33404767e
25 changed files with 1894 additions and 16 deletions

View File

@@ -0,0 +1,71 @@
#pragma once
#include "XCEngine/RHI/RHICommandList.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
namespace XCEngine {
namespace RHI {
class VulkanDevice;
class VulkanTexture;
class VulkanCommandList : public RHICommandList {
public:
VulkanCommandList() = default;
~VulkanCommandList() override;
bool Initialize(VulkanDevice* device);
void Shutdown() override;
void Reset() override;
void Close() override;
void TransitionBarrier(RHIResourceView* resource, ResourceStates stateBefore, ResourceStates stateAfter) override;
void BeginRenderPass(class RHIRenderPass* renderPass, class RHIFramebuffer* framebuffer,
const Rect& renderArea, uint32_t clearValueCount, const ClearValue* clearValues) override;
void EndRenderPass() override;
void SetShader(RHIShader* shader) override;
void SetPipelineState(RHIPipelineState* pso) override;
void SetGraphicsDescriptorSets(uint32_t firstSet, uint32_t count, RHIDescriptorSet** descriptorSets, RHIPipelineLayout* pipelineLayout) override;
void SetComputeDescriptorSets(uint32_t firstSet, uint32_t count, RHIDescriptorSet** descriptorSets, RHIPipelineLayout* pipelineLayout) override;
void SetPrimitiveTopology(PrimitiveTopology topology) override;
void SetViewport(const Viewport& viewport) override;
void SetViewports(uint32_t count, const Viewport* viewports) override;
void SetScissorRect(const Rect& rect) override;
void SetScissorRects(uint32_t count, const Rect* rects) override;
void SetRenderTargets(uint32_t count, RHIResourceView** renderTargets, RHIResourceView* depthStencil = nullptr) override;
void SetStencilRef(uint8_t ref) override;
void SetBlendFactor(const float factor[4]) override;
void SetVertexBuffers(uint32_t startSlot, uint32_t count, RHIResourceView** buffers, const uint64_t* offsets, const uint32_t* strides) override;
void SetIndexBuffer(RHIResourceView* buffer, uint64_t offset) override;
void Draw(uint32_t vertexCount, uint32_t instanceCount = 1, uint32_t startVertex = 0, uint32_t startInstance = 0) override;
void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) override;
void Clear(float r, float g, float b, float a, uint32_t buffers) override;
void ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) override;
void ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) override;
void CopyResource(RHIResourceView* dst, RHIResourceView* src) override;
void Dispatch(uint32_t x, uint32_t y, uint32_t z) override;
void* GetNativeHandle() override { return m_commandBuffer; }
VkCommandBuffer GetCommandBuffer() const { return m_commandBuffer; }
private:
void TransitionTexture(VulkanTexture* texture, ResourceStates newState);
VulkanDevice* m_device = nullptr;
VkCommandPool m_commandPool = VK_NULL_HANDLE;
VkCommandBuffer m_commandBuffer = VK_NULL_HANDLE;
RHIResourceView* m_currentColorTarget = nullptr;
RHIResourceView* m_currentDepthTarget = nullptr;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,43 @@
#pragma once
#include "XCEngine/RHI/RHICommandQueue.h"
#include "XCEngine/RHI/RHIFence.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
namespace XCEngine {
namespace RHI {
class VulkanDevice;
class VulkanCommandQueue : public RHICommandQueue {
public:
VulkanCommandQueue() = default;
~VulkanCommandQueue() override = default;
bool Initialize(VulkanDevice* device, CommandQueueType type);
void Shutdown() override;
void ExecuteCommandLists(uint32_t count, void** lists) override;
void Signal(RHIFence* fence, uint64_t value) override;
void Wait(RHIFence* fence, uint64_t value) override;
uint64_t GetCompletedValue() override;
void WaitForIdle() override;
CommandQueueType GetType() const override { return m_type; }
uint64_t GetTimestampFrequency() const override { return 1000000000ull; }
void* GetNativeHandle() override { return m_queue; }
void WaitForPreviousFrame() override {}
uint64_t GetCurrentFrame() const override { return m_currentFrame; }
VkQueue GetQueue() const { return m_queue; }
private:
VulkanDevice* m_device = nullptr;
VkQueue m_queue = VK_NULL_HANDLE;
CommandQueueType m_type = CommandQueueType::Direct;
uint64_t m_currentFrame = 0;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,85 @@
#pragma once
#ifndef VK_USE_PLATFORM_WIN32_KHR
#define VK_USE_PLATFORM_WIN32_KHR
#endif
#include <vulkan/vulkan.h>
#include "XCEngine/RHI/RHIEnums.h"
#include <string>
namespace XCEngine {
namespace RHI {
inline std::wstring WidenAscii(const char* value) {
if (value == nullptr) {
return {};
}
const std::string ascii(value);
return std::wstring(ascii.begin(), ascii.end());
}
inline VkFormat ToVulkanFormat(Format format) {
switch (format) {
case Format::R8G8B8A8_UNorm:
return VK_FORMAT_R8G8B8A8_UNORM;
case Format::D24_UNorm_S8_UInt:
return VK_FORMAT_D24_UNORM_S8_UINT;
case Format::D32_Float:
return VK_FORMAT_D32_SFLOAT;
case Format::R32_UInt:
return VK_FORMAT_R32_UINT;
case Format::R32G32_Float:
return VK_FORMAT_R32G32_SFLOAT;
case Format::R32G32B32A32_Float:
return VK_FORMAT_R32G32B32A32_SFLOAT;
default:
return VK_FORMAT_UNDEFINED;
}
}
inline Format ToRHIFormat(VkFormat format) {
switch (format) {
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_B8G8R8A8_UNORM:
return Format::R8G8B8A8_UNorm;
case VK_FORMAT_D24_UNORM_S8_UINT:
return Format::D24_UNorm_S8_UInt;
case VK_FORMAT_D32_SFLOAT:
return Format::D32_Float;
case VK_FORMAT_R32_UINT:
return Format::R32_UInt;
case VK_FORMAT_R32G32_SFLOAT:
return Format::R32G32_Float;
case VK_FORMAT_R32G32B32A32_SFLOAT:
return Format::R32G32B32A32_Float;
default:
return Format::Unknown;
}
}
inline VkImageAspectFlags GetImageAspectMask(Format format) {
switch (format) {
case Format::D24_UNorm_S8_UInt:
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
case Format::D32_Float:
case Format::D16_UNorm:
return VK_IMAGE_ASPECT_DEPTH_BIT;
default:
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
inline uint32_t ResolveVulkanApiMajor(uint32_t apiVersion) {
return VK_API_VERSION_MAJOR(apiVersion);
}
inline uint32_t ResolveVulkanApiMinor(uint32_t apiVersion) {
return VK_API_VERSION_MINOR(apiVersion);
}
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,74 @@
#pragma once
#include "XCEngine/RHI/RHIDevice.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
namespace XCEngine {
namespace RHI {
class VulkanCommandQueue;
class VulkanCommandList;
class VulkanDevice : public RHIDevice {
public:
VulkanDevice() = default;
~VulkanDevice() override;
bool Initialize(const RHIDeviceDesc& desc) override;
void Shutdown() override;
RHIBuffer* CreateBuffer(const BufferDesc& desc) override;
RHITexture* CreateTexture(const TextureDesc& desc) override;
RHITexture* CreateTexture(const TextureDesc& desc, const void* initialData, size_t initialDataSize, uint32_t rowPitch = 0) override;
RHISwapChain* CreateSwapChain(const SwapChainDesc& desc, RHICommandQueue* presentQueue) override;
RHICommandList* CreateCommandList(const CommandListDesc& desc) override;
RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override;
RHIShader* CreateShader(const ShaderCompileDesc& desc) override;
RHIPipelineState* CreatePipelineState(const GraphicsPipelineDesc& desc) override;
RHIPipelineLayout* CreatePipelineLayout(const RHIPipelineLayoutDesc& desc) override;
RHIFence* CreateFence(const FenceDesc& desc) override;
RHISampler* CreateSampler(const SamplerDesc& desc) override;
RHIRenderPass* CreateRenderPass(uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments, const AttachmentDesc* depthStencilAttachment) override;
RHIFramebuffer* CreateFramebuffer(class RHIRenderPass* renderPass, uint32_t width, uint32_t height, uint32_t colorAttachmentCount, RHIResourceView** colorAttachments, RHIResourceView* depthStencilAttachment) override;
RHIDescriptorPool* CreateDescriptorPool(const DescriptorPoolDesc& desc) override;
RHIDescriptorSet* CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) override;
RHIResourceView* CreateVertexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) override;
RHIResourceView* CreateIndexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) override;
RHIResourceView* CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) override;
RHIResourceView* CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) override;
RHIResourceView* CreateShaderResourceView(RHITexture* texture, const ResourceViewDesc& desc) override;
RHIResourceView* CreateUnorderedAccessView(RHITexture* texture, const ResourceViewDesc& desc) override;
const RHICapabilities& GetCapabilities() const override { return m_capabilities; }
const RHIDeviceInfo& GetDeviceInfo() const override { return m_deviceInfo; }
void* GetNativeDevice() override { return m_device; }
VkInstance GetInstance() const { return m_instance; }
VkPhysicalDevice GetPhysicalDevice() const { return m_physicalDevice; }
VkDevice GetDevice() const { return m_device; }
VkQueue GetGraphicsQueue() const { return m_graphicsQueue; }
uint32_t GetGraphicsQueueFamilyIndex() const { return m_graphicsQueueFamilyIndex; }
uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
private:
bool CreateInstance();
bool PickPhysicalDevice();
bool CreateLogicalDevice();
void QueryDeviceInfo();
RHIDeviceDesc m_deviceDesc = {};
VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
VkDevice m_device = VK_NULL_HANDLE;
VkQueue m_graphicsQueue = VK_NULL_HANDLE;
uint32_t m_graphicsQueueFamilyIndex = UINT32_MAX;
RHICapabilities m_capabilities = {};
RHIDeviceInfo m_deviceInfo = {};
bool m_initialized = false;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,25 @@
#pragma once
#include "XCEngine/RHI/RHIFence.h"
namespace XCEngine {
namespace RHI {
class VulkanFence : public RHIFence {
public:
explicit VulkanFence(uint64_t initialValue = 0)
: m_value(initialValue) {}
void Shutdown() override {}
void Signal() override { ++m_value; }
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; }
private:
uint64_t m_value = 0;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,38 @@
#pragma once
#include "XCEngine/RHI/RHIResourceView.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
#include "XCEngine/RHI/Vulkan/VulkanTexture.h"
namespace XCEngine {
namespace RHI {
class VulkanResourceView : public RHIResourceView {
public:
VulkanResourceView() = default;
~VulkanResourceView() override;
bool InitializeAsRenderTarget(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
void Shutdown() override;
void* GetNativeHandle() override { return m_imageView; }
bool IsValid() const override { return m_imageView != VK_NULL_HANDLE; }
ResourceViewType GetViewType() const override { return m_viewType; }
ResourceViewDimension GetDimension() const override { return m_dimension; }
Format GetFormat() const override { return m_format; }
VulkanTexture* GetTexture() const { return m_texture; }
VkImageView GetImageView() const { return m_imageView; }
private:
VkDevice m_device = VK_NULL_HANDLE;
VkImageView m_imageView = VK_NULL_HANDLE;
VulkanTexture* m_texture = nullptr;
ResourceViewType m_viewType = ResourceViewType::RenderTarget;
ResourceViewDimension m_dimension = ResourceViewDimension::Texture2D;
Format m_format = Format::Unknown;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,15 @@
#pragma once
#include "XCEngine/RHI/RHIScreenshot.h"
namespace XCEngine {
namespace RHI {
class VulkanScreenshot : public RHIScreenshot {
public:
bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) override;
void Shutdown() override {}
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,59 @@
#pragma once
#include "XCEngine/RHI/RHISwapChain.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
#include <memory>
#include <vector>
struct HWND__;
namespace XCEngine {
namespace RHI {
class VulkanDevice;
class VulkanCommandQueue;
class VulkanTexture;
class VulkanSwapChain : public RHISwapChain {
public:
VulkanSwapChain() = default;
~VulkanSwapChain() override;
bool Initialize(VulkanDevice* device, VulkanCommandQueue* presentQueue, HWND__* window, uint32_t width, uint32_t height);
bool AcquireNextImage();
void Shutdown() override;
uint32_t GetCurrentBackBufferIndex() const override { return m_currentImageIndex; }
RHITexture* GetCurrentBackBuffer() override;
void Present(uint32_t syncInterval = 1, uint32_t flags = 0) override;
void Resize(uint32_t width, uint32_t height) override;
void* GetNativeHandle() override { return m_swapChain; }
uint32_t GetWidth() const { return m_width; }
uint32_t GetHeight() const { return m_height; }
VkSwapchainKHR GetSwapChain() const { return m_swapChain; }
VkSurfaceKHR GetSurface() const { return m_surface; }
VkFormat GetVkFormat() const { return m_surfaceFormat; }
VulkanDevice* GetDevice() const { return m_device; }
private:
bool CreateSurface(HWND__* window);
bool CreateSwapChainResources();
void DestroySwapChainResources();
VulkanDevice* m_device = nullptr;
VulkanCommandQueue* m_presentQueue = nullptr;
HWND__* m_window = nullptr;
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSwapchainKHR m_swapChain = VK_NULL_HANDLE;
VkFormat m_surfaceFormat = VK_FORMAT_UNDEFINED;
uint32_t m_width = 0;
uint32_t m_height = 0;
uint32_t m_currentImageIndex = 0;
std::vector<std::unique_ptr<VulkanTexture>> m_backBuffers;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,57 @@
#pragma once
#include "XCEngine/RHI/RHITexture.h"
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
#include <string>
namespace XCEngine {
namespace RHI {
class VulkanTexture : public RHITexture {
public:
VulkanTexture() = default;
~VulkanTexture() override;
bool InitializeSwapChainImage(
VkDevice device,
VkImage image,
uint32_t width,
uint32_t height,
Format format,
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; }
Format GetFormat() const override { return m_format; }
TextureType GetTextureType() const override { return m_textureType; }
ResourceStates GetState() const override { return m_state; }
void SetState(ResourceStates state) override { m_state = state; }
void* GetNativeHandle() override { return m_image; }
const std::string& GetName() const override { return m_name; }
void SetName(const std::string& name) override { m_name = name; }
VkImage GetImage() const { return m_image; }
VkFormat GetVkFormat() const { return m_vkFormat; }
private:
VkDevice m_device = VK_NULL_HANDLE;
VkImage m_image = VK_NULL_HANDLE;
uint32_t m_width = 0;
uint32_t m_height = 0;
Format m_format = Format::Unknown;
TextureType m_textureType = TextureType::Texture2D;
ResourceStates m_state = ResourceStates::Common;
VkFormat m_vkFormat = VK_FORMAT_UNDEFINED;
std::string m_name;
};
} // namespace RHI
} // namespace XCEngine