diff options
| author | azhirnov <zh1dron@gmail.com> | 2020-10-28 16:33:03 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2020-10-28 18:04:08 +0000 |
| commit | 135d5dc6743fc89d7a19c539fa06eca33506f51b (patch) | |
| tree | 9c8ed6e0d40a010f20657e62acbe955fba0757da /Graphics/GraphicsEngineVulkan | |
| parent | Fixed vexing gcc/clang liker error (diff) | |
| download | DiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.tar.gz DiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.zip | |
added ray tracing implementation for dx12 and vulkan
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
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; |
