summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-28 16:33:03 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-28 18:04:08 +0000
commit135d5dc6743fc89d7a19c539fa06eca33506f51b (patch)
tree9c8ed6e0d40a010f20657e62acbe955fba0757da /Graphics/GraphicsEngineVulkan
parentFixed vexing gcc/clang liker error (diff)
downloadDiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.tar.gz
DiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.zip
added ray tracing implementation for dx12 and vulkan
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp11
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp18
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp29
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp53
-rw-r--r--Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp15
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp67
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp31
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h3
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h11
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h6
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp10
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp14
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp35
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp309
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp20
-rw-r--r--Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp187
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp63
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp35
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp31
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp16
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp65
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp87
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp30
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp123
33 files changed, 901 insertions, 421 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp
index eb485370..e907337d 100644
--- a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp
@@ -50,10 +50,20 @@ public:
bool bIsDeviceInternal = false);
~BottomLevelASVkImpl();
+ /// Implementation of IBottomLevelAS::GetScratchBufferSizes() in Vulkan backend.
virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; }
+ /// Implementation of IBottomLevelAS::GetNativeHandle() in Vulkan backend.
+ virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final
+ {
+ auto Handle = GetVkBLAS();
+ return reinterpret_cast<void*>(Handle);
+ }
+
+ /// Implementation of IBottomLevelASVk::GetVkBLAS().
virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkBLAS() const override { return m_VulkanBLAS; }
+ /// Implementation of IBottomLevelASVk::GetVkDeviceAddress().
virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override { return m_DeviceAddress; }
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelASVk, TBottomLevelASBase);
@@ -62,6 +72,7 @@ private:
VkDeviceAddress m_DeviceAddress = 0;
VulkanUtilities::AccelStructWrapper m_VulkanBLAS;
VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation;
+ VkDeviceSize m_MemoryAlignedOffset = 0;
ScratchBufferSizes m_ScratchSize;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
index 98438da3..41a8cac3 100644
--- a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
@@ -137,17 +137,7 @@ public:
std::string PoolName,
std::vector<VkDescriptorPoolSize> PoolSizes,
uint32_t MaxSets,
- bool AllowFreeing) noexcept:
- m_DeviceVkImpl{DeviceVkImpl },
- m_PoolName {std::move(PoolName) },
- m_PoolSizes (std::move(PoolSizes)),
- m_MaxSets {MaxSets },
- m_AllowFreeing{AllowFreeing }
- {
-#ifdef DILIGENT_DEVELOPMENT
- m_AllocatedPoolCounter = 0;
-#endif
- }
+ bool AllowFreeing) noexcept;
~DescriptorPoolManager();
DescriptorPoolManager (const DescriptorPoolManager&) = delete;
@@ -175,9 +165,9 @@ protected:
RenderDeviceVkImpl& m_DeviceVkImpl;
const std::string m_PoolName;
- const std::vector<VkDescriptorPoolSize> m_PoolSizes;
- const uint32_t m_MaxSets;
- const bool m_AllowFreeing;
+ std::vector<VkDescriptorPoolSize> m_PoolSizes;
+ const uint32_t m_MaxSets;
+ const bool m_AllowFreeing;
std::mutex m_Mutex;
std::deque<VulkanUtilities::DescriptorPoolWrapper> m_Pools;
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
index 26142ba0..40e19d80 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
@@ -50,6 +50,9 @@
#include "HashUtils.hpp"
#include "ManagedVulkanObject.hpp"
#include "QueryManagerVk.hpp"
+#include "BottomLevelASVkImpl.hpp"
+#include "TopLevelASVkImpl.hpp"
+#include "ShaderBindingTableVkImpl.hpp"
namespace Diligent
@@ -65,6 +68,8 @@ struct DeviceContextVkImplTraits
using QueryType = QueryVkImpl;
using FramebufferType = FramebufferVkImpl;
using RenderPassType = RenderPassVkImpl;
+ using BottomLevelASType = BottomLevelASVkImpl;
+ using TopLevelASType = TopLevelASVkImpl;
};
/// Device context implementation in Vulkan backend.
@@ -294,6 +299,20 @@ public:
virtual void DILIGENT_CALL_TYPE BufferMemoryBarrier(IBuffer* pBuffer, VkAccessFlags NewAccessFlags) override final;
+ // Transitions BLAS state from OldState to NewState, and optionally updates internal state.
+ // If OldState == RESOURCE_STATE_UNKNOWN, internal BLAS state is used as old state.
+ void TransitionBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateInternalState);
+
+ // Transitions TLAS state from OldState to NewState, and optionally updates internal state.
+ // If OldState == RESOURCE_STATE_UNKNOWN, internal TLAS state is used as old state.
+ void TransitionTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateInternalState);
+
void AddWaitSemaphore(ManagedSemaphore* pWaitSemaphore, VkPipelineStageFlags WaitDstStageMask)
{
VERIFY_EXPR(pWaitSemaphore != nullptr);
@@ -386,6 +405,15 @@ private:
VkImageLayout ExpectedLayout,
const char* OperationName);
+ __forceinline void TransitionOrVerifyBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName);
+
+ __forceinline void TransitionOrVerifyTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName);
__forceinline void EnsureVkCmdBuffer()
{
@@ -438,6 +466,7 @@ private:
__forceinline void PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType);
__forceinline BufferVkImpl* PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode);
__forceinline void PrepareForDispatchCompute();
+ __forceinline void PrepareForRayTracing();
void DvpLogRenderPass_PSOMismatch();
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index 6abe5213..e13f1a76 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -178,16 +178,16 @@ public:
FramebufferCache& GetFramebufferCache() { return m_FramebufferCache; }
RenderPassCache& GetImplicitRenderPassCache() { return m_ImplicitRenderPassCache; }
- VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties)
+ VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties, VkMemoryAllocateFlags AllocateFlags = 0)
{
- return m_MemoryMgr.Allocate(MemReqs, MemoryProperties);
+ return m_MemoryMgr.Allocate(MemReqs, MemoryProperties, AllocateFlags);
}
- VulkanUtilities::VulkanMemoryAllocation AllocateMemory(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex)
+ VulkanUtilities::VulkanMemoryAllocation AllocateMemory(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, VkMemoryAllocateFlags AllocateFlags = 0)
{
const auto& MemoryProps = m_PhysicalDevice->GetMemoryProperties();
VERIFY_EXPR(MemoryTypeIndex < MemoryProps.memoryTypeCount);
const auto MemoryFlags = MemoryProps.memoryTypes[MemoryTypeIndex].propertyFlags;
- return m_MemoryMgr.Allocate(Size, Alignment, MemoryTypeIndex, (MemoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0);
+ return m_MemoryMgr.Allocate(Size, Alignment, MemoryTypeIndex, (MemoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0, AllocateFlags);
}
VulkanUtilities::VulkanMemoryManager& GetGlobalMemoryManager() { return m_MemoryMgr; }
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
index 92d83160..1b2db950 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp
@@ -30,20 +30,20 @@
/// \file
/// Definition of the Diligent::ShaderBindingTableVkImpl class
-#include "BufferVkImpl.hpp"
#include "RenderDeviceVk.h"
#include "RenderDeviceVkImpl.hpp"
#include "ShaderBindingTableVk.h"
#include "ShaderBindingTableBase.hpp"
+#include "PipelineStateVkImpl.hpp"
#include "VulkanUtilities/VulkanObjectWrappers.hpp"
namespace Diligent
{
-class ShaderBindingTableVkImpl final : public ShaderBindingTableBase<IShaderBindingTableVk, RenderDeviceVkImpl>
+class ShaderBindingTableVkImpl final : public ShaderBindingTableBase<IShaderBindingTableVk, PipelineStateVkImpl, RenderDeviceVkImpl>
{
public:
- using TShaderBindingTableBase = ShaderBindingTableBase<IShaderBindingTableVk, RenderDeviceVkImpl>;
+ using TShaderBindingTableBase = ShaderBindingTableBase<IShaderBindingTableVk, PipelineStateVkImpl, RenderDeviceVkImpl>;
ShaderBindingTableVkImpl(IReferenceCounters* pRefCounters,
RenderDeviceVkImpl* pRenderDeviceVk,
@@ -56,37 +56,14 @@ public:
virtual void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override;
virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override;
-
- virtual void DILIGENT_CALL_TYPE BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindHitGroup(ITopLevelAS* pTLAS,
- const char* InstanceName,
- const char* GeometryName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindHitGroups(ITopLevelAS* pTLAS,
- const char* InstanceName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize) override;
-
- virtual void DILIGENT_CALL_TYPE BindCallableShader(Uint32 Index,
- const char* ShaderName,
- const void* Data,
- Uint32 DataSize) override;
-
virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override;
- virtual void DILIGENT_CALL_TYPE GetVkStridedBufferRegions(VkStridedBufferRegionKHR& RaygenShaderBindingTable,
- VkStridedBufferRegionKHR& MissShaderBindingTable,
- VkStridedBufferRegionKHR& HitShaderBindingTable,
- VkStridedBufferRegionKHR& CallableShaderBindingTable) override;
+ virtual void DILIGENT_CALL_TYPE GetVkStridedBufferRegions(IDeviceContextVk* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ VkStridedBufferRegionKHR& RaygenShaderBindingTable,
+ VkStridedBufferRegionKHR& MissShaderBindingTable,
+ VkStridedBufferRegionKHR& HitShaderBindingTable,
+ VkStridedBufferRegionKHR& CallableShaderBindingTable) override;
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTableVk, TShaderBindingTableBase);
@@ -94,17 +71,7 @@ private:
void ValidateDesc(const ShaderBindingTableDesc& Desc) const;
private:
- RefCntAutoPtr<BufferVkImpl> m_pBuffer;
- std::vector<Uint32> m_ShaderRecords;
-
- Uint32 m_MissShadersOffset = 0;
- Uint32 m_HitGroupsOffset = 0;
- Uint32 m_CallbaleShadersOffset = 0;
- Uint32 m_MissShaderCount = 0;
- Uint32 m_HitGroupCount = 0;
- Uint32 m_CallableShaderCount = 0;
- Uint32 m_ShaderGroupHandleSize = 0;
- Uint32 m_ShaderGroupBaseAlignment = 0;
+ RefCntAutoPtr<IBuffer> m_pBuffer;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
index 11c1ebef..b2801eca 100644
--- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp
@@ -50,18 +50,27 @@ public:
bool bIsDeviceInternal = false);
~TopLevelASVkImpl();
+ /// Implementation of ITopLevelAS::GetScratchBufferSizes() in Vulkan backend.
virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; }
- virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkTLAS() const override { return m_VulkanTLAS; }
+ /// Implementation of ITopLevelAS::GetNativeHandle() in Vulkan backend.
+ virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final
+ {
+ auto Handle = GetVkTLAS();
+ return reinterpret_cast<void*>(Handle);
+ }
- virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override { return m_DeviceAddress; }
+ /// Implementation of ITopLevelASVk::GetVkTLAS().
+ virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkTLAS() const override { return m_VulkanTLAS; }
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelASVk, TTopLevelASBase);
+ const VkAccelerationStructureKHR* GetVkTLASPtr() const { return &m_VulkanTLAS; }
+
private:
- VkDeviceAddress m_DeviceAddress = 0;
VulkanUtilities::AccelStructWrapper m_VulkanTLAS;
VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation;
+ VkDeviceSize m_MemoryAlignedOffset = 0;
ScratchBufferSizes m_ScratchSize;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
index e88c93d2..8f90a914 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
@@ -65,8 +65,9 @@ VkSamplerMipmapMode FilterTypeToVkMipmapMode(FILTER_TYPE FilterType);
VkSamplerAddressMode AddressModeToVkAddressMode(TEXTURE_ADDRESS_MODE AddressMode);
VkBorderColor BorderColorToVkBorderColor(const Float32 BorderColor[]);
-VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags);
-VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsideRenderPass = false);
+VkPipelineStageFlags ResourceStateFlagsToVkPipelineStageFlags(RESOURCE_STATE StateFlags, VkPipelineStageFlags ShaderStages);
+VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags);
+VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsideRenderPass = false);
RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags);
RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout);
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
index 0cd6de63..50a4c99f 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
@@ -36,8 +36,8 @@ namespace VulkanUtilities
class VulkanCommandBuffer
{
public:
- VulkanCommandBuffer(VkPipelineStageFlags EnabledGraphicsShaderStages) noexcept :
- m_EnabledGraphicsShaderStages{EnabledGraphicsShaderStages}
+ VulkanCommandBuffer(VkPipelineStageFlags EnabledShaderStages) noexcept :
+ m_EnabledShaderStages{EnabledShaderStages}
{}
// clang-format off
@@ -280,6 +280,17 @@ public:
}
}
+ __forceinline void BindRayTracingPipeline(VkPipeline RayTracingPipeline)
+ {
+ // 9.8
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RayTracingPipeline != RayTracingPipeline)
+ {
+ vkCmdBindPipeline(m_VkCmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, RayTracingPipeline);
+ m_State.RayTracingPipeline = RayTracingPipeline;
+ }
+ }
+
__forceinline void SetViewports(uint32_t FirstViewport, uint32_t ViewportCount, const VkViewport* pViewports)
{
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
@@ -331,7 +342,7 @@ public:
VkImageLayout OldLayout,
VkImageLayout NewLayout,
const VkImageSubresourceRange& SubresRange,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages = 0,
VkPipelineStageFlags DestStages = 0);
@@ -349,7 +360,7 @@ public:
// dependencies between attachments
EndRenderPass();
}
- TransitionImageLayout(m_VkCmdBuffer, Image, OldLayout, NewLayout, SubresRange, m_EnabledGraphicsShaderStages, SrcStages, DestStages);
+ TransitionImageLayout(m_VkCmdBuffer, Image, OldLayout, NewLayout, SubresRange, m_EnabledShaderStages, SrcStages, DestStages);
}
@@ -357,7 +368,7 @@ public:
VkBuffer Buffer,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages = 0,
VkPipelineStageFlags DestStages = 0);
@@ -374,7 +385,31 @@ public:
// dependencies between attachments
EndRenderPass();
}
- BufferMemoryBarrier(m_VkCmdBuffer, Buffer, srcAccessMask, dstAccessMask, m_EnabledGraphicsShaderStages, SrcStages, DestStages);
+ BufferMemoryBarrier(m_VkCmdBuffer, Buffer, srcAccessMask, dstAccessMask, m_EnabledShaderStages, SrcStages, DestStages);
+ }
+
+
+ // for Acceleration structures
+ static void ASMemoryBarrier(VkCommandBuffer CmdBuffer,
+ VkAccessFlags srcAccessMask,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags EnabledShaderStages,
+ VkPipelineStageFlags SrcStages = 0,
+ VkPipelineStageFlags DestStages = 0);
+
+ __forceinline void ASMemoryBarrier(VkAccessFlags srcAccessMask,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags SrcStages = 0,
+ VkPipelineStageFlags DestStages = 0)
+ {
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RenderPass != VK_NULL_HANDLE)
+ {
+ // Image layout transitions within a render pass execute
+ // dependencies between attachments
+ EndRenderPass();
+ }
+ ASMemoryBarrier(m_VkCmdBuffer, srcAccessMask, dstAccessMask, m_EnabledShaderStages, SrcStages, DestStages);
}
__forceinline void BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
@@ -575,6 +610,12 @@ public:
const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos)
{
#if DILIGENT_USE_VOLK
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RenderPass != VK_NULL_HANDLE)
+ {
+ // Build AS operations must be performed outside of render pass.
+ EndRenderPass();
+ }
vkCmdBuildAccelerationStructureKHR(m_VkCmdBuffer, infoCount, pInfos, ppOffsetInfos);
#else
UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically");
@@ -584,6 +625,12 @@ public:
__forceinline void CopyAccelerationStructure(const VkCopyAccelerationStructureInfoKHR& Info)
{
#if DILIGENT_USE_VOLK
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RenderPass != VK_NULL_HANDLE)
+ {
+ // Copy AS operations must be performed outside of render pass.
+ EndRenderPass();
+ }
vkCmdCopyAccelerationStructureKHR(m_VkCmdBuffer, &Info);
#else
UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically");
@@ -599,6 +646,9 @@ public:
uint32_t depth)
{
#if DILIGENT_USE_VOLK
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ VERIFY(m_State.RayTracingPipeline != VK_NULL_HANDLE, "No ray tracing pipeline bound");
+
vkCmdTraceRaysKHR(m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, width, height, depth);
#else
UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically");
@@ -613,12 +663,15 @@ public:
}
VkCommandBuffer GetVkCmdBuffer() const { return m_VkCmdBuffer; }
+ VkPipelineStageFlags GetEnabledShaderStages() const { return m_EnabledShaderStages; }
+
struct StateCache
{
VkRenderPass RenderPass = VK_NULL_HANDLE;
VkFramebuffer Framebuffer = VK_NULL_HANDLE;
VkPipeline GraphicsPipeline = VK_NULL_HANDLE;
VkPipeline ComputePipeline = VK_NULL_HANDLE;
+ VkPipeline RayTracingPipeline = VK_NULL_HANDLE;
VkBuffer IndexBuffer = VK_NULL_HANDLE;
VkDeviceSize IndexBufferOffset = 0;
VkIndexType IndexType = VK_INDEX_TYPE_MAX_ENUM;
@@ -633,7 +686,7 @@ public:
private:
StateCache m_State;
VkCommandBuffer m_VkCmdBuffer = VK_NULL_HANDLE;
- const VkPipelineStageFlags m_EnabledGraphicsShaderStages;
+ const VkPipelineStageFlags m_EnabledShaderStages;
};
} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
index 5e60a343..f68d7138 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
@@ -219,8 +219,9 @@ public:
dataSize, pData, stride, flags);
}
- VkPipelineStageFlags GetEnabledGraphicsShaderStages() const { return m_EnabledGraphicsShaderStages; }
- VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const;
+ VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const;
+
+ VkPipelineStageFlags GetEnabledShaderStages() const { return m_EnabledShaderStages; }
const VkPhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; }
const ExtensionFeatures& GetEnabledExtFeatures() const { return m_EnabledExtFeatures; }
@@ -242,7 +243,7 @@ private:
VkDevice m_VkDevice = VK_NULL_HANDLE;
const VkAllocationCallbacks* const m_VkAllocator;
- VkPipelineStageFlags m_EnabledGraphicsShaderStages = 0;
+ VkPipelineStageFlags m_EnabledShaderStages = 0;
const VkPhysicalDeviceFeatures m_EnabledFeatures;
ExtensionFeatures m_EnabledExtFeatures = {};
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp
index 4ada51be..4d9eaa7f 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.hpp
@@ -95,10 +95,11 @@ struct VulkanMemoryAllocation
class VulkanMemoryPage
{
public:
- VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
- VkDeviceSize PageSize,
- uint32_t MemoryTypeIndex,
- bool IsHostVisible) noexcept;
+ VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
+ VkDeviceSize PageSize,
+ uint32_t MemoryTypeIndex,
+ bool IsHostVisible,
+ VkMemoryAllocateFlags AllocateFlags) noexcept;
~VulkanMemoryPage();
// clang-format off
@@ -198,8 +199,8 @@ public:
VulkanMemoryManager& operator= (VulkanMemoryManager&&) = delete;
// clang-format on
- VulkanMemoryAllocation Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible);
- VulkanMemoryAllocation Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps);
+ VulkanMemoryAllocation Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible, VkMemoryAllocateFlags AllocateFlags);
+ VulkanMemoryAllocation Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps, VkMemoryAllocateFlags AllocateFlags);
void ShrinkMemory();
protected:
@@ -218,19 +219,23 @@ protected:
std::mutex m_PagesMtx;
struct MemoryPageIndex
{
- const uint32_t MemoryTypeIndex;
- const bool IsHostVisible;
+ const uint32_t MemoryTypeIndex;
+ const VkMemoryAllocateFlags AllocateFlags;
+ const bool IsHostVisible;
// clang-format off
- MemoryPageIndex(uint32_t _MemoryTypeIndex,
- bool _IsHostVisible) :
- MemoryTypeIndex(_MemoryTypeIndex),
- IsHostVisible (_IsHostVisible)
+ MemoryPageIndex(uint32_t _MemoryTypeIndex,
+ bool _IsHostVisible,
+ VkMemoryAllocateFlags _AllocateFlags) :
+ MemoryTypeIndex{_MemoryTypeIndex},
+ AllocateFlags {_AllocateFlags},
+ IsHostVisible {_IsHostVisible}
{}
bool operator == (const MemoryPageIndex& rhs)const
{
return MemoryTypeIndex == rhs.MemoryTypeIndex &&
+ AllocateFlags == rhs.AllocateFlags &&
IsHostVisible == rhs.IsHostVisible;
}
// clang-format on
@@ -239,7 +244,7 @@ protected:
{
size_t operator()(const MemoryPageIndex& PageIndex) const
{
- return Diligent::ComputeHash(PageIndex.MemoryTypeIndex, PageIndex.IsHostVisible);
+ return Diligent::ComputeHash(PageIndex.MemoryTypeIndex, PageIndex.AllocateFlags, PageIndex.IsHostVisible);
}
};
};
diff --git a/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h
index 345b0f3b..ea785a51 100644
--- a/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h
@@ -61,7 +61,8 @@ DILIGENT_END_INTERFACE
#if DILIGENT_C_INTERFACE
-# define IBottomLevelASVk_GetVkBLAS(This) CALL_IFACE_METHOD(BottomLevelASVk, GetVkBLAS, This)
+# define IBottomLevelASVk_GetVkBLAS(This) CALL_IFACE_METHOD(BottomLevelASVk, GetVkBLAS, This)
+# define IBottomLevelASVk_GetVkDeviceAddress(This) CALL_IFACE_METHOD(BottomLevelASVk, GetVkDeviceAddress, This)
#endif
diff --git a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h
index 76e0eadd..d879faac 100644
--- a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h
@@ -31,6 +31,7 @@
/// Definition of the Diligent::IShaderBindingTableVk interface
#include "../../GraphicsEngine/interface/ShaderBindingTable.h"
+#include "DeviceContextVk.h"
DILIGENT_BEGIN_NAMESPACE(Diligent)
@@ -51,10 +52,12 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable)
{
/// AZ TODO
VIRTUAL void METHOD(GetVkStridedBufferRegions)(THIS_
- VkStridedBufferRegionKHR REF RaygenShaderBindingTable,
- VkStridedBufferRegionKHR REF MissShaderBindingTable,
- VkStridedBufferRegionKHR REF HitShaderBindingTable,
- VkStridedBufferRegionKHR REF CallableShaderBindingTable) PURE;
+ IDeviceContextVk* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ VkStridedBufferRegionKHR REF RaygenShaderBindingTable,
+ VkStridedBufferRegionKHR REF MissShaderBindingTable,
+ VkStridedBufferRegionKHR REF HitShaderBindingTable,
+ VkStridedBufferRegionKHR REF CallableShaderBindingTable) PURE;
};
DILIGENT_END_INTERFACE
// clang-format on
diff --git a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h
index c09f10c0..161de182 100644
--- a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h
@@ -50,9 +50,6 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelASVk, ITopLevelAS)
{
/// Returns a Vulkan TLAS object handle.
VIRTUAL VkAccelerationStructureKHR METHOD(GetVkTLAS)(THIS) CONST PURE;
-
- /// Returns a Vulkan TLAS device address.
- VIRTUAL VkDeviceAddress METHOD(GetVkDeviceAddress)(THIS) CONST PURE;
};
DILIGENT_END_INTERFACE
@@ -60,8 +57,7 @@ DILIGENT_END_INTERFACE
#if DILIGENT_C_INTERFACE
-# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This)
-# define ITopLevelASVk_GetVkDeviceAddress(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkDeviceAddress, This)
+# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This)
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp
index 6e0bcbb8..a1172130 100644
--- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp
@@ -60,7 +60,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters,
if (m_Desc.pTriangles != nullptr)
{
Uint32 MaxPrimitiveCount = 0;
- for (uint32_t i = 0; i < CreateInfo.maxGeometryCount; ++i)
+ for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i)
{
auto& src = m_Desc.pTriangles[i];
auto& dst = Geometries[i];
@@ -81,7 +81,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters,
else if (m_Desc.pBoxes != nullptr)
{
Uint32 MaxBoxCount = 0;
- for (uint32_t i = 0; i < CreateInfo.maxGeometryCount; ++i)
+ for (uint32_t i = 0; i < m_Desc.BoxCount; ++i)
{
auto& src = m_Desc.pBoxes[i];
auto& dst = Geometries[i];
@@ -122,10 +122,12 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Failed to find suitable memory type for BLAS '", m_Desc.Name, '\'');
VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
+ VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (m_MemoryAlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
auto Memory = m_MemoryAllocation.Page->GetVkMemory();
- auto err = LogicalDevice.BindASMemory(m_VulkanBLAS, Memory, 0);
+ auto err = LogicalDevice.BindASMemory(m_VulkanBLAS, Memory, m_MemoryAlignedOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory");
m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanBLAS);
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index 6b29af25..ef6685a3 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -87,7 +87,7 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | // The buffer can be used as the source of a transfer command
VK_BUFFER_USAGE_TRANSFER_DST_BIT; // The buffer can be used as the destination of a transfer command
- static_assert(BIND_FLAGS_LAST == 0x400, "AZ TODO");
+ static_assert(BIND_FLAGS_LAST == 0x400, "Please update this function to handle the new bind flags");
for (Uint32 BindFlag = 1; BindFlag <= m_Desc.BindFlags; BindFlag <<= 1)
{
@@ -245,11 +245,15 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, vkMemoryFlags);
}
+ VkMemoryAllocateFlags AllocateFlags = 0;
+ if (VkBuffCI.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
+ AllocateFlags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
+
if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex)
LOG_ERROR_AND_THROW("Failed to find suitable memory type for buffer '", m_Desc.Name, '\'');
VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, AllocateFlags);
m_BufferMemoryAlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (m_BufferMemoryAlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
@@ -317,12 +321,12 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
VkCommandBuffer vkCmdBuff;
pRenderDeviceVk->AllocateTransientCmdPool(CmdPool, vkCmdBuff, "Transient command pool to copy staging data to a device buffer");
- auto EnabledGraphicsShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
- VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledGraphicsShaderStages);
+ auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
+ VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledShaderStages);
InitialState = RESOURCE_STATE_COPY_DEST;
VkAccessFlags AccessFlags = ResourceStateFlagsToVkAccessFlags(InitialState);
VERIFY_EXPR(AccessFlags == VK_ACCESS_TRANSFER_WRITE_BIT);
- VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, m_VulkanBuffer, 0, AccessFlags, EnabledGraphicsShaderStages);
+ VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, m_VulkanBuffer, 0, AccessFlags, EnabledShaderStages);
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
// as copy will be the only command in the cmd buffer
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
index e7fbc9bd..6d0e1ab2 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
@@ -53,14 +53,17 @@ VulkanUtilities::CommandPoolWrapper CommandPoolManager::AllocateCommandPool(cons
{
std::lock_guard<std::mutex> LockGuard{m_Mutex};
+ auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice();
+
VulkanUtilities::CommandPoolWrapper CmdPool;
if (!m_CmdPools.empty())
{
CmdPool = std::move(m_CmdPools.front());
m_CmdPools.pop_front();
+
+ LogicalDevice.ResetCommandPool(CmdPool);
}
- auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice();
if (CmdPool == VK_NULL_HANDLE)
{
VkCommandPoolCreateInfo CmdPoolCI = {};
@@ -74,8 +77,6 @@ VulkanUtilities::CommandPoolWrapper CommandPoolManager::AllocateCommandPool(cons
DEV_CHECK_ERR(CmdPool != VK_NULL_HANDLE, "Failed to create Vulkan command pool");
}
- LogicalDevice.ResetCommandPool(CmdPool);
-
#ifdef DILIGENT_DEVELOPMENT
++m_AllocatedPoolCounter;
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
index 412ddd7b..6557ac6d 100644
--- a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
@@ -59,6 +59,41 @@ VulkanUtilities::DescriptorPoolWrapper DescriptorPoolManager::CreateDescriptorPo
return m_DeviceVkImpl.GetLogicalDevice().CreateDescriptorPool(PoolCI, DebugName);
}
+DescriptorPoolManager::DescriptorPoolManager(RenderDeviceVkImpl& DeviceVkImpl,
+ std::string PoolName,
+ std::vector<VkDescriptorPoolSize> PoolSizes,
+ uint32_t MaxSets,
+ bool AllowFreeing) noexcept :
+ // clang-format off
+ m_DeviceVkImpl{DeviceVkImpl },
+ m_PoolName {std::move(PoolName) },
+ m_PoolSizes (std::move(PoolSizes)),
+ m_MaxSets {MaxSets },
+ m_AllowFreeing{AllowFreeing }
+// clang-format on
+{
+ const auto& Feats = m_DeviceVkImpl.GetLogicalDevice().GetEnabledExtFeatures();
+
+ for (auto iter = m_PoolSizes.begin(); iter != m_PoolSizes.end();)
+ {
+ switch (iter->type)
+ {
+ case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
+ if (Feats.RayTracing.rayTracing == VK_FALSE)
+ iter = m_PoolSizes.erase(iter);
+ else
+ ++iter;
+ break;
+ default:
+ ++iter;
+ }
+ }
+
+#ifdef DILIGENT_DEVELOPMENT
+ m_AllocatedPoolCounter = 0;
+#endif
+}
+
DescriptorPoolManager::~DescriptorPoolManager()
{
DEV_CHECK_ERR(m_AllocatedPoolCounter == 0, "Not all allocated descriptor pools are returned to the pool manager");
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 42f69dac..554352ad 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -36,9 +36,6 @@
#include "VulkanTypeConversions.hpp"
#include "CommandListVkImpl.hpp"
#include "FenceVkImpl.hpp"
-#include "BottomLevelASVkImpl.hpp"
-#include "TopLevelASVkImpl.hpp"
-#include "ShaderBindingTableVkImpl.hpp"
#include "GraphicsAccessories.hpp"
namespace Diligent
@@ -72,7 +69,7 @@ DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* p
bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : EngineCI.NumCommandsToFlushCmdBuffer,
bIsDeferred
},
- m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledGraphicsShaderStages() },
+ m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledShaderStages() },
m_CmdListAllocator { GetRawAllocator(), sizeof(CommandListVkImpl), 64 },
// Command pools must be thread safe because command buffers are returned into pools by release queues
// potentially running in another thread
@@ -303,7 +300,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
}
case PIPELINE_TYPE_RAY_TRACING:
{
- //m_CommandBuffer.BindRayTracingPipeline(vkPipeline);
+ m_CommandBuffer.BindRayTracingPipeline(vkPipeline);
break;
}
default:
@@ -659,6 +656,19 @@ void DeviceContextVkImpl::PrepareForDispatchCompute()
#endif
}
+void DeviceContextVkImpl::PrepareForRayTracing()
+{
+ EnsureVkCmdBuffer();
+
+ if (m_DescrSetBindInfo.DynamicOffsetCount != 0)
+ {
+ if (!m_DescrSetBindInfo.DynamicDescriptorsBound || m_DescrSetBindInfo.DynamicBuffersPresent)
+ {
+ m_pPipelineState->BindDescriptorSetsWithDynamicOffsets(GetCommandBuffer(), m_ContextId, this, m_DescrSetBindInfo);
+ }
+ }
+}
+
void DeviceContextVkImpl::DispatchCompute(const DispatchComputeAttribs& Attribs)
{
if (!DvpVerifyDispatchArguments(Attribs))
@@ -2390,7 +2400,9 @@ void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& Textur
// to make sure that all UAV writes are complete and visible.
auto OldLayout = ResourceStateToVkImageLayout(OldState);
auto NewLayout = ResourceStateToVkImageLayout(NewState);
- m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange);
+ auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
+ auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
+ m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange, OldStages, NewStages);
if (UpdateTextureState)
{
TextureVk.SetState(NewState);
@@ -2479,7 +2491,7 @@ void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE
// When both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
// to make sure that all UAV writes are complete and visible.
- if (((OldState & NewState) != NewState) || NewState == RESOURCE_STATE_UNORDERED_ACCESS)
+ if (((OldState & NewState) != NewState) || NewState == RESOURCE_STATE_UNORDERED_ACCESS || NewState == RESOURCE_STATE_BUILD_AS_WRITE)
{
DEV_CHECK_ERR(BufferVk.m_VulkanBuffer != VK_NULL_HANDLE, "Cannot transition suballocated buffer");
VERIFY_EXPR(BufferVk.GetDynamicOffset(m_ContextId, this) == 0);
@@ -2488,7 +2500,9 @@ void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE
auto vkBuff = BufferVk.GetVkBuffer();
auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
- m_CommandBuffer.BufferMemoryBarrier(vkBuff, OldAccessFlags, NewAccessFlags);
+ auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
+ auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
+ m_CommandBuffer.BufferMemoryBarrier(vkBuff, OldAccessFlags, NewAccessFlags, OldStages, NewStages);
if (UpdateBufferState)
{
BufferVk.SetState(NewState);
@@ -2522,6 +2536,142 @@ void DeviceContextVkImpl::TransitionOrVerifyBufferState(BufferVkImpl&
#endif
}
+void DeviceContextVkImpl::TransitionBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateInternalState)
+{
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
+ if (OldState == RESOURCE_STATE_UNKNOWN)
+ {
+ if (BLAS.IsInKnownState())
+ {
+ OldState = BLAS.GetState();
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to transition the state of BLAS '", BLAS.GetDesc().Name, "' because the BLAS state is unknown and is not explicitly specified");
+ return;
+ }
+ }
+ else
+ {
+ if (BLAS.IsInKnownState() && BLAS.GetState() != OldState)
+ {
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(BLAS.GetState()), " of BLAS '",
+ BLAS.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
+ }
+ }
+
+ if ((OldState & NewState) != NewState)
+ {
+ EnsureVkCmdBuffer();
+ auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
+ auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
+ auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
+ auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
+ m_CommandBuffer.ASMemoryBarrier(OldAccessFlags, NewAccessFlags, OldStages, NewStages);
+ if (UpdateInternalState)
+ {
+ BLAS.SetState(NewState);
+ }
+ }
+}
+
+void DeviceContextVkImpl::TransitionTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateInternalState)
+{
+ // AZ TODO: transit BLAS state too?
+
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
+ if (OldState == RESOURCE_STATE_UNKNOWN)
+ {
+ if (TLAS.IsInKnownState())
+ {
+ OldState = TLAS.GetState();
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to transition the state of TLAS '", TLAS.GetDesc().Name, "' because the TLAS state is unknown and is not explicitly specified");
+ return;
+ }
+ }
+ else
+ {
+ if (TLAS.IsInKnownState() && TLAS.GetState() != OldState)
+ {
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(TLAS.GetState()), " of TLAS '",
+ TLAS.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
+ }
+ }
+
+ if ((OldState & NewState) != NewState)
+ {
+ EnsureVkCmdBuffer();
+ auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
+ auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
+ auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages());
+ auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages());
+ m_CommandBuffer.ASMemoryBarrier(OldAccessFlags, NewAccessFlags, OldStages, NewStages);
+ if (UpdateInternalState)
+ {
+ TLAS.SetState(NewState);
+ }
+ }
+}
+
+void DeviceContextVkImpl::TransitionOrVerifyBLASState(BottomLevelASVkImpl& BLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName)
+{
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
+ if (BLAS.IsInKnownState())
+ {
+ if (!BLAS.CheckState(RequiredState))
+ {
+ TransitionBLASState(BLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyBLASState(BLAS, RequiredState, OperationName);
+ }
+#endif
+}
+
+void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl& TLAS,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ const char* OperationName)
+{
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass");
+ if (TLAS.IsInKnownState())
+ {
+ if (!TLAS.CheckState(RequiredState))
+ {
+ TransitionTLASState(TLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyTLASState(TLAS, RequiredState, OperationName);
+ }
+#endif
+}
+
VulkanDynamicAllocation DeviceContextVkImpl::AllocateDynamicSpace(Uint32 SizeInBytes, Uint32 Alignment)
{
auto DynAlloc = m_DynamicHeap.Allocate(SizeInBytes, Alignment);
@@ -2554,24 +2704,27 @@ void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTra
}
VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
- if (Barrier.pTexture)
+ RefCntAutoPtr<TextureVkImpl> pTexture{Barrier.pResource, IID_TextureVk};
+ if (pTexture)
{
- auto* pTextureVkImpl = ValidatedCast<TextureVkImpl>(Barrier.pTexture);
-
VkImageSubresourceRange SubResRange;
SubResRange.aspectMask = 0;
SubResRange.baseMipLevel = Barrier.FirstMipLevel;
SubResRange.levelCount = (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS) ? VK_REMAINING_MIP_LEVELS : Barrier.MipLevelsCount;
SubResRange.baseArrayLayer = Barrier.FirstArraySlice;
SubResRange.layerCount = (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES) ? VK_REMAINING_ARRAY_LAYERS : Barrier.ArraySliceCount;
- TransitionTextureState(*pTextureVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState, &SubResRange);
+ TransitionTextureState(*pTexture, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState, &SubResRange);
+ continue;
}
- else
+
+ RefCntAutoPtr<BufferVkImpl> pBuffer{Barrier.pResource, IID_BufferVk};
+ if (pBuffer)
{
- VERIFY_EXPR(Barrier.pBuffer != nullptr);
- auto* pBufferVkImpl = ValidatedCast<BufferVkImpl>(Barrier.pBuffer);
- TransitionBufferState(*pBufferVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
+ TransitionBufferState(*pBuffer, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
+ continue;
}
+
+ UNEXPECTED("unsupported resource type");
}
}
@@ -2635,13 +2788,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
if (!TDeviceContextBase::BuildBLAS(Attribs, 0))
return;
-
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
@@ -2649,6 +2799,12 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
auto* pScratchVk = ValidatedCast<BufferVkImpl>(Attribs.pScratchBuffer);
auto& BLASDesc = pBLASVk->GetDesc();
+ EnsureVkCmdBuffer();
+
+ const char* OpName = "Build BottomLevelAS (DeviceContextVkImpl::BuildBLAS)";
+ TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+ TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VkAccessFlagBits(0), OpName);
+
VkAccelerationStructureBuildGeometryInfoKHR Info = {};
std::vector<VkAccelerationStructureBuildOffsetInfoKHR> Offsets;
std::vector<VkAccelerationStructureGeometryKHR> Geometries;
@@ -2679,17 +2835,21 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
tri.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
tri.pNext = nullptr;
- auto* pVB = ValidatedCast<IBufferVk>(src.pVertexBuffer);
+ auto* pVB = ValidatedCast<BufferVkImpl>(src.pVertexBuffer);
tri.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16);
tri.vertexStride = src.VertexStride;
tri.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + src.VertexOffset;
+ TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
+
if (src.pIndexBuffer)
{
- auto* pIB = ValidatedCast<IBufferVk>(src.pIndexBuffer);
+ auto* pIB = ValidatedCast<BufferVkImpl>(src.pIndexBuffer);
tri.indexType = TypeToVkIndexType(src.IndexType);
tri.indexData.deviceAddress = pIB->GetVkDeviceAddress() + src.IndexOffset;
off.primitiveCount = src.IndexCount / 3;
+
+ TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
}
else
{
@@ -2700,11 +2860,18 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
if (src.pTransformBuffer)
{
- auto* pTB = ValidatedCast<IBufferVk>(src.pTransformBuffer);
+ VERIFY_EXPR(BLASDesc.pTriangles[j].AllowsTransforms);
+
+ auto* pTB = ValidatedCast<BufferVkImpl>(src.pTransformBuffer);
tri.transformData.deviceAddress = pTB->GetVkDeviceAddress() + src.TransformBufferOffset;
+
+ TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
}
else
+ {
+ VERIFY_EXPR(!BLASDesc.pTriangles[j].AllowsTransforms);
tri.transformData.deviceAddress = 0;
+ }
off.firstVertex = 0;
off.primitiveOffset = 0;
@@ -2730,22 +2897,25 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
continue;
}
- auto* pBB = ValidatedCast<IBufferVk>(src.pBoxBuffer);
+ dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ dst.pNext = nullptr;
+ dst.flags = GeometryFlagsToVkGeometryFlags(src.Flags);
+ dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR;
+
+ auto* pBB = ValidatedCast<BufferVkImpl>(src.pBoxBuffer);
box.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR;
box.pNext = nullptr;
box.stride = src.BoxStride;
box.data.deviceAddress = pBB->GetVkDeviceAddress() + src.BoxOffset;
+ TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
+
off.firstVertex = 0;
off.transformOffset = 0;
off.primitiveOffset = 0;
off.primitiveCount = src.BoxCount;
}
}
- else
- {
- UNEXPECTED("pTriangleData or pBoxData must not be null");
- }
VkAccelerationStructureGeometryKHR const* GeometriesPtr = Geometries.data();
VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = Offsets.data();
@@ -2763,6 +2933,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs)
EnsureVkCmdBuffer();
m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
@@ -2770,23 +2941,27 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
if (!TDeviceContextBase::BuildTLAS(Attribs, 0))
return;
- static_assert(TLASInstanceDataSize == sizeof(VkAccelerationStructureInstanceKHR), "AZ TODO");
-
- // AZ TODO: transitions
+ static_assert(TLAS_INSTANCE_DATA_SIZE == sizeof(VkAccelerationStructureInstanceKHR), "Value in TLAS_INSTANCE_DATA_SIZE doesn't match the actual instance description size");
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
auto* pTLASVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pTLAS);
auto* pScratchVk = ValidatedCast<BufferVkImpl>(Attribs.pScratchBuffer);
- auto* pInstancesVk = ValidatedCast<BufferVkImpl>(Attribs.pInstancesBuffer);
+ auto* pInstancesVk = ValidatedCast<BufferVkImpl>(Attribs.pInstanceBuffer);
auto& TLASDesc = pTLASVk->GetDesc();
- pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount);
+ EnsureVkCmdBuffer();
+
+ const char* OpName = "Build TopLevelAS (DeviceContextVkImpl::BuildTLAS)";
+ TransitionOrVerifyTLASState(*pTLASVk, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+ TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VkAccessFlagBits(0), OpName);
+
+ pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.HitShadersPerInstance);
// copy instance data into instance buffer
{
@@ -2798,34 +2973,42 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
{
auto& src = Attribs.pInstances[i];
auto& dst = static_cast<VkAccelerationStructureInstanceKHR*>(pMappedInstances)[i];
- auto* pBLASVk = ValidatedCast<IBottomLevelASVk>(src.pBLAS);
+ auto* pBLASVk = ValidatedCast<BottomLevelASVkImpl>(src.pBLAS);
static_assert(sizeof(dst.transform) == sizeof(src.Transform), "size mismatch");
std::memcpy(&dst.transform, src.Transform, sizeof(dst.transform));
- dst.instanceCustomIndex = src.customId;
- dst.instanceShaderBindingTableRecordOffset = src.contributionToHitGroupIndex;
+ dst.instanceCustomIndex = src.CustomId;
+ dst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(src.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize
dst.mask = src.Mask;
dst.flags = InstanceFlagsToVkGeometryInstanceFlags(src.Flags);
dst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress();
+
+ TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
}
- UpdateBufferRegion(pInstancesVk, Attribs.InstancesBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode);
+ UpdateBufferRegion(pInstancesVk, Attribs.InstanceBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode);
}
+ TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName);
VkAccelerationStructureBuildGeometryInfoKHR Info = {};
VkAccelerationStructureBuildOffsetInfoKHR Offset = {};
VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = &Offset;
- VkAccelerationStructureGeometryKHR Geometry = {VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR};
+ VkAccelerationStructureGeometryKHR Geometry = {};
VkAccelerationStructureGeometryKHR const* GeometriesPtr = &Geometry;
Offset.primitiveCount = Attribs.InstanceCount;
- Geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
+ Geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
+ Geometry.pNext = nullptr;
+ Geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
+ Geometry.flags = 0;
+
auto& inst = Geometry.geometry.instances;
inst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
+ inst.pNext = nullptr;
inst.arrayOfPointers = VK_FALSE;
- inst.data.deviceAddress = pInstancesVk->GetVkDeviceAddress() + Attribs.InstancesBufferOffset;
+ inst.data.deviceAddress = pInstancesVk->GetVkDeviceAddress() + Attribs.InstanceBufferOffset;
Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
Info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; // type must be compatible with create info
@@ -2838,8 +3021,8 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs)
Info.ppGeometries = &GeometriesPtr;
Info.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset;
- EnsureVkCmdBuffer();
m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs)
@@ -2847,12 +3030,10 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs)
if (!TDeviceContextBase::CopyBLAS(Attribs, 0))
return;
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
@@ -2867,7 +3048,13 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs)
Info.mode = CopyASModeToVkCopyAccelerationStructureMode(Attribs.Mode);
EnsureVkCmdBuffer();
+
+ const char* OpName = "Copy BottomLevelAS (DeviceContextVkImpl::CopyBLAS)";
+ TransitionOrVerifyBLASState(*pSrcVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ TransitionOrVerifyBLASState(*pDstVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
m_CommandBuffer.CopyAccelerationStructure(Info);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
@@ -2875,11 +3062,11 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
if (!TDeviceContextBase::CopyTLAS(Attribs, 0))
return;
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
- auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE);
+ {
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
+ }
#endif
auto* pSrcVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pSrc);
@@ -2893,7 +3080,13 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs)
Info.mode = CopyASModeToVkCopyAccelerationStructureMode(Attribs.Mode);
EnsureVkCmdBuffer();
+
+ const char* OpName = "Copy TopLevelAS (DeviceContextVkImpl::CopyTLAS)";
+ TransitionOrVerifyTLASState(*pSrcVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName);
+ TransitionOrVerifyTLASState(*pDstVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName);
+
m_CommandBuffer.CopyAccelerationStructure(Info);
+ ++m_State.NumCommands;
}
void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs)
@@ -2901,12 +3094,10 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs)
if (!TDeviceContextBase::TraceRays(Attribs, 0))
return;
- // AZ TODO: transitions
-
#ifdef DILIGENT_DEBUG
{
- const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE);
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE);
}
#endif
@@ -2916,12 +3107,12 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs)
VkStridedBufferRegionKHR CallableShaderBindingTable = {};
auto* pSBTVk = ValidatedCast<ShaderBindingTableVkImpl>(Attribs.pSBT);
+ pSBTVk->GetVkStridedBufferRegions(this, Attribs.TransitionMode, RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable);
- pSBTVk->GetVkStridedBufferRegions(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable);
-
- EnsureVkCmdBuffer();
+ PrepareForRayTracing();
m_CommandBuffer.TraceRays(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable,
Attribs.DimensionX, Attribs.DimensionY, Attribs.DimensionZ);
+ ++m_State.NumCommands;
}
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 8aaee7f7..548a9cf3 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -390,24 +390,32 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo&
#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ray tracing PSO '", CreateInfo.PSODesc.Name, "' is invalid: ", ##__VA_ARGS__)
ShaderGroups.reserve(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount);
- Uint32 GroupIndex = 0;
- Uint32 ShaderIndex = 0;
+ Uint32 GroupIndex = 0;
+ std::array<Uint32, 6> ShaderIndices = {};
std::unordered_map<const IShader*, Uint32> UniqueShaders;
- const auto ShaderToIndex = [&ShaderIndex, &UniqueShaders](const IShader* pShader) -> Uint32 {
+ const auto ShaderToIndex = [&ShaderIndices, &UniqueShaders](const IShader* pShader) -> Uint32 {
if (pShader != nullptr)
{
- auto Result = UniqueShaders.emplace(pShader, ShaderIndex);
+ Uint32& Index = ShaderIndices[GetShaderTypePipelineIndex(pShader->GetDesc().ShaderType, PIPELINE_TYPE_RAY_TRACING)];
+ auto Result = UniqueShaders.emplace(pShader, Index);
if (Result.second)
{
- ++ShaderIndex;
+ ++Index;
}
return Result.first->second;
}
return VK_SHADER_UNUSED_KHR;
};
+ Uint32 ShaderCount = 0;
+ for (auto& Stage : ShaderStages)
+ {
+ ShaderIndices[GetShaderTypePipelineIndex(Stage.Type, PIPELINE_TYPE_RAY_TRACING)] = ShaderCount;
+ ShaderCount += static_cast<Uint32>(Stage.Count());
+ }
+
for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i)
{
const auto& GeneralShader = CreateInfo.pGeneralShaders[i];
@@ -485,7 +493,7 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo&
++ShaderIndex2;
}
}
- VERIFY_EXPR(ShaderIndex == ShaderIndex2);
+ VERIFY_EXPR(UniqueShaders.size() == ShaderIndex2);
#endif
#undef LOG_PSO_ERROR_AND_THROW
}
diff --git a/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp b/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp
index fb09687b..ec94814e 100644
--- a/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp
@@ -97,7 +97,7 @@ QueryManagerVk::QueryManagerVk(RenderDeviceVkImpl* pRenderDeviceVk,
VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT |
VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
- const auto EnabledShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
+ const auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
if (EnabledShaderStages & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)
{
QueryPoolCI.pipelineStatistics |=
diff --git a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
index 381ee631..a0801cb7 100644
--- a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
@@ -225,7 +225,7 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
{
auto& QueryData = *reinterpret_cast<QueryDataPipelineStatistics*>(pData);
- const auto EnabledShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
+ const auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
auto Idx = 0;
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
index 36fa5af0..6f5091e0 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp
@@ -27,6 +27,7 @@
#include "pch.h"
#include "ShaderBindingTableVkImpl.hpp"
+#include "BufferVkImpl.hpp"
#include "VulkanTypeConversions.hpp"
namespace Diligent
@@ -40,10 +41,8 @@ ShaderBindingTableVkImpl::ShaderBindingTableVkImpl(IReferenceCounters*
{
ValidateDesc(Desc);
- const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
-
- m_ShaderGroupHandleSize = Props.shaderGroupHandleSize;
- m_ShaderGroupBaseAlignment = Props.shaderGroupBaseAlignment;
+ const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize;
}
ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl()
@@ -52,12 +51,12 @@ ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl()
void ShaderBindingTableVkImpl::ValidateDesc(const ShaderBindingTableDesc& Desc) const
{
- const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
- if (Desc.ShaderRecordSize + Props.shaderGroupHandleSize > Props.maxShaderGroupStride)
+ if (Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize > RTLimits.maxShaderGroupStride)
{
LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""),
- "' is invalid: ShaderRecordSize is too big, max size is: ", Props.maxShaderGroupStride - Props.shaderGroupHandleSize);
+ "' is invalid: ShaderRecordSize is too big, max size is: ", RTLimits.maxShaderGroupStride - RTLimits.shaderGroupHandleSize);
}
}
@@ -68,6 +67,12 @@ void ShaderBindingTableVkImpl::Verify() const
void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc)
{
+ m_RayGenShaderRecord.clear();
+ m_MissShadersRecord.clear();
+ m_CallableShadersRecord.clear();
+ m_HitGroupsRecord.clear();
+ m_Changed = true;
+
try
{
ValidateShaderBindingTableDesc(Desc);
@@ -75,116 +80,130 @@ void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc)
}
catch (const std::runtime_error&)
{
+ // AZ TODO
return;
}
m_Desc = Desc;
- // free memory
- decltype(m_ShaderRecords) temp{};
- std::swap(temp, m_ShaderRecords);
-
- m_MissShadersOffset = 0;
- m_HitGroupsOffset = 0;
- m_CallbaleShadersOffset = 0;
- m_MissShaderCount = 0;
- m_HitGroupCount = 0;
- m_CallableShaderCount = 0;
+ const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize;
}
void ShaderBindingTableVkImpl::ResetHitGroups(Uint32 HitShadersPerInstance)
{
// AZ TODO
-}
-void ShaderBindingTableVkImpl::BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize)
-{
- // AZ TODO
+ m_Changed = true;
}
-void ShaderBindingTableVkImpl::BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize)
+void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs)
{
// AZ TODO
}
-void ShaderBindingTableVkImpl::BindHitGroup(ITopLevelAS* pTLAS,
- const char* InstanceName,
- const char* GeometryName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize)
+void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(IDeviceContextVk* pContext,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ VkStridedBufferRegionKHR& RaygenShaderBindingTable,
+ VkStridedBufferRegionKHR& MissShaderBindingTable,
+ VkStridedBufferRegionKHR& HitShaderBindingTable,
+ VkStridedBufferRegionKHR& CallableShaderBindingTable)
{
- // AZ TODO
-}
+ const auto ShaderGroupBaseAlignment = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupBaseAlignment;
-void ShaderBindingTableVkImpl::BindHitGroups(ITopLevelAS* pTLAS,
- const char* InstanceName,
- Uint32 RayOffsetInHitGroupIndex,
- const char* ShaderGroupName,
- const void* Data,
- Uint32 DataSize)
-{
- // AZ TODO
-}
+ const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 {
+ return Align(static_cast<Uint32>(offset), ShaderGroupBaseAlignment);
+ };
-void ShaderBindingTableVkImpl::BindCallableShader(Uint32 Index,
- const char* ShaderName,
- const void* Data,
- Uint32 DataSize)
-{
- // AZ TODO
-}
+ const Uint32 RayGenOffset = 0;
+ const Uint32 MissShaderOffset = AlignToLarger(m_RayGenShaderRecord.size());
+ const Uint32 HitGroupOffset = AlignToLarger(MissShaderOffset + m_MissShadersRecord.size());
+ const Uint32 CallableShadersOffset = AlignToLarger(HitGroupOffset + m_HitGroupsRecord.size());
+ const Uint32 BufSize = AlignToLarger(CallableShadersOffset + m_CallableShadersRecord.size());
-void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs)
-{
- // AZ TODO
-}
+ // recreate buffer
+ if (m_pBuffer == nullptr || m_pBuffer->GetDesc().uiSizeInBytes < BufSize)
+ {
+ m_pBuffer = nullptr;
-void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(VkStridedBufferRegionKHR& RaygenShaderBindingTable,
- VkStridedBufferRegionKHR& MissShaderBindingTable,
- VkStridedBufferRegionKHR& HitShaderBindingTable,
- VkStridedBufferRegionKHR& CallableShaderBindingTable)
-{
- const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing;
+ String BuffName = String{GetDesc().Name} + " - internal buffer";
+ BufferDesc BuffDesc;
+ BuffDesc.Name = BuffName.c_str();
+ BuffDesc.Usage = USAGE_DEFAULT;
+ BuffDesc.BindFlags = BIND_RAY_TRACING;
+ BuffDesc.uiSizeInBytes = BufSize;
+
+ GetDevice()->CreateBuffer(BuffDesc, nullptr, &m_pBuffer);
+ VERIFY_EXPR(m_pBuffer != nullptr);
+ }
+
+ if (m_pBuffer == nullptr)
+ return; // something goes wrong
- const VkDeviceSize Stride = m_Desc.ShaderRecordSize + Props.shaderGroupHandleSize;
- VERIFY_EXPR(Stride <= Props.maxShaderGroupStride);
+ VkBuffer BuffHandle = m_pBuffer.RawPtr<BufferVkImpl>()->GetVkBuffer();
- RaygenShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- RaygenShaderBindingTable.offset = 0;
- RaygenShaderBindingTable.size = Stride;
- RaygenShaderBindingTable.stride = Stride;
+ if (m_RayGenShaderRecord.size())
+ {
+ RaygenShaderBindingTable.buffer = BuffHandle;
+ RaygenShaderBindingTable.offset = RayGenOffset;
+ RaygenShaderBindingTable.size = m_RayGenShaderRecord.size();
+ RaygenShaderBindingTable.stride = m_ShaderRecordStride;
+ }
+
+ if (m_MissShadersRecord.size())
+ {
+ MissShaderBindingTable.buffer = BuffHandle;
+ MissShaderBindingTable.offset = MissShaderOffset;
+ MissShaderBindingTable.size = m_MissShadersRecord.size();
+ MissShaderBindingTable.stride = m_ShaderRecordStride;
+ }
- if (m_MissShaderCount > 0)
+ if (m_HitGroupsRecord.size())
{
- MissShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- MissShaderBindingTable.offset = m_MissShadersOffset;
- MissShaderBindingTable.size = Stride * m_MissShaderCount;
- MissShaderBindingTable.stride = Stride;
+ HitShaderBindingTable.buffer = BuffHandle;
+ HitShaderBindingTable.offset = HitGroupOffset;
+ HitShaderBindingTable.size = m_HitGroupsRecord.size();
+ HitShaderBindingTable.stride = m_ShaderRecordStride;
}
- else
- MissShaderBindingTable = {};
- if (m_HitGroupCount > 0)
+ if (m_CallableShadersRecord.size())
{
- HitShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- HitShaderBindingTable.offset = m_HitGroupsOffset;
- HitShaderBindingTable.size = Stride * m_HitGroupCount;
- HitShaderBindingTable.stride = Stride;
+ CallableShaderBindingTable.buffer = BuffHandle;
+ CallableShaderBindingTable.offset = CallableShadersOffset;
+ CallableShaderBindingTable.size = m_CallableShadersRecord.size();
+ CallableShaderBindingTable.stride = m_ShaderRecordStride;
}
- else
- HitShaderBindingTable = {};
- if (m_CallableShaderCount > 0)
+ if (!m_Changed)
+ return;
+
+ m_Changed = false;
+
+ // update buffer data
+ if (m_RayGenShaderRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, RayGenOffset, static_cast<Uint32>(m_RayGenShaderRecord.size()), m_RayGenShaderRecord.data(), TransitionMode);
+
+ if (m_MissShadersRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, MissShaderOffset, static_cast<Uint32>(m_MissShadersRecord.size()), m_MissShadersRecord.data(), TransitionMode);
+
+ if (m_HitGroupsRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, HitGroupOffset, static_cast<Uint32>(m_HitGroupsRecord.size()), m_HitGroupsRecord.data(), TransitionMode);
+
+ if (m_CallableShadersRecord.size())
+ pContext->UpdateBuffer(m_pBuffer, CallableShadersOffset, static_cast<Uint32>(m_CallableShadersRecord.size()), m_CallableShadersRecord.data(), TransitionMode);
+
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ StateTransitionDesc Barrier;
+ Barrier.pResource = m_pBuffer;
+ Barrier.NewState = RESOURCE_STATE_RAY_TRACING;
+ Barrier.UpdateResourceState = true;
+ pContext->TransitionResourceStates(1, &Barrier);
+ }
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
{
- CallableShaderBindingTable.buffer = m_pBuffer->GetVkBuffer();
- CallableShaderBindingTable.offset = m_CallbaleShadersOffset;
- CallableShaderBindingTable.size = Stride * m_CallableShaderCount;
- CallableShaderBindingTable.stride = Stride;
+ VERIFY_EXPR(m_pBuffer->GetState() == RESOURCE_STATE_RAY_TRACING);
}
- else
- CallableShaderBindingTable = {};
}
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index 8a9da14e..8101fefc 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -33,6 +33,7 @@
#include "TextureViewVkImpl.hpp"
#include "TextureVkImpl.hpp"
#include "SamplerVkImpl.hpp"
+#include "TopLevelASVkImpl.hpp"
#include "VulkanTypeConversions.hpp"
namespace Diligent
@@ -323,31 +324,31 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure:
{
- //auto* pTLASVk = Res.pObject.RawPtr<TopLevelASVkImpl>();
- //if (pTLASVk != nullptr && pTLASVk->IsInKnownState())
- //{
- // constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING;
- // const bool IsInRequiredState = pTLASVk->CheckState(RequiredState);
- // if (VerifyOnly)
- // {
- // if (!IsInRequiredState)
- // {
- // LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ",
- // GetResourceStateString(RequiredState), ". Actual state: ",
- // GetResourceStateString(pTLASVk->GetState()),
- // ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
- // "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state "
- // "with IDeviceContext::TransitionResourceStates().");
- // }
- // }
- // else
- // {
- // if (!IsInRequiredState)
- // {
- // pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- // }
- // }
- //}
+ auto* pTLASVk = Res.pObject.RawPtr<TopLevelASVkImpl>();
+ if (pTLASVk != nullptr && pTLASVk->IsInKnownState())
+ {
+ constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING;
+ const bool IsInRequiredState = pTLASVk->CheckState(RequiredState);
+ if (VerifyOnly)
+ {
+ if (!IsInRequiredState)
+ {
+ LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ",
+ GetResourceStateString(RequiredState), ". Actual state: ",
+ GetResourceStateString(pTLASVk->GetState()),
+ ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
+ "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state "
+ "with IDeviceContext::TransitionResourceStates().");
+ }
+ }
+ else
+ {
+ if (!IsInRequiredState)
+ {
+ pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
+ }
+ }
+ }
}
break;
@@ -532,13 +533,13 @@ VkWriteDescriptorSetAccelerationStructureKHR ShaderResourceCacheVk::Resource::Ge
VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration structure resource is expected");
DEV_CHECK_ERR(pObject != nullptr, "Unable to get acceleration structure write info: cached object is null");
- //auto* pTLASVk = pObject.RawPtr<const TopLevelASVkImpl>();
+ auto* pTLASVk = pObject.RawPtr<const TopLevelASVkImpl>();
- VkWriteDescriptorSetAccelerationStructureKHR DescrAS = {};
- //DescrAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
- //DescrAS.pNext = nullptr;
- //DescrAS.accelerationStructureCount = 1;
- //DescrAS.pAccelerationStructures = pTLASVk->GetVkTLASPtr();
+ VkWriteDescriptorSetAccelerationStructureKHR DescrAS;
+ DescrAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
+ DescrAS.pNext = nullptr;
+ DescrAS.accelerationStructureCount = 1;
+ DescrAS.pAccelerationStructures = pTLASVk->GetVkTLASPtr();
return DescrAS;
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 8a48c27c..45ed73de 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -39,6 +39,7 @@
#include "ShaderResourceVariableBase.hpp"
#include "StringTools.hpp"
#include "PipelineStateVkImpl.hpp"
+#include "TopLevelASVkImpl.hpp"
namespace Diligent
{
@@ -97,7 +98,7 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE
ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) :
Type{Stage},
Shaders{{pShader}},
- SPIRVs{{pShader->GetSPIRV()}}
+ SPIRVs{{{pShader->GetSPIRV()}}}
{
}
@@ -1094,22 +1095,22 @@ void ShaderResourceLayoutVk::VkResource::CacheAccelerationStructure(IDeviceObjec
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd) const
{
- // VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected");
- // RefCntAutoPtr<TopLevelASVkImpl> pTLASVk{pTLAS, IID_TopLevelASVk};
- //#ifdef DILIGENT_DEVELOPMENT
- // // AZ TODO
- //#endif
- // if (UpdateCachedResource(DstRes, std::move(pTLASVk), [](const TopLevelASVkImpl*, const TopLevelASVkImpl*) {}))
- // {
- // // Do not update descriptor for a dynamic TLAS. All dynamic resource descriptors
- // // are updated at once by CommitDynamicResources() when SRB is committed.
- // if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- // {
- // VkWriteDescriptorSetAccelerationStructureKHR DescrASInfo = DstRes.GetAccelerationStructureWriteInfo();
- // UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, nullptr, &DescrASInfo);
- // }
- // //
- // }
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected");
+ RefCntAutoPtr<TopLevelASVkImpl> pTLASVk{pTLAS, IID_TopLevelASVk};
+#ifdef DILIGENT_DEVELOPMENT
+ // AZ TODO
+#endif
+ if (UpdateCachedResource(DstRes, std::move(pTLASVk), [](const TopLevelASVkImpl*, const TopLevelASVkImpl*) {}))
+ {
+ // Do not update descriptor for a dynamic TLAS. All dynamic resource descriptors
+ // are updated at once by CommitDynamicResources() when SRB is committed.
+ if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
+ {
+ VkWriteDescriptorSetAccelerationStructureKHR DescrASInfo = DstRes.GetAccelerationStructureWriteInfo();
+ UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, nullptr, &DescrASInfo);
+ }
+ //
+ }
}
void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const
diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
index ab53d639..27be99fc 100644
--- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
@@ -423,12 +423,24 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
swapchain_ci.imageColorSpace = ColorSpace;
DEV_CHECK_ERR(m_SwapChainDesc.Usage != 0, "No swap chain usage flags defined");
- if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_RENDER_TARGET)
- swapchain_ci.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_SHADER_INPUT)
- swapchain_ci.imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
- if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_COPY_SOURCE)
- swapchain_ci.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ static_assert(SWAP_CHAIN_USAGE_LAST == SWAP_CHAIN_USAGE_UNORDERED_ACCESS, "Please update this function to handle the new swapchain usage");
+
+ for (Uint32 UsageBit = 1; UsageBit <= m_SwapChainDesc.Usage; UsageBit <<= 1)
+ {
+ if ((m_SwapChainDesc.Usage & UsageBit) == 0)
+ continue;
+
+ switch (static_cast<SWAP_CHAIN_USAGE_FLAGS>(UsageBit))
+ {
+ // clang-format off
+ case SWAP_CHAIN_USAGE_RENDER_TARGET: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; break;
+ case SWAP_CHAIN_USAGE_SHADER_INPUT: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT; break;
+ case SWAP_CHAIN_USAGE_COPY_SOURCE: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; break;
+ case SWAP_CHAIN_USAGE_UNORDERED_ACCESS: swapchain_ci.imageUsage |= VK_IMAGE_USAGE_STORAGE_BIT; break;
+ default: UNEXPECTED("unknown swapchain usage flag");
+ // clang-format on
+ }
+ }
// vkCmdClearColorImage() command requires the image to use VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout
// that requires VK_IMAGE_USAGE_TRANSFER_DST_BIT to be set
@@ -639,9 +651,10 @@ VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk)
m_ImageAcquiredFenceSubmitted[m_SemaphoreIndex] = (res == VK_SUCCESS);
if (res == VK_SUCCESS)
{
- // Next command in the device context must wait for the next image to be acquired
- // Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2)
- pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ // Next command in the device context must wait for the next image to be acquired.
+ // Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2).
+ // Swapchain may be used as UAV in compute or ray tracing shader, so we must wait on all stages.
+ pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
if (!m_SwapChainImagesInitialized[m_BackBufferIndex])
{
// Vulkan validation layers do not like uninitialized memory.
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 488e4bf6..dca627d7 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -223,13 +223,13 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
// For either clear or copy command, dst layout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
VkImageSubresourceRange SubresRange;
- SubresRange.aspectMask = aspectMask;
- SubresRange.baseArrayLayer = 0;
- SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
- SubresRange.baseMipLevel = 0;
- SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
- auto EnabledGraphicsShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
- VulkanUtilities::VulkanCommandBuffer::TransitionImageLayout(vkCmdBuff, m_VulkanImage, ImageCI.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange, EnabledGraphicsShaderStages);
+ SubresRange.aspectMask = aspectMask;
+ SubresRange.baseArrayLayer = 0;
+ SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ SubresRange.baseMipLevel = 0;
+ SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ auto EnabledShaderStages = LogicalDevice.GetEnabledShaderStages();
+ VulkanUtilities::VulkanCommandBuffer::TransitionImageLayout(vkCmdBuff, m_VulkanImage, ImageCI.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange, EnabledShaderStages);
SetState(RESOURCE_STATE_COPY_DEST);
const auto CurrentLayout = GetLayout();
VERIFY_EXPR(CurrentLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
@@ -350,7 +350,7 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
err = LogicalDevice.BindBufferMemory(StagingBuffer, StagingBufferMemory, AlignedStagingMemOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
- VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledGraphicsShaderStages);
+ VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledShaderStages);
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
// as copy will be the only command in the cmd buffer
diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp
index 76248d41..ae10b74b 100644
--- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp
@@ -76,14 +76,14 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Failed to find suitable memory type for TLAS '", m_Desc.Name, '\'');
VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
+ m_MemoryAlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
+ VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (m_MemoryAlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
auto Memory = m_MemoryAllocation.Page->GetVkMemory();
- auto err = LogicalDevice.BindASMemory(m_VulkanTLAS, Memory, 0);
+ auto err = LogicalDevice.BindASMemory(m_VulkanTLAS, Memory, m_MemoryAlignedOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory");
- m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanTLAS);
-
MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo);
m_ScratchSize.Build = static_cast<Uint32>(MemReqs.size);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index 6358174c..40882b09 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -1152,6 +1152,55 @@ VkBorderColor BorderColorToVkBorderColor(const Float32 BorderColor[])
}
+static VkPipelineStageFlags ResourceStateFlagToVkPipelineStage(RESOURCE_STATE StateFlag, VkPipelineStageFlags ShaderStages)
+{
+ static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "This function must be updated to handle new resource state flag");
+ VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set");
+ switch (StateFlag)
+ {
+ // clang-format off
+ case RESOURCE_STATE_UNDEFINED: return 0;
+ case RESOURCE_STATE_VERTEX_BUFFER: return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ case RESOURCE_STATE_CONSTANT_BUFFER: return ShaderStages;
+ case RESOURCE_STATE_INDEX_BUFFER: return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+ case RESOURCE_STATE_RENDER_TARGET: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ case RESOURCE_STATE_UNORDERED_ACCESS: return ShaderStages;
+ case RESOURCE_STATE_DEPTH_WRITE: return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ case RESOURCE_STATE_DEPTH_READ: return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ case RESOURCE_STATE_SHADER_RESOURCE: return ShaderStages;
+ case RESOURCE_STATE_STREAM_OUT: return 0;
+ case RESOURCE_STATE_INDIRECT_ARGUMENT: return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+ case RESOURCE_STATE_COPY_DEST: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_COPY_SOURCE: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_RESOLVE_DEST: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_RESOLVE_SOURCE: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ case RESOURCE_STATE_PRESENT: return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ case RESOURCE_STATE_BUILD_AS_READ: return VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
+ case RESOURCE_STATE_BUILD_AS_WRITE: return VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
+ case RESOURCE_STATE_RAY_TRACING: return VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
+ // clang-format on
+
+ default:
+ UNEXPECTED("Unexpected resource state flag");
+ return 0;
+ }
+}
+
+VkPipelineStageFlags ResourceStateFlagsToVkPipelineStageFlags(RESOURCE_STATE StateFlags, VkPipelineStageFlags ShaderStages)
+{
+ VERIFY(Uint32{StateFlags} < (RESOURCE_STATE_MAX_BIT << 1), "Resource state flags are out of range");
+
+ VkPipelineStageFlags Stages = 0;
+ for (Uint32 Bit = 1; Bit <= StateFlags; Bit <<= 1)
+ {
+ if (StateFlags & Bit)
+ Stages |= ResourceStateFlagToVkPipelineStage(static_cast<RESOURCE_STATE>(Bit), ShaderStages);
+ }
+ return Stages;
+}
+
+
static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
{
// Currently not used:
@@ -1189,7 +1238,8 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_ACCESS_TRANSFER_READ_BIT;
case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
case RESOURCE_STATE_PRESENT: return 0;
- case RESOURCE_STATE_BUILD_AS: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
+ case RESOURCE_STATE_BUILD_AS_READ: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
+ case RESOURCE_STATE_BUILD_AS_WRITE: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
case RESOURCE_STATE_RAY_TRACING: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
// clang-format on
@@ -1218,7 +1268,7 @@ public:
}
private:
- static constexpr const Uint32 MaxFlagBitPos = 18;
+ static constexpr const Uint32 MaxFlagBitPos = 19;
std::array<VkAccessFlags, MaxFlagBitPos + 1> FlagBitPosToVkAccessFlagsMap;
};
@@ -1239,7 +1289,7 @@ VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags)
return AccessFlags;
}
-RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlagBits AccessFlagBit)
+static RESOURCE_STATE VkAccessFlagToResourceStates(VkAccessFlagBits AccessFlagBit)
{
VERIFY((AccessFlagBit & (AccessFlagBit - 1)) == 0, "Single access flag bit is expected");
@@ -1271,8 +1321,6 @@ RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlagBits AccessFlagBit)
case VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV: return RESOURCE_STATE_UNKNOWN;
case VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT: return RESOURCE_STATE_UNKNOWN;
case VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV: return RESOURCE_STATE_UNKNOWN;
- case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR: return RESOURCE_STATE_RAY_TRACING;
- case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: return RESOURCE_STATE_BUILD_AS;
// clang-format on
default:
UNEXPECTED("Unknown access flag");
@@ -1288,7 +1336,7 @@ public:
{
for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit)
{
- FlagBitPosToResourceState[bit] = VkAccessFlagsToResourceStates(static_cast<VkAccessFlagBits>(1 << bit));
+ FlagBitPosToResourceState[bit] = VkAccessFlagToResourceStates(static_cast<VkAccessFlagBits>(1 << bit));
}
}
@@ -1354,7 +1402,8 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsi
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case RESOURCE_STATE_INPUT_ATTACHMENT: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case RESOURCE_STATE_PRESENT: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- case RESOURCE_STATE_BUILD_AS: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
+ case RESOURCE_STATE_BUILD_AS_READ: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
+ case RESOURCE_STATE_BUILD_AS_WRITE: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
case RESOURCE_STATE_RAY_TRACING: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
// clang-format on
@@ -1376,7 +1425,7 @@ RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout)
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return RESOURCE_STATE_DEPTH_WRITE;
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return RESOURCE_STATE_DEPTH_READ;
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return RESOURCE_STATE_SHADER_RESOURCE;
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return RESOURCE_STATE_COPY_SOURCE; // AZ TODO: check for resolve state
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return RESOURCE_STATE_COPY_SOURCE;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return RESOURCE_STATE_COPY_DEST;
case VK_IMAGE_LAYOUT_PREINITIALIZED: UNEXPECTED("This layout is not supported"); return RESOURCE_STATE_UNDEFINED;
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: UNEXPECTED("This layout is not supported"); return RESOURCE_STATE_UNDEFINED;
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
index 5a1894c0..ae460cde 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
@@ -79,7 +79,7 @@ VulkanUploadHeap::UploadPageInfo VulkanUploadHeap::CreateNewPage(VkDeviceSize Si
"at least one bit set corresponding to a VkMemoryType with a propertyFlags that has both the "
"VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit AND the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set. (11.6)");
- auto MemAllocation = GlobalMemoryMgr.Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, true);
+ auto MemAllocation = GlobalMemoryMgr.Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, true, VkMemoryAllocateFlags{0});
auto AlignedOffset = (MemAllocation.UnalignedOffset + (MemReqs.alignment - 1)) & ~(MemReqs.alignment - 1);
auto err = LogicalDevice.BindBufferMemory(NewBuffer, MemAllocation.Page->GetVkMemory(), AlignedOffset);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
index 11444c33..4d47ca3e 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
@@ -32,7 +32,7 @@ namespace VulkanUtilities
{
static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags AccessFlags,
- const VkPipelineStageFlags EnabledGraphicsShaderStages)
+ const VkPipelineStageFlags EnabledShaderStages)
{
// 6.1.3
VkPipelineStageFlags Stages = 0;
@@ -65,7 +65,7 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags
// Read access to a uniform buffer
case VK_ACCESS_UNIFORM_READ_BIT:
- Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ Stages |= EnabledShaderStages;
break;
// Read access to an input attachment within a render pass during fragment shading
@@ -75,12 +75,12 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags
// Read access to a storage buffer, uniform texel buffer, storage texel buffer, sampled image, or storage image
case VK_ACCESS_SHADER_READ_BIT:
- Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ Stages |= EnabledShaderStages;
break;
// Write access to a storage buffer, storage texel buffer, or storage image
case VK_ACCESS_SHADER_WRITE_BIT:
- Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ Stages |= EnabledShaderStages;
break;
// Read access to a color attachment, such as via blending, logic operations, or via certain subpass load operations
@@ -134,6 +134,16 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags
case VK_ACCESS_MEMORY_WRITE_BIT:
break;
+ // AZ TODO: comment
+ case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR:
+ Stages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
+ break;
+
+ // AZ TODO: comment
+ case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR:
+ Stages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
+ break;
+
default:
UNEXPECTED("Unknown memory access flag");
}
@@ -223,8 +233,12 @@ static VkPipelineStageFlags AccessMaskFromImageLayout(VkImageLayout Layout,
AccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
break;
+ // When transitioning the image to VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ // there is no need to delay subsequent processing, or perform any visibility operations (as vkQueuePresentKHR
+ // performs automatic visibility operations). To achieve this, the dstAccessMask member of the VkImageMemoryBarrier
+ // should be set to 0, and the dstStageMask parameter should be set to VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT.
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- AccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ AccessMask = 0;
break;
default:
@@ -240,7 +254,7 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
VkImageLayout OldLayout,
VkImageLayout NewLayout,
const VkImageSubresourceRange& SubresRange,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages,
VkPipelineStageFlags DestStages)
{
@@ -268,7 +282,7 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
}
else if (ImgBarrier.srcAccessMask != 0)
{
- SrcStages = PipelineStageFromAccessFlags(ImgBarrier.srcAccessMask, EnabledGraphicsShaderStages);
+ SrcStages = PipelineStageFromAccessFlags(ImgBarrier.srcAccessMask, EnabledShaderStages);
}
else
{
@@ -282,11 +296,11 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
{
if (NewLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
{
- DestStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ DestStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
else if (ImgBarrier.dstAccessMask != 0)
{
- DestStages = PipelineStageFromAccessFlags(ImgBarrier.dstAccessMask, EnabledGraphicsShaderStages);
+ DestStages = PipelineStageFromAccessFlags(ImgBarrier.dstAccessMask, EnabledShaderStages);
}
else
{
@@ -327,7 +341,7 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
VkBuffer Buffer,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
- VkPipelineStageFlags EnabledGraphicsShaderStages,
+ VkPipelineStageFlags EnabledShaderStages,
VkPipelineStageFlags SrcStages,
VkPipelineStageFlags DestStages)
{
@@ -344,7 +358,7 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
if (SrcStages == 0)
{
if (BuffBarrier.srcAccessMask != 0)
- SrcStages = PipelineStageFromAccessFlags(BuffBarrier.srcAccessMask, EnabledGraphicsShaderStages);
+ SrcStages = PipelineStageFromAccessFlags(BuffBarrier.srcAccessMask, EnabledShaderStages);
else
{
// An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
@@ -356,7 +370,7 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
if (DestStages == 0)
{
VERIFY(BuffBarrier.dstAccessMask != 0, "Dst access mask must not be zero");
- DestStages = PipelineStageFromAccessFlags(BuffBarrier.dstAccessMask, EnabledGraphicsShaderStages);
+ DestStages = PipelineStageFromAccessFlags(BuffBarrier.dstAccessMask, EnabledShaderStages);
}
vkCmdPipelineBarrier(CmdBuffer,
@@ -371,6 +385,55 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
nullptr);
}
+void VulkanCommandBuffer::ASMemoryBarrier(VkCommandBuffer CmdBuffer,
+ VkAccessFlags srcAccessMask,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags EnabledShaderStages,
+ VkPipelineStageFlags SrcStages,
+ VkPipelineStageFlags DestStages)
+{
+ VkMemoryBarrier Barrier = {};
+ Barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ Barrier.pNext = nullptr;
+ Barrier.srcAccessMask = srcAccessMask;
+ Barrier.dstAccessMask = dstAccessMask;
+
+ if (SrcStages == 0)
+ {
+ if (Barrier.srcAccessMask != 0)
+ SrcStages = PipelineStageFromAccessFlags(Barrier.srcAccessMask, EnabledShaderStages);
+ else
+ {
+ // An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
+ // mask will effectively not wait for any prior commands to complete. (6.1.2)
+ SrcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ }
+ }
+
+ if (DestStages == 0)
+ {
+ VERIFY(Barrier.dstAccessMask != 0, "Dst access mask must not be zero");
+ DestStages = PipelineStageFromAccessFlags(Barrier.dstAccessMask, EnabledShaderStages);
+ }
+
+ // Other stages are not valid for acceleration structures
+ constexpr VkPipelineStageFlags StagesMask = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+
+ SrcStages &= StagesMask;
+ DestStages &= StagesMask;
+
+ vkCmdPipelineBarrier(CmdBuffer,
+ SrcStages, // must not be 0
+ DestStages, // must not be 0
+ 0, // a bitmask specifying how execution and memory dependencies are formed
+ 1, // memoryBarrierCount
+ &Barrier, // pMemoryBarriers
+ 0,
+ nullptr,
+ 0,
+ nullptr);
+}
+
void VulkanCommandBuffer::FlushBarriers()
{
}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
index 358bdec5..7639c309 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
@@ -64,15 +64,19 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe
// https://github.com/zeux/volk#optimizing-device-calls
volkLoadDevice(m_VkDevice);
- if (PhysicalDevice.GetExtFeatures().RayTracingNV)
+ if (m_EnabledExtFeatures.RayTracingNV)
EnableRayTracingKHRviaNV();
#endif
- m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ m_EnabledShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
if (DeviceCI.pEnabledFeatures->geometryShader)
- m_EnabledGraphicsShaderStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
if (DeviceCI.pEnabledFeatures->tessellationShader)
- m_EnabledGraphicsShaderStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
+ if (m_EnabledExtFeatures.MeshShader.meshShader != VK_FALSE && m_EnabledExtFeatures.MeshShader.taskShader != VK_FALSE)
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV | VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV;
+ if (m_EnabledExtFeatures.RayTracing.rayTracing != VK_FALSE)
+ m_EnabledShaderStages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
}
VkQueue VulkanLogicalDevice::GetQueue(uint32_t queueFamilyIndex, uint32_t queueIndex)
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
index f9cdcdea..2e2cdd31 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
@@ -40,10 +40,11 @@ VulkanMemoryAllocation::~VulkanMemoryAllocation()
}
}
-VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
- VkDeviceSize PageSize,
- uint32_t MemoryTypeIndex,
- bool IsHostVisible) noexcept :
+VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
+ VkDeviceSize PageSize,
+ uint32_t MemoryTypeIndex,
+ bool IsHostVisible,
+ VkMemoryAllocateFlags AllocateFlags) noexcept :
// clang-format off
m_ParentMemoryMgr{ParentMemoryMgr},
m_AllocationMgr {static_cast<AllocationsMgrOffsetType>(PageSize), ParentMemoryMgr.m_Allocator}
@@ -53,13 +54,22 @@ VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
"PageSize (", PageSize, ") exceeds maximum allowed value ",
std::numeric_limits<AllocationsMgrOffsetType>::max());
- VkMemoryAllocateInfo MemAlloc = {};
+ VkMemoryAllocateInfo MemAlloc = {};
+ VkMemoryAllocateFlagsInfo MemFlagInfo = {};
MemAlloc.pNext = nullptr;
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
MemAlloc.allocationSize = PageSize;
MemAlloc.memoryTypeIndex = MemoryTypeIndex;
+ if (AllocateFlags)
+ {
+ MemAlloc.pNext = &MemFlagInfo;
+ MemFlagInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
+ MemFlagInfo.pNext = nullptr;
+ MemFlagInfo.flags = AllocateFlags;
+ }
+
auto MemoryName = Diligent::FormatString("Device memory page. Size: ", Diligent::FormatMemorySize(PageSize, 2), ", type: ", MemoryTypeIndex);
m_VkMemory = ParentMemoryMgr.m_LogicalDevice.AllocateDeviceMemory(MemAlloc, MemoryName.c_str());
@@ -116,7 +126,7 @@ void VulkanMemoryPage::Free(VulkanMemoryAllocation&& Allocation)
Allocation = VulkanMemoryAllocation{};
}
-VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps)
+VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps, VkMemoryAllocateFlags AllocateFlags)
{
// memoryTypeBits is a bitmask and contains one bit set for every supported memory type for the resource.
// Bit i is set if and only if the memory type i in the VkPhysicalDeviceMemoryProperties structure for the
@@ -145,10 +155,10 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements&
}
bool HostVisible = (MemoryProps & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
- return Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, HostVisible);
+ return Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, HostVisible, AllocateFlags);
}
-VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible)
+VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex, bool HostVisible, VkMemoryAllocateFlags AllocateFlags)
{
VulkanMemoryAllocation Allocation;
@@ -159,7 +169,7 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice
// even though on integrated GPUs same pages can be used for both GPU-only and staging
// allocations. Staging allocations are short-living and will be released when upload is
// complete, while GPU-only allocations are expected to be long-living.
- MemoryPageIndex PageIdx{MemoryTypeIndex, HostVisible};
+ MemoryPageIndex PageIdx{MemoryTypeIndex, HostVisible, AllocateFlags};
std::lock_guard<std::mutex> Lock{m_PagesMtx};
auto range = m_Pages.equal_range(PageIdx);
@@ -180,7 +190,7 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice
m_CurrAllocatedSize[stat_ind] += PageSize;
m_PeakAllocatedSize[stat_ind] = std::max(m_PeakAllocatedSize[stat_ind], m_CurrAllocatedSize[stat_ind]);
- auto it = m_Pages.emplace(PageIdx, VulkanMemoryPage{*this, PageSize, MemoryTypeIndex, HostVisible});
+ auto it = m_Pages.emplace(PageIdx, VulkanMemoryPage{*this, PageSize, MemoryTypeIndex, HostVisible, AllocateFlags});
LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "': created new ", (HostVisible ? "host-visible" : "device-local"),
" page. (", Diligent::FormatMemorySize(PageSize, 2), ", type idx: ", MemoryTypeIndex,
"). Current allocated size: ", Diligent::FormatMemorySize(m_CurrAllocatedSize[stat_ind], 2));
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
index f7a6b8f6..5b5434d5 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp
@@ -56,18 +56,18 @@ PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr;
PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr;
PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr;
-VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device,
- const VkBufferCreateInfo* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkBuffer* pBuffer)
+VKAPI_ATTR VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device,
+ const VkBufferCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkBuffer* pBuffer)
{
const_cast<VkBufferCreateInfo*>(pCreateInfo)->usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
return Origin_vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
}
-void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device,
- VkBuffer buffer,
- const VkAllocationCallbacks* pAllocator)
+VKAPI_ATTR void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device,
+ VkBuffer buffer,
+ const VkAllocationCallbacks* pAllocator)
{
Origin_vkDestroyBuffer(device, buffer, pAllocator);
@@ -81,8 +81,8 @@ void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device,
}
}
-VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice device,
- const VkBufferDeviceAddressInfo* pInfo)
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice device,
+ const VkBufferDeviceAddressInfo* pInfo)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR);
VERIFY_EXPR(pInfo->pNext == nullptr);
@@ -134,10 +134,10 @@ BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressKHR& Addr)
}
-VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice device,
- const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkAccelerationStructureKHR* pAccelerationStructure)
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice device,
+ const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkAccelerationStructureKHR* pAccelerationStructure)
{
VERIFY_EXPR(pCreateInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR);
VERIFY_EXPR(pCreateInfo->pNext == nullptr);
@@ -154,7 +154,9 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR)
{
- CreateInfo.info.instanceCount = pCreateInfo->maxGeometryCount;
+ VERIFY_EXPR(pCreateInfo->maxGeometryCount == 1);
+
+ CreateInfo.info.instanceCount = pCreateInfo->pGeometryInfos->maxPrimitiveCount;
}
else if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR)
{
@@ -183,7 +185,6 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
{
dst.geometry.triangles.vertexData = VK_NULL_HANDLE;
dst.geometry.triangles.vertexOffset = 0;
- dst.geometry.triangles.vertexCount = src.maxVertexCount;
dst.geometry.triangles.vertexStride = 0;
dst.geometry.triangles.vertexFormat = src.vertexFormat;
dst.geometry.triangles.indexData = VK_NULL_HANDLE;
@@ -200,7 +201,8 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
}
else
{
- dst.geometry.triangles.indexCount = src.maxPrimitiveCount * 3;
+ dst.geometry.triangles.indexCount = src.maxPrimitiveCount * 3;
+ dst.geometry.triangles.vertexCount = std::max(src.maxPrimitiveCount * 6, src.maxVertexCount);
}
}
else if (dst.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR)
@@ -224,11 +226,12 @@ VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice
return vkCreateAccelerationStructureNV(device, &CreateInfo, pAllocator, reinterpret_cast<VkAccelerationStructureNV*>(pAccelerationStructure));
}
-void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevice device,
- const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo,
- VkMemoryRequirements2* pMemoryRequirements)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevice device,
+ const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR);
+ VERIFY_EXPR(pMemoryRequirements->sType == VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2);
VERIFY_EXPR(pInfo->pNext == nullptr);
VERIFY_EXPR(pInfo->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR);
@@ -241,16 +244,16 @@ void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevic
return vkGetAccelerationStructureMemoryRequirementsNV(device, &Info, pMemoryRequirements);
}
-VkResult VKAPI_CALL Redirect_vkBindAccelerationStructureMemoryKHR(VkDevice device,
- uint32_t bindInfoCount,
- const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos)
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkBindAccelerationStructureMemoryKHR(VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos)
{
VERIFY_EXPR(pBindInfos->sType == VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV);
return vkBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos);
}
-VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(VkDevice device,
- const VkAccelerationStructureDeviceAddressInfoKHR* pInfo)
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(VkDevice device,
+ const VkAccelerationStructureDeviceAddressInfoKHR* pInfo)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR);
VERIFY_EXPR(pInfo->pNext == nullptr);
@@ -260,10 +263,10 @@ VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(V
return result;
}
-void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer,
- uint32_t infoCount,
- const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
- const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer,
+ uint32_t infoCount,
+ const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
+ const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos)
{
std::vector<VkGeometryNV> Geometries;
@@ -321,6 +324,12 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
dst.flags = src.flags;
dst.geometryType = src.geometryType;
+ dst.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
+ dst.geometry.triangles.pNext = nullptr;
+
+ dst.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
+ dst.geometry.aabbs.pNext = nullptr;
+
if (dst.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR)
{
VERIFY_EXPR(src.geometry.triangles.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR);
@@ -331,8 +340,6 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
BufferAndOffset IB = DeviceAddressToBuffer(src.geometry.triangles.indexData);
BufferAndOffset TB = DeviceAddressToBuffer(src.geometry.triangles.transformData);
- dst.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
- dst.geometry.triangles.pNext = nullptr;
dst.geometry.triangles.vertexData = VB.Buffer;
dst.geometry.triangles.vertexOffset = VB.Offset;
dst.geometry.triangles.vertexCount = 0;
@@ -353,7 +360,8 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
else
{
dst.geometry.triangles.indexOffset += off.primitiveOffset;
- dst.geometry.triangles.indexCount = off.primitiveCount * 3;
+ dst.geometry.triangles.indexCount = off.primitiveCount * 3;
+ dst.geometry.triangles.vertexCount = off.primitiveCount * 6;
}
}
else
@@ -364,8 +372,6 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
BufferAndOffset Data = DeviceAddressToBuffer(src.geometry.aabbs.data);
- dst.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
- dst.geometry.aabbs.pNext = nullptr;
dst.geometry.aabbs.aabbData = Data.Buffer;
dst.geometry.aabbs.numAABBs = off.primitiveCount;
dst.geometry.aabbs.stride = static_cast<uint32_t>(src.geometry.aabbs.stride);
@@ -389,8 +395,8 @@ void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer
}
}
-void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
- const VkCopyAccelerationStructureInfoKHR* pInfo)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
+ const VkCopyAccelerationStructureInfoKHR* pInfo)
{
VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR);
VERIFY_EXPR(pInfo->pNext == nullptr);
@@ -398,14 +404,14 @@ void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer
vkCmdCopyAccelerationStructureNV(commandBuffer, pInfo->dst, pInfo->src, pInfo->mode);
}
-void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
- const VkStridedBufferRegionKHR* pRaygenShaderBindingTable,
- const VkStridedBufferRegionKHR* pMissShaderBindingTable,
- const VkStridedBufferRegionKHR* pHitShaderBindingTable,
- const VkStridedBufferRegionKHR* pCallableShaderBindingTable,
- uint32_t width,
- uint32_t height,
- uint32_t depth)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
+ const VkStridedBufferRegionKHR* pRaygenShaderBindingTable,
+ const VkStridedBufferRegionKHR* pMissShaderBindingTable,
+ const VkStridedBufferRegionKHR* pHitShaderBindingTable,
+ const VkStridedBufferRegionKHR* pCallableShaderBindingTable,
+ uint32_t width,
+ uint32_t height,
+ uint32_t depth)
{
vkCmdTraceRaysNV(commandBuffer,
pRaygenShaderBindingTable->buffer, pRaygenShaderBindingTable->offset,
@@ -415,22 +421,28 @@ void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer comma
width, height, depth);
}
-VkResult VKAPI_CALL Redirect_vkGetRayTracingShaderGroupHandlesKHR(VkDevice device,
- VkPipeline pipeline,
- uint32_t firstGroup,
- uint32_t groupCount,
- size_t dataSize,
- void* pData)
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkGetRayTracingShaderGroupHandlesKHR(VkDevice device,
+ VkPipeline pipeline,
+ uint32_t firstGroup,
+ uint32_t groupCount,
+ size_t dataSize,
+ void* pData)
{
return vkGetRayTracingShaderGroupHandlesNV(device, pipeline, firstGroup, groupCount, dataSize, pData);
}
-VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device,
- VkPipelineCache pipelineCache,
- uint32_t createInfoCount,
- const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
- const VkAllocationCallbacks* pAllocator,
- VkPipeline* pPipelines)
+VKAPI_ATTR void VKAPI_CALL Redirect_vkDestroyAccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator)
+{
+ return vkDestroyAccelerationStructureNV(device, accelerationStructure, pAllocator);
+}
+
+
+VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device,
+ VkPipelineCache pipelineCache,
+ uint32_t createInfoCount,
+ const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
+ const VkAllocationCallbacks* pAllocator,
+ VkPipeline* pPipelines)
{
std::vector<VkRayTracingPipelineCreateInfoNV> Infos;
std::vector<VkRayTracingShaderGroupCreateInfoNV> Groups;
@@ -506,6 +518,7 @@ void EnableRayTracingKHRviaNV()
vkGetRayTracingShaderGroupHandlesKHR = &Redirect_vkGetRayTracingShaderGroupHandlesKHR;
vkCreateRayTracingPipelinesKHR = &Redirect_vkCreateRayTracingPipelinesKHR;
vkCmdTraceRaysKHR = &Redirect_vkCmdTraceRaysKHR;
+ vkDestroyAccelerationStructureKHR = &Redirect_vkDestroyAccelerationStructureKHR;
Origin_vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressKHR;
Origin_vkCreateBuffer = vkCreateBuffer;