Add Vulkan sphere integration support
This commit is contained in:
@@ -9,6 +9,7 @@ namespace XCEngine {
|
|||||||
namespace RHI {
|
namespace RHI {
|
||||||
|
|
||||||
class VulkanDescriptorSet;
|
class VulkanDescriptorSet;
|
||||||
|
class VulkanDevice;
|
||||||
|
|
||||||
class VulkanDescriptorPool : public RHIDescriptorPool {
|
class VulkanDescriptorPool : public RHIDescriptorPool {
|
||||||
public:
|
public:
|
||||||
@@ -29,8 +30,11 @@ public:
|
|||||||
|
|
||||||
VkDevice GetDevice() const { return m_device; }
|
VkDevice GetDevice() const { return m_device; }
|
||||||
VkDescriptorPool GetDescriptorPool() const { return m_descriptorPool; }
|
VkDescriptorPool GetDescriptorPool() const { return m_descriptorPool; }
|
||||||
|
VulkanDevice* GetDeviceOwner() const { return m_deviceOwner; }
|
||||||
|
void SetDeviceOwner(VulkanDevice* deviceOwner) { m_deviceOwner = deviceOwner; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
VulkanDevice* m_deviceOwner = nullptr;
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
|
VkDescriptorPool m_descriptorPool = VK_NULL_HANDLE;
|
||||||
DescriptorHeapType m_type = DescriptorHeapType::CBV_SRV_UAV;
|
DescriptorHeapType m_type = DescriptorHeapType::CBV_SRV_UAV;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "XCEngine/RHI/RHIDescriptorSet.h"
|
#include "XCEngine/RHI/RHIDescriptorSet.h"
|
||||||
|
#include "XCEngine/RHI/Vulkan/VulkanBuffer.h"
|
||||||
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
|
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -47,6 +49,12 @@ public:
|
|||||||
VkDescriptorSetLayout GetDescriptorSetLayout() const { return m_descriptorSetLayout; }
|
VkDescriptorSetLayout GetDescriptorSetLayout() const { return m_descriptorSetLayout; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct ConstantBindingRecord {
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
std::unique_ptr<VulkanBuffer> buffer;
|
||||||
|
size_t descriptorRange = 0;
|
||||||
|
};
|
||||||
|
|
||||||
const DescriptorSetLayoutBinding* FindBinding(uint32_t binding) const;
|
const DescriptorSetLayoutBinding* FindBinding(uint32_t binding) const;
|
||||||
|
|
||||||
VkDevice m_device = VK_NULL_HANDLE;
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
@@ -55,6 +63,7 @@ private:
|
|||||||
VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE;
|
VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE;
|
||||||
std::vector<DescriptorSetLayoutBinding> m_bindings;
|
std::vector<DescriptorSetLayoutBinding> m_bindings;
|
||||||
std::unordered_map<uint32_t, uint32_t> m_bindingToIndex;
|
std::unordered_map<uint32_t, uint32_t> m_bindingToIndex;
|
||||||
|
std::unordered_map<uint32_t, ConstantBindingRecord> m_constantBindings;
|
||||||
std::vector<uint8_t> m_constantBufferData;
|
std::vector<uint8_t> m_constantBufferData;
|
||||||
bool m_constantDirty = false;
|
bool m_constantDirty = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ public:
|
|||||||
VkPipeline GetPipeline() const { return m_pipeline; }
|
VkPipeline GetPipeline() const { return m_pipeline; }
|
||||||
VkPipelineLayout GetPipelineLayout() const { return m_pipelineLayout; }
|
VkPipelineLayout GetPipelineLayout() const { return m_pipelineLayout; }
|
||||||
VkRenderPass GetRenderPass() const { return m_renderPass; }
|
VkRenderPass GetRenderPass() const { return m_renderPass; }
|
||||||
|
bool HasDepthStencilAttachment() const {
|
||||||
|
return m_depthStencilFormat != 0 && static_cast<Format>(m_depthStencilFormat) != Format::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VulkanDevice* m_deviceOwner = nullptr;
|
VulkanDevice* m_deviceOwner = nullptr;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public:
|
|||||||
~VulkanResourceView() override;
|
~VulkanResourceView() override;
|
||||||
|
|
||||||
bool InitializeAsRenderTarget(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
|
bool InitializeAsRenderTarget(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
|
||||||
|
bool InitializeAsDepthStencil(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
|
||||||
bool InitializeAsShaderResource(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
|
bool InitializeAsShaderResource(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc);
|
||||||
bool InitializeAsVertexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc);
|
bool InitializeAsVertexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc);
|
||||||
bool InitializeAsIndexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc);
|
bool InitializeAsIndexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc);
|
||||||
|
|||||||
@@ -73,6 +73,18 @@ VkPipelineStageFlags ToVulkanStageMask(ResourceStates state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkImageAspectFlags ResolveClearAspectMask(Format format, uint32_t buffers) {
|
||||||
|
VkImageAspectFlags aspectMask = 0;
|
||||||
|
const VkImageAspectFlags formatAspectMask = GetImageAspectMask(format);
|
||||||
|
if ((buffers & 2) != 0) {
|
||||||
|
aspectMask |= formatAspectMask & VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
}
|
||||||
|
if ((buffers & 4) != 0) {
|
||||||
|
aspectMask |= formatAspectMask & VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
}
|
||||||
|
return aspectMask;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
VulkanCommandList::~VulkanCommandList() {
|
VulkanCommandList::~VulkanCommandList() {
|
||||||
@@ -398,40 +410,71 @@ void VulkanCommandList::DrawIndexed(uint32_t indexCount, uint32_t instanceCount,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandList::Clear(float r, float g, float b, float a, uint32_t buffers) {
|
void VulkanCommandList::Clear(float r, float g, float b, float a, uint32_t buffers) {
|
||||||
(void)buffers;
|
if ((buffers & 1) != 0) {
|
||||||
|
auto* colorView = static_cast<VulkanResourceView*>(m_currentColorTarget);
|
||||||
|
if (colorView != nullptr && colorView->GetTexture() != nullptr) {
|
||||||
|
EndActiveRenderPass();
|
||||||
|
|
||||||
auto* colorView = static_cast<VulkanResourceView*>(m_currentColorTarget);
|
VulkanTexture* texture = colorView->GetTexture();
|
||||||
if (colorView == nullptr || colorView->GetTexture() == nullptr) {
|
TransitionTexture(texture, ResourceStates::CopyDst);
|
||||||
return;
|
|
||||||
|
VkClearColorValue clearColor = {};
|
||||||
|
clearColor.float32[0] = r;
|
||||||
|
clearColor.float32[1] = g;
|
||||||
|
clearColor.float32[2] = b;
|
||||||
|
clearColor.float32[3] = a;
|
||||||
|
|
||||||
|
VkImageSubresourceRange range = {};
|
||||||
|
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
range.baseMipLevel = 0;
|
||||||
|
range.levelCount = 1;
|
||||||
|
range.baseArrayLayer = 0;
|
||||||
|
range.layerCount = 1;
|
||||||
|
|
||||||
|
vkCmdClearColorImage(
|
||||||
|
m_commandBuffer,
|
||||||
|
texture->GetImage(),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
&clearColor,
|
||||||
|
1,
|
||||||
|
&range);
|
||||||
|
|
||||||
|
TransitionTexture(texture, ResourceStates::RenderTarget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EndActiveRenderPass();
|
if ((buffers & (2 | 4)) != 0) {
|
||||||
|
auto* depthView = static_cast<VulkanResourceView*>(m_currentDepthTarget);
|
||||||
|
if (depthView != nullptr && depthView->GetTexture() != nullptr) {
|
||||||
|
EndActiveRenderPass();
|
||||||
|
|
||||||
VulkanTexture* texture = colorView->GetTexture();
|
VulkanTexture* texture = depthView->GetTexture();
|
||||||
TransitionTexture(texture, ResourceStates::CopyDst);
|
TransitionTexture(texture, ResourceStates::CopyDst);
|
||||||
|
|
||||||
VkClearColorValue clearColor = {};
|
VkImageSubresourceRange range = {};
|
||||||
clearColor.float32[0] = r;
|
range.aspectMask = ResolveClearAspectMask(texture->GetFormat(), buffers);
|
||||||
clearColor.float32[1] = g;
|
range.baseMipLevel = 0;
|
||||||
clearColor.float32[2] = b;
|
range.levelCount = 1;
|
||||||
clearColor.float32[3] = a;
|
range.baseArrayLayer = 0;
|
||||||
|
range.layerCount = 1;
|
||||||
|
|
||||||
VkImageSubresourceRange range = {};
|
if (range.aspectMask != 0) {
|
||||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
VkClearDepthStencilValue clearValue = {};
|
||||||
range.baseMipLevel = 0;
|
clearValue.depth = 1.0f;
|
||||||
range.levelCount = 1;
|
clearValue.stencil = 0;
|
||||||
range.baseArrayLayer = 0;
|
|
||||||
range.layerCount = 1;
|
|
||||||
|
|
||||||
vkCmdClearColorImage(
|
vkCmdClearDepthStencilImage(
|
||||||
m_commandBuffer,
|
m_commandBuffer,
|
||||||
texture->GetImage(),
|
texture->GetImage(),
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
&clearColor,
|
&clearValue,
|
||||||
1,
|
1,
|
||||||
&range);
|
&range);
|
||||||
|
}
|
||||||
|
|
||||||
TransitionTexture(texture, ResourceStates::RenderTarget);
|
TransitionTexture(texture, ResourceStates::DepthWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
|
void VulkanCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const float color[4]) {
|
||||||
@@ -440,9 +483,36 @@ void VulkanCommandList::ClearRenderTarget(RHIResourceView* renderTarget, const f
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
|
void VulkanCommandList::ClearDepthStencil(RHIResourceView* depthStencil, float depth, uint8_t stencil) {
|
||||||
(void)depthStencil;
|
auto* depthView = static_cast<VulkanResourceView*>(depthStencil != nullptr ? depthStencil : m_currentDepthTarget);
|
||||||
(void)depth;
|
if (depthView == nullptr || depthView->GetTexture() == nullptr) {
|
||||||
(void)stencil;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndActiveRenderPass();
|
||||||
|
|
||||||
|
VulkanTexture* texture = depthView->GetTexture();
|
||||||
|
TransitionTexture(texture, ResourceStates::CopyDst);
|
||||||
|
|
||||||
|
VkClearDepthStencilValue clearValue = {};
|
||||||
|
clearValue.depth = depth;
|
||||||
|
clearValue.stencil = stencil;
|
||||||
|
|
||||||
|
VkImageSubresourceRange range = {};
|
||||||
|
range.aspectMask = GetImageAspectMask(texture->GetFormat());
|
||||||
|
range.baseMipLevel = 0;
|
||||||
|
range.levelCount = 1;
|
||||||
|
range.baseArrayLayer = 0;
|
||||||
|
range.layerCount = 1;
|
||||||
|
|
||||||
|
vkCmdClearDepthStencilImage(
|
||||||
|
m_commandBuffer,
|
||||||
|
texture->GetImage(),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
&clearValue,
|
||||||
|
1,
|
||||||
|
&range);
|
||||||
|
|
||||||
|
TransitionTexture(texture, ResourceStates::DepthWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src) {
|
void VulkanCommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src) {
|
||||||
@@ -470,15 +540,28 @@ bool VulkanCommandList::EnsureGraphicsRenderPass() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* depthView = static_cast<VulkanResourceView*>(m_currentDepthTarget);
|
||||||
|
const bool expectsDepthAttachment = m_currentPipelineState->HasDepthStencilAttachment();
|
||||||
|
if (expectsDepthAttachment &&
|
||||||
|
(depthView == nullptr || depthView->GetTexture() == nullptr || depthView->GetImageView() == VK_NULL_HANDLE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
VulkanTexture* texture = colorView->GetTexture();
|
VulkanTexture* texture = colorView->GetTexture();
|
||||||
TransitionTexture(texture, ResourceStates::RenderTarget);
|
TransitionTexture(texture, ResourceStates::RenderTarget);
|
||||||
|
if (expectsDepthAttachment) {
|
||||||
|
TransitionTexture(depthView->GetTexture(), ResourceStates::DepthWrite);
|
||||||
|
}
|
||||||
|
|
||||||
VkFramebufferCreateInfo framebufferInfo = {};
|
VkFramebufferCreateInfo framebufferInfo = {};
|
||||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
framebufferInfo.renderPass = m_currentPipelineState->GetRenderPass();
|
framebufferInfo.renderPass = m_currentPipelineState->GetRenderPass();
|
||||||
framebufferInfo.attachmentCount = 1;
|
VkImageView attachments[2] = { colorView->GetImageView(), VK_NULL_HANDLE };
|
||||||
const VkImageView attachment = colorView->GetImageView();
|
framebufferInfo.attachmentCount = expectsDepthAttachment ? 2 : 1;
|
||||||
framebufferInfo.pAttachments = &attachment;
|
if (expectsDepthAttachment) {
|
||||||
|
attachments[1] = depthView->GetImageView();
|
||||||
|
}
|
||||||
|
framebufferInfo.pAttachments = attachments;
|
||||||
framebufferInfo.width = texture->GetWidth();
|
framebufferInfo.width = texture->GetWidth();
|
||||||
framebufferInfo.height = texture->GetHeight();
|
framebufferInfo.height = texture->GetHeight();
|
||||||
framebufferInfo.layers = 1;
|
framebufferInfo.layers = 1;
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ void VulkanDescriptorPool::Shutdown() {
|
|||||||
vkDestroyDescriptorPool(m_device, m_descriptorPool, nullptr);
|
vkDestroyDescriptorPool(m_device, m_descriptorPool, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_deviceOwner = nullptr;
|
||||||
m_descriptorPool = VK_NULL_HANDLE;
|
m_descriptorPool = VK_NULL_HANDLE;
|
||||||
m_device = VK_NULL_HANDLE;
|
m_device = VK_NULL_HANDLE;
|
||||||
m_type = DescriptorHeapType::CBV_SRV_UAV;
|
m_type = DescriptorHeapType::CBV_SRV_UAV;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "XCEngine/RHI/Vulkan/VulkanDescriptorSet.h"
|
#include "XCEngine/RHI/Vulkan/VulkanDescriptorSet.h"
|
||||||
|
|
||||||
|
#include "XCEngine/RHI/Vulkan/VulkanBuffer.h"
|
||||||
|
#include "XCEngine/RHI/Vulkan/VulkanDevice.h"
|
||||||
#include "XCEngine/RHI/Vulkan/VulkanDescriptorPool.h"
|
#include "XCEngine/RHI/Vulkan/VulkanDescriptorPool.h"
|
||||||
#include "XCEngine/RHI/Vulkan/VulkanResourceView.h"
|
#include "XCEngine/RHI/Vulkan/VulkanResourceView.h"
|
||||||
#include "XCEngine/RHI/Vulkan/VulkanSampler.h"
|
#include "XCEngine/RHI/Vulkan/VulkanSampler.h"
|
||||||
@@ -56,6 +58,7 @@ void VulkanDescriptorSet::Shutdown() {
|
|||||||
m_descriptorSet = VK_NULL_HANDLE;
|
m_descriptorSet = VK_NULL_HANDLE;
|
||||||
m_bindings.clear();
|
m_bindings.clear();
|
||||||
m_bindingToIndex.clear();
|
m_bindingToIndex.clear();
|
||||||
|
m_constantBindings.clear();
|
||||||
m_constantBufferData.clear();
|
m_constantBufferData.clear();
|
||||||
m_constantDirty = false;
|
m_constantDirty = false;
|
||||||
}
|
}
|
||||||
@@ -128,17 +131,72 @@ void VulkanDescriptorSet::UpdateSampler(uint32_t offset, RHISampler* sampler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDescriptorSet::WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset) {
|
void VulkanDescriptorSet::WriteConstant(uint32_t binding, const void* data, size_t size, size_t offset) {
|
||||||
(void)binding;
|
|
||||||
|
|
||||||
if (data == nullptr || size == 0) {
|
if (data == nullptr || size == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_constantBufferData.size() < offset + size) {
|
const DescriptorSetLayoutBinding* layoutBinding = FindBinding(binding);
|
||||||
m_constantBufferData.resize(offset + size);
|
if (layoutBinding == nullptr ||
|
||||||
|
static_cast<DescriptorType>(layoutBinding->type) != DescriptorType::CBV) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& constantBinding = m_constantBindings[binding];
|
||||||
|
const size_t requiredSize = offset + size;
|
||||||
|
if (constantBinding.data.size() < requiredSize) {
|
||||||
|
constantBinding.data.resize(requiredSize);
|
||||||
|
}
|
||||||
|
if (m_constantBufferData.size() < requiredSize) {
|
||||||
|
m_constantBufferData.resize(requiredSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(constantBinding.data.data() + offset, data, size);
|
||||||
std::memcpy(m_constantBufferData.data() + offset, data, size);
|
std::memcpy(m_constantBufferData.data() + offset, data, size);
|
||||||
|
|
||||||
|
VulkanDevice* deviceOwner = m_pool != nullptr ? m_pool->GetDeviceOwner() : nullptr;
|
||||||
|
if (deviceOwner != nullptr) {
|
||||||
|
const size_t bufferSize = constantBinding.data.size();
|
||||||
|
if (constantBinding.buffer == nullptr || constantBinding.buffer->GetSize() < bufferSize) {
|
||||||
|
if (constantBinding.buffer != nullptr) {
|
||||||
|
constantBinding.buffer->Shutdown();
|
||||||
|
constantBinding.buffer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferDesc bufferDesc = {};
|
||||||
|
bufferDesc.size = bufferSize;
|
||||||
|
bufferDesc.stride = static_cast<uint32_t>(bufferSize);
|
||||||
|
bufferDesc.bufferType = static_cast<uint32_t>(BufferType::Constant);
|
||||||
|
|
||||||
|
constantBinding.buffer = std::make_unique<VulkanBuffer>();
|
||||||
|
if (!constantBinding.buffer->Initialize(
|
||||||
|
deviceOwner,
|
||||||
|
bufferDesc,
|
||||||
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
|
||||||
|
constantBinding.buffer.reset();
|
||||||
|
m_constantDirty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constantBinding.buffer->SetData(constantBinding.data.data(), constantBinding.data.size(), 0);
|
||||||
|
constantBinding.descriptorRange = constantBinding.data.size();
|
||||||
|
|
||||||
|
VkDescriptorBufferInfo bufferInfo = {};
|
||||||
|
bufferInfo.buffer = constantBinding.buffer->GetBuffer();
|
||||||
|
bufferInfo.offset = 0;
|
||||||
|
bufferInfo.range = static_cast<VkDeviceSize>(constantBinding.descriptorRange);
|
||||||
|
|
||||||
|
VkWriteDescriptorSet write = {};
|
||||||
|
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
write.dstSet = m_descriptorSet;
|
||||||
|
write.dstBinding = binding;
|
||||||
|
write.descriptorCount = 1;
|
||||||
|
write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
write.pBufferInfo = &bufferInfo;
|
||||||
|
vkUpdateDescriptorSets(m_device, 1, &write, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
m_constantDirty = true;
|
m_constantDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -666,6 +666,7 @@ RHIFramebuffer* VulkanDevice::CreateFramebuffer(class RHIRenderPass* renderPass,
|
|||||||
|
|
||||||
RHIDescriptorPool* VulkanDevice::CreateDescriptorPool(const DescriptorPoolDesc& desc) {
|
RHIDescriptorPool* VulkanDevice::CreateDescriptorPool(const DescriptorPoolDesc& desc) {
|
||||||
auto* pool = new VulkanDescriptorPool();
|
auto* pool = new VulkanDescriptorPool();
|
||||||
|
pool->SetDeviceOwner(this);
|
||||||
if (pool->Initialize(m_device, desc)) {
|
if (pool->Initialize(m_device, desc)) {
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
@@ -708,8 +709,12 @@ RHIResourceView* VulkanDevice::CreateRenderTargetView(RHITexture* texture, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
RHIResourceView* VulkanDevice::CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) {
|
RHIResourceView* VulkanDevice::CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) {
|
||||||
(void)texture;
|
auto* view = new VulkanResourceView();
|
||||||
(void)desc;
|
if (view->InitializeAsDepthStencil(m_device, static_cast<VulkanTexture*>(texture), desc)) {
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete view;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ bool VulkanPipelineState::Initialize(VulkanDevice* device, const GraphicsPipelin
|
|||||||
m_ownsPipelineLayout = true;
|
m_ownsPipelineLayout = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<VkAttachmentDescription> attachments;
|
||||||
|
attachments.reserve(2);
|
||||||
|
|
||||||
VkAttachmentDescription colorAttachment = {};
|
VkAttachmentDescription colorAttachment = {};
|
||||||
colorAttachment.format = ToVulkanFormat(static_cast<Format>(m_renderTargetFormats[0]));
|
colorAttachment.format = ToVulkanFormat(static_cast<Format>(m_renderTargetFormats[0]));
|
||||||
colorAttachment.samples = ToVulkanSampleCount(m_sampleCount);
|
colorAttachment.samples = ToVulkanSampleCount(m_sampleCount);
|
||||||
@@ -154,20 +157,42 @@ bool VulkanPipelineState::Initialize(VulkanDevice* device, const GraphicsPipelin
|
|||||||
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
attachments.push_back(colorAttachment);
|
||||||
|
|
||||||
VkAttachmentReference colorAttachmentRef = {};
|
VkAttachmentReference colorAttachmentRef = {};
|
||||||
colorAttachmentRef.attachment = 0;
|
colorAttachmentRef.attachment = 0;
|
||||||
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
VkAttachmentReference depthAttachmentRef = {};
|
||||||
|
const bool hasDepthAttachment = HasDepthStencilAttachment();
|
||||||
|
if (hasDepthAttachment) {
|
||||||
|
VkAttachmentDescription depthAttachment = {};
|
||||||
|
depthAttachment.format = ToVulkanFormat(static_cast<Format>(m_depthStencilFormat));
|
||||||
|
depthAttachment.samples = ToVulkanSampleCount(m_sampleCount);
|
||||||
|
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
attachments.push_back(depthAttachment);
|
||||||
|
|
||||||
|
depthAttachmentRef.attachment = 1;
|
||||||
|
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
VkSubpassDescription subpass = {};
|
VkSubpassDescription subpass = {};
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
subpass.colorAttachmentCount = 1;
|
subpass.colorAttachmentCount = 1;
|
||||||
subpass.pColorAttachments = &colorAttachmentRef;
|
subpass.pColorAttachments = &colorAttachmentRef;
|
||||||
|
if (hasDepthAttachment) {
|
||||||
|
subpass.pDepthStencilAttachment = &depthAttachmentRef;
|
||||||
|
}
|
||||||
|
|
||||||
VkRenderPassCreateInfo renderPassInfo = {};
|
VkRenderPassCreateInfo renderPassInfo = {};
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
renderPassInfo.attachmentCount = 1;
|
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||||
renderPassInfo.pAttachments = &colorAttachment;
|
renderPassInfo.pAttachments = attachments.data();
|
||||||
renderPassInfo.subpassCount = 1;
|
renderPassInfo.subpassCount = 1;
|
||||||
renderPassInfo.pSubpasses = &subpass;
|
renderPassInfo.pSubpasses = &subpass;
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,31 @@ bool VulkanResourceView::InitializeAsRenderTarget(VkDevice device, VulkanTexture
|
|||||||
return vkCreateImageView(device, &viewInfo, nullptr, &m_imageView) == VK_SUCCESS;
|
return vkCreateImageView(device, &viewInfo, nullptr, &m_imageView) == VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VulkanResourceView::InitializeAsDepthStencil(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc) {
|
||||||
|
if (device == VK_NULL_HANDLE || texture == nullptr || texture->GetImage() == VK_NULL_HANDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device = device;
|
||||||
|
m_texture = texture;
|
||||||
|
m_viewType = ResourceViewType::DepthStencil;
|
||||||
|
m_dimension = desc.dimension != ResourceViewDimension::Unknown ? desc.dimension : ResourceViewDimension::Texture2D;
|
||||||
|
m_format = desc.format != 0 ? static_cast<Format>(desc.format) : texture->GetFormat();
|
||||||
|
|
||||||
|
VkImageViewCreateInfo viewInfo = {};
|
||||||
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
viewInfo.image = texture->GetImage();
|
||||||
|
viewInfo.viewType = ToVulkanImageViewType(m_dimension, texture->GetTextureType());
|
||||||
|
viewInfo.format = m_format != Format::Unknown ? ToVulkanFormat(m_format) : texture->GetVkFormat();
|
||||||
|
viewInfo.subresourceRange.aspectMask = GetImageAspectMask(m_format != Format::Unknown ? m_format : texture->GetFormat());
|
||||||
|
viewInfo.subresourceRange.baseMipLevel = desc.mipLevel;
|
||||||
|
viewInfo.subresourceRange.levelCount = 1;
|
||||||
|
viewInfo.subresourceRange.baseArrayLayer = desc.firstArraySlice;
|
||||||
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
return vkCreateImageView(device, &viewInfo, nullptr, &m_imageView) == VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
bool VulkanResourceView::InitializeAsShaderResource(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc) {
|
bool VulkanResourceView::InitializeAsShaderResource(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc) {
|
||||||
if (device == VK_NULL_HANDLE || texture == nullptr || texture->GetImage() == VK_NULL_HANDLE) {
|
if (device == VK_NULL_HANDLE || texture == nullptr || texture->GetImage() == VK_NULL_HANDLE) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -139,13 +139,35 @@ void RHIIntegrationFixture::SetUp() {
|
|||||||
mBackBufferViews.push_back(rtv);
|
mBackBufferViews.push_back(rtv);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDepthStencilTexture = new D3D12Texture();
|
auto* depthStencilTexture = new D3D12Texture();
|
||||||
ASSERT_NE(mDepthStencilTexture, nullptr);
|
ASSERT_NE(depthStencilTexture, nullptr);
|
||||||
ASSERT_TRUE(mDepthStencilTexture->InitializeDepthStencil(device, width, height));
|
ASSERT_TRUE(depthStencilTexture->InitializeDepthStencil(device, width, height));
|
||||||
|
mDepthStencilTexture = depthStencilTexture;
|
||||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = D3D12ResourceView::CreateDepthStencilDesc(Format::D24_UNorm_S8_UInt, D3D12_DSV_DIMENSION_TEXTURE2D);
|
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = D3D12ResourceView::CreateDepthStencilDesc(Format::D24_UNorm_S8_UInt, D3D12_DSV_DIMENSION_TEXTURE2D);
|
||||||
auto* d3d12DSV = new D3D12ResourceView();
|
auto* d3d12DSV = new D3D12ResourceView();
|
||||||
d3d12DSV->InitializeAsDepthStencil(device, mDepthStencilTexture->GetResource(), &dsvDesc, mDSVHeap, 0);
|
d3d12DSV->InitializeAsDepthStencil(device, depthStencilTexture->GetResource(), &dsvDesc, mDSVHeap, 0);
|
||||||
mDSV = d3d12DSV;
|
mDepthStencilView = d3d12DSV;
|
||||||
|
} else if (GetParam() == RHIType::Vulkan) {
|
||||||
|
TextureDesc depthDesc = {};
|
||||||
|
depthDesc.width = static_cast<uint32_t>(width);
|
||||||
|
depthDesc.height = static_cast<uint32_t>(height);
|
||||||
|
depthDesc.depth = 1;
|
||||||
|
depthDesc.mipLevels = 1;
|
||||||
|
depthDesc.arraySize = 1;
|
||||||
|
depthDesc.format = static_cast<uint32_t>(Format::D24_UNorm_S8_UInt);
|
||||||
|
depthDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||||
|
depthDesc.sampleCount = 1;
|
||||||
|
depthDesc.sampleQuality = 0;
|
||||||
|
depthDesc.flags = 0;
|
||||||
|
|
||||||
|
mDepthStencilTexture = mDevice->CreateTexture(depthDesc);
|
||||||
|
ASSERT_NE(mDepthStencilTexture, nullptr);
|
||||||
|
|
||||||
|
ResourceViewDesc depthViewDesc = {};
|
||||||
|
depthViewDesc.dimension = ResourceViewDimension::Texture2D;
|
||||||
|
depthViewDesc.format = static_cast<uint32_t>(Format::D24_UNorm_S8_UInt);
|
||||||
|
mDepthStencilView = mDevice->CreateDepthStencilView(mDepthStencilTexture, depthViewDesc);
|
||||||
|
ASSERT_NE(mDepthStencilView, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
mScreenshot = RHIScreenshot::Create(GetParam());
|
mScreenshot = RHIScreenshot::Create(GetParam());
|
||||||
@@ -179,7 +201,7 @@ void RHIIntegrationFixture::SetRenderTargetForClear(bool includeDepthStencil) {
|
|||||||
d3d12CmdList->TransitionBarrier(backBuffer->GetResource(), ResourceStates::Present, ResourceStates::RenderTarget);
|
d3d12CmdList->TransitionBarrier(backBuffer->GetResource(), ResourceStates::Present, ResourceStates::RenderTarget);
|
||||||
RHIResourceView* rtv = mBackBufferViews[mCurrentBackBufferIndex];
|
RHIResourceView* rtv = mBackBufferViews[mCurrentBackBufferIndex];
|
||||||
Log("[TEST] SetRenderTargetForClear: calling SetRenderTargets, rtv=%p", (void*)rtv);
|
Log("[TEST] SetRenderTargetForClear: calling SetRenderTargets, rtv=%p", (void*)rtv);
|
||||||
mCommandList->SetRenderTargets(1, &rtv, includeDepthStencil ? mDSV : nullptr);
|
mCommandList->SetRenderTargets(1, &rtv, includeDepthStencil ? mDepthStencilView : nullptr);
|
||||||
Log("[TEST] SetRenderTargetForClear: done");
|
Log("[TEST] SetRenderTargetForClear: done");
|
||||||
} else {
|
} else {
|
||||||
Log("[TEST] SetRenderTargetForClear: skipped - condition failed");
|
Log("[TEST] SetRenderTargetForClear: skipped - condition failed");
|
||||||
@@ -204,7 +226,7 @@ void RHIIntegrationFixture::SetRenderTargetForClear(bool includeDepthStencil) {
|
|||||||
|
|
||||||
ASSERT_NE(mBackBufferViews[backBufferIndex], nullptr);
|
ASSERT_NE(mBackBufferViews[backBufferIndex], nullptr);
|
||||||
RHIResourceView* rtv = mBackBufferViews[backBufferIndex];
|
RHIResourceView* rtv = mBackBufferViews[backBufferIndex];
|
||||||
mCommandList->SetRenderTargets(1, &rtv, nullptr);
|
mCommandList->SetRenderTargets(1, &rtv, includeDepthStencil ? mDepthStencilView : nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,19 +254,19 @@ void RHIIntegrationFixture::TearDown() {
|
|||||||
}
|
}
|
||||||
mBackBufferViews.clear();
|
mBackBufferViews.clear();
|
||||||
|
|
||||||
|
if (mDepthStencilView) {
|
||||||
|
mDepthStencilView->Shutdown();
|
||||||
|
delete mDepthStencilView;
|
||||||
|
mDepthStencilView = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDepthStencilTexture) {
|
||||||
|
mDepthStencilTexture->Shutdown();
|
||||||
|
delete mDepthStencilTexture;
|
||||||
|
mDepthStencilTexture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetParam() == RHIType::D3D12) {
|
if (GetParam() == RHIType::D3D12) {
|
||||||
if (mDSV) {
|
|
||||||
mDSV->Shutdown();
|
|
||||||
delete mDSV;
|
|
||||||
mDSV = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDepthStencilTexture) {
|
|
||||||
mDepthStencilTexture->Shutdown();
|
|
||||||
delete mDepthStencilTexture;
|
|
||||||
mDepthStencilTexture = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mRTVHeap) {
|
if (mRTVHeap) {
|
||||||
mRTVHeap->Shutdown();
|
mRTVHeap->Shutdown();
|
||||||
delete mRTVHeap;
|
delete mRTVHeap;
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
#include "XCEngine/RHI/RHICommandList.h"
|
#include "XCEngine/RHI/RHICommandList.h"
|
||||||
#include "XCEngine/RHI/RHISwapChain.h"
|
#include "XCEngine/RHI/RHISwapChain.h"
|
||||||
#include "XCEngine/RHI/RHIScreenshot.h"
|
#include "XCEngine/RHI/RHIScreenshot.h"
|
||||||
|
#include "XCEngine/RHI/RHIResourceView.h"
|
||||||
#include "XCEngine/RHI/RHIEnums.h"
|
#include "XCEngine/RHI/RHIEnums.h"
|
||||||
|
#include "XCEngine/RHI/RHITexture.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
||||||
#include "XCEngine/Debug/Logger.h"
|
#include "XCEngine/Debug/Logger.h"
|
||||||
#include "XCEngine/Debug/ConsoleLogSink.h"
|
#include "XCEngine/Debug/ConsoleLogSink.h"
|
||||||
@@ -68,12 +70,12 @@ private:
|
|||||||
HWND mWindow = nullptr;
|
HWND mWindow = nullptr;
|
||||||
int mCurrentBackBufferIndex = 0;
|
int mCurrentBackBufferIndex = 0;
|
||||||
std::vector<RHIResourceView*> mBackBufferViews;
|
std::vector<RHIResourceView*> mBackBufferViews;
|
||||||
|
RHITexture* mDepthStencilTexture = nullptr;
|
||||||
|
RHIResourceView* mDepthStencilView = nullptr;
|
||||||
|
|
||||||
#if defined(XCENGINE_SUPPORT_D3D12)
|
#if defined(XCENGINE_SUPPORT_D3D12)
|
||||||
D3D12DescriptorHeap* mRTVHeap = nullptr;
|
D3D12DescriptorHeap* mRTVHeap = nullptr;
|
||||||
D3D12DescriptorHeap* mDSVHeap = nullptr;
|
D3D12DescriptorHeap* mDSVHeap = nullptr;
|
||||||
D3D12Texture* mDepthStencilTexture = nullptr;
|
|
||||||
RHIResourceView* mDSV = nullptr;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ set(PACKAGE_DIR ${CMAKE_SOURCE_DIR}/tests/opengl/package)
|
|||||||
|
|
||||||
get_filename_component(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ABSOLUTE)
|
get_filename_component(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ABSOLUTE)
|
||||||
|
|
||||||
|
find_package(Vulkan QUIET)
|
||||||
|
|
||||||
add_executable(rhi_integration_sphere
|
add_executable(rhi_integration_sphere
|
||||||
main.cpp
|
main.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../fixtures/RHIIntegrationFixture.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/../fixtures/RHIIntegrationFixture.cpp
|
||||||
@@ -33,6 +35,60 @@ target_link_libraries(rhi_integration_sphere PRIVATE
|
|||||||
GTest::gtest
|
GTest::gtest
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(Vulkan_FOUND)
|
||||||
|
set(XCENGINE_GLSLANG_VALIDATOR_HINT "$ENV{VULKAN_SDK}")
|
||||||
|
find_program(
|
||||||
|
XCENGINE_GLSLANG_VALIDATOR
|
||||||
|
NAMES glslangValidator glslangValidator.exe
|
||||||
|
HINTS
|
||||||
|
"${XCENGINE_GLSLANG_VALIDATOR_HINT}/Bin"
|
||||||
|
"${Vulkan_ROOT}/Bin")
|
||||||
|
|
||||||
|
if(NOT XCENGINE_GLSLANG_VALIDATOR)
|
||||||
|
file(GLOB XCENGINE_VULKAN_BIN_DIRS "D:/VulkanSDK/*/Bin")
|
||||||
|
if(XCENGINE_VULKAN_BIN_DIRS)
|
||||||
|
list(SORT XCENGINE_VULKAN_BIN_DIRS COMPARE NATURAL ORDER DESCENDING)
|
||||||
|
foreach(XCENGINE_VULKAN_BIN_DIR IN LISTS XCENGINE_VULKAN_BIN_DIRS)
|
||||||
|
find_program(
|
||||||
|
XCENGINE_GLSLANG_VALIDATOR
|
||||||
|
NAMES glslangValidator glslangValidator.exe
|
||||||
|
PATHS "${XCENGINE_VULKAN_BIN_DIR}"
|
||||||
|
NO_DEFAULT_PATH)
|
||||||
|
if(XCENGINE_GLSLANG_VALIDATOR)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT XCENGINE_GLSLANG_VALIDATOR)
|
||||||
|
message(FATAL_ERROR "glslangValidator not found for Vulkan sphere shaders")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(SPHERE_VULKAN_VERTEX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Res/Shader/sphere_vulkan.vert)
|
||||||
|
set(SPHERE_VULKAN_FRAGMENT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Res/Shader/sphere_vulkan.frag)
|
||||||
|
|
||||||
|
add_custom_command(TARGET rhi_integration_sphere PRE_BUILD
|
||||||
|
COMMAND ${XCENGINE_GLSLANG_VALIDATOR}
|
||||||
|
-V
|
||||||
|
-S
|
||||||
|
vert
|
||||||
|
-o
|
||||||
|
$<TARGET_FILE_DIR:rhi_integration_sphere>/sphere_vulkan.vert.spv
|
||||||
|
${SPHERE_VULKAN_VERTEX_SOURCE}
|
||||||
|
COMMAND ${XCENGINE_GLSLANG_VALIDATOR}
|
||||||
|
-V
|
||||||
|
-S
|
||||||
|
frag
|
||||||
|
-o
|
||||||
|
$<TARGET_FILE_DIR:rhi_integration_sphere>/sphere_vulkan.frag.spv
|
||||||
|
${SPHERE_VULKAN_FRAGMENT_SOURCE}
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
target_link_libraries(rhi_integration_sphere PRIVATE Vulkan::Vulkan)
|
||||||
|
target_compile_definitions(rhi_integration_sphere PRIVATE XCENGINE_SUPPORT_VULKAN)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(rhi_integration_sphere PRIVATE
|
target_compile_definitions(rhi_integration_sphere PRIVATE
|
||||||
UNICODE
|
UNICODE
|
||||||
_UNICODE
|
_UNICODE
|
||||||
|
|||||||
11
tests/RHI/integration/sphere/Res/Shader/sphere_vulkan.frag
Normal file
11
tests/RHI/integration/sphere/Res/Shader/sphere_vulkan.frag
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(set = 2, binding = 0) uniform texture2D uTexture;
|
||||||
|
layout(set = 3, binding = 0) uniform sampler uSampler;
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 vTexCoord;
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragColor = texture(sampler2D(uTexture, uSampler), vTexCoord);
|
||||||
|
}
|
||||||
19
tests/RHI/integration/sphere/Res/Shader/sphere_vulkan.vert
Normal file
19
tests/RHI/integration/sphere/Res/Shader/sphere_vulkan.vert
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 aPosition;
|
||||||
|
layout(location = 1) in vec2 aTexCoord;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0, std140) uniform MatrixBuffer {
|
||||||
|
mat4 gProjectionMatrix;
|
||||||
|
mat4 gViewMatrix;
|
||||||
|
mat4 gModelMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 vTexCoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 positionWS = gModelMatrix * aPosition;
|
||||||
|
vec4 positionVS = gViewMatrix * positionWS;
|
||||||
|
gl_Position = gProjectionMatrix * positionVS;
|
||||||
|
vTexCoord = aTexCoord;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -61,6 +62,27 @@ std::filesystem::path ResolveRuntimePath(const char* relativePath) {
|
|||||||
return GetExecutableDirectory() / relativePath;
|
return GetExecutableDirectory() / relativePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> LoadBinaryFileRelative(const char* filename) {
|
||||||
|
const std::filesystem::path path = ResolveRuntimePath(filename);
|
||||||
|
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::streamsize size = file.tellg();
|
||||||
|
if (size <= 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> bytes(static_cast<size_t>(size));
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
if (!file.read(reinterpret_cast<char*>(bytes.data()), size)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
void GenerateSphere(std::vector<Vertex>& vertices, std::vector<uint32_t>& indices, float radius, int segments) {
|
void GenerateSphere(std::vector<Vertex>& vertices, std::vector<uint32_t>& indices, float radius, int segments) {
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
indices.clear();
|
indices.clear();
|
||||||
@@ -188,7 +210,16 @@ void main() {
|
|||||||
)";
|
)";
|
||||||
|
|
||||||
const char* GetScreenshotFilename(RHIType type) {
|
const char* GetScreenshotFilename(RHIType type) {
|
||||||
return type == RHIType::D3D12 ? "sphere_d3d12.ppm" : "sphere_opengl.ppm";
|
switch (type) {
|
||||||
|
case RHIType::D3D12:
|
||||||
|
return "sphere_d3d12.ppm";
|
||||||
|
case RHIType::OpenGL:
|
||||||
|
return "sphere_opengl.ppm";
|
||||||
|
case RHIType::Vulkan:
|
||||||
|
return "sphere_vulkan.ppm";
|
||||||
|
default:
|
||||||
|
return "sphere_unknown.ppm";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetComparisonThreshold(RHIType type) {
|
int GetComparisonThreshold(RHIType type) {
|
||||||
@@ -275,7 +306,7 @@ GraphicsPipelineDesc CreateSpherePipelineDesc(RHIType type, RHIPipelineLayout* p
|
|||||||
desc.fragmentShader.sourceLanguage = ShaderLanguage::HLSL;
|
desc.fragmentShader.sourceLanguage = ShaderLanguage::HLSL;
|
||||||
desc.fragmentShader.entryPoint = L"MainPS";
|
desc.fragmentShader.entryPoint = L"MainPS";
|
||||||
desc.fragmentShader.profile = L"ps_5_0";
|
desc.fragmentShader.profile = L"ps_5_0";
|
||||||
} else {
|
} else if (type == RHIType::OpenGL) {
|
||||||
desc.vertexShader.source.assign(kSphereVertexShader, kSphereVertexShader + strlen(kSphereVertexShader));
|
desc.vertexShader.source.assign(kSphereVertexShader, kSphereVertexShader + strlen(kSphereVertexShader));
|
||||||
desc.vertexShader.sourceLanguage = ShaderLanguage::GLSL;
|
desc.vertexShader.sourceLanguage = ShaderLanguage::GLSL;
|
||||||
desc.vertexShader.profile = L"vs_4_30";
|
desc.vertexShader.profile = L"vs_4_30";
|
||||||
@@ -283,6 +314,14 @@ GraphicsPipelineDesc CreateSpherePipelineDesc(RHIType type, RHIPipelineLayout* p
|
|||||||
desc.fragmentShader.source.assign(kSphereFragmentShader, kSphereFragmentShader + strlen(kSphereFragmentShader));
|
desc.fragmentShader.source.assign(kSphereFragmentShader, kSphereFragmentShader + strlen(kSphereFragmentShader));
|
||||||
desc.fragmentShader.sourceLanguage = ShaderLanguage::GLSL;
|
desc.fragmentShader.sourceLanguage = ShaderLanguage::GLSL;
|
||||||
desc.fragmentShader.profile = L"fs_4_30";
|
desc.fragmentShader.profile = L"fs_4_30";
|
||||||
|
} else if (type == RHIType::Vulkan) {
|
||||||
|
desc.vertexShader.source = LoadBinaryFileRelative("sphere_vulkan.vert.spv");
|
||||||
|
desc.vertexShader.sourceLanguage = ShaderLanguage::SPIRV;
|
||||||
|
desc.vertexShader.entryPoint = L"main";
|
||||||
|
|
||||||
|
desc.fragmentShader.source = LoadBinaryFileRelative("sphere_vulkan.frag.spv");
|
||||||
|
desc.fragmentShader.sourceLanguage = ShaderLanguage::SPIRV;
|
||||||
|
desc.fragmentShader.entryPoint = L"main";
|
||||||
}
|
}
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
@@ -657,6 +696,9 @@ TEST_P(SphereTest, RenderSphere) {
|
|||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(D3D12, SphereTest, ::testing::Values(RHIType::D3D12));
|
INSTANTIATE_TEST_SUITE_P(D3D12, SphereTest, ::testing::Values(RHIType::D3D12));
|
||||||
INSTANTIATE_TEST_SUITE_P(OpenGL, SphereTest, ::testing::Values(RHIType::OpenGL));
|
INSTANTIATE_TEST_SUITE_P(OpenGL, SphereTest, ::testing::Values(RHIType::OpenGL));
|
||||||
|
#if defined(XCENGINE_SUPPORT_VULKAN)
|
||||||
|
INSTANTIATE_TEST_SUITE_P(Vulkan, SphereTest, ::testing::Values(RHIType::Vulkan));
|
||||||
|
#endif
|
||||||
|
|
||||||
GTEST_API_ int main(int argc, char** argv) {
|
GTEST_API_ int main(int argc, char** argv) {
|
||||||
Logger::Get().Initialize();
|
Logger::Get().Initialize();
|
||||||
|
|||||||
Reference in New Issue
Block a user