From 7838459ef71fe5f0979f30df8348a6981363d6c8 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sun, 4 Oct 2020 23:23:28 +0300 Subject: Added Vulkan implementation --- Graphics/GraphicsEngineVulkan/CMakeLists.txt | 9 + .../include/BottomLevelASVkImpl.hpp | 68 +++++ .../GraphicsEngineVulkan/include/BufferVkImpl.hpp | 3 + .../include/DeviceContextVkImpl.hpp | 21 +- .../include/FramebufferVkImpl.hpp | 2 +- .../include/RenderDeviceVkImpl.hpp | 12 + .../include/RenderPassVkImpl.hpp | 2 +- .../include/ShaderBindingTableVkImpl.hpp | 112 ++++++++ .../include/TopLevelASVkImpl.hpp | 68 +++++ .../include/VulkanTypeConversions.hpp | 8 +- .../VulkanUtilities/VulkanCommandBuffer.hpp | 43 ++- .../include/VulkanUtilities/VulkanHeaders.h | 10 +- .../VulkanUtilities/VulkanLogicalDevice.hpp | 18 +- .../VulkanUtilities/VulkanPhysicalDevice.hpp | 20 +- .../interface/BottomLevelASVk.h | 68 +++++ Graphics/GraphicsEngineVulkan/interface/BufferVk.h | 4 + .../interface/ShaderBindingTableVk.h | 67 +++++ .../GraphicsEngineVulkan/interface/TopLevelASVk.h | 67 +++++ .../src/BottomLevelASVkImpl.cpp | 148 ++++++++++ Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp | 143 ++++++---- .../src/DeviceContextVkImpl.cpp | 298 ++++++++++++++++++++- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 44 ++- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 24 +- .../src/RenderDeviceVkImpl.cpp | 46 +++- .../src/ShaderBindingTableVkImpl.cpp | 196 ++++++++++++++ .../GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp | 106 ++++++++ .../src/VulkanTypeConversions.cpp | 125 ++++++++- .../src/VulkanUtilities/VulkanDebug.cpp | 27 ++ .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 51 +++- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 52 +++- 30 files changed, 1757 insertions(+), 105 deletions(-) create mode 100644 Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp create mode 100644 Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp create mode 100644 Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp create mode 100644 Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h create mode 100644 Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h create mode 100644 Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h create mode 100644 Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp create mode 100644 Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp create mode 100644 Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt index 323b4ccf..761653a4 100644 --- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt +++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt @@ -36,6 +36,9 @@ set(INCLUDE include/VulkanErrors.hpp include/VulkanTypeConversions.hpp include/VulkanUploadHeap.hpp + include/BottomLevelASVkImpl.hpp + include/TopLevelASVkImpl.hpp + include/ShaderBindingTableVkImpl.hpp ) set(VULKAN_UTILS_INCLUDE @@ -70,6 +73,9 @@ set(INTERFACE interface/SwapChainVk.h interface/TextureVk.h interface/TextureViewVk.h + interface/BottomLevelASVk.h + interface/TopLevelASVk.h + interface/ShaderBindingTableVk.h ) @@ -104,6 +110,9 @@ set(SRC src/TextureViewVkImpl.cpp src/VulkanTypeConversions.cpp src/VulkanUploadHeap.cpp + src/BottomLevelASVkImpl.cpp + src/TopLevelASVkImpl.cpp + src/ShaderBindingTableVkImpl.cpp ) set(VULKAN_UTILS_SRC diff --git a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp new file mode 100644 index 00000000..ccf8f574 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp @@ -0,0 +1,68 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::BottomLevelASVkImpl class + +#include "RenderDeviceVk.h" +#include "RenderDeviceVkImpl.hpp" +#include "BottomLevelASVk.h" +#include "BottomLevelASBase.hpp" +#include "VulkanUtilities/VulkanObjectWrappers.hpp" + +namespace Diligent +{ + +class BottomLevelASVkImpl final : public BottomLevelASBase +{ +public: + using TBottomLevelASBase = BottomLevelASBase; + + BottomLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const BottomLevelASDesc& Desc, + bool bIsDeviceInternal = false); + ~BottomLevelASVkImpl(); + + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; } + + virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkBLAS() const override { return m_VulkanBLAS; } + + virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override { return m_DeviceAddress; } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelASVk, TBottomLevelASBase); + +private: + VkDeviceAddress m_DeviceAddress; + VulkanUtilities::AccelStructWrapper m_VulkanBLAS; + VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; + ScratchBufferSizes m_ScratchSize; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.hpp index 8d1c187d..a3e3d438 100644 --- a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.hpp @@ -106,6 +106,9 @@ public: /// Implementation of IBufferVk::GetAccessFlags(). virtual VkAccessFlags DILIGENT_CALL_TYPE GetAccessFlags() const override final; + /// Implementation of IBufferVk::GetVkDeviceAddress(). + virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override final; + bool CheckAccessFlags(VkAccessFlags AccessFlags) const { return (GetAccessFlags() & AccessFlags) == AccessFlags; diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index e01178a5..26142ba0 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -135,13 +135,13 @@ public: ITextureView* pDepthStencil, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - /// Implementation of IDeviceContext::BeginRenderPass() in Direct3D11 backend. + /// Implementation of IDeviceContext::BeginRenderPass() in Vulkan backend. virtual void DILIGENT_CALL_TYPE BeginRenderPass(const BeginRenderPassAttribs& Attribs) override final; - /// Implementation of IDeviceContext::NextSubpass() in Direct3D11 backend. + /// Implementation of IDeviceContext::NextSubpass() in Vulkan backend. virtual void DILIGENT_CALL_TYPE NextSubpass() override final; - /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend. + /// Implementation of IDeviceContext::EndRenderPass() in Vulkan backend. virtual void DILIGENT_CALL_TYPE EndRenderPass() override final; // clang-format off @@ -249,6 +249,21 @@ public: /// Implementation of IDeviceContext::Flush() in Vulkan backend. virtual void DILIGENT_CALL_TYPE Flush() override final; + /// Implementation of IDeviceContext::BuildBLAS() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE BuildBLAS(const BLASBuildAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::BuildTLAS() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE BuildTLAS(const TLASBuildAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::CopyBLAS() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CopyBLAS(const CopyBLASAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::CopyTLAS() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CopyTLAS(const CopyTLASAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::TraceRays() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; + // Transitions texture subresources from OldState to NewState, and optionally updates // internal texture state. // If OldState == RESOURCE_STATE_UNKNOWN, internal texture state is used as old state. diff --git a/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp index f449d416..23097d22 100644 --- a/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp @@ -40,7 +40,7 @@ namespace Diligent class FixedBlockMemoryAllocator; -/// Render pass implementation in Direct3D11 backend. +/// Framebuffer implementation in Vulkan backend. class FramebufferVkImpl final : public FramebufferBase { public: diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 25a9f44b..94b91cae 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -112,6 +112,18 @@ public: virtual void DILIGENT_CALL_TYPE CreateFramebuffer(const FramebufferDesc& Desc, IFramebuffer** ppFramebuffer) override final; + /// Implementation of IRenderDevice::CreateBLAS() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateBLAS(const BottomLevelASDesc& Desc, + IBottomLevelAS** ppBLAS) override final; + + /// Implementation of IRenderDevice::CreateTLAS() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateTLAS(const TopLevelASDesc& Desc, + ITopLevelAS** ppTLAS) override final; + + /// Implementation of IRenderDevice::CreateSBT() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateSBT(const ShaderBindingTableDesc& Desc, + IShaderBindingTable** ppSBT) override final; + /// Implementation of IRenderDeviceVk::GetVkDevice(). virtual VkDevice DILIGENT_CALL_TYPE GetVkDevice() override final { return m_LogicalVkDevice->GetVkDevice(); } diff --git a/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp index 5c77784f..05962047 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp @@ -41,7 +41,7 @@ namespace Diligent class FixedBlockMemoryAllocator; -/// Render pass implementation in Direct3D11 backend. +/// Render pass implementation in Vulkan backend. class RenderPassVkImpl final : public RenderPassBase { public: diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp new file mode 100644 index 00000000..bba64381 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp @@ -0,0 +1,112 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::ShaderBindingTableVkImpl class + +#include "BufferVkImpl.hpp" +#include "RenderDeviceVk.h" +#include "RenderDeviceVkImpl.hpp" +#include "ShaderBindingTableVk.h" +#include "ShaderBindingTableBase.hpp" +#include "VulkanUtilities/VulkanObjectWrappers.hpp" + +namespace Diligent +{ + +class ShaderBindingTableVkImpl final : public ShaderBindingTableBase +{ +public: + using TShaderBindingTableBase = ShaderBindingTableBase; + + ShaderBindingTableVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const ShaderBindingTableDesc& Desc, + bool bIsDeviceInternal = false); + ~ShaderBindingTableVkImpl(); + + virtual void DILIGENT_CALL_TYPE Verify() const override; + + 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; + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTableVk, TShaderBindingTableBase); + +private: + void ValidateDesc(const ShaderBindingTableDesc& Desc) const; + +private: + RefCntAutoPtr m_pBuffer; + std::vector m_ShaderRecords; + Uint32 m_MissShadersOffset; + Uint32 m_HitGroupsOffset; + Uint32 m_CallbaleShadersOffset; + Uint32 m_MissShaderCount; + Uint32 m_HitGroupCount; + Uint32 m_CallableShaderCount; + Uint32 m_ShaderGroupHandleSize; + Uint32 m_ShaderGroupBaseAlignment; + +#ifdef DILIGENT_DEBUG +#endif +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp new file mode 100644 index 00000000..311266e7 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -0,0 +1,68 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::TopLevelASVkImpl class + +#include "RenderDeviceVk.h" +#include "RenderDeviceVkImpl.hpp" +#include "TopLevelASVk.h" +#include "TopLevelASBase.hpp" +#include "VulkanUtilities/VulkanObjectWrappers.hpp" + +namespace Diligent +{ + +class TopLevelASVkImpl final : public TopLevelASBase +{ +public: + using TTopLevelASBase = TopLevelASBase; + + TopLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const TopLevelASDesc& Desc, + bool bIsDeviceInternal = false); + ~TopLevelASVkImpl(); + + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; } + + virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkTLAS() const override { return m_VulkanTLAS; } + + virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override { return m_DeviceAddress; } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelASVk, TTopLevelASBase); + +private: + VkDeviceAddress m_DeviceAddress; + VulkanUtilities::AccelStructWrapper m_VulkanTLAS; + VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; + ScratchBufferSizes m_ScratchSize; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp index dbba5b7e..51083968 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp @@ -40,7 +40,8 @@ namespace Diligent VkFormat TexFormatToVkFormat(TEXTURE_FORMAT TexFmt); TEXTURE_FORMAT VkFormatToTexFormat(VkFormat VkFmt); -VkFormat TypeToVkFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormalized); +VkFormat TypeToVkFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormalized); +VkIndexType TypeToVkIndexType(VALUE_TYPE IndexType); VkPipelineRasterizationStateCreateInfo RasterizerStateDesc_To_VkRasterizationStateCI(const struct RasterizerStateDesc& RasterizerDesc); VkPipelineDepthStencilStateCreateInfo DepthStencilStateDesc_To_VkDepthStencilStateCI(const struct DepthStencilStateDesc& DepthStencilDesc); @@ -82,4 +83,9 @@ ATTACHMENT_STORE_OP VkAttachmentStoreOpToAttachmentStoreOp(VkAttachmentStoreOp V VkPipelineStageFlags PipelineStageFlagsToVkPipelineStageFlags(PIPELINE_STAGE_FLAGS PipelineStageFlags); VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags); +VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags); +VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags); +VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags); +VkCopyAccelerationStructureModeKHR CopyASModeToVkCopyAccelerationStructureMode(COPY_AS_MODE Mode); + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp index 7d66600d..04189820 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp @@ -140,27 +140,27 @@ public: __forceinline void DrawMesh(uint32_t TaskCount, uint32_t FirstTask) { -#ifdef VK_NV_mesh_shader +#if DILIGENT_USE_VOLK VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksNV() must be called inside render pass"); VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound"); vkCmdDrawMeshTasksNV(m_VkCmdBuffer, TaskCount, FirstTask); #else - UNSUPPORTED("DrawMesh is not supported in current Vulkan headers"); + UNSUPPORTED("DrawMesh is not supported when vulkan library linked statically"); #endif } __forceinline void DrawMeshIndirect(VkBuffer Buffer, VkDeviceSize Offset, uint32_t DrawCount, uint32_t Stride) { -#ifdef VK_NV_mesh_shader +#if DILIGENT_USE_VOLK VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksNV() must be called inside render pass"); VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound"); vkCmdDrawMeshTasksIndirectNV(m_VkCmdBuffer, Buffer, Offset, DrawCount, Stride); #else - UNSUPPORTED("DrawMeshIndirect is not supported in current Vulkan headers"); + UNSUPPORTED("DrawMeshIndirect is not supported when vulkan library linked statically"); #endif } @@ -570,6 +570,41 @@ public: dstBuffer, dstOffset, stride, flags); } + __forceinline void BuildAccelerationStructure(uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos) + { +#if DILIGENT_USE_VOLK + vkCmdBuildAccelerationStructureKHR(m_VkCmdBuffer, infoCount, pInfos, ppOffsetInfos); +#else + UNSUPPORTED("Ray tracing is not supported when vulkan library linked statically"); +#endif + } + + __forceinline void CopyAccelerationStructure(const VkCopyAccelerationStructureInfoKHR& Info) + { +#if DILIGENT_USE_VOLK + vkCmdCopyAccelerationStructureKHR(m_VkCmdBuffer, &Info); +#else + UNSUPPORTED("Ray tracing is not supported when vulkan library linked statically"); +#endif + } + + __forceinline void TraceRays(const VkStridedBufferRegionKHR& RaygenShaderBindingTable, + const VkStridedBufferRegionKHR& MissShaderBindingTable, + const VkStridedBufferRegionKHR& HitShaderBindingTable, + const VkStridedBufferRegionKHR& CallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth) + { +#if DILIGENT_USE_VOLK + vkCmdTraceRaysKHR(m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, width, height, depth); +#else + UNSUPPORTED("Ray tracing is not supported when vulkan library linked statically"); +#endif + } + void FlushBarriers(); __forceinline void SetVkCmdBuffer(VkCommandBuffer VkCmdBuffer) diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h index ee6461fd..769391cf 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h @@ -30,15 +30,17 @@ #if DILIGENT_USE_VOLK # define VK_NO_PROTOTYPES #endif + +// TODO: remove it when ray tracing will be released +#define VK_ENABLE_BETA_EXTENSIONS + #include "vulkan/vulkan.h" +#include "vulkan/vulkan_beta.h" + #define VK_FORMAT_RANGE_SIZE (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1) #if DILIGENT_USE_VOLK # include "volk/volk.h" -#else -// Don't use extensions when statically linked with Vulkan -# undef VK_KHR_get_physical_device_properties2 -# undef VK_NV_mesh_shader #endif #if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(_X11_XLIB_H_) diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp index 3f06cb0e..c2fba2a4 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp @@ -28,7 +28,7 @@ #pragma once #include -#include "VulkanHeaders.h" +#include "VulkanPhysicalDevice.hpp" namespace VulkanUtilities { @@ -57,7 +57,8 @@ enum class VulkanHandleTypeId : uint32_t Semaphore, Queue, Event, - QueryPool + QueryPool, + AccelerationStructureKHR }; template @@ -81,12 +82,13 @@ using DescriptorPoolWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(DescriptorPool); using DescriptorSetLayoutWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(DescriptorSetLayout); using SemaphoreWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(Semaphore); using QueryPoolWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(QueryPool); +using AccelStructWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(AccelerationStructureKHR); #undef DEFINE_VULKAN_OBJECT_WRAPPER class VulkanLogicalDevice : public std::enable_shared_from_this { public: - static std::shared_ptr Create(VkPhysicalDevice vkPhysicalDevice, + static std::shared_ptr Create(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, const VkAllocationCallbacks* vkAllocator); @@ -140,6 +142,7 @@ public: SemaphoreWrapper CreateSemaphore(const VkSemaphoreCreateInfo& SemaphoreCI, const char* DebugName = "") const; QueryPoolWrapper CreateQueryPool(const VkQueryPoolCreateInfo& QueryPoolCI, const char* DebugName = "") const; + AccelStructWrapper CreateAccelStruct(const VkAccelerationStructureCreateInfoKHR& CI, const char* DebugName = "") const; VkCommandBuffer AllocateVkCommandBuffer(const VkCommandBufferAllocateInfo& AllocInfo, const char* DebugName = "") const; VkDescriptorSet AllocateVkDescriptorSet(const VkDescriptorSetAllocateInfo& AllocInfo, const char* DebugName = "") const; @@ -161,14 +164,19 @@ public: void ReleaseVulkanObject(DescriptorSetLayoutWrapper&& DescriptorSetLayout) const; void ReleaseVulkanObject(SemaphoreWrapper&& Semaphore) const; void ReleaseVulkanObject(QueryPoolWrapper&& QueryPool) const; + void ReleaseVulkanObject(AccelStructWrapper&& AccelStruct) const; void FreeDescriptorSet(VkDescriptorPool Pool, VkDescriptorSet Set) const; VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer vkBuffer) const; - VkMemoryRequirements GetImageMemoryRequirements (VkImage vkImage ) const; + VkMemoryRequirements GetImageMemoryRequirements (VkImage vkImage ) const; + + VkMemoryRequirements GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const; + VkDeviceAddress GetAccelerationStructureDeviceAddress(VkAccelerationStructureKHR AS) const; VkResult BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const; VkResult BindImageMemory (VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) const; + VkResult BindASMemory (VkAccelerationStructureKHR AS, VkDeviceMemory memory, VkDeviceSize memoryOffset) const; // clang-format on VkResult MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const; @@ -212,7 +220,7 @@ public: const VkPhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; } private: - VulkanLogicalDevice(VkPhysicalDevice vkPhysicalDevice, + VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, const VkAllocationCallbacks* vkAllocator); diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp index b4e734c7..1e9a6edf 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp @@ -39,10 +39,20 @@ class VulkanPhysicalDevice public: struct ExtensionFeatures { - VkPhysicalDeviceMeshShaderFeaturesNV MeshShader = {}; - VkPhysicalDevice16BitStorageFeaturesKHR Storage16Bit = {}; - VkPhysicalDevice8BitStorageFeaturesKHR Storage8Bit = {}; - VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {}; + VkPhysicalDeviceMeshShaderFeaturesNV MeshShader = {}; + VkPhysicalDevice16BitStorageFeaturesKHR Storage16Bit = {}; + VkPhysicalDevice8BitStorageFeaturesKHR Storage8Bit = {}; + VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {}; + VkPhysicalDeviceRayTracingFeaturesKHR RayTracing = {}; + VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {}; + VkPhysicalDeviceDescriptorIndexingFeaturesEXT DescriptorIndexing = {}; + }; + + struct ExtensionProperties + { + VkPhysicalDeviceMeshShaderPropertiesNV MeshShader = {}; + VkPhysicalDeviceRayTracingPropertiesKHR RayTracing = {}; + VkPhysicalDeviceDescriptorIndexingPropertiesEXT DescriptorIndexing = {}; }; public: @@ -70,6 +80,7 @@ public: const VkPhysicalDeviceProperties& GetProperties() const { return m_Properties; } const VkPhysicalDeviceFeatures& GetFeatures() const { return m_Features; } const ExtensionFeatures& GetExtFeatures() const { return m_ExtFeatures; } + const ExtensionProperties& GetExtProperties() const { return m_ExtProperties; } const VkPhysicalDeviceMemoryProperties& GetMemoryProperties() const { return m_MemoryProperties; } VkFormatProperties GetPhysicalDeviceFormatProperties(VkFormat imageFormat) const; @@ -82,6 +93,7 @@ private: VkPhysicalDeviceFeatures m_Features = {}; VkPhysicalDeviceMemoryProperties m_MemoryProperties = {}; ExtensionFeatures m_ExtFeatures = {}; + ExtensionProperties m_ExtProperties = {}; std::vector m_QueueFamilyProperties; std::vector m_SupportedExtensions; }; diff --git a/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h new file mode 100644 index 00000000..eb0c2da5 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h @@ -0,0 +1,68 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::IBottomLevelASVk interface + +#include "../../GraphicsEngine/interface/BottomLevelAS.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + + +// {7212AFC9-02E2-4D7F-81A8-1CE5353CEA2D} +static const INTERFACE_ID IID_BottomLevelASVk = + {0x7212afc9, 0x2e2, 0x4d7f, {0x81, 0xa8, 0x1c, 0xe5, 0x35, 0x3c, 0xea, 0x2d}}; + +#define DILIGENT_INTERFACE_NAME IBottomLevelASVk +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define IBottomLevelASVkInclusiveMethods \ + IBottomLevelASInclusiveMethods; \ + IBottomLevelASVkMethods BottomLevelASVk + +/// Exposes Vulkan-specific functionality of a Bottom-level acceleration structure object. +DILIGENT_BEGIN_INTERFACE(IBottomLevelASVk, IBottomLevelAS) +{ + /// Returns a Vulkan BLAS object handle + VIRTUAL VkAccelerationStructureKHR METHOD(GetVkBLAS)(THIS) CONST PURE; + + /// Returns a Vulkan BLAS device address + VIRTUAL VkDeviceAddress METHOD(GetVkDeviceAddress)(THIS) CONST PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +# define IBottomLevelASVk_GetVkBLAS(This) CALL_IFACE_METHOD(BottomLevelASVk, GetVkBLAS, This) + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h index ea889795..0c95af96 100644 --- a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h @@ -62,6 +62,9 @@ DILIGENT_BEGIN_INTERFACE(IBufferVk, IBuffer) /// If the buffer state is known to the engine (i.e. not Diligent::RESOURCE_STATE_UNKNOWN), /// returns Vulkan access flags corresponding to the state. If the state is unknown, returns 0. VIRTUAL VkAccessFlags METHOD(GetAccessFlags)(THIS) CONST PURE; + + /// Returns a vulkan device address + VIRTUAL VkDeviceAddress METHOD(GetVkDeviceAddress)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE @@ -72,6 +75,7 @@ DILIGENT_END_INTERFACE # define IBufferVk_GetVkBuffer(This) CALL_IFACE_METHOD(BufferVk, GetVkBuffer, This) # define IBufferVk_SetAccessFlags(This, ...) CALL_IFACE_METHOD(BufferVk, SetAccessFlags, This, __VA_ARGS__) # define IBufferVk_GetAccessFlags(This) CALL_IFACE_METHOD(BufferVk, GetAccessFlags, This) +# define IBufferVk_GetVkDeviceAddress(This) CALL_IFACE_METHOD(BufferVk, GetVkDeviceAddress, This) #endif diff --git a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h new file mode 100644 index 00000000..e3222728 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h @@ -0,0 +1,67 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::IShaderBindingTableVk interface + +#include "../../GraphicsEngine/interface/ShaderBindingTable.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {31ED9B4B-4FF4-44D8-AE71-12B5D8AF7F93} +static const INTERFACE_ID IID_ShaderBindingTableVk = + {0x31ed9b4b, 0x4ff4, 0x44d8, {0xae, 0x71, 0x12, 0xb5, 0xd8, 0xaf, 0x7f, 0x93}}; + +#define DILIGENT_INTERFACE_NAME IShaderBindingTableVk +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define IShaderBindingTableVkInclusiveMethods \ + IShaderBindingTableInclusiveMethods; \ + IShaderBindingTableVkMethods ShaderBindingTableVk + +/// Exposes Vulkan-specific functionality of a Shader binding table object. +DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable) +{ + /// AZ TODO + VIRTUAL void METHOD(GetVkStridedBufferRegions)(VkStridedBufferRegionKHR & RaygenShaderBindingTable, + VkStridedBufferRegionKHR & MissShaderBindingTable, + VkStridedBufferRegionKHR & HitShaderBindingTable, + VkStridedBufferRegionKHR & CallableShaderBindingTable) PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +# define IShaderBindingTableVk_GetVkStridedBufferRegions(This, ...) CALL_IFACE_METHOD(ShaderBindingTableVk, GetVkStridedBufferRegions, This, __VA_ARGS__) + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h new file mode 100644 index 00000000..3d0b8b09 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h @@ -0,0 +1,67 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::ITopLevelASVk interface + +#include "../../GraphicsEngine/interface/TopLevelAS.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {356FFFFA-9E57-49F7-8FF4-7017B61BE6A8} +static const INTERFACE_ID IID_TopLevelASVk = + {0x356ffffa, 0x9e57, 0x49f7, {0x8f, 0xf4, 0x70, 0x17, 0xb6, 0x1b, 0xe6, 0xa8}}; + +#define DILIGENT_INTERFACE_NAME ITopLevelASVk +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define ITopLevelASVkInclusiveMethods \ + ITopLevelASInclusiveMethods; \ + ITopLevelASVkMethods TopLevelASVk + +/// Exposes Vulkan-specific functionality of a Top-level acceleration structure object. +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 + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This) + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp new file mode 100644 index 00000000..85c74834 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -0,0 +1,148 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "BottomLevelASVkImpl.hpp" +#include "VulkanTypeConversions.hpp" + +namespace Diligent +{ + +BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const BottomLevelASDesc& Desc, + bool bIsDeviceInternal) : + TBottomLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal}, + m_DeviceAddress{0} +{ + const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); + const auto& Limits = PhysicalDevice.GetExtProperties().RayTracing; + + VkAccelerationStructureCreateInfoKHR CreateInfo = {}; + std::vector Geometries; + + CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); + CreateInfo.maxGeometryCount = std::max(m_Desc.BoxCount, m_Desc.TriangleCount); + CreateInfo.compactedSize = 0; // AZ TODO + + VERIFY_EXPR(CreateInfo.maxGeometryCount <= Limits.maxGeometryCount); + + Geometries.resize(CreateInfo.maxGeometryCount); + CreateInfo.pGeometryInfos = Geometries.data(); + + // Specs says: the geometryType member of each geometry in pGeometries must be the same. + if (m_Desc.pTriangles != nullptr) + { + Uint32 MaxPrimitiveCount = 0; + for (uint32_t i = 0; i < CreateInfo.maxGeometryCount; ++i) + { + auto& src = m_Desc.pTriangles[i]; + auto& dst = Geometries[i]; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + dst.maxPrimitiveCount = (src.IndexType == VT_UNDEFINED ? src.MaxVertexCount : src.MaxIndexCount) / 3; + dst.indexType = TypeToVkIndexType(src.IndexType); + dst.maxVertexCount = src.MaxVertexCount; + dst.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); + dst.allowsTransforms = src.AllowsTransforms; + + MaxPrimitiveCount += dst.maxPrimitiveCount; + } + VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxPrimitiveCount); + } + else if (m_Desc.pBoxes != nullptr) + { + Uint32 MaxBoxCount = 0; + for (uint32_t i = 0; i < CreateInfo.maxGeometryCount; ++i) + { + auto& src = m_Desc.pBoxes[i]; + auto& dst = Geometries[i]; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; + dst.maxPrimitiveCount = src.MaxBoxCount; + dst.indexType = VK_INDEX_TYPE_NONE_KHR; + dst.maxVertexCount = 0; + dst.vertexFormat = VK_FORMAT_UNDEFINED; + dst.allowsTransforms = VK_FALSE; + + MaxBoxCount += dst.maxPrimitiveCount; + } + VERIFY_EXPR(MaxBoxCount <= Limits.maxPrimitiveCount); + } + + m_VulkanBLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); + + VkAccelerationStructureMemoryRequirementsInfoKHR MemInfo = {}; + VkMemoryRequirements MemReqs = {}; + + MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; + MemInfo.accelerationStructure = m_VulkanBLAS; + MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; + + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + + uint32_t MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex) + 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); + + auto Memory = m_MemoryAllocation.Page->GetVkMemory(); + auto err = LogicalDevice.BindASMemory(m_VulkanBLAS, Memory, 0); + CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory"); + + m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanBLAS); + + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Build = static_cast(MemReqs.size); + + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Update = static_cast(MemReqs.size); +} + +BottomLevelASVkImpl::~BottomLevelASVkImpl() +{ + // Vk object can only be destroyed when it is no longer used by the GPU + if (m_VulkanBLAS != VK_NULL_HANDLE) + m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanBLAS), m_Desc.CommandQueueMask); + if (m_MemoryAllocation.Page != nullptr) + m_pDevice->SafeReleaseDeviceObject(std::move(m_MemoryAllocation), m_Desc.CommandQueueMask); +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp index 8edb3472..80130696 100644 --- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp @@ -86,54 +86,86 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters, VkBuffCI.usage = 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 - if (m_Desc.BindFlags & BIND_UNORDERED_ACCESS) - { - // VkBuffCI.usage |= m_Desc.Mode == BUFFER_MODE_FORMATTED ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - // HLSL formatted buffers are mapped to GLSL storage buffers: - // - // RWBuffer RWBuff - // - // | - // V - // - // layout(std140, binding = 3) buffer RWBuff - // { - // uvec4 data[]; - // }g_RWBuff; - // - // So we have to set both VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT and VK_BUFFER_USAGE_STORAGE_BUFFER_BIT bits - VkBuffCI.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - - // Each element of pDynamicOffsets of vkCmdBindDescriptorSets function which corresponds to a descriptor - // binding with type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC must be a multiple of - // VkPhysicalDeviceLimits::minStorageBufferOffsetAlignment (13.2.5) - m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minTexelBufferOffsetAlignment)); - m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minStorageBufferOffsetAlignment)); - } - if (m_Desc.BindFlags & BIND_SHADER_RESOURCE) - { - // VkBuffCI.usage |= m_Desc.Mode == BUFFER_MODE_FORMATTED ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - // HLSL buffer SRVs are mapped to storge buffers in GLSL, so we need to set both - // VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT and VK_BUFFER_USAGE_STORAGE_BUFFER_BIT flags - VkBuffCI.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minTexelBufferOffsetAlignment)); - m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minStorageBufferOffsetAlignment)); - } - if (m_Desc.BindFlags & BIND_VERTEX_BUFFER) - VkBuffCI.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - if (m_Desc.BindFlags & BIND_INDEX_BUFFER) - VkBuffCI.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - if (m_Desc.BindFlags & BIND_INDIRECT_DRAW_ARGS) - VkBuffCI.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; - if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER) + static_assert(BIND_FLAGS_LAST == 0x400, "AZ TODO"); + + for (Uint32 BindFlag = 1; BindFlag <= m_Desc.BindFlags; BindFlag <<= 1) { - VkBuffCI.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + if ((m_Desc.BindFlags & BindFlag) != BindFlag) + continue; + + switch (BindFlag) + { + case BIND_UNORDERED_ACCESS: + { + // VkBuffCI.usage |= m_Desc.Mode == BUFFER_MODE_FORMATTED ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + // HLSL formatted buffers are mapped to GLSL storage buffers: + // + // RWBuffer RWBuff + // + // | + // V + // + // layout(std140, binding = 3) buffer RWBuff + // { + // uvec4 data[]; + // }g_RWBuff; + // + // So we have to set both VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT and VK_BUFFER_USAGE_STORAGE_BUFFER_BIT bits + VkBuffCI.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + + // Each element of pDynamicOffsets of vkCmdBindDescriptorSets function which corresponds to a descriptor + // binding with type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC must be a multiple of + // VkPhysicalDeviceLimits::minStorageBufferOffsetAlignment (13.2.5) + m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minTexelBufferOffsetAlignment)); + m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minStorageBufferOffsetAlignment)); + break; + } + case BIND_SHADER_RESOURCE: + { + // VkBuffCI.usage |= m_Desc.Mode == BUFFER_MODE_FORMATTED ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + // HLSL buffer SRVs are mapped to storge buffers in GLSL, so we need to set both + // VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT and VK_BUFFER_USAGE_STORAGE_BUFFER_BIT flags + VkBuffCI.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + + m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minTexelBufferOffsetAlignment)); + m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minStorageBufferOffsetAlignment)); + break; + } + case BIND_VERTEX_BUFFER: + { + VkBuffCI.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + break; + } + case BIND_INDEX_BUFFER: + { + VkBuffCI.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + break; + } + case BIND_INDIRECT_DRAW_ARGS: + { + VkBuffCI.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; + break; + } + case BIND_UNIFORM_BUFFER: + { + VkBuffCI.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - // Each element of pDynamicOffsets parameter of vkCmdBindDescriptorSets function which corresponds to a descriptor - // binding with type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC must be a multiple of - // VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment (13.2.5) - m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minUniformBufferOffsetAlignment)); + // Each element of pDynamicOffsets parameter of vkCmdBindDescriptorSets function which corresponds to a descriptor + // binding with type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC must be a multiple of + // VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment (13.2.5) + m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast(DeviceLimits.minUniformBufferOffsetAlignment)); + break; + } + case BIND_RAY_TRACING: + { + VkBuffCI.usage |= VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + break; + } + default: + UNEXPECTED("unsupported buffer binding type"); + break; + } } if (m_Desc.Usage == USAGE_DYNAMIC) @@ -457,6 +489,27 @@ VkAccessFlags BufferVkImpl::GetAccessFlags() const return ResourceStateFlagsToVkAccessFlags(GetState()); } +VkDeviceAddress BufferVkImpl::GetVkDeviceAddress() const +{ + constexpr auto DeviceAddressFlags = BIND_RAY_TRACING; + + if (m_VulkanBuffer != VK_NULL_HANDLE && !!(m_Desc.BindFlags & DeviceAddressFlags)) + { + VkBufferDeviceAddressInfoKHR BufferInfo = {}; + + BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR; + BufferInfo.buffer = m_VulkanBuffer; + VkDeviceAddress Result = vkGetBufferDeviceAddressKHR(m_pDevice->GetLogicalDevice().GetVkDevice(), &BufferInfo); + VERIFY_EXPR(Result > 0); + return Result; + } + else + { + UNEXPECTED("Can't get device address for buffer"); + return 0; + } +} + #ifdef DILIGENT_DEVELOPMENT void BufferVkImpl::DvpVerifyDynamicAllocation(DeviceContextVkImpl* pCtx) const { diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 2d7b9591..d3f87287 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -36,6 +36,9 @@ #include "VulkanTypeConversions.hpp" #include "CommandListVkImpl.hpp" #include "FenceVkImpl.hpp" +#include "BottomLevelASVkImpl.hpp" +#include "TopLevelASVkImpl.hpp" +#include "ShaderBindingTableVkImpl.hpp" #include "GraphicsAccessories.hpp" namespace Diligent @@ -514,7 +517,7 @@ void DeviceContextVkImpl::PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE Ind } #endif DEV_CHECK_ERR(IndexType == VT_UINT16 || IndexType == VT_UINT32, "Unsupported index format. Only R16_UINT and R32_UINT are allowed."); - VkIndexType vkIndexType = IndexType == VT_UINT16 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32; + VkIndexType vkIndexType = TypeToVkIndexType(IndexType); m_CommandBuffer.BindIndexBuffer(m_pIndexBuffer->GetVkBuffer(), m_IndexDataStartOffset + m_pIndexBuffer->GetDynamicOffset(m_ContextId, this), vkIndexType); } @@ -575,6 +578,12 @@ void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs) if (!DvpVerifyDrawMeshArguments(Attribs)) return; +#ifdef DILIGENT_DEBUG + auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().MeshShader.meshShader == VK_TRUE && PhysicalDevice.GetExtFeatures().MeshShader.taskShader == VK_TRUE); + VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount); +#endif + PrepareForDraw(Attribs.Flags); m_CommandBuffer.DrawMesh(Attribs.ThreadGroupCount, 0); @@ -586,6 +595,11 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib if (!DvpVerifyDrawMeshIndirectArguments(Attribs, pAttribsBuffer)) return; +#ifdef DILIGENT_DEBUG + auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().MeshShader.meshShader == VK_TRUE && PhysicalDevice.GetExtFeatures().MeshShader.taskShader == VK_TRUE); +#endif + // We must prepare indirect draw attribs buffer first because state transitions must // be performed outside of render pass, and PrepareForDraw commits render pass BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode); @@ -2597,4 +2611,286 @@ void DeviceContextVkImpl::ResolveTextureSubresource(ITexture* 1, &ResolveRegion); } +void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) +{ + if (!TDeviceContextBase::BuildBLAS(Attribs, 0)) + return; + + + // AZ TODO: transitions + +#ifdef DILIGENT_DEBUG + auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); +#endif + + auto* pBLASVk = ValidatedCast(Attribs.pBLAS); + auto* pScratchVk = ValidatedCast(Attribs.pScratchBuffer); + auto& BLASDesc = pBLASVk->GetDesc(); + + VkAccelerationStructureBuildGeometryInfoKHR Info = {}; + std::vector Offsets; + std::vector Geometries; + + if (Attribs.pTriangleData != nullptr) + { + Geometries.resize(Attribs.TriangleDataCount); + Offsets.resize(Attribs.TriangleDataCount); + + for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) + { + auto& src = Attribs.pTriangleData[i]; + Uint32 j = pBLASVk->GetGeometryIndex(src.GeometryName); + auto& dst = Geometries.data()[j]; + auto& tri = dst.geometry.triangles; + auto& off = Offsets.data()[j]; + + if (j >= Geometries.size()) + { + UNEXPECTED("Failed to find geometry by name"); + continue; + } + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + dst.pNext = nullptr; + dst.flags = GeometryFlagsToVkGeometryFlags(src.Flags); + dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + tri.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + tri.pNext = nullptr; + + auto* pVB = ValidatedCast(src.pVertexBuffer); + tri.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); + tri.vertexStride = src.VertexStride; + tri.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + src.VertexOffset; + + if (src.pIndexBuffer) + { + auto* pIB = ValidatedCast(src.pIndexBuffer); + tri.indexType = TypeToVkIndexType(src.IndexType); + tri.indexData.deviceAddress = pIB->GetVkDeviceAddress() + src.IndexOffset; + off.primitiveCount = src.IndexCount / 3; + } + else + { + tri.indexType = VK_INDEX_TYPE_NONE_KHR; + tri.indexData.deviceAddress = 0; + off.primitiveCount = src.VertexCount / 3; + } + + if (src.pTransformBuffer) + { + auto* pTB = ValidatedCast(src.pTransformBuffer); + tri.transformData.deviceAddress = pTB->GetVkDeviceAddress() + src.TransformBufferOffset; + } + else + tri.transformData.deviceAddress = 0; + + off.firstVertex = 0; + off.primitiveOffset = 0; + off.transformOffset = 0; + } + } + else if (Attribs.pBoxData != nullptr) + { + Geometries.resize(Attribs.BoxDataCount); + Offsets.resize(Attribs.BoxDataCount); + + for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) + { + auto& src = Attribs.pBoxData[i]; + Uint32 j = pBLASVk->GetGeometryIndex(src.GeometryName); + auto& dst = Geometries.data()[j]; + auto& box = dst.geometry.aabbs; + auto& off = Offsets.data()[j]; + + if (j >= Geometries.size()) + { + UNEXPECTED("Failed to find geometry by name"); + continue; + } + + auto* pBB = ValidatedCast(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; + + off.firstVertex = 0; + off.transformOffset = 0; + off.primitiveOffset = 0; + off.primitiveCount = src.BoxCount; + } + } + + VkAccelerationStructureGeometryKHR const* GeometriesPtr = Geometries.data(); + VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = Offsets.data(); + + Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + Info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; // type must be compatible with create info + Info.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(BLASDesc.Flags); // flags must be compatible with create info + Info.update = VK_FALSE; + Info.srcAccelerationStructure = VK_NULL_HANDLE; + Info.dstAccelerationStructure = pBLASVk->GetVkBLAS(); + Info.geometryArrayOfPointers = VK_FALSE; + Info.geometryCount = static_cast(Geometries.size()); + Info.ppGeometries = &GeometriesPtr; + Info.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset; + + EnsureVkCmdBuffer(); + m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr); +} + +void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) +{ + if (!TDeviceContextBase::BuildTLAS(Attribs, 0)) + return; + + static_assert(TLASInstanceDataSize == sizeof(VkAccelerationStructureInstanceKHR), "AZ TODO"); + + // AZ TODO: transitions + +#ifdef DILIGENT_DEBUG + auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); +#endif + + auto* pTLASVk = ValidatedCast(Attribs.pTLAS); + auto* pScratchVk = ValidatedCast(Attribs.pScratchBuffer); + auto* pInstancesVk = ValidatedCast(Attribs.pInstancesBuffer); + auto& TLASDesc = pTLASVk->GetDesc(); + + pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount); + + // copy instance data into instance buffer + { + size_t Size = Attribs.InstanceCount * sizeof(VkAccelerationStructureInstanceKHR); + auto TmpSpace = m_UploadHeap.Allocate(Size, 16); + void* pMappedInstances = TmpSpace.CPUAddress; + + for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) + { + auto& src = Attribs.pInstances[i]; + auto& dst = static_cast(pMappedInstances)[i]; + auto* pBLASVk = ValidatedCast(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.mask = src.Mask; + dst.flags = InstanceFlagsToVkGeometryInstanceFlags(src.Flags); + dst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); + } + + UpdateBufferRegion(pInstancesVk, Attribs.InstancesBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode); + } + + VkAccelerationStructureBuildGeometryInfoKHR Info = {}; + VkAccelerationStructureBuildOffsetInfoKHR Offset = {}; + VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = &Offset; + VkAccelerationStructureGeometryKHR Geometry = {VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR}; + VkAccelerationStructureGeometryKHR const* GeometriesPtr = &Geometry; + + Offset.primitiveCount = Attribs.InstanceCount; + + Geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + auto& inst = Geometry.geometry.instances; + inst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + inst.arrayOfPointers = VK_FALSE; + inst.data.deviceAddress = pInstancesVk->GetVkDeviceAddress() + Attribs.InstancesBufferOffset; + + 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 + Info.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(TLASDesc.Flags); // flags must be compatible with create info + Info.update = VK_FALSE; + Info.srcAccelerationStructure = VK_NULL_HANDLE; + Info.dstAccelerationStructure = pTLASVk->GetVkTLAS(); + Info.geometryArrayOfPointers = VK_FALSE; + Info.geometryCount = 1; + Info.ppGeometries = &GeometriesPtr; + Info.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset; + + EnsureVkCmdBuffer(); + m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr); +} + +void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) +{ + if (!TDeviceContextBase::CopyBLAS(Attribs, 0)) + return; + + // AZ TODO: transitions + +#ifdef DILIGENT_DEBUG + auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); +#endif + + auto* pSrcVk = ValidatedCast(Attribs.pSrc); + auto* pDstVk = ValidatedCast(Attribs.pDst); + + VkCopyAccelerationStructureInfoKHR Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; + Info.src = pSrcVk->GetVkBLAS(); + Info.dst = pDstVk->GetVkBLAS(); + Info.mode = CopyASModeToVkCopyAccelerationStructureMode(Attribs.Mode); + + EnsureVkCmdBuffer(); + m_CommandBuffer.CopyAccelerationStructure(Info); +} + +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); +#endif + + auto* pSrcVk = ValidatedCast(Attribs.pSrc); + auto* pDstVk = ValidatedCast(Attribs.pDst); + + VkCopyAccelerationStructureInfoKHR Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; + Info.src = pSrcVk->GetVkTLAS(); + Info.dst = pDstVk->GetVkTLAS(); + Info.mode = CopyASModeToVkCopyAccelerationStructureMode(Attribs.Mode); + + EnsureVkCmdBuffer(); + m_CommandBuffer.CopyAccelerationStructure(Info); +} + +void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) +{ + if (!TDeviceContextBase::TraceRays(Attribs, 0)) + return; + + // AZ TODO: transitions + +#ifdef DILIGENT_DEBUG + auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); +#endif + + VkStridedBufferRegionKHR RaygenShaderBindingTable = {}; + VkStridedBufferRegionKHR MissShaderBindingTable = {}; + VkStridedBufferRegionKHR HitShaderBindingTable = {}; + VkStridedBufferRegionKHR CallableShaderBindingTable = {}; + + auto* pSBTVk = ValidatedCast(Attribs.pSBT); + + pSBTVk->GetVkStridedBufferRegions(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable); + + EnsureVkCmdBuffer(); + m_CommandBuffer.TraceRays(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable, + Attribs.DimensionX, Attribs.DimensionY, Attribs.DimensionZ); +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 6a81faba..185f1da5 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -269,15 +269,24 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); // clang-format on + + auto RayTracingFeats = DeiceExtFeatures.RayTracing; + auto BufferDeviceAddressFeats = DeiceExtFeatures.BufferDeviceAddress; + auto DescriptorIndexingFeats = DeiceExtFeatures.DescriptorIndexing; + ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE, MeshShaders, "Ray tracing are"); #undef FeatureSupport // To enable some device extensions you must enable instance extension VK_KHR_get_physical_device_properties2 // and add feature description to DeviceCreateInfo.pNext. - const auto SupportsFeatures2 = Instance->IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + bool SupportsFeatures2 = Instance->IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + + // Enable extensions if (SupportsFeatures2) { void** NextExt = const_cast(&DeviceCreateInfo.pNext); + + // Mesh shader if (EngineCI.Features.MeshShaders != DEVICE_FEATURE_STATE_DISABLED) { VERIFY_EXPR(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE); @@ -383,21 +392,42 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E DeviceExtensions.push_back(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME); } - *NextExt = nullptr; - } + // Ray tracing + if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED) + { + if (RayTracingFeats.rayTracing != VK_FALSE) + { + // required extensions + DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); + DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); + DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); + DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); + DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); + DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME); + + *NextExt = &RayTracingFeats; + NextExt = &RayTracingFeats.pNext; + *NextExt = &DescriptorIndexingFeats; + NextExt = &DescriptorIndexingFeats.pNext; + *NextExt = &BufferDeviceAddressFeats; + NextExt = &BufferDeviceAddressFeats.pNext; + } + } + // make sure that last pNext is null + *NextExt = nullptr; + } #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 30, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); DeviceCreateInfo.enabledExtensionCount = static_cast(DeviceExtensions.size()); - auto vkAllocator = Instance->GetVkAllocator(); - auto vkPhysicalDevice = PhysicalDevice->GetVkDeviceHandle(); - auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(vkPhysicalDevice, DeviceCreateInfo, vkAllocator); + auto vkAllocator = Instance->GetVkAllocator(); + auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, DeviceCreateInfo, vkAllocator); auto& RawMemAllocator = GetRawAllocator(); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index 2fd063c9..32c0cb29 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -43,18 +43,24 @@ namespace Diligent static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType) { - static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type"); + static_assert(SHADER_TYPE_LAST == 0x2000, "Please update the switch below to handle the new shader type"); switch (ShaderType) { // clang-format off - case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; - case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; - case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT; - case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; - case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV; - case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV; + case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; + case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; + case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT; + case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; + case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV; + case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV; + case SHADER_TYPE_RAY_GEN: return VK_SHADER_STAGE_RAYGEN_BIT_KHR; + case SHADER_TYPE_RAY_MISS: return VK_SHADER_STAGE_MISS_BIT_KHR; + case SHADER_TYPE_RAY_CLOSEST_HIT: return VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + case SHADER_TYPE_RAY_ANY_HIT: return VK_SHADER_STAGE_ANY_HIT_BIT_KHR; + case SHADER_TYPE_RAY_INTERSECTION: return VK_SHADER_STAGE_INTERSECTION_BIT_KHR; + case SHADER_TYPE_CALLABLE: return VK_SHADER_STAGE_CALLABLE_BIT_KHR; // clang-format on default: UNEXPECTED("Unknown shader type"); diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index c36b98b0..6e5ec710 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -39,6 +39,9 @@ #include "QueryVkImpl.hpp" #include "RenderPassVkImpl.hpp" #include "FramebufferVkImpl.hpp" +#include "BottomLevelASVkImpl.hpp" +#include "TopLevelASVkImpl.hpp" +#include "ShaderBindingTableVkImpl.hpp" #include "EngineMemory.h" namespace Diligent @@ -75,7 +78,10 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* sizeof(FenceVkImpl), sizeof(QueryVkImpl), sizeof(RenderPassVkImpl), - sizeof(FramebufferVkImpl) + sizeof(FramebufferVkImpl), + sizeof(BottomLevelASVkImpl), + sizeof(TopLevelASVkImpl), + sizeof(ShaderBindingTableVkImpl) } }, m_VulkanInstance {Instance }, @@ -220,7 +226,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED; #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 30, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary)."); + static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary)."); #endif const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits; @@ -717,4 +723,40 @@ void RenderDeviceVkImpl::CreateFramebuffer(const FramebufferDesc& Desc, IFramebu }); } +void RenderDeviceVkImpl::CreateBLAS(const BottomLevelASDesc& Desc, + IBottomLevelAS** ppBLAS) +{ + CreateDeviceObject("BottomLevelAS", Desc, ppBLAS, + [&]() // + { + BottomLevelASVkImpl* pBottomLevelASVk(NEW_RC_OBJ(m_BLASAllocator, "BottomLevelASVkImpl instance", BottomLevelASVkImpl)(this, Desc)); + pBottomLevelASVk->QueryInterface(IID_BottomLevelAS, reinterpret_cast(ppBLAS)); + OnCreateDeviceObject(pBottomLevelASVk); + }); +} + +void RenderDeviceVkImpl::CreateTLAS(const TopLevelASDesc& Desc, + ITopLevelAS** ppTLAS) +{ + CreateDeviceObject("TopLevelAS", Desc, ppTLAS, + [&]() // + { + TopLevelASVkImpl* pTopLevelASVk(NEW_RC_OBJ(m_TLASAllocator, "TopLevelASVkImpl instance", TopLevelASVkImpl)(this, Desc)); + pTopLevelASVk->QueryInterface(IID_TopLevelAS, reinterpret_cast(ppTLAS)); + OnCreateDeviceObject(pTopLevelASVk); + }); +} + +void RenderDeviceVkImpl::CreateSBT(const ShaderBindingTableDesc& Desc, + IShaderBindingTable** ppSBT) +{ + CreateDeviceObject("ShaderBindingTable", Desc, ppSBT, + [&]() // + { + ShaderBindingTableVkImpl* pSBTVk(NEW_RC_OBJ(m_SBTAllocator, "ShaderBindingTableVkImpl instance", ShaderBindingTableVkImpl)(this, Desc)); + pSBTVk->QueryInterface(IID_ShaderBindingTable, reinterpret_cast(ppSBT)); + OnCreateDeviceObject(pSBTVk); + }); +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp new file mode 100644 index 00000000..21b06fb3 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp @@ -0,0 +1,196 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "ShaderBindingTableVkImpl.hpp" +#include "VulkanTypeConversions.hpp" + +namespace Diligent +{ + +ShaderBindingTableVkImpl::ShaderBindingTableVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const ShaderBindingTableDesc& Desc, + bool bIsDeviceInternal) : + TShaderBindingTableBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal}, + m_MissShadersOffset{0}, + m_HitGroupsOffset{0}, + m_CallbaleShadersOffset{0}, + m_MissShaderCount{0}, + m_HitGroupCount{0}, + m_CallableShaderCount{0} +{ + ValidateDesc(Desc); + + auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; + + m_ShaderGroupHandleSize = Props.shaderGroupHandleSize; + m_ShaderGroupBaseAlignment = Props.shaderGroupBaseAlignment; +} + +ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl() +{ +} + +void ShaderBindingTableVkImpl::ValidateDesc(const ShaderBindingTableDesc& Desc) const +{ + auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; + + if (Desc.ShaderRecordSize + Props.shaderGroupHandleSize > Props.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); + } +} + +void ShaderBindingTableVkImpl::Verify() const +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc) +{ + try + { + ValidateShaderBindingTableDesc(Desc); + ValidateDesc(Desc); + } + catch (const std::runtime_error&) + { + 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; +} + +void ShaderBindingTableVkImpl::ResetHitGroups(Uint32 HitShadersPerInstance) +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::BindHitGroup(ITopLevelAS* pTLAS, + const char* InstanceName, + const char* GeometryName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data, + Uint32 DataSize) +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::BindHitGroups(ITopLevelAS* pTLAS, + const char* InstanceName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data, + Uint32 DataSize) +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::BindCallableShader(Uint32 Index, + const char* ShaderName, + const void* Data, + Uint32 DataSize) +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs) +{ + // AZ TODO +} + +void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(VkStridedBufferRegionKHR& RaygenShaderBindingTable, + VkStridedBufferRegionKHR& MissShaderBindingTable, + VkStridedBufferRegionKHR& HitShaderBindingTable, + VkStridedBufferRegionKHR& CallableShaderBindingTable) +{ + auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; + + const VkDeviceSize Stride = m_Desc.ShaderRecordSize + Props.shaderGroupHandleSize; + VERIFY_EXPR(Stride <= Props.maxShaderGroupStride); + + RaygenShaderBindingTable.buffer = m_pBuffer->GetVkBuffer(); + RaygenShaderBindingTable.offset = 0; + RaygenShaderBindingTable.size = Stride; + RaygenShaderBindingTable.stride = Stride; + + if (m_MissShaderCount > 0) + { + MissShaderBindingTable.buffer = m_pBuffer->GetVkBuffer(); + MissShaderBindingTable.offset = m_MissShadersOffset; + MissShaderBindingTable.size = Stride * m_MissShaderCount; + MissShaderBindingTable.stride = Stride; + } + else + MissShaderBindingTable = {}; + + if (m_HitGroupCount > 0) + { + HitShaderBindingTable.buffer = m_pBuffer->GetVkBuffer(); + HitShaderBindingTable.offset = m_HitGroupsOffset; + HitShaderBindingTable.size = Stride * m_HitGroupCount; + HitShaderBindingTable.stride = Stride; + } + else + HitShaderBindingTable = {}; + + if (m_CallableShaderCount > 0) + { + CallableShaderBindingTable.buffer = m_pBuffer->GetVkBuffer(); + CallableShaderBindingTable.offset = m_CallbaleShadersOffset; + CallableShaderBindingTable.size = Stride * m_CallableShaderCount; + CallableShaderBindingTable.stride = Stride; + } + else + CallableShaderBindingTable = {}; +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp new file mode 100644 index 00000000..0fb2f334 --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "TopLevelASVkImpl.hpp" +#include "VulkanTypeConversions.hpp" + +namespace Diligent +{ + +TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const TopLevelASDesc& Desc, + bool bIsDeviceInternal) : + TTopLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal}, + m_DeviceAddress{0} +{ + const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); + const auto& Limits = PhysicalDevice.GetExtProperties().RayTracing; + + VERIFY_EXPR(m_Desc.MaxInstanceCount <= Limits.maxInstanceCount); + + VkAccelerationStructureCreateInfoKHR CreateInfo = {}; + VkAccelerationStructureCreateGeometryTypeInfoKHR InstanceInfo = {}; + + CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); + CreateInfo.maxGeometryCount = 1; + CreateInfo.pGeometryInfos = &InstanceInfo; + CreateInfo.compactedSize = 0; // AZ TODO + + InstanceInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + InstanceInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + InstanceInfo.maxPrimitiveCount = m_Desc.MaxInstanceCount; + + m_VulkanTLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); + + VkAccelerationStructureMemoryRequirementsInfoKHR MemInfo = {}; + VkMemoryRequirements MemReqs = {}; + + MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; + MemInfo.accelerationStructure = m_VulkanTLAS; + MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; + + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + + uint32_t MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex) + 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); + + auto Memory = m_MemoryAllocation.Page->GetVkMemory(); + auto err = LogicalDevice.BindASMemory(m_VulkanTLAS, Memory, 0); + 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(MemReqs.size); + + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Update = static_cast(MemReqs.size); +} + +TopLevelASVkImpl::~TopLevelASVkImpl() +{ + // Vk object can only be destroyed when it is no longer used by the GPU + if (m_VulkanTLAS != VK_NULL_HANDLE) + m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanTLAS), m_Desc.CommandQueueMask); + if (m_MemoryAllocation.Page != nullptr) + m_pDevice->SafeReleaseDeviceObject(std::move(m_MemoryAllocation), m_Desc.CommandQueueMask); +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index fb151407..b797968c 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -444,7 +444,7 @@ public: TEXTURE_FORMAT operator[](VkFormat VkFmt) const { - if (VkFmt < VK_FORMAT_RANGE_SIZE) + if (VkFmt < _countof(m_VkFmtToTexFmtMap)) { return m_VkFmtToTexFmtMap[VkFmt]; } @@ -456,7 +456,7 @@ public: } private: - TEXTURE_FORMAT m_VkFmtToTexFmtMap[VK_FORMAT_RANGE_SIZE] = {}; + TEXTURE_FORMAT m_VkFmtToTexFmtMap[VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1] = {}; std::unordered_map m_VkFmtToTexFmtMapExt; }; @@ -632,6 +632,21 @@ VkFormat TypeToVkFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormal } } +VkIndexType TypeToVkIndexType(VALUE_TYPE IndexType) +{ + switch (IndexType) + { + // clang-format off + case VT_UNDEFINED: return VK_INDEX_TYPE_NONE_KHR; // only for ray tracing + case VT_UINT16: return VK_INDEX_TYPE_UINT16; + case VT_UINT32: return VK_INDEX_TYPE_UINT32; + // clang-format on + default: + UNEXPECTED("Unexpected index type"); + return VK_INDEX_TYPE_UINT32; + } +} + VkPolygonMode FillModeToVkPolygonMode(FILL_MODE FillMode) { switch (FillMode) @@ -1151,10 +1166,8 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag) //VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX //VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT //VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV - //VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX - //VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX - static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "This function must be updated to handle new resource state flag"); + static_assert(RESOURCE_STATE_MAX_BIT == 0x40000, "This function must be updated to handle new resource state flag"); VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set"); switch (StateFlag) { @@ -1176,6 +1189,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_RAY_TRACING: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; // clang-format on default: @@ -1203,7 +1218,7 @@ public: } private: - static constexpr const Uint32 MaxFlagBitPos = 16; + static constexpr const Uint32 MaxFlagBitPos = 18; std::array FlagBitPosToVkAccessFlagsMap; }; @@ -1256,8 +1271,8 @@ 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_NV: return RESOURCE_STATE_UNKNOWN; - case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_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"); @@ -1317,7 +1332,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsi //VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, //VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "This function must be updated to handle new resource state flag"); + static_assert(RESOURCE_STATE_MAX_BIT == 0x40000, "This function must be updated to handle new resource state flag"); VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set"); switch (StateFlag) { @@ -1339,6 +1354,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_RAY_TRACING: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED; // clang-format on default: @@ -1349,7 +1366,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsi RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout) { - static_assert(RESOURCE_STATE_MAX_BIT == 0x10000, "This function must be updated to handle new resource state flag"); + static_assert(RESOURCE_STATE_MAX_BIT == 0x40000, "This function must be updated to handle new resource state flag"); switch (Layout) { // clang-format off @@ -1359,7 +1376,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; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return RESOURCE_STATE_COPY_SOURCE; // AZ TODO: check for resolve state 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; @@ -1511,4 +1528,90 @@ VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags) } #undef ASSERT_SAME +VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags) +{ + static_assert(RAYTRACING_BUILD_AS_FLAGS_LAST == 0x10, "AZ TODO"); + + VkBuildAccelerationStructureFlagsKHR Result = 0; + for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + { + if ((Flags & Bit) != Bit) + continue; + + switch (RAYTRACING_BUILD_AS_FLAGS(Bit)) + { + // clang-format off + case RAYTRACING_BUILD_AS_ALLOW_UPDATE: Result |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; break; + case RAYTRACING_BUILD_AS_ALLOW_COMPACTION: Result |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR; break; + case RAYTRACING_BUILD_AS_PREFER_FAST_TRACE: Result |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; break; + case RAYTRACING_BUILD_AS_PREFER_FAST_BUILD: Result |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR; break; + case RAYTRACING_BUILD_AS_LOW_MEMORY: Result |= VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR; break; + default: UNEXPECTED("unknown build AS flag"); + // clang-format on + } + } + return Result; +} + +VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags) +{ + static_assert(RAYTRACING_GEOMETRY_FLAGS_LAST == 0x02, "AZ TODO"); + + VkGeometryFlagsKHR Result = 0; + for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + { + if ((Flags & Bit) != Bit) + continue; + + switch (RAYTRACING_GEOMETRY_FLAGS(Bit)) + { + // clang-format off + case RAYTRACING_GEOMETRY_OPAQUE: Result |= VK_GEOMETRY_OPAQUE_BIT_KHR; break; + case RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION: Result |= VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR; break; + default: UNEXPECTED("unknown geometry flag"); + // clang-format on + } + } + return Result; +} + +VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags) +{ + static_assert(RAYTRACING_INSTANCE_FLAGS_LAST == 0x08, "AZ TODO"); + + VkGeometryInstanceFlagsKHR Result = 0; + for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + { + if ((Flags & Bit) != Bit) + continue; + + switch (RAYTRACING_INSTANCE_FLAGS(Bit)) + { + // clang-format off + case RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE: return VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; + case RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE: return VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR; + case RAYTRACING_INSTANCE_FORCE_OPAQUE: return VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR; + case RAYTRACING_INSTANCE_FORCE_NO_OPAQUE: return VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR; + default: UNEXPECTED("unknown instance flag"); + // clang-format on + } + } + return Result; +} + +VkCopyAccelerationStructureModeKHR CopyASModeToVkCopyAccelerationStructureMode(COPY_AS_MODE Mode) +{ + static_assert(COPY_AS_MODE_LAST == 0, "AZ TODO"); + + switch (Mode) + { + // clang-format off + case COPY_AS_MODE_CLONE: return VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; + // clang-format on + } + + UNEXPECTED("unknown AS copy mode"); + return VkCopyAccelerationStructureModeKHR(0); +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp index 4feb8692..ae1d3f11 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp @@ -400,6 +400,11 @@ void SetQueryPoolName(VkDevice device, VkQueryPool queryPool, const char* name) SetObjectName(device, (uint64_t)queryPool, VK_OBJECT_TYPE_QUERY_POOL, name); } +void SetAccelStructName(VkDevice device, VkAccelerationStructureKHR accelStruct, const char* name) +{ + SetObjectName(device, (uint64_t)accelStruct, VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, name); +} + template <> void SetVulkanObjectName(VkDevice device, VkCommandPool cmdPool, const char* name) @@ -527,6 +532,11 @@ void SetVulkanObjectName(VkDevice de SetQueryPoolName(device, queryPool, name); } +template <> +void SetVulkanObjectName(VkDevice device, VkAccelerationStructureKHR accelStruct, const char* name) +{ + SetAccelStructName(device, accelStruct, name); +} const char* VkResultToString(VkResult errorCode) @@ -558,6 +568,21 @@ const char* VkResultToString(VkResult errorCode) STR(ERROR_INCOMPATIBLE_DISPLAY_KHR); STR(ERROR_VALIDATION_FAILED_EXT); STR(ERROR_INVALID_SHADER_NV); + STR(ERROR_FRAGMENTED_POOL); + STR(ERROR_UNKNOWN); + STR(ERROR_OUT_OF_POOL_MEMORY); + STR(ERROR_INVALID_EXTERNAL_HANDLE); + STR(ERROR_FRAGMENTATION); + STR(ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS); + STR(ERROR_INCOMPATIBLE_VERSION_KHR); + STR(ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT); + STR(ERROR_NOT_PERMITTED_EXT); + STR(ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT); + STR(THREAD_IDLE_KHR); + STR(THREAD_DONE_KHR); + STR(OPERATION_DEFERRED_KHR); + STR(OPERATION_NOT_DEFERRED_KHR); + STR(PIPELINE_COMPILE_REQUIRED_EXT); #undef STR // clang-format on default: @@ -589,6 +614,8 @@ const char* VkAccessFlagBitToString(VkAccessFlagBits Bit) ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_HOST_WRITE_BIT) ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_MEMORY_READ_BIT) ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_MEMORY_WRITE_BIT) + ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR) + ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) #undef ACCESS_FLAG_BIT_TO_STRING default: UNEXPECTED("Unexpected bit"); return ""; // clang-format on diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index 5b720fd7..45d9bfa5 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -34,11 +34,11 @@ namespace VulkanUtilities { -std::shared_ptr VulkanLogicalDevice::Create(VkPhysicalDevice vkPhysicalDevice, +std::shared_ptr VulkanLogicalDevice::Create(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, const VkAllocationCallbacks* vkAllocator) { - auto* LogicalDevice = new VulkanLogicalDevice{vkPhysicalDevice, DeviceCI, vkAllocator}; + auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, vkAllocator}; return std::shared_ptr{LogicalDevice}; } @@ -47,13 +47,13 @@ VulkanLogicalDevice::~VulkanLogicalDevice() vkDestroyDevice(m_VkDevice, m_VkAllocator); } -VulkanLogicalDevice::VulkanLogicalDevice(VkPhysicalDevice vkPhysicalDevice, +VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, const VkAllocationCallbacks* vkAllocator) : m_VkAllocator{vkAllocator}, m_EnabledFeatures{*DeviceCI.pEnabledFeatures} { - auto res = vkCreateDevice(vkPhysicalDevice, &DeviceCI, vkAllocator, &m_VkDevice); + auto res = vkCreateDevice(PhysicalDevice.GetVkDeviceHandle(), &DeviceCI, vkAllocator, &m_VkDevice); CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device"); #if DILIGENT_USE_VOLK @@ -264,6 +264,12 @@ QueryPoolWrapper VulkanLogicalDevice::CreateQueryPool(const VkQueryPoolCreateInf return CreateVulkanObject(vkCreateQueryPool, QueryPoolCI, DebugName, "query pool"); } +AccelStructWrapper VulkanLogicalDevice::CreateAccelStruct(const VkAccelerationStructureCreateInfoKHR& CI, const char* DebugName) const +{ + VERIFY_EXPR(CI.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR); + return CreateVulkanObject(vkCreateAccelerationStructureKHR, CI, DebugName, "acceleration structure"); +} + VkCommandBuffer VulkanLogicalDevice::AllocateVkCommandBuffer(const VkCommandBufferAllocateInfo& AllocInfo, const char* DebugName) const { VERIFY_EXPR(AllocInfo.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO); @@ -405,6 +411,12 @@ void VulkanLogicalDevice::ReleaseVulkanObject(QueryPoolWrapper&& QueryPool) cons QueryPool.m_VkObject = VK_NULL_HANDLE; } +void VulkanLogicalDevice::ReleaseVulkanObject(AccelStructWrapper&& AccelStruct) const +{ + vkDestroyAccelerationStructureKHR(m_VkDevice, AccelStruct.m_VkObject, m_VkAllocator); + AccelStruct.m_VkObject = VK_NULL_HANDLE; +} + void VulkanLogicalDevice::FreeDescriptorSet(VkDescriptorPool Pool, VkDescriptorSet Set) const { VERIFY_EXPR(Pool != VK_NULL_HANDLE && Set != VK_NULL_HANDLE); @@ -428,6 +440,13 @@ VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkI return MemReqs; } +VkMemoryRequirements VulkanLogicalDevice::GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const +{ + VkMemoryRequirements2 MemReqs = {}; + vkGetAccelerationStructureMemoryRequirementsKHR(m_VkDevice, &Info, &MemReqs); + return MemReqs.memoryRequirements; +} + VkResult VulkanLogicalDevice::BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const { return vkBindBufferMemory(m_VkDevice, buffer, memory, memoryOffset); @@ -438,6 +457,30 @@ VkResult VulkanLogicalDevice::BindImageMemory(VkImage image, VkDeviceMemory memo return vkBindImageMemory(m_VkDevice, image, memory, memoryOffset); } +VkResult VulkanLogicalDevice::BindASMemory(VkAccelerationStructureKHR AS, VkDeviceMemory memory, VkDeviceSize memoryOffset) const +{ + VkBindAccelerationStructureMemoryInfoKHR Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; + Info.memory = memory; + Info.memoryOffset = memoryOffset; + Info.deviceIndexCount = 0; + Info.pDeviceIndices = nullptr; + Info.accelerationStructure = AS; + + return vkBindAccelerationStructureMemoryKHR(m_VkDevice, 1, &Info); +} + +VkDeviceAddress VulkanLogicalDevice::GetAccelerationStructureDeviceAddress(VkAccelerationStructureKHR AS) const +{ + VkAccelerationStructureDeviceAddressInfoKHR Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; + Info.accelerationStructure = AS; + + return vkGetAccelerationStructureDeviceAddressKHR(m_VkDevice, &Info); +} + VkResult VulkanLogicalDevice::MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const { return vkMapMemory(m_VkDevice, memory, offset, size, flags, ppData); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index 92a5e4d4..12567cd0 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -68,12 +68,13 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, VERIFY_EXPR(ExtensionCount == m_SupportedExtensions.size()); } -#ifdef VK_KHR_get_physical_device_properties2 +#if DILIGENT_USE_VOLK if (Instance.IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { VkPhysicalDeviceFeatures2 Feats2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; void** NextFeat = &Feats2.pNext; + void** NextProp = &Props2.pNext; if (IsExtensionSupported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) { @@ -103,23 +104,68 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, } } - // Enable mesh shader extension. + // Get mesh shader features and properties. if (IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME)) { *NextFeat = &m_ExtFeatures.MeshShader; NextFeat = &m_ExtFeatures.MeshShader.pNext; m_ExtFeatures.MeshShader.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV; + + *NextProp = &m_ExtProperties.MeshShader; + NextProp = &m_ExtProperties.MeshShader.pNext; + + m_ExtProperties.MeshShader.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV; + } + + // Get ray tracing features and properties. + if (IsExtensionSupported(VK_KHR_RAY_TRACING_EXTENSION_NAME)) + { + *NextFeat = &m_ExtFeatures.RayTracing; + NextFeat = &m_ExtFeatures.RayTracing.pNext; + + m_ExtFeatures.RayTracing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR; + + *NextProp = &m_ExtProperties.RayTracing; + NextProp = &m_ExtProperties.RayTracing.pNext; + + m_ExtProperties.RayTracing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR; + } + + + // Additional extension that required for ray tracing. + if (IsExtensionSupported(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) + { + *NextFeat = &m_ExtFeatures.BufferDeviceAddress; + NextFeat = &m_ExtFeatures.BufferDeviceAddress.pNext; + + m_ExtFeatures.BufferDeviceAddress.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR; + } + + // Additional extension that required for ray tracing. + if (IsExtensionSupported(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) + { + *NextFeat = &m_ExtFeatures.DescriptorIndexing; + NextFeat = &m_ExtFeatures.DescriptorIndexing.pNext; + + m_ExtFeatures.DescriptorIndexing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; + + *NextProp = &m_ExtProperties.DescriptorIndexing; + NextProp = &m_ExtProperties.DescriptorIndexing.pNext; + + m_ExtProperties.DescriptorIndexing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; } + // make sure that last pNext is null *NextFeat = nullptr; + *NextProp = nullptr; // Initialize device extension features by current physical device features. // Some flags may not be supported by hardware. vkGetPhysicalDeviceFeatures2KHR(m_VkDevice, &Feats2); vkGetPhysicalDeviceProperties2KHR(m_VkDevice, &Props2); } -#endif +#endif // DILIGENT_USE_VOLK } uint32_t VulkanPhysicalDevice::FindQueueFamily(VkQueueFlags QueueFlags) const -- cgit v1.2.3 From fa6be16a6251b956810caaaa39d2ef8b9c41615a Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sun, 4 Oct 2020 23:33:58 +0300 Subject: Added KHR extension emulation via NV extension --- Graphics/GraphicsEngineVulkan/CMakeLists.txt | 1 + .../VulkanUtilities/VulkanLogicalDevice.hpp | 2 + .../VulkanUtilities/VulkanPhysicalDevice.hpp | 1 + .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 9 +- .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 3 + .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 28 ++ .../VulkanUtilities/VulkanRayTracingKHRviaNV.cpp | 514 +++++++++++++++++++++ 7 files changed, 556 insertions(+), 2 deletions(-) create mode 100644 Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt index 761653a4..6ce17f34 100644 --- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt +++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt @@ -124,6 +124,7 @@ set(VULKAN_UTILS_SRC src/VulkanUtilities/VulkanLogicalDevice.cpp src/VulkanUtilities/VulkanMemoryManager.cpp src/VulkanUtilities/VulkanPhysicalDevice.cpp + src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp ) set(GENERATE_MIPS_SHADER shaders/GenerateMipsCS.csh) diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp index c2fba2a4..a8366551 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp @@ -239,4 +239,6 @@ private: const VkPhysicalDeviceFeatures m_EnabledFeatures; }; +void EnableRayTracingKHRviaNV(); + } // namespace VulkanUtilities diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp index 1e9a6edf..b9bf651c 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp @@ -44,6 +44,7 @@ public: VkPhysicalDevice8BitStorageFeaturesKHR Storage8Bit = {}; VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {}; VkPhysicalDeviceRayTracingFeaturesKHR RayTracing = {}; + bool RayTracingNV = false; // indicates that KHR extension emulated by NV extension VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {}; VkPhysicalDeviceDescriptorIndexingFeaturesEXT DescriptorIndexing = {}; }; diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 185f1da5..692b5428 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -273,7 +273,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E auto RayTracingFeats = DeiceExtFeatures.RayTracing; auto BufferDeviceAddressFeats = DeiceExtFeatures.BufferDeviceAddress; auto DescriptorIndexingFeats = DeiceExtFeatures.DescriptorIndexing; - ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE, MeshShaders, "Ray tracing are"); + ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeiceExtFeatures.RayTracingNV, MeshShaders, "Ray tracing are"); #undef FeatureSupport @@ -396,7 +396,12 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // Ray tracing if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED) { - if (RayTracingFeats.rayTracing != VK_FALSE) + if (DeiceExtFeatures.RayTracingNV) + { + DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); + DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME); + } + else if (RayTracingFeats.rayTracing != VK_FALSE) { // required extensions DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index 45d9bfa5..87bfc450 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -60,6 +60,9 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe // Since we only use one device at this time, load device function entries // https://github.com/zeux/volk#optimizing-device-calls volkLoadDevice(m_VkDevice); + + if (PhysicalDevice.GetExtFeatures().RayTracingNV) + EnableRayTracingKHRviaNV(); #endif m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index 12567cd0..22659277 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -71,6 +71,8 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, #if DILIGENT_USE_VOLK if (Instance.IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { + VkPhysicalDeviceRayTracingPropertiesNV RayTracingNV = {}; + VkPhysicalDeviceFeatures2 Feats2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; void** NextFeat = &Feats2.pNext; @@ -131,7 +133,15 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.RayTracing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR; } + else if (IsExtensionSupported(VK_NV_RAY_TRACING_EXTENSION_NAME)) + { + m_ExtFeatures.RayTracingNV = true; + *NextProp = &RayTracingNV; + NextProp = &RayTracingNV.pNext; + + RayTracingNV.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV; + } // Additional extension that required for ray tracing. if (IsExtensionSupported(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) @@ -164,6 +174,24 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, // Some flags may not be supported by hardware. vkGetPhysicalDeviceFeatures2KHR(m_VkDevice, &Feats2); vkGetPhysicalDeviceProperties2KHR(m_VkDevice, &Props2); + + // Emulate KHR extension + if (m_ExtFeatures.RayTracingNV) + { + //m_ExtFeatures.RayTracing.sType + //m_ExtFeatures.RayTracing.rayTracingPrimitiveCulling = true; // AZ TODO + m_ExtFeatures.RayTracing.rayTracing = VK_TRUE; + + m_ExtProperties.RayTracing.shaderGroupHandleSize = RayTracingNV.shaderGroupHandleSize; + m_ExtProperties.RayTracing.maxRecursionDepth = RayTracingNV.maxRecursionDepth; + m_ExtProperties.RayTracing.maxShaderGroupStride = RayTracingNV.maxShaderGroupStride; + m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment; + m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount; + m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount; + m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount; + m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures; + m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0; + } } #endif // DILIGENT_USE_VOLK } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp new file mode 100644 index 00000000..de16fe6a --- /dev/null +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp @@ -0,0 +1,514 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "VulkanErrors.hpp" +#include "VulkanUtilities/VulkanLogicalDevice.hpp" + +// for KHR ray tracing emulation +#include +#include + +namespace VulkanUtilities +{ + +// KHR ray tracing emulation. +// Will be deprecated after the release of KHR extension. +#if DILIGENT_USE_VOLK +static_assert(sizeof(VkAccelerationStructureKHR) == sizeof(VkAccelerationStructureNV), "not compatible with NV extension"); +static_assert(sizeof(VkDeviceAddress) == 8, "not compatible with NV extension"); + +static std::mutex g_BufferDeviceAddressGuard; +static std::unordered_map g_DeviceAddressToBuffer; +static std::unordered_map g_BufferToDeviceAddress; +static uint32_t g_BufferDeviceAddressCounter = 0; +static const VkDeviceAddress g_BufferMask = 0xFFFFFFFF00000000ull; + +static PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr; +static PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr; +static PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr; + +static VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device, + const VkBufferCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkBuffer* pBuffer) +{ + const_cast(pCreateInfo)->usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + return Origin_vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer); +} + +static void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device, + VkBuffer buffer, + const VkAllocationCallbacks* pAllocator) +{ + Origin_vkDestroyBuffer(device, buffer, pAllocator); + + std::unique_lock lock{g_BufferDeviceAddressGuard}; + + auto iter = g_BufferToDeviceAddress.find(buffer); + if (iter != g_BufferToDeviceAddress.end()) + { + g_DeviceAddressToBuffer.erase(iter->second); + g_BufferToDeviceAddress.erase(iter); + } +} + +static 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); + + std::unique_lock lock{g_BufferDeviceAddressGuard}; + + // find in existing buffers + auto iter = g_BufferToDeviceAddress.find(pInfo->buffer); + if (iter != g_BufferToDeviceAddress.end()) + return iter->second; + + // create new device address + VkDeviceAddress Addr = VkDeviceAddress(++g_BufferDeviceAddressCounter) << 32; + g_BufferToDeviceAddress.insert_or_assign(pInfo->buffer, Addr); + g_DeviceAddressToBuffer.insert_or_assign(Addr, pInfo->buffer); + return Addr; +} + +struct BufferAndOffset +{ + VkBuffer Buffer; + VkDeviceSize Offset; +}; +static BufferAndOffset DeviceAddressToBuffer(VkDeviceAddress Addr) +{ + if (Addr == 0) + return {VK_NULL_HANDLE, 0}; + + std::unique_lock lock{g_BufferDeviceAddressGuard}; + + auto iter = g_DeviceAddressToBuffer.find(Addr & g_BufferMask); + if (iter == g_DeviceAddressToBuffer.end()) + { + UNEXPECTED("Failed to map device address to buffer"); + return {VK_NULL_HANDLE, 0}; + } + + return {iter->second, Addr & ~g_BufferMask}; +} + +static BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressConstKHR& Addr) +{ + return DeviceAddressToBuffer(Addr.deviceAddress); +} + +static BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressKHR& Addr) +{ + return DeviceAddressToBuffer(Addr.deviceAddress); +} + + +static 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); + VERIFY_EXPR(pCreateInfo->deviceAddress == 0); + + VkAccelerationStructureCreateInfoNV CreateInfo = {}; + std::vector Geometries; + + CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV; + CreateInfo.compactedSize = pCreateInfo->compactedSize; + CreateInfo.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV; + CreateInfo.info.type = pCreateInfo->type; + CreateInfo.info.flags = pCreateInfo->flags; + + if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) + { + CreateInfo.info.instanceCount = pCreateInfo->maxGeometryCount; + } + else if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + { + Geometries.resize(pCreateInfo->maxGeometryCount); + + for (uint32_t i = 0; i < pCreateInfo->maxGeometryCount; ++i) + { + auto& src = pCreateInfo->pGeometryInfos[i]; + auto& dst = Geometries[i]; + + VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR); + VERIFY_EXPR(src.pNext == nullptr); + + dst.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV; + dst.pNext = nullptr; + dst.geometryType = src.geometryType; + dst.flags = 0; + + 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) + { + 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; + dst.geometry.triangles.indexOffset = 0; + dst.geometry.triangles.indexCount = 0; + dst.geometry.triangles.indexType = src.indexType; + dst.geometry.triangles.transformData = VK_NULL_HANDLE; + dst.geometry.triangles.transformOffset = 0; + + if (dst.geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR) + { + VERIFY_EXPR(src.maxVertexCount == src.maxPrimitiveCount * 3); + dst.geometry.triangles.vertexCount = src.maxPrimitiveCount * 3; + } + else + { + dst.geometry.triangles.indexCount = src.maxPrimitiveCount * 3; + } + } + else if (dst.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR) + { + dst.geometry.aabbs.aabbData = VK_NULL_HANDLE; + dst.geometry.aabbs.numAABBs = src.maxPrimitiveCount; + dst.geometry.aabbs.stride = 0; + dst.geometry.aabbs.offset = 0; + } + } + + CreateInfo.info.geometryCount = static_cast(Geometries.size()); + CreateInfo.info.pGeometries = Geometries.data(); + } + else + { + UNEXPECTED("unknown AS type"); + return VK_RESULT_MAX_ENUM; + } + + return vkCreateAccelerationStructureNV(device, &CreateInfo, pAllocator, reinterpret_cast(pAccelerationStructure)); +} + +static 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(pInfo->pNext == nullptr); + VERIFY_EXPR(pInfo->buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR); + + VkAccelerationStructureMemoryRequirementsInfoNV Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; + Info.type = pInfo->type; + Info.accelerationStructure = pInfo->accelerationStructure; + + return vkGetAccelerationStructureMemoryRequirementsNV(device, &Info, pMemoryRequirements); +} + +static 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); +} + +static 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); + + VkDeviceAddress result = 0; + vkGetAccelerationStructureHandleNV(device, pInfo->accelerationStructure, sizeof(result), &result); + return result; +} + +static void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos) +{ + std::vector Geometries; + + for (uint32_t i = 0; i < infoCount; ++i) + { + auto& SrcInfo = pInfos[i]; + auto& SrcOffset = ppOffsetInfos[i]; + + VERIFY_EXPR(SrcInfo.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR); + VERIFY_EXPR(SrcInfo.pNext == nullptr); + + BufferAndOffset Scratch = DeviceAddressToBuffer(SrcInfo.scratchData); + + VkAccelerationStructureInfoNV Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV; + Info.pNext = nullptr; + Info.type = SrcInfo.type; + Info.flags = SrcInfo.flags; + + if (Info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) + { + VERIFY_EXPR(SrcInfo.geometryCount == 1); + VERIFY_EXPR(SrcInfo.geometryArrayOfPointers == VK_FALSE); + VERIFY_EXPR((*SrcInfo.ppGeometries)[0].geometry.instances.arrayOfPointers == VK_FALSE); + + Info.instanceCount = SrcOffset->primitiveCount; + + BufferAndOffset Instance = DeviceAddressToBuffer((*SrcInfo.ppGeometries)[0].geometry.instances.data); + + vkCmdBuildAccelerationStructureNV(commandBuffer, &Info, + Instance.Buffer, Instance.Offset + SrcOffset[0].primitiveOffset, + SrcInfo.update, + SrcInfo.dstAccelerationStructure, SrcInfo.srcAccelerationStructure, + Scratch.Buffer, Scratch.Offset); + } + else if (Info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + { + VERIFY_EXPR(SrcInfo.geometryArrayOfPointers == VK_FALSE); + + Geometries.resize(SrcInfo.geometryCount); + + for (uint32_t j = 0; j < SrcInfo.geometryCount; ++j) + { + auto& src = (*SrcInfo.ppGeometries)[j]; + auto& dst = Geometries[j]; + auto& off = SrcOffset[j]; + + VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR); + VERIFY_EXPR(src.pNext == nullptr); + VERIFY_EXPR(src.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR || src.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR); + + dst.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV; + dst.pNext = nullptr; + dst.flags = src.flags; + dst.geometryType = src.geometryType; + + if (dst.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR) + { + VERIFY_EXPR(src.geometry.triangles.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR); + VERIFY_EXPR(src.geometry.triangles.pNext == nullptr); + VERIFY_EXPR(off.firstVertex == 0); + + BufferAndOffset VB = DeviceAddressToBuffer(src.geometry.triangles.vertexData); + 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; + dst.geometry.triangles.vertexStride = src.geometry.triangles.vertexStride; + dst.geometry.triangles.vertexFormat = src.geometry.triangles.vertexFormat; + dst.geometry.triangles.indexData = IB.Buffer; + dst.geometry.triangles.indexOffset = IB.Offset; + dst.geometry.triangles.indexCount = 0; + dst.geometry.triangles.indexType = src.geometry.triangles.indexType; + dst.geometry.triangles.transformData = TB.Buffer; + dst.geometry.triangles.transformOffset = TB.Offset + off.transformOffset; + + if (dst.geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR) + { + dst.geometry.triangles.vertexOffset += off.primitiveOffset; + dst.geometry.triangles.vertexCount = off.primitiveCount * 3; + } + else + { + dst.geometry.triangles.indexOffset += off.primitiveOffset; + dst.geometry.triangles.indexCount = off.primitiveCount * 3; + } + } + else + { + VERIFY_EXPR(src.geometry.aabbs.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR); + VERIFY_EXPR(src.geometry.aabbs.pNext == nullptr); + VERIFY_EXPR(src.geometry.aabbs.stride <= std::numeric_limits::max()); + + 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(src.geometry.aabbs.stride); + dst.geometry.aabbs.offset = Data.Offset + off.primitiveOffset; + } + } + + Info.geometryCount = static_cast(Geometries.size()); + Info.pGeometries = Geometries.data(); + + vkCmdBuildAccelerationStructureNV(commandBuffer, &Info, + VK_NULL_HANDLE, 0, + SrcInfo.update, + SrcInfo.dstAccelerationStructure, SrcInfo.srcAccelerationStructure, + Scratch.Buffer, Scratch.Offset); + } + else + { + UNEXPECTED("unknown AS type"); + } + } +} + +static 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); + + vkCmdCopyAccelerationStructureNV(commandBuffer, pInfo->dst, pInfo->src, pInfo->mode); +} + +static 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, + pMissShaderBindingTable->buffer, pMissShaderBindingTable->offset, pMissShaderBindingTable->stride, + pHitShaderBindingTable->buffer, pHitShaderBindingTable->offset, pHitShaderBindingTable->stride, + pCallableShaderBindingTable->buffer, pCallableShaderBindingTable->offset, pCallableShaderBindingTable->stride, + width, height, depth); +} + +static 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); +} + +static VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines) +{ + std::vector Infos; + std::vector Groups; + Infos.resize(createInfoCount); + + size_t GroupCount = 0; + for (uint32_t i = 0; i < createInfoCount; ++i) + { + GroupCount += pCreateInfos[i].groupCount; + } + Groups.resize(GroupCount); + GroupCount = 0; + + for (uint32_t i = 0; i < createInfoCount; ++i) + { + auto& src = pCreateInfos[i]; + auto& dst = Infos[i]; + + VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR); + VERIFY_EXPR(src.pNext == nullptr); + VERIFY_EXPR(src.libraries.libraryCount == 0); + VERIFY_EXPR(src.libraries.pLibraries == nullptr); + VERIFY_EXPR(src.pLibraryInterface == nullptr); + + // copy groups + for (uint32_t j = 0; j < src.groupCount; ++j) + { + auto& srcg = src.pGroups[j]; + auto& dstg = Groups[GroupCount + j]; + + VERIFY_EXPR(srcg.sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR); + VERIFY_EXPR(srcg.pNext == nullptr); + + dstg.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV; + dstg.pNext = nullptr; + dstg.type = srcg.type; + dstg.generalShader = srcg.generalShader; + dstg.closestHitShader = srcg.closestHitShader; + dstg.anyHitShader = srcg.anyHitShader; + dstg.intersectionShader = srcg.intersectionShader; + + VERIFY_EXPR(srcg.pNext == nullptr); + } + + dst.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV; + dst.pNext = nullptr; + dst.flags = src.flags; + dst.stageCount = src.stageCount; + dst.pStages = src.pStages; + dst.groupCount = src.groupCount; + dst.pGroups = Groups.data() + GroupCount; + dst.maxRecursionDepth = src.maxRecursionDepth; + dst.layout = src.layout; + dst.basePipelineHandle = src.basePipelineHandle; + dst.basePipelineIndex = src.basePipelineIndex; + + GroupCount += src.groupCount; + } + + return vkCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, Infos.data(), pAllocator, pPipelines); +} + +void EnableRayTracingKHRviaNV() +{ + vkCreateAccelerationStructureKHR = &Redirect_vkCreateAccelerationStructureKHR; + vkGetAccelerationStructureMemoryRequirementsKHR = &Redirect_vkGetAccelerationStructureMemoryRequirementsKHR; + vkBindAccelerationStructureMemoryKHR = &Redirect_vkBindAccelerationStructureMemoryKHR; + vkGetAccelerationStructureDeviceAddressKHR = &Redirect_vkGetAccelerationStructureDeviceAddressKHR; + vkCmdBuildAccelerationStructureKHR = &Redirect_vkCmdBuildAccelerationStructureKHR; + vkCmdCopyAccelerationStructureKHR = &Redirect_vkCmdCopyAccelerationStructureKHR; + vkGetRayTracingShaderGroupHandlesKHR = &Redirect_vkGetRayTracingShaderGroupHandlesKHR; + vkCreateRayTracingPipelinesKHR = &Redirect_vkCreateRayTracingPipelinesKHR; + vkCmdTraceRaysKHR = &Redirect_vkCmdTraceRaysKHR; + + Origin_vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressKHR; + Origin_vkCreateBuffer = vkCreateBuffer; + Origin_vkDestroyBuffer = vkDestroyBuffer; + vkCreateBuffer = &Wrap_vkCreateBuffer; + vkDestroyBuffer = &Wrap_vkDestroyBuffer; + vkGetBufferDeviceAddressKHR = &Wrap_vkGetBufferDeviceAddressKHR; + vkGetBufferDeviceAddress = &Wrap_vkGetBufferDeviceAddressKHR; + vkGetBufferDeviceAddressEXT = &Wrap_vkGetBufferDeviceAddressKHR; +} +#endif // DILIGENT_USE_VOLK + +} // namespace VulkanUtilities -- cgit v1.2.3 From 73fd82a29d3175e156754010f5de261d6f561f16 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 4 Oct 2020 16:59:33 -0700 Subject: A few random fixes to ray tracing API and implementation --- .../include/BottomLevelASVkImpl.hpp | 2 +- .../include/ShaderBindingTableVkImpl.hpp | 20 ++- .../include/TopLevelASVkImpl.hpp | 2 +- .../VulkanUtilities/VulkanCommandBuffer.hpp | 10 +- .../include/VulkanUtilities/VulkanHeaders.h | 2 +- .../VulkanUtilities/VulkanPhysicalDevice.hpp | 2 +- .../interface/BottomLevelASVk.h | 4 +- Graphics/GraphicsEngineVulkan/interface/BufferVk.h | 2 +- .../interface/ShaderBindingTableVk.h | 11 +- .../GraphicsEngineVulkan/interface/TopLevelASVk.h | 7 +- .../src/BottomLevelASVkImpl.cpp | 7 +- .../src/DeviceContextVkImpl.cpp | 43 ++++-- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 6 +- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 2 +- .../src/ShaderBindingTableVkImpl.cpp | 16 +-- .../GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp | 3 +- .../src/VulkanTypeConversions.cpp | 52 +++---- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 4 +- .../VulkanUtilities/VulkanRayTracingKHRviaNV.cpp | 149 +++++++++++---------- 19 files changed, 187 insertions(+), 157 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp index ccf8f574..eb485370 100644 --- a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp @@ -59,7 +59,7 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelASVk, TBottomLevelASBase); private: - VkDeviceAddress m_DeviceAddress; + VkDeviceAddress m_DeviceAddress = 0; VulkanUtilities::AccelStructWrapper m_VulkanBLAS; VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; ScratchBufferSizes m_ScratchSize; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp index bba64381..92d83160 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp @@ -96,17 +96,15 @@ private: private: RefCntAutoPtr m_pBuffer; std::vector m_ShaderRecords; - Uint32 m_MissShadersOffset; - Uint32 m_HitGroupsOffset; - Uint32 m_CallbaleShadersOffset; - Uint32 m_MissShaderCount; - Uint32 m_HitGroupCount; - Uint32 m_CallableShaderCount; - Uint32 m_ShaderGroupHandleSize; - Uint32 m_ShaderGroupBaseAlignment; - -#ifdef DILIGENT_DEBUG -#endif + + 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; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index 311266e7..11c1ebef 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -59,7 +59,7 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelASVk, TTopLevelASBase); private: - VkDeviceAddress m_DeviceAddress; + VkDeviceAddress m_DeviceAddress = 0; VulkanUtilities::AccelStructWrapper m_VulkanTLAS; VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; ScratchBufferSizes m_ScratchSize; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp index 04189820..0cd6de63 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp @@ -147,7 +147,7 @@ public: vkCmdDrawMeshTasksNV(m_VkCmdBuffer, TaskCount, FirstTask); #else - UNSUPPORTED("DrawMesh is not supported when vulkan library linked statically"); + UNSUPPORTED("DrawMesh is not supported when vulkan library is linked statically"); #endif } @@ -160,7 +160,7 @@ public: vkCmdDrawMeshTasksIndirectNV(m_VkCmdBuffer, Buffer, Offset, DrawCount, Stride); #else - UNSUPPORTED("DrawMeshIndirect is not supported when vulkan library linked statically"); + UNSUPPORTED("DrawMeshIndirect is not supported when vulkan library is linked statically"); #endif } @@ -577,7 +577,7 @@ public: #if DILIGENT_USE_VOLK vkCmdBuildAccelerationStructureKHR(m_VkCmdBuffer, infoCount, pInfos, ppOffsetInfos); #else - UNSUPPORTED("Ray tracing is not supported when vulkan library linked statically"); + UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically"); #endif } @@ -586,7 +586,7 @@ public: #if DILIGENT_USE_VOLK vkCmdCopyAccelerationStructureKHR(m_VkCmdBuffer, &Info); #else - UNSUPPORTED("Ray tracing is not supported when vulkan library linked statically"); + UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically"); #endif } @@ -601,7 +601,7 @@ public: #if DILIGENT_USE_VOLK vkCmdTraceRaysKHR(m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, width, height, depth); #else - UNSUPPORTED("Ray tracing is not supported when vulkan library linked statically"); + UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically"); #endif } diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h index 769391cf..4b352cd6 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h @@ -31,7 +31,7 @@ # define VK_NO_PROTOTYPES #endif -// TODO: remove it when ray tracing will be released +// TODO: remove when ray tracing is released #define VK_ENABLE_BETA_EXTENSIONS #include "vulkan/vulkan.h" diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp index b9bf651c..0adde0d6 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp @@ -44,7 +44,7 @@ public: VkPhysicalDevice8BitStorageFeaturesKHR Storage8Bit = {}; VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {}; VkPhysicalDeviceRayTracingFeaturesKHR RayTracing = {}; - bool RayTracingNV = false; // indicates that KHR extension emulated by NV extension + bool RayTracingNV = false; // indicates that KHR extension is emulated by NV extension VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {}; VkPhysicalDeviceDescriptorIndexingFeaturesEXT DescriptorIndexing = {}; }; diff --git a/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h index eb0c2da5..345b0f3b 100644 --- a/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/BottomLevelASVk.h @@ -49,10 +49,10 @@ static const INTERFACE_ID IID_BottomLevelASVk = /// Exposes Vulkan-specific functionality of a Bottom-level acceleration structure object. DILIGENT_BEGIN_INTERFACE(IBottomLevelASVk, IBottomLevelAS) { - /// Returns a Vulkan BLAS object handle + /// Returns a Vulkan BLAS object handle. VIRTUAL VkAccelerationStructureKHR METHOD(GetVkBLAS)(THIS) CONST PURE; - /// Returns a Vulkan BLAS device address + /// Returns a Vulkan BLAS device address. VIRTUAL VkDeviceAddress METHOD(GetVkDeviceAddress)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE diff --git a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h index 0c95af96..af1f8673 100644 --- a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h @@ -63,7 +63,7 @@ DILIGENT_BEGIN_INTERFACE(IBufferVk, IBuffer) /// returns Vulkan access flags corresponding to the state. If the state is unknown, returns 0. VIRTUAL VkAccessFlags METHOD(GetAccessFlags)(THIS) CONST PURE; - /// Returns a vulkan device address + /// Returns a Vulkan device address. VIRTUAL VkDeviceAddress METHOD(GetVkDeviceAddress)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE diff --git a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h index e3222728..76e0eadd 100644 --- a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h @@ -45,16 +45,19 @@ static const INTERFACE_ID IID_ShaderBindingTableVk = IShaderBindingTableInclusiveMethods; \ IShaderBindingTableVkMethods ShaderBindingTableVk +// clang-format off /// Exposes Vulkan-specific functionality of a Shader binding table object. DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable) { /// AZ TODO - VIRTUAL void METHOD(GetVkStridedBufferRegions)(VkStridedBufferRegionKHR & RaygenShaderBindingTable, - VkStridedBufferRegionKHR & MissShaderBindingTable, - VkStridedBufferRegionKHR & HitShaderBindingTable, - VkStridedBufferRegionKHR & CallableShaderBindingTable) PURE; + VIRTUAL void METHOD(GetVkStridedBufferRegions)(THIS_ + VkStridedBufferRegionKHR REF RaygenShaderBindingTable, + VkStridedBufferRegionKHR REF MissShaderBindingTable, + VkStridedBufferRegionKHR REF HitShaderBindingTable, + VkStridedBufferRegionKHR REF CallableShaderBindingTable) PURE; }; DILIGENT_END_INTERFACE +// clang-format on #include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" diff --git a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h index 3d0b8b09..c09f10c0 100644 --- a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h @@ -48,10 +48,10 @@ static const INTERFACE_ID IID_TopLevelASVk = /// Exposes Vulkan-specific functionality of a Top-level acceleration structure object. DILIGENT_BEGIN_INTERFACE(ITopLevelASVk, ITopLevelAS) { - /// Returns a Vulkan TLAS object handle + /// Returns a Vulkan TLAS object handle. VIRTUAL VkAccelerationStructureKHR METHOD(GetVkTLAS)(THIS) CONST PURE; - /// Returns a Vulkan TLAS device address + /// Returns a Vulkan TLAS device address. VIRTUAL VkDeviceAddress METHOD(GetVkDeviceAddress)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE @@ -60,7 +60,8 @@ DILIGENT_END_INTERFACE #if DILIGENT_C_INTERFACE -# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This) +# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This) +# define ITopLevelASVk_GetVkDeviceAddress(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkDeviceAddress, This) #endif diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp index 85c74834..6e0bcbb8 100644 --- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -36,8 +36,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const BottomLevelASDesc& Desc, bool bIsDeviceInternal) : - TBottomLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal}, - m_DeviceAddress{0} + TBottomLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal} { const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); @@ -100,6 +99,10 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, } VERIFY_EXPR(MaxBoxCount <= Limits.maxPrimitiveCount); } + else + { + UNEXPECTED("Either pTriangles or pBoxes must not be null"); + } m_VulkanBLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index d3f87287..ba36ff7c 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -579,9 +579,12 @@ void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs) return; #ifdef DILIGENT_DEBUG - auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - VERIFY_EXPR(PhysicalDevice.GetExtFeatures().MeshShader.meshShader == VK_TRUE && PhysicalDevice.GetExtFeatures().MeshShader.taskShader == VK_TRUE); - VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount); + { + const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + const auto& MeshShaderFeats = PhysicalDevice.GetExtFeatures().MeshShader; + VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); + VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount); + } #endif PrepareForDraw(Attribs.Flags); @@ -596,8 +599,10 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib return; #ifdef DILIGENT_DEBUG - auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - VERIFY_EXPR(PhysicalDevice.GetExtFeatures().MeshShader.meshShader == VK_TRUE && PhysicalDevice.GetExtFeatures().MeshShader.taskShader == VK_TRUE); + { + const auto& MeshShaderFeats = m_pDevice->GetPhysicalDevice().GetExtFeatures().MeshShader; + VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); + } #endif // We must prepare indirect draw attribs buffer first because state transitions must @@ -2620,8 +2625,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) // AZ TODO: transitions #ifdef DILIGENT_DEBUG - auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); + { + const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE); + } #endif auto* pBLASVk = ValidatedCast(Attribs.pBLAS); @@ -2721,6 +2728,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) off.primitiveCount = src.BoxCount; } } + else + { + UNEXPECTED("pTriangleData or pBoxData must not be null"); + } VkAccelerationStructureGeometryKHR const* GeometriesPtr = Geometries.data(); VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = Offsets.data(); @@ -2750,8 +2761,10 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) // AZ TODO: transitions #ifdef DILIGENT_DEBUG - auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); + { + const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE); + } #endif auto* pTLASVk = ValidatedCast(Attribs.pTLAS); @@ -2823,8 +2836,10 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) // AZ TODO: transitions #ifdef DILIGENT_DEBUG - auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); + { + const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing != VK_FALSE); + } #endif auto* pSrcVk = ValidatedCast(Attribs.pSrc); @@ -2875,8 +2890,10 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) // AZ TODO: transitions #ifdef DILIGENT_DEBUG - auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); + { + const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); + VERIFY_EXPR(PhysicalDevice.GetExtFeatures().RayTracing.rayTracing == VK_TRUE); + } #endif VkStridedBufferRegionKHR RaygenShaderBindingTable = {}; diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 692b5428..7a7d8a07 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -273,7 +273,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E auto RayTracingFeats = DeiceExtFeatures.RayTracing; auto BufferDeviceAddressFeats = DeiceExtFeatures.BufferDeviceAddress; auto DescriptorIndexingFeats = DeiceExtFeatures.DescriptorIndexing; - ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeiceExtFeatures.RayTracingNV, MeshShaders, "Ray tracing are"); + ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeiceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); #undef FeatureSupport @@ -418,6 +418,10 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E *NextExt = &BufferDeviceAddressFeats; NextExt = &BufferDeviceAddressFeats.pNext; } + else + { + UNEXPECTED("Either KHR or NV extension must be enabled"); + } } // make sure that last pNext is null diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index 32c0cb29..b7d2b1f4 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -43,7 +43,7 @@ namespace Diligent static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType) { - static_assert(SHADER_TYPE_LAST == 0x2000, "Please update the switch below to handle the new shader type"); + static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type"); switch (ShaderType) { // clang-format off diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp index 21b06fb3..36fa5af0 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp @@ -36,17 +36,11 @@ ShaderBindingTableVkImpl::ShaderBindingTableVkImpl(IReferenceCounters* RenderDeviceVkImpl* pRenderDeviceVk, const ShaderBindingTableDesc& Desc, bool bIsDeviceInternal) : - TShaderBindingTableBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal}, - m_MissShadersOffset{0}, - m_HitGroupsOffset{0}, - m_CallbaleShadersOffset{0}, - m_MissShaderCount{0}, - m_HitGroupCount{0}, - m_CallableShaderCount{0} + TShaderBindingTableBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal} { ValidateDesc(Desc); - auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; + const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; m_ShaderGroupHandleSize = Props.shaderGroupHandleSize; m_ShaderGroupBaseAlignment = Props.shaderGroupBaseAlignment; @@ -58,7 +52,7 @@ ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl() void ShaderBindingTableVkImpl::ValidateDesc(const ShaderBindingTableDesc& Desc) const { - auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; + const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; if (Desc.ShaderRecordSize + Props.shaderGroupHandleSize > Props.maxShaderGroupStride) { @@ -87,7 +81,7 @@ void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc) m_Desc = Desc; // free memory - decltype(m_ShaderRecords) temp; + decltype(m_ShaderRecords) temp{}; std::swap(temp, m_ShaderRecords); m_MissShadersOffset = 0; @@ -152,7 +146,7 @@ void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(VkStridedBufferRegionKH VkStridedBufferRegionKHR& HitShaderBindingTable, VkStridedBufferRegionKHR& CallableShaderBindingTable) { - auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; + const auto& Props = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; const VkDeviceSize Stride = m_Desc.ShaderRecordSize + Props.shaderGroupHandleSize; VERIFY_EXPR(Stride <= Props.maxShaderGroupStride); diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp index 0fb2f334..76248d41 100644 --- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp @@ -36,8 +36,7 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const TopLevelASDesc& Desc, bool bIsDeviceInternal) : - TTopLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal}, - m_DeviceAddress{0} + TTopLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal} { const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index b797968c..fa03bca6 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -444,7 +444,7 @@ public: TEXTURE_FORMAT operator[](VkFormat VkFmt) const { - if (VkFmt < _countof(m_VkFmtToTexFmtMap)) + if (VkFmt < VK_FORMAT_RANGE_SIZE) { return m_VkFmtToTexFmtMap[VkFmt]; } @@ -456,7 +456,7 @@ public: } private: - TEXTURE_FORMAT m_VkFmtToTexFmtMap[VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1] = {}; + TEXTURE_FORMAT m_VkFmtToTexFmtMap[VK_FORMAT_RANGE_SIZE] = {}; std::unordered_map m_VkFmtToTexFmtMapExt; }; @@ -640,7 +640,7 @@ VkIndexType TypeToVkIndexType(VALUE_TYPE IndexType) case VT_UNDEFINED: return VK_INDEX_TYPE_NONE_KHR; // only for ray tracing case VT_UINT16: return VK_INDEX_TYPE_UINT16; case VT_UINT32: return VK_INDEX_TYPE_UINT32; - // clang-format on + // clang-format on default: UNEXPECTED("Unexpected index type"); return VK_INDEX_TYPE_UINT32; @@ -1167,7 +1167,7 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag) //VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT //VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV - static_assert(RESOURCE_STATE_MAX_BIT == 0x40000, "This function must be updated to handle new resource state flag"); + 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) { @@ -1332,7 +1332,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsi //VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, //VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - static_assert(RESOURCE_STATE_MAX_BIT == 0x40000, "This function must be updated to handle new resource state flag"); + 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) { @@ -1366,7 +1366,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsi RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout) { - static_assert(RESOURCE_STATE_MAX_BIT == 0x40000, "This function must be updated to handle new resource state flag"); + static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "This function must be updated to handle new resource state flag"); switch (Layout) { // clang-format off @@ -1530,7 +1530,8 @@ VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags) VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags) { - static_assert(RAYTRACING_BUILD_AS_FLAGS_LAST == 0x10, "AZ TODO"); + static_assert(RAYTRACING_BUILD_AS_FLAGS_LAST == RAYTRACING_BUILD_AS_LOW_MEMORY, + "Please update the switch below to handle the new ray tracing build flag"); VkBuildAccelerationStructureFlagsKHR Result = 0; for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) @@ -1538,7 +1539,7 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF if ((Flags & Bit) != Bit) continue; - switch (RAYTRACING_BUILD_AS_FLAGS(Bit)) + switch (static_cast(Bit)) { // clang-format off case RAYTRACING_BUILD_AS_ALLOW_UPDATE: Result |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; break; @@ -1546,8 +1547,8 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF case RAYTRACING_BUILD_AS_PREFER_FAST_TRACE: Result |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; break; case RAYTRACING_BUILD_AS_PREFER_FAST_BUILD: Result |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR; break; case RAYTRACING_BUILD_AS_LOW_MEMORY: Result |= VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR; break; + // clang-format on default: UNEXPECTED("unknown build AS flag"); - // clang-format on } } return Result; @@ -1555,7 +1556,8 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags) { - static_assert(RAYTRACING_GEOMETRY_FLAGS_LAST == 0x02, "AZ TODO"); + static_assert(RAYTRACING_GEOMETRY_FLAGS_LAST == RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION, + "Please update the switch below to handle the new ray tracing geometry flag"); VkGeometryFlagsKHR Result = 0; for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) @@ -1563,13 +1565,13 @@ VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flag if ((Flags & Bit) != Bit) continue; - switch (RAYTRACING_GEOMETRY_FLAGS(Bit)) + switch (static_cast(Bit)) { // clang-format off case RAYTRACING_GEOMETRY_OPAQUE: Result |= VK_GEOMETRY_OPAQUE_BIT_KHR; break; case RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION: Result |= VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR; break; + // clang-format on default: UNEXPECTED("unknown geometry flag"); - // clang-format on } } return Result; @@ -1577,7 +1579,8 @@ VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flag VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags) { - static_assert(RAYTRACING_INSTANCE_FLAGS_LAST == 0x08, "AZ TODO"); + static_assert(RAYTRACING_INSTANCE_FLAGS_LAST == RAYTRACING_INSTANCE_FORCE_NO_OPAQUE, + "Please update the switch below to handle the new ray tracing instance flag"); VkGeometryInstanceFlagsKHR Result = 0; for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) @@ -1585,15 +1588,15 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS if ((Flags & Bit) != Bit) continue; - switch (RAYTRACING_INSTANCE_FLAGS(Bit)) + switch (static_cast(Bit)) { // clang-format off - case RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE: return VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; - case RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE: return VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR; - case RAYTRACING_INSTANCE_FORCE_OPAQUE: return VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR; - case RAYTRACING_INSTANCE_FORCE_NO_OPAQUE: return VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR; + case RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE: Result |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; break; + case RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE: Result |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR; break; + case RAYTRACING_INSTANCE_FORCE_OPAQUE: Result |= VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR; break; + case RAYTRACING_INSTANCE_FORCE_NO_OPAQUE: Result |= VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR; break; + // clang-format on default: UNEXPECTED("unknown instance flag"); - // clang-format on } } return Result; @@ -1601,17 +1604,18 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS VkCopyAccelerationStructureModeKHR CopyASModeToVkCopyAccelerationStructureMode(COPY_AS_MODE Mode) { - static_assert(COPY_AS_MODE_LAST == 0, "AZ TODO"); + static_assert(COPY_AS_MODE_LAST == COPY_AS_MODE_CLONE, + "Please update the switch below to handle the new copy AS mode"); switch (Mode) { // clang-format off case COPY_AS_MODE_CLONE: return VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; - // clang-format on + // clang-format on + default: + UNEXPECTED("unknown AS copy mode"); + return static_cast(0); } - - UNEXPECTED("unknown AS copy mode"); - return VkCopyAccelerationStructureModeKHR(0); } } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index 22659277..3e5f28d4 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -143,7 +143,7 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, RayTracingNV.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV; } - // Additional extension that required for ray tracing. + // Additional extension that is required for ray tracing. if (IsExtensionSupported(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) { *NextFeat = &m_ExtFeatures.BufferDeviceAddress; @@ -152,7 +152,7 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtFeatures.BufferDeviceAddress.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR; } - // Additional extension that required for ray tracing. + // Additional extension that is required for ray tracing. if (IsExtensionSupported(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) { *NextFeat = &m_ExtFeatures.DescriptorIndexing; diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp index de16fe6a..f7a6b8f6 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp @@ -25,44 +25,49 @@ * of the possibility of such damages. */ -#include "VulkanErrors.hpp" -#include "VulkanUtilities/VulkanLogicalDevice.hpp" -// for KHR ray tracing emulation +// KHR ray tracing emulation through NVidia extension. +// Will be deprecated after the release of KHR extension. + #include #include +#include + +#include "VulkanErrors.hpp" +#include "VulkanUtilities/VulkanLogicalDevice.hpp" namespace VulkanUtilities { -// KHR ray tracing emulation. -// Will be deprecated after the release of KHR extension. #if DILIGENT_USE_VOLK -static_assert(sizeof(VkAccelerationStructureKHR) == sizeof(VkAccelerationStructureNV), "not compatible with NV extension"); -static_assert(sizeof(VkDeviceAddress) == 8, "not compatible with NV extension"); - -static std::mutex g_BufferDeviceAddressGuard; -static std::unordered_map g_DeviceAddressToBuffer; -static std::unordered_map g_BufferToDeviceAddress; -static uint32_t g_BufferDeviceAddressCounter = 0; -static const VkDeviceAddress g_BufferMask = 0xFFFFFFFF00000000ull; - -static PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr; -static PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr; -static PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr; - -static VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device, - const VkBufferCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkBuffer* pBuffer) +static_assert(sizeof(VkAccelerationStructureKHR) == sizeof(VkAccelerationStructureNV), "KHR is incompatible with NV extension"); +static_assert(sizeof(VkDeviceAddress) == 8, "KHR is incompatible with NV extension"); + +namespace +{ + +std::mutex g_BufferDeviceAddressGuard; +std::unordered_map g_DeviceAddressToBuffer; +std::unordered_map g_BufferToDeviceAddress; +uint32_t g_BufferDeviceAddressCounter = 0; +constexpr VkDeviceAddress g_BufferMask = 0xFFFFFFFF00000000ull; + +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) { const_cast(pCreateInfo)->usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; return Origin_vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer); } -static void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device, - VkBuffer buffer, - const VkAllocationCallbacks* pAllocator) +void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device, + VkBuffer buffer, + const VkAllocationCallbacks* pAllocator) { Origin_vkDestroyBuffer(device, buffer, pAllocator); @@ -76,8 +81,8 @@ static void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device, } } -static VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice device, - const VkBufferDeviceAddressInfo* pInfo) +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); @@ -90,9 +95,9 @@ static VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice return iter->second; // create new device address - VkDeviceAddress Addr = VkDeviceAddress(++g_BufferDeviceAddressCounter) << 32; - g_BufferToDeviceAddress.insert_or_assign(pInfo->buffer, Addr); - g_DeviceAddressToBuffer.insert_or_assign(Addr, pInfo->buffer); + VkDeviceAddress Addr = VkDeviceAddress{++g_BufferDeviceAddressCounter} << 32; + g_BufferToDeviceAddress[pInfo->buffer] = Addr; + g_DeviceAddressToBuffer[Addr] = pInfo->buffer; return Addr; } @@ -101,7 +106,7 @@ struct BufferAndOffset VkBuffer Buffer; VkDeviceSize Offset; }; -static BufferAndOffset DeviceAddressToBuffer(VkDeviceAddress Addr) +BufferAndOffset DeviceAddressToBuffer(VkDeviceAddress Addr) { if (Addr == 0) return {VK_NULL_HANDLE, 0}; @@ -118,21 +123,21 @@ static BufferAndOffset DeviceAddressToBuffer(VkDeviceAddress Addr) return {iter->second, Addr & ~g_BufferMask}; } -static BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressConstKHR& Addr) +BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressConstKHR& Addr) { return DeviceAddressToBuffer(Addr.deviceAddress); } -static BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressKHR& Addr) +BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressKHR& Addr) { return DeviceAddressToBuffer(Addr.deviceAddress); } -static VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice device, - const VkAccelerationStructureCreateInfoKHR* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkAccelerationStructureKHR* pAccelerationStructure) +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); @@ -219,9 +224,9 @@ static VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevice return vkCreateAccelerationStructureNV(device, &CreateInfo, pAllocator, reinterpret_cast(pAccelerationStructure)); } -static void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR(VkDevice device, - const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo, - VkMemoryRequirements2* pMemoryRequirements) +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(pInfo->pNext == nullptr); @@ -236,16 +241,16 @@ static void VKAPI_CALL Redirect_vkGetAccelerationStructureMemoryRequirementsKHR( return vkGetAccelerationStructureMemoryRequirementsNV(device, &Info, pMemoryRequirements); } -static VkResult VKAPI_CALL Redirect_vkBindAccelerationStructureMemoryKHR(VkDevice device, - uint32_t bindInfoCount, - const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos) +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); } -static VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddressKHR(VkDevice device, - const VkAccelerationStructureDeviceAddressInfoKHR* pInfo) +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); @@ -255,10 +260,10 @@ static VkDeviceAddress VKAPI_CALL Redirect_vkGetAccelerationStructureDeviceAddre return result; } -static void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer, - uint32_t infoCount, - const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, - const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos) +void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer, + uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos) { std::vector Geometries; @@ -384,8 +389,8 @@ static void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuff } } -static void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer, - const VkCopyAccelerationStructureInfoKHR* pInfo) +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); @@ -393,14 +398,14 @@ static void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandBuffe vkCmdCopyAccelerationStructureNV(commandBuffer, pInfo->dst, pInfo->src, pInfo->mode); } -static 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) +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, @@ -410,22 +415,22 @@ static void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer width, height, depth); } -static VkResult VKAPI_CALL Redirect_vkGetRayTracingShaderGroupHandlesKHR(VkDevice device, - VkPipeline pipeline, - uint32_t firstGroup, - uint32_t groupCount, - size_t dataSize, - void* pData) +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); } -static VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device, - VkPipelineCache pipelineCache, - uint32_t createInfoCount, - const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, - const VkAllocationCallbacks* pAllocator, - VkPipeline* pPipelines) +VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines) { std::vector Infos; std::vector Groups; @@ -488,6 +493,8 @@ static VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice return vkCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, Infos.data(), pAllocator, pPipelines); } +} // namespace + void EnableRayTracingKHRviaNV() { vkCreateAccelerationStructureKHR = &Redirect_vkCreateAccelerationStructureKHR; -- cgit v1.2.3 From 33372bb90cd4c7d522c98fdc56fd65755373f9bb Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 5 Oct 2020 09:12:33 -0700 Subject: Fixed Mac/iOS build --- Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp | 7 ++++++- .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 23 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp index 80130696..7085765c 100644 --- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp @@ -493,8 +493,9 @@ VkDeviceAddress BufferVkImpl::GetVkDeviceAddress() const { constexpr auto DeviceAddressFlags = BIND_RAY_TRACING; - if (m_VulkanBuffer != VK_NULL_HANDLE && !!(m_Desc.BindFlags & DeviceAddressFlags)) + if (m_VulkanBuffer != VK_NULL_HANDLE && (m_Desc.BindFlags & DeviceAddressFlags) != 0) { +#if DILIGENT_USE_VOLK VkBufferDeviceAddressInfoKHR BufferInfo = {}; BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR; @@ -502,6 +503,10 @@ VkDeviceAddress BufferVkImpl::GetVkDeviceAddress() const VkDeviceAddress Result = vkGetBufferDeviceAddressKHR(m_pDevice->GetLogicalDevice().GetVkDevice(), &BufferInfo); VERIFY_EXPR(Result > 0); return Result; +#else + UNSUPPORTED("vkGetBufferDeviceAddressKHR is only available through Volk"); + return VkDeviceAddress{}; +#endif } else { diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index 87bfc450..f9e190d8 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -269,8 +269,13 @@ QueryPoolWrapper VulkanLogicalDevice::CreateQueryPool(const VkQueryPoolCreateInf AccelStructWrapper VulkanLogicalDevice::CreateAccelStruct(const VkAccelerationStructureCreateInfoKHR& CI, const char* DebugName) const { +#if DILIGENT_USE_VOLK VERIFY_EXPR(CI.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR); return CreateVulkanObject(vkCreateAccelerationStructureKHR, CI, DebugName, "acceleration structure"); +#else + UNSUPPORTED("vkCreateAccelerationStructureKHR is only available through Volk"); + return AccelStructWrapper{}; +#endif } VkCommandBuffer VulkanLogicalDevice::AllocateVkCommandBuffer(const VkCommandBufferAllocateInfo& AllocInfo, const char* DebugName) const @@ -416,8 +421,12 @@ void VulkanLogicalDevice::ReleaseVulkanObject(QueryPoolWrapper&& QueryPool) cons void VulkanLogicalDevice::ReleaseVulkanObject(AccelStructWrapper&& AccelStruct) const { +#if DILIGENT_USE_VOLK vkDestroyAccelerationStructureKHR(m_VkDevice, AccelStruct.m_VkObject, m_VkAllocator); AccelStruct.m_VkObject = VK_NULL_HANDLE; +#else + UNSUPPORTED("vkDestroyAccelerationStructureKHR is only available through Volk"); +#endif } void VulkanLogicalDevice::FreeDescriptorSet(VkDescriptorPool Pool, VkDescriptorSet Set) const @@ -446,7 +455,11 @@ VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkI VkMemoryRequirements VulkanLogicalDevice::GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const { VkMemoryRequirements2 MemReqs = {}; +#if DILIGENT_USE_VOLK vkGetAccelerationStructureMemoryRequirementsKHR(m_VkDevice, &Info, &MemReqs); +#else + UNSUPPORTED("vkGetAccelerationStructureMemoryRequirementsKHR is only available through Volk"); +#endif return MemReqs.memoryRequirements; } @@ -462,6 +475,7 @@ VkResult VulkanLogicalDevice::BindImageMemory(VkImage image, VkDeviceMemory memo VkResult VulkanLogicalDevice::BindASMemory(VkAccelerationStructureKHR AS, VkDeviceMemory memory, VkDeviceSize memoryOffset) const { +#if DILIGENT_USE_VOLK VkBindAccelerationStructureMemoryInfoKHR Info = {}; Info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; @@ -472,16 +486,25 @@ VkResult VulkanLogicalDevice::BindASMemory(VkAccelerationStructureKHR AS, VkDevi Info.accelerationStructure = AS; return vkBindAccelerationStructureMemoryKHR(m_VkDevice, 1, &Info); +#else + UNSUPPORTED("vkBindAccelerationStructureMemoryKHR is only available through Volk"); + return VK_ERROR_FEATURE_NOT_PRESENT; +#endif } VkDeviceAddress VulkanLogicalDevice::GetAccelerationStructureDeviceAddress(VkAccelerationStructureKHR AS) const { +#if DILIGENT_USE_VOLK VkAccelerationStructureDeviceAddressInfoKHR Info = {}; Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; Info.accelerationStructure = AS; return vkGetAccelerationStructureDeviceAddressKHR(m_VkDevice, &Info); +#else + UNSUPPORTED("vkGetAccelerationStructureDeviceAddressKHR is only available through Volk"); + return VK_ERROR_FEATURE_NOT_PRESENT; +#endif } VkResult VulkanLogicalDevice::MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const -- cgit v1.2.3 From 7f26e40e0898391a32e6a05d91ef1a217d885668 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sun, 25 Oct 2020 15:53:05 +0300 Subject: PSO refactoring for ray tracing --- .../include/PipelineLayout.hpp | 6 +- .../include/PipelineStateVkImpl.hpp | 3 +- .../include/RenderDeviceVkImpl.hpp | 3 + .../include/ShaderResourceBindingVkImpl.hpp | 2 +- .../include/ShaderResourceCacheVk.hpp | 13 +- .../include/ShaderResourceLayoutVk.hpp | 162 +++-- .../include/ShaderVariableVk.hpp | 4 +- .../include/VulkanUtilities/VulkanInstance.hpp | 8 +- .../VulkanUtilities/VulkanLogicalDevice.hpp | 12 +- .../VulkanUtilities/VulkanObjectWrappers.hpp | 5 + .../VulkanUtilities/VulkanPhysicalDevice.hpp | 2 + .../src/DeviceContextVkImpl.cpp | 10 +- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 129 ++-- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 38 +- .../src/PipelineStateVkImpl.cpp | 499 ++++++++++---- .../src/RenderDeviceVkImpl.cpp | 53 +- .../src/ShaderResourceCacheVk.cpp | 48 +- .../src/ShaderResourceLayoutVk.cpp | 758 ++++++++++++++------- .../GraphicsEngineVulkan/src/ShaderVariableVk.cpp | 14 +- Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp | 8 + .../src/VulkanUtilities/VulkanInstance.cpp | 21 +- .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 41 +- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 14 +- 23 files changed, 1269 insertions(+), 584 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp index 73fced1f..8a0fab15 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp @@ -48,7 +48,7 @@ class ShaderResourceCacheVk; class PipelineLayout { public: - static VkDescriptorType GetVkDescriptorType(const SPIRVShaderResourceAttribs& Res); + static VkDescriptorType GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type); PipelineLayout(); void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask); @@ -69,8 +69,7 @@ public: SHADER_TYPE ShaderType, Uint32& DescriptorSet, Uint32& Binding, - Uint32& OffsetInCache, - std::vector& SPIRV); + Uint32& OffsetInCache); Uint32 GetTotalDescriptors(SHADER_RESOURCE_VARIABLE_TYPE VarType) const { @@ -137,7 +136,6 @@ public: // set by the same Vulkan command. If there are no dynamic descriptors, this // function also binds descriptor sets rightaway. void PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, - bool IsCompute, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const; diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index d4f2fc36..a02c8d74 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -59,6 +59,7 @@ public: PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo); PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const ComputePipelineStateCreateInfo& CreateInfo); + PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const RayTracingPipelineStateCreateInfo& CreateInfo); ~PipelineStateVkImpl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; @@ -168,7 +169,7 @@ private: // Resource layout index in m_ShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index d85e9ff3..9ceed3e4 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -78,6 +78,9 @@ public: /// Implementation of IRenderDevice::CreateComputePipelineState() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateRayTracingPipelineState() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateBuffer() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp index 00f2c33a..68401f52 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp @@ -83,7 +83,7 @@ private: // Resource layout index in m_ShaderResourceCache array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; bool m_bStaticResourcesInitialized = false; Uint8 m_NumShaders = 0; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp index 7d77ff48..0bcf79a0 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp @@ -112,12 +112,13 @@ public: /*1-7*/ // Unused /* 8 */ RefCntAutoPtr pObject; - VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const; - VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const; - VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler)const; - VkBufferView GetBufferViewWriteInfo () const; - VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const; - VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const; + VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const; + VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const; + VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler) const; + VkBufferView GetBufferViewWriteInfo () const; + VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const; + VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const; + VkWriteDescriptorSetAccelerationStructureKHR GetAccelerationStructureWriteInfo() const; // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 9452a390..e5cddb0c 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -113,18 +113,21 @@ namespace Diligent class ShaderVkImpl; /// Diligent::ShaderResourceLayoutVk class -// sizeof(ShaderResourceLayoutVk)==56 (MS compiler, x64) +// sizeof(ShaderResourceLayoutVk)==72 (MS compiler, x64) class ShaderResourceLayoutVk { public: struct ShaderStageInfo { - ShaderStageInfo(SHADER_TYPE _Type, - const ShaderVkImpl* _pShader); + ShaderStageInfo() {} + ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader); - const SHADER_TYPE Type; - const ShaderVkImpl* const pShader; - std::vector SPIRV; + void Append(const ShaderVkImpl* pShader); + size_t Count() const; + + SHADER_TYPE Type = SHADER_TYPE_UNKNOWN; + std::vector Shaders; + std::vector> SPIRVs; }; using TShaderStages = std::vector; @@ -144,10 +147,10 @@ public: // This method is called by PipelineStateVkImpl class instance to initialize static // shader resource layout and the cache - void InitializeStaticResourceLayout(const ShaderVkImpl* pShader, - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderResourceCacheVk& StaticResourceCache); + void InitializeStaticResourceLayout(const std::vector& Shaders, + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderResourceCacheVk& StaticResourceCache); // This method is called by PipelineStateVkImpl class instance to initialize resource // layouts for all shader stages in the pipeline. @@ -160,7 +163,7 @@ public: bool VerifyVariables, bool VerifyImmutableSamplers); - // sizeof(VkResource) == 24 (x64) + // sizeof(VkResource) == 32 (x64) struct VkResource { // clang-format off @@ -178,40 +181,56 @@ public: static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1; + using ResourceType = SPIRVShaderResourceAttribs::ResourceType; + /* 0 */ const Uint16 Binding; -/* 2 */ const Uint16 DescriptorSet; +/* 2 */ const Uint16 ArraySize; /* 4.0 */ const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set /* 6.5 */ const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler // assigned to separate image /* 7.5 */ const Uint32 VariableType : VariableTypeBits; /* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits; +/* 8 */ const Uint8 DescriptorSet; + +/* 9 */ const ResourceType Type; +/* 10.0*/ const Uint8 ResourceDim : 7; +/* 10.7*/ const Uint8 IsMS : 1; +/* 16 */ const char* const Name; +/* 24 */ const ShaderResourceLayoutVk& ParentResLayout; + // clang-format on -/* 8 */ const SPIRVShaderResourceAttribs& SpirvAttribs; -/* 16 */ const ShaderResourceLayoutVk& ParentResLayout; - - VkResource(const ShaderResourceLayoutVk& _ParentLayout, - const SPIRVShaderResourceAttribs& _SpirvAttribs, - SHADER_RESOURCE_VARIABLE_TYPE _VariableType, - uint32_t _Binding, - uint32_t _DescriptorSet, - Uint32 _CacheOffset, - Uint32 _SamplerInd, - bool _ImmutableSamplerAssigned = false)noexcept : + VkResource(const ShaderResourceLayoutVk& _ParentLayout, + const char* _Name, + Uint16 _ArraySize, + ResourceType _Type, + Uint8 _ResourceDim, + Uint8 _IsMS, + SHADER_RESOURCE_VARIABLE_TYPE _VariableType, + uint32_t _Binding, + uint32_t _DescriptorSet, + Uint32 _CacheOffset, + Uint32 _SamplerInd, + bool _ImmutableSamplerAssigned = false) noexcept : + // clang-format off Binding {static_cast(_Binding) }, DescriptorSet {static_cast(_DescriptorSet)}, CacheOffset {_CacheOffset }, SamplerInd {_SamplerInd }, VariableType {_VariableType }, ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, - SpirvAttribs {_SpirvAttribs }, + Name {_Name }, + ArraySize {_ArraySize }, + Type {_Type }, + ResourceDim {_ResourceDim }, + IsMS {_IsMS }, ParentResLayout {_ParentLayout } + // clang-format on { - VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) ); - VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) ); - VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max() ); + VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits)); + VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits)); + VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max()); VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); } - // clang-format on // Checks if a resource is bound in ResourceCache at the given ArrayIndex bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const; @@ -220,17 +239,18 @@ public: void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const; // Updates resource descriptor in the descriptor set - inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, - uint32_t ArrayElement, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView) const; + inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, + uint32_t ArrayElement, + const VkDescriptorImageInfo* pImageInfo, + const VkDescriptorBufferInfo* pBufferInfo, + const VkBufferView* pTexelBufferView, + const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo = nullptr) const; bool IsImmutableSamplerAssigned() const { VERIFY(ImmutableSamplerAssigned == 0 || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, + Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Immutable sampler can only be assigned to a sampled image or separate sampler"); return ImmutableSamplerAssigned != 0; } @@ -240,6 +260,31 @@ public: return static_cast(VariableType); } + String GetPrintName(Uint32 ArrayInd) const + { + VERIFY_EXPR(ArrayInd < ArraySize); + if (ArraySize > 1) + { + std::stringstream ss; + ss << Name << '[' << ArrayInd << ']'; + return ss.str(); + } + else + return Name; + } + + ShaderResourceDesc GetResourceDesc() const; + + RESOURCE_DIMENSION GetResourceDimension() const + { + return static_cast(ResourceDim); + } + + bool IsMultisample() const + { + return IsMS != 0; + } + private: void CacheUniformBuffer(IDeviceObject* pBuffer, ShaderResourceCacheVk::Resource& DstRes, @@ -276,6 +321,11 @@ public: VkDescriptorSet vkDescrSet, Uint32 ArrayInd) const; + void CacheAccelerationStructure(IDeviceObject* pTLAS, + ShaderResourceCacheVk::Resource& DstRes, + VkDescriptorSet vkDescrSet, + Uint32 ArrayInd) const; + template bool UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes, RefCntAutoPtr&& pObject, @@ -310,15 +360,10 @@ public: const Char* GetShaderName() const { - return m_pResources->GetShaderName(); + return ""; // AZ TODO } - SHADER_TYPE GetShaderType() const - { - return m_pResources->GetShaderType(); - } - - const SPIRVShaderResources& GetResources() const { return *m_pResources; } + SHADER_TYPE GetShaderType() const { return m_ShaderType; } const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const { @@ -327,7 +372,7 @@ public: return Resources[GetResourceOffset(VarType, r)]; } - bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedSamplers(); } + bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; } private: Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const @@ -358,12 +403,14 @@ private: return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } - void AllocateMemory(const ShaderVkImpl* pShader, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - bool AllocateImmutableSamplers); + using ResourceNameToIndex_t = std::unordered_map; + void AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers); using ImmutableSamplerPtrType = RefCntAutoPtr; ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept @@ -374,16 +421,17 @@ private: } // clang-format off -/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; -/* 8 */ std::unique_ptr > m_ResourceBuffer; +/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; +/* 8 */ std::unique_ptr > m_ResourceBuffer; // AZ TODO: use linear allocator +/*24 */ StringPool m_StringPool; + +/*48 */ std::array m_NumResources = {}; - // We must use shared_ptr to reference ShaderResources instance, because - // there may be multiple objects referencing the same set of resources -/*24 */ std::shared_ptr m_pResources; +/*56 */ Uint32 m_NumImmutableSamplers = 0; +/*60 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; +/*64 */ bool m_IsUsingSeparateSamplers = false; -/*40 */ std::array m_NumResources = {}; -/*48 */ Uint32 m_NumImmutableSamplers = 0; -/*56*/ // End of class +/*72 */ // End of class // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp index 27689c1e..6c88bf56 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp @@ -183,14 +183,14 @@ public: Uint32 FirstElement, Uint32 NumElements) override final { - VerifyAndCorrectSetArrayArguments(m_Resource.SpirvAttribs.Name, m_Resource.SpirvAttribs.ArraySize, FirstElement, NumElements); + VerifyAndCorrectSetArrayArguments(m_Resource.Name, m_Resource.ArraySize, FirstElement, NumElements); for (Uint32 Elem = 0; Elem < NumElements; ++Elem) m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache); } virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final { - ResourceDesc = m_Resource.SpirvAttribs.GetResourceDesc(); + ResourceDesc = m_Resource.GetResourceDesc(); } virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp index f5b921a6..c28be56c 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp @@ -44,7 +44,8 @@ public: VulkanInstance& operator = ( VulkanInstance&&) = delete; // clang-format on - static std::shared_ptr Create(bool EnableValidation, + static std::shared_ptr Create(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator); @@ -69,10 +70,12 @@ public: VkAllocationCallbacks* GetVkAllocator()const{return m_pVkAllocator;} VkInstance GetVkInstance() const{return m_VkInstance; } + uint32_t GetVkVersion() const{return m_VkVersion; } // clang-format on private: - VulkanInstance(bool EnableValidation, + VulkanInstance(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator); @@ -80,6 +83,7 @@ private: bool m_DebugUtilsEnabled = false; VkAllocationCallbacks* const m_pVkAllocator; VkInstance m_VkInstance = VK_NULL_HANDLE; + uint32_t m_VkVersion = VK_API_VERSION_1_0; std::vector m_Layers; std::vector m_Extensions; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp index a8366551..5e60a343 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp @@ -88,8 +88,11 @@ using AccelStructWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(AccelerationStru class VulkanLogicalDevice : public std::enable_shared_from_this { public: + using ExtensionFeatures = VulkanPhysicalDevice::ExtensionFeatures; + static std::shared_ptr Create(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator); // clang-format off @@ -131,8 +134,9 @@ public: RenderPassWrapper CreateRenderPass (const VkRenderPassCreateInfo& RenderPassCI,const char* DebugName = "") const; DeviceMemoryWrapper AllocateDeviceMemory(const VkMemoryAllocateInfo & AllocInfo, const char* DebugName = "") const; - PipelineWrapper CreateComputePipeline (const VkComputePipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; - PipelineWrapper CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; + PipelineWrapper CreateComputePipeline (const VkComputePipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; + PipelineWrapper CreateGraphicsPipeline (const VkGraphicsPipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; + PipelineWrapper CreateRayTracingPipeline(const VkRayTracingPipelineCreateInfoKHR& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; ShaderModuleWrapper CreateShaderModule (const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName = "") const; PipelineLayoutWrapper CreatePipelineLayout (const VkPipelineLayoutCreateInfo& LayoutCI, const char* DebugName = "") const; @@ -216,12 +220,15 @@ public: } VkPipelineStageFlags GetEnabledGraphicsShaderStages() const { return m_EnabledGraphicsShaderStages; } + VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const; const VkPhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; } + const ExtensionFeatures& GetEnabledExtFeatures() const { return m_EnabledExtFeatures; } private: VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator); template GetPhysicalDevice(); - const auto& MeshShaderFeats = PhysicalDevice.GetExtFeatures().MeshShader; + const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); + const auto& MeshShaderFeats = LogicalDevice.GetEnabledExtFeatures().MeshShader; VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount); } @@ -612,7 +618,7 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib #ifdef DILIGENT_DEBUG { - const auto& MeshShaderFeats = m_pDevice->GetPhysicalDevice().GetExtFeatures().MeshShader; + const auto& MeshShaderFeats = m_pDevice->GetLogicalDevice().GetEnabledExtFeatures().MeshShader; VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index d37655a5..fcb64973 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -138,6 +138,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E try { auto Instance = VulkanUtilities::VulkanInstance::Create( + VK_API_VERSION_1_2, // AZ TODO: use 1.2 only for ray tracing, wave ops extensions EngineCI.EnableValidation, EngineCI.GlobalExtensionCount, EngineCI.ppGlobalExtensionNames, @@ -238,7 +239,11 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height }; - const auto& DeviceExtFeatures = PhysicalDevice->GetExtFeatures(); + const VulkanUtilities::VulkanPhysicalDevice::ExtensionFeatures& DeviceExtFeatures = PhysicalDevice->GetExtFeatures(); + VulkanUtilities::VulkanPhysicalDevice::ExtensionFeatures EnabledExtFeats = {}; + + // SPIRV 1.5 is in Vulkan 1.2 core + EnabledExtFeats.Spirv15 = DeviceExtFeatures.Spirv15; #define ENABLE_FEATURE(IsFeatureSupported, Feature, FeatureName) \ do \ @@ -247,33 +252,25 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E GetFeatureState(EngineCI.Features.Feature, IsFeatureSupported, FeatureName); \ } while (false) + ENABLE_FEATURE(DeviceExtFeatures.MeshShader.taskShader != VK_FALSE && DeviceExtFeatures.MeshShader.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); - auto MeshShaderFeats = DeviceExtFeatures.MeshShader; - ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); - - auto ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8; // clang-format off - ENABLE_FEATURE(ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); - ENABLE_FEATURE(ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); + ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); + ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); // clang-format on - auto Storage16BitFeats = DeviceExtFeatures.Storage16Bit; // clang-format off - ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); - ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); - ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); + ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); // clang-format on - auto Storage8BitFeats = DeviceExtFeatures.Storage8Bit; // clang-format off - ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); - ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); // clang-format on - auto RayTracingFeats = DeviceExtFeatures.RayTracing; - auto BufferDeviceAddressFeats = DeviceExtFeatures.BufferDeviceAddress; - auto DescriptorIndexingFeats = DeviceExtFeatures.DescriptorIndexing; - ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); + ENABLE_FEATURE((DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE && DeviceExtFeatures.Spirv14) || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); #undef FeatureSupport @@ -289,31 +286,33 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // Mesh shader if (EngineCI.Features.MeshShaders != DEVICE_FEATURE_STATE_DISABLED) { - VERIFY_EXPR(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE); + EnabledExtFeats.MeshShader = DeviceExtFeatures.MeshShader; + VERIFY_EXPR(EnabledExtFeats.MeshShader.taskShader != VK_FALSE && EnabledExtFeats.MeshShader.meshShader != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME), "VK_NV_mesh_shader extension must be supported as it has already been checked by VulkanPhysicalDevice and " "both taskShader and meshShader features are TRUE"); DeviceExtensions.push_back(VK_NV_MESH_SHADER_EXTENSION_NAME); - *NextExt = &MeshShaderFeats; - NextExt = &MeshShaderFeats.pNext; + *NextExt = &EnabledExtFeats.MeshShader; + NextExt = &EnabledExtFeats.MeshShader.pNext; } if (EngineCI.Features.ShaderFloat16 != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.ShaderInt8 != DEVICE_FEATURE_STATE_DISABLED) { - VERIFY_EXPR(ShaderFloat16Int8.shaderFloat16 != VK_FALSE || ShaderFloat16Int8.shaderInt8 != VK_FALSE); + EnabledExtFeats.ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8; + VERIFY_EXPR(EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 != VK_FALSE || EnabledExtFeats.ShaderFloat16Int8.shaderInt8 != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME), "VK_KHR_shader_float16_int8 extension must be supported as it has already been checked by VulkanPhysicalDevice " "and at least one of shaderFloat16 or shaderInt8 features is TRUE"); DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); if (EngineCI.Features.ShaderFloat16 == DEVICE_FEATURE_STATE_DISABLED) - ShaderFloat16Int8.shaderFloat16 = VK_FALSE; + EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 = VK_FALSE; if (EngineCI.Features.ShaderInt8 == DEVICE_FEATURE_STATE_DISABLED) - ShaderFloat16Int8.shaderInt8 = VK_FALSE; + EnabledExtFeats.ShaderFloat16Int8.shaderInt8 = VK_FALSE; - *NextExt = &ShaderFloat16Int8; - NextExt = &ShaderFloat16Int8.pNext; + *NextExt = &EnabledExtFeats.ShaderFloat16Int8; + NextExt = &EnabledExtFeats.ShaderFloat16Int8.pNext; } bool StorageBufferStorageClassExtensionRequired = false; @@ -325,9 +324,10 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE); - VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE); - VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.storageInputOutput16 != VK_FALSE); + EnabledExtFeats.Storage16Bit = DeviceExtFeatures.Storage16Bit; + VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess != VK_FALSE); + VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE); + VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageInputOutput16 != VK_FALSE); // clang-format on VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_16BIT_STORAGE_EXTENSION_NAME), @@ -344,14 +344,14 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E StorageBufferStorageClassExtensionRequired = true; if (EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage16BitFeats.storageBuffer16BitAccess = VK_FALSE; + EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess = VK_FALSE; if (EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage16BitFeats.uniformAndStorageBuffer16BitAccess = VK_FALSE; + EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess = VK_FALSE; if (EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED) - Storage16BitFeats.storageInputOutput16 = VK_FALSE; + EnabledExtFeats.Storage16Bit.storageInputOutput16 = VK_FALSE; - *NextExt = &Storage16BitFeats; - NextExt = &Storage16BitFeats.pNext; + *NextExt = &EnabledExtFeats.Storage16Bit; + NextExt = &EnabledExtFeats.Storage16Bit.pNext; } // clang-format off @@ -360,8 +360,9 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE); - VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE); + EnabledExtFeats.Storage8Bit = DeviceExtFeatures.Storage8Bit; + VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess != VK_FALSE); + VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE); // clang-format on VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_8BIT_STORAGE_EXTENSION_NAME), @@ -378,12 +379,12 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E StorageBufferStorageClassExtensionRequired = true; if (EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage8BitFeats.storageBuffer8BitAccess = VK_FALSE; + EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess = VK_FALSE; if (EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage8BitFeats.uniformAndStorageBuffer8BitAccess = VK_FALSE; + EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess = VK_FALSE; - *NextExt = &Storage8BitFeats; - NextExt = &Storage8BitFeats.pNext; + *NextExt = &EnabledExtFeats.Storage8Bit; + NextExt = &EnabledExtFeats.Storage8Bit.pNext; } if (StorageBufferStorageClassExtensionRequired) @@ -398,29 +399,37 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E { if (DeviceExtFeatures.RayTracingNV) { + EnabledExtFeats.RayTracingNV = DeviceExtFeatures.RayTracingNV; DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME); } - else if (RayTracingFeats.rayTracing != VK_FALSE) - { - // required extensions - DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME); - - *NextExt = &RayTracingFeats; - NextExt = &RayTracingFeats.pNext; - *NextExt = &DescriptorIndexingFeats; - NextExt = &DescriptorIndexingFeats.pNext; - *NextExt = &BufferDeviceAddressFeats; - NextExt = &BufferDeviceAddressFeats.pNext; - } - else + else if (DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE) { - UNEXPECTED("Either KHR or NV extension must be enabled"); + DeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // required for VK_EXT_descriptor_indexing + DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME); // required for VK_KHR_ray_tracing + + EnabledExtFeats.RayTracing = DeviceExtFeatures.RayTracing; + EnabledExtFeats.BufferDeviceAddress = DeviceExtFeatures.BufferDeviceAddress; + EnabledExtFeats.DescriptorIndexing = DeviceExtFeatures.DescriptorIndexing; + + if (!DeviceExtFeatures.Spirv15) + { + DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); // required for VK_KHR_spirv_1_4 + DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for ray tracing shaders + EnabledExtFeats.Spirv14 = DeviceExtFeatures.Spirv14; + } + + *NextExt = &EnabledExtFeats.RayTracing; + NextExt = &EnabledExtFeats.RayTracing.pNext; + *NextExt = &EnabledExtFeats.DescriptorIndexing; + NextExt = &EnabledExtFeats.DescriptorIndexing.pNext; + *NextExt = &EnabledExtFeats.BufferDeviceAddress; + NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext; } } @@ -436,7 +445,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E DeviceCreateInfo.enabledExtensionCount = static_cast(DeviceExtensions.size()); auto vkAllocator = Instance->GetVkAllocator(); - auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, DeviceCreateInfo, vkAllocator); + auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, DeviceCreateInfo, EnabledExtFeats, vkAllocator); auto& RawMemAllocator = GetRawAllocator(); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index b221659a..d0e37670 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -45,18 +45,19 @@ class ResourceTypeToVkDescriptorType public: ResourceTypeToVkDescriptorType() { - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please add the corresponding decriptor type"); - m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::InputAttachment] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please add the corresponding decriptor type"); + m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + m_Map[SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + m_Map[SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_MAX_ENUM; // atomic counter doesn't exist in Vulkan + m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::InputAttachment] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + m_Map[SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure] = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; } VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType) const @@ -68,10 +69,10 @@ private: std::array m_Map = {}; }; -VkDescriptorType PipelineLayout::GetVkDescriptorType(const SPIRVShaderResourceAttribs& Res) +VkDescriptorType PipelineLayout::GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type) { static const ResourceTypeToVkDescriptorType ResTypeToVkDescrType; - return ResTypeToVkDescrType[Res.Type]; + return ResTypeToVkDescrType[Type]; } PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayoutManager(IMemoryAllocator& MemAllocator) : @@ -331,7 +332,7 @@ void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIR Binding = DescrSet.NumLayoutBindings; VkBinding.binding = Binding; - VkBinding.descriptorType = GetVkDescriptorType(ResAttribs); + VkBinding.descriptorType = GetVkDescriptorType(ResAttribs.Type); VkBinding.descriptorCount = ResAttribs.ArraySize; // There are no limitations on what combinations of stages can use a descriptor binding (13.2.1) VkBinding.stageFlags = ShaderTypeToVkShaderStageFlagBit(ShaderType); @@ -369,16 +370,13 @@ void PipelineLayout::AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResA SHADER_TYPE ShaderType, Uint32& DescriptorSet, // Output parameter Uint32& Binding, // Output parameter - Uint32& OffsetInCache, - std::vector& SPIRV) + Uint32& OffsetInCache) { VERIFY((ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) || vkImmutableSampler == VK_NULL_HANDLE, "Immutable sampler should only be specified for combined image samplers or separate samplers"); m_LayoutMgr.AllocateResourceSlot(ResAttribs, VariableType, vkImmutableSampler, ShaderType, DescriptorSet, Binding, OffsetInCache); - SPIRV[ResAttribs.BindingDecorationOffset] = Binding; - SPIRV[ResAttribs.DescriptorSetDecorationOffset] = DescriptorSet; } void PipelineLayout::Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) @@ -435,7 +433,6 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl, } void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, - bool IsCompute, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const @@ -481,7 +478,6 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkIm BindInfo.DynamicOffsetCount = TotalDynamicDescriptors; if (TotalDynamicDescriptors > BindInfo.DynamicOffsets.size()) BindInfo.DynamicOffsets.resize(TotalDynamicDescriptors); - BindInfo.BindPoint = IsCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS; BindInfo.pResourceCache = &ResourceCache; #ifdef DILIGENT_DEBUG BindInfo.pDbgPipelineLayout = this; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 83512870..c7b9e05f 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -44,98 +44,24 @@ namespace Diligent { - -RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc( - Uint32 NumRenderTargets, - const TEXTURE_FORMAT RTVFormats[], - TEXTURE_FORMAT DSVFormat, - Uint8 SampleCount, - std::array& Attachments, - std::array& AttachmentReferences, - SubpassDesc& SubpassDesc) +namespace { - VERIFY_EXPR(NumRenderTargets <= MAX_RENDER_TARGETS); - - RenderPassDesc RPDesc; - - RPDesc.AttachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets; - uint32_t AttachmentInd = 0; - AttachmentReference* pDepthAttachmentReference = nullptr; - if (DSVFormat != TEX_FORMAT_UNKNOWN) - { - auto& DepthAttachment = Attachments[AttachmentInd]; - - DepthAttachment.Format = DSVFormat; - DepthAttachment.SampleCount = SampleCount; - DepthAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area - // will be preserved. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT. - DepthAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render - // area are written to memory. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT. - DepthAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_LOAD; - DepthAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_STORE; - DepthAttachment.InitialState = RESOURCE_STATE_DEPTH_WRITE; - DepthAttachment.FinalState = RESOURCE_STATE_DEPTH_WRITE; - - pDepthAttachmentReference = &AttachmentReferences[AttachmentInd]; - pDepthAttachmentReference->AttachmentIndex = AttachmentInd; - pDepthAttachmentReference->State = RESOURCE_STATE_DEPTH_WRITE; - - ++AttachmentInd; - } - - AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr; - for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd) - { - auto& ColorAttachment = Attachments[AttachmentInd]; - - ColorAttachment.Format = RTVFormats[rt]; - ColorAttachment.SampleCount = SampleCount; - ColorAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area - // will be preserved. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT. - ColorAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render - // area are written to memory. For attachments with a color format, - // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. - ColorAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_DISCARD; - ColorAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_DISCARD; - ColorAttachment.InitialState = RESOURCE_STATE_RENDER_TARGET; - ColorAttachment.FinalState = RESOURCE_STATE_RENDER_TARGET; - - auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd]; - ColorAttachmentRef.AttachmentIndex = AttachmentInd; - ColorAttachmentRef.State = RESOURCE_STATE_RENDER_TARGET; - } - - RPDesc.pAttachments = Attachments.data(); - RPDesc.SubpassCount = 1; - RPDesc.pSubpasses = &SubpassDesc; - RPDesc.DependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies. - RPDesc.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing - // dependencies between pairs of subpasses, or NULL if dependencyCount is zero. - - - SubpassDesc.InputAttachmentCount = 0; - SubpassDesc.pInputAttachments = nullptr; - SubpassDesc.RenderTargetAttachmentCount = NumRenderTargets; - SubpassDesc.pRenderTargetAttachments = pColorAttachmentsReference; - SubpassDesc.pResolveAttachments = nullptr; - SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference; - SubpassDesc.PreserveAttachmentCount = 0; - SubpassDesc.pPreserveAttachments = nullptr; - - return RPDesc; -} - -static bool StripReflection(std::vector& SPIRV) +bool StripReflection(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, std::vector& SPIRV) { #if DILIGENT_NO_HLSL - return false; + return true; #else std::vector StrippedSPIRV; - spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0); + spv_target_env Target = SPV_ENV_VULKAN_1_0; + const auto& ExtFeats = LogicalDevice.GetEnabledExtFeatures(); + + if (ExtFeats.Spirv15) + Target = SPV_ENV_VULKAN_1_2; + else if (ExtFeats.Spirv14) + Target = SPV_ENV_VULKAN_1_1_SPIRV_1_4; + + spvtools::Optimizer SpirvOptimizer(Target); // Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions // removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation. SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass()); @@ -149,21 +75,25 @@ static bool StripReflection(std::vector& SPIRV) #endif } -static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, - ShaderResourceLayoutVk::TShaderStages& ShaderStages, - std::vector& vkShaderModules, - std::vector& vkPipelineShaderStages) +void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, + ShaderResourceLayoutVk::TShaderStages& ShaderStages, + std::vector& ShaderModules, + std::vector& Stages) { for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& StageInfo = ShaderStages[s]; + const auto& Shaders = ShaderStages[s].Shaders; + auto& SPIRVs = ShaderStages[s].SPIRVs; + const auto ShaderType = ShaderStages[s].Type; + + VERIFY_EXPR(Shaders.size() == SPIRVs.size()); VkPipelineShaderStageCreateInfo StageCI = {}; StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; StageCI.pNext = nullptr; StageCI.flags = 0; // reserved for future use - StageCI.stage = ShaderTypeToVkShaderStageFlagBit(StageInfo.Type); + StageCI.stage = ShaderTypeToVkShaderStageFlagBit(ShaderType); VkShaderModuleCreateInfo ShaderModuleCI = {}; @@ -171,33 +101,39 @@ static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& ShaderModuleCI.pNext = nullptr; ShaderModuleCI.flags = 0; - // We have to strip reflection instructions to fix the follownig validation error: - // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string - // Optimizer also performs validation and may catch problems with the byte code. - if (!StripReflection(StageInfo.SPIRV)) - LOG_ERROR("Failed to strip reflection information from shader '", StageInfo.pShader->GetDesc().Name, "'. This may indicate a problem with the byte code."); + for (size_t i = 0; i < Shaders.size(); ++i) + { + auto* pShader = Shaders[i]; + auto& SPIRV = SPIRVs[i]; + + // We have to strip reflection instructions to fix the follownig validation error: + // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string + // Optimizer also performs validation and may catch problems with the byte code. + if (!StripReflection(LogicalDevice, SPIRV)) + LOG_ERROR("Failed to strip reflection information from shader '", pShader->GetDesc().Name, "'. This may indicate a problem with the byte code."); - ShaderModuleCI.codeSize = StageInfo.SPIRV.size() * sizeof(uint32_t); - ShaderModuleCI.pCode = StageInfo.SPIRV.data(); + ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t); + ShaderModuleCI.pCode = SPIRV.data(); - vkShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, StageInfo.pShader->GetDesc().Name)); + ShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, pShader->GetDesc().Name)); - StageCI.module = vkShaderModules.back(); - StageCI.pName = StageInfo.pShader->GetEntryPoint(); - StageCI.pSpecializationInfo = nullptr; + StageCI.module = ShaderModules.back(); + StageCI.pName = pShader->GetEntryPoint(); + StageCI.pSpecializationInfo = nullptr; - vkPipelineShaderStages.push_back(StageCI); + Stages.push_back(StageCI); + } } - VERIFY_EXPR(vkShaderModules.size() == vkPipelineShaderStages.size()); + VERIFY_EXPR(ShaderModules.size() == Stages.size()); } -static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - VulkanUtilities::PipelineWrapper& Pipeline) +void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + VulkanUtilities::PipelineWrapper& Pipeline) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); @@ -218,13 +154,13 @@ static void CreateComputePipeline(RenderDeviceVkImpl* } -static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - const GraphicsPipelineDesc& GraphicsPipeline, - VulkanUtilities::PipelineWrapper& Pipeline, - RefCntAutoPtr& pRenderPass) +void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const GraphicsPipelineDesc& GraphicsPipeline, + VulkanUtilities::PipelineWrapper& Pipeline, + RefCntAutoPtr& pRenderPass) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); @@ -401,6 +337,240 @@ static void CreateGraphicsPipeline(RenderDeviceVkImpl* Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); } + +void CreateRayTracingPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const std::vector& ShaderGroups, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const RayTracingPipelineDesc& RayTracingPipeline, + VulkanUtilities::PipelineWrapper& Pipeline) +{ + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); + const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracing; + + DEV_CHECK_ERR(RayTracingPipeline.MaxRecursionDepth <= RTLimits.maxRecursionDepth, + "RayTracingPipeline.MaxRecursionDepth must not exceed ", RTLimits.maxRecursionDepth); + + VkRayTracingPipelineCreateInfoKHR PipelineCI = {}; + + PipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; + PipelineCI.pNext = nullptr; +#ifdef DILIGENT_DEBUG + PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; +#endif + + PipelineCI.stageCount = static_cast(Stages.size()); + PipelineCI.pStages = Stages.data(); + PipelineCI.layout = Layout.GetVkPipelineLayout(); + + PipelineCI.groupCount = static_cast(ShaderGroups.size()); + PipelineCI.pGroups = ShaderGroups.data(); + PipelineCI.maxRecursionDepth = RayTracingPipeline.MaxRecursionDepth; + PipelineCI.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; + PipelineCI.libraries.pNext = nullptr; + PipelineCI.libraries.libraryCount = 0; + PipelineCI.libraries.pLibraries = nullptr; + PipelineCI.pLibraryInterface = nullptr; + PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from + PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from + + Pipeline = LogicalDevice.CreateRayTracingPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); +} + + +template +void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateInfo, + TNameToGroupIndexMap& NameToGroupIndex, + std::vector& ShaderGroups, + const ShaderResourceLayoutVk::TShaderStages& ShaderStages, + LinearAllocator& MemPool) +{ +#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; + + std::unordered_map UniqueShaders; + + const auto ShaderToIndex = [&ShaderIndex, &UniqueShaders](const IShader* pShader) -> Uint32 { + if (pShader != nullptr) + { + auto Result = UniqueShaders.emplace(pShader, ShaderIndex); + if (Result.second) + { + ++ShaderIndex; + } + return Result.first->second; + } + return VK_SHADER_UNUSED_KHR; + }; + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + VkRayTracingShaderGroupCreateInfoKHR Group = {}; + + Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + Group.generalShader = ShaderToIndex(CreateInfo.pGeneralShaders[i].pShader); + Group.closestHitShader = VK_SHADER_UNUSED_KHR; + Group.anyHitShader = VK_SHADER_UNUSED_KHR; + Group.intersectionShader = VK_SHADER_UNUSED_KHR; + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pGeneralShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique"); + + ShaderGroups.push_back(Group); + } + + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + VkRayTracingShaderGroupCreateInfoKHR Group = {}; + + Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; + Group.generalShader = VK_SHADER_UNUSED_KHR; + Group.closestHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pClosestHitShader); + Group.anyHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pAnyHitShader); + Group.intersectionShader = VK_SHADER_UNUSED_KHR; + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pTriangleHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique"); + + ShaderGroups.push_back(Group); + } + + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + VkRayTracingShaderGroupCreateInfoKHR Group = {}; + + Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; + Group.generalShader = VK_SHADER_UNUSED_KHR; + Group.intersectionShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pIntersectionShader); + Group.closestHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pClosestHitShader); + Group.anyHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pAnyHitShader); + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pProceduralHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique"); + + ShaderGroups.push_back(Group); + } + + VERIFY_EXPR(Uint32(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount) == GroupIndex); + +#ifdef DILIGENT_DEVELOPMENT + Uint32 ShaderIndex2 = 0; + for (auto& Stage : ShaderStages) + { + for (auto* pShader : Stage.Shaders) + { + auto iter = UniqueShaders.find(static_cast(pShader)); + if (iter != UniqueShaders.end()) + VERIFY_EXPR(iter->second == ShaderIndex2); + else + UNEXPECTED("shader is not used in ray tracing shader groups"); + + ++ShaderIndex2; + } + } + VERIFY_EXPR(ShaderIndex == ShaderIndex2); +#endif +#undef LOG_PSO_ERROR_AND_THROW +} + +} // namespace + + +RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc( + Uint32 NumRenderTargets, + const TEXTURE_FORMAT RTVFormats[], + TEXTURE_FORMAT DSVFormat, + Uint8 SampleCount, + std::array& Attachments, + std::array& AttachmentReferences, + SubpassDesc& SubpassDesc) +{ + VERIFY_EXPR(NumRenderTargets <= MAX_RENDER_TARGETS); + + RenderPassDesc RPDesc; + + RPDesc.AttachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets; + + uint32_t AttachmentInd = 0; + AttachmentReference* pDepthAttachmentReference = nullptr; + if (DSVFormat != TEX_FORMAT_UNKNOWN) + { + auto& DepthAttachment = Attachments[AttachmentInd]; + + DepthAttachment.Format = DSVFormat; + DepthAttachment.SampleCount = SampleCount; + DepthAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area + // will be preserved. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT. + DepthAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render + // area are written to memory. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT. + DepthAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_LOAD; + DepthAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_STORE; + DepthAttachment.InitialState = RESOURCE_STATE_DEPTH_WRITE; + DepthAttachment.FinalState = RESOURCE_STATE_DEPTH_WRITE; + + pDepthAttachmentReference = &AttachmentReferences[AttachmentInd]; + pDepthAttachmentReference->AttachmentIndex = AttachmentInd; + pDepthAttachmentReference->State = RESOURCE_STATE_DEPTH_WRITE; + + ++AttachmentInd; + } + + AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr; + for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd) + { + auto& ColorAttachment = Attachments[AttachmentInd]; + + ColorAttachment.Format = RTVFormats[rt]; + ColorAttachment.SampleCount = SampleCount; + ColorAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area + // will be preserved. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT. + ColorAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render + // area are written to memory. For attachments with a color format, + // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. + ColorAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_DISCARD; + ColorAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_DISCARD; + ColorAttachment.InitialState = RESOURCE_STATE_RENDER_TARGET; + ColorAttachment.FinalState = RESOURCE_STATE_RENDER_TARGET; + + auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd]; + ColorAttachmentRef.AttachmentIndex = AttachmentInd; + ColorAttachmentRef.State = RESOURCE_STATE_RENDER_TARGET; + } + + RPDesc.pAttachments = Attachments.data(); + RPDesc.SubpassCount = 1; + RPDesc.pSubpasses = &SubpassDesc; + RPDesc.DependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies. + RPDesc.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing + // dependencies between pairs of subpasses, or NULL if dependencyCount is zero. + + + SubpassDesc.InputAttachmentCount = 0; + SubpassDesc.pInputAttachments = nullptr; + SubpassDesc.RenderTargetAttachmentCount = NumRenderTargets; + SubpassDesc.pRenderTargetAttachments = pColorAttachmentsReference; + SubpassDesc.pResolveAttachments = nullptr; + SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference; + SubpassDesc.PreserveAttachmentCount = 0; + SubpassDesc.pPreserveAttachments = nullptr; + + return RPDesc; +} + void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages) { @@ -416,7 +586,7 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); auto& StaticResLayout = m_ShaderResourceLayouts[GetNumShaderStages() + s]; - StaticResLayout.InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); + StaticResLayout.InitializeStaticResourceLayout(StageInfo.Shaders, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); m_StaticVarsMgrs[s].Initialize(StaticResLayout, GetRawAllocator(), nullptr, 0); } @@ -509,6 +679,7 @@ void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); } + PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo) : @@ -554,6 +725,75 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p } } +PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVk, + const RayTracingPipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + try + { + m_ResourceLayoutIndex.fill(-1); + + TShaderStages ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + const auto ShaderGroupHandleSize = pDeviceVk->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; + TNameToGroupIndexMap NameToGroupIndex; + LinearAllocator MemPool{GetRawAllocator()}; + + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages * 2); + MemPool.AddSpace(NumShaderStages); + + ReserveSpaceForPipelineDesc(CreateInfo, ShaderGroupHandleSize, MemPool); + + MemPool.Reserve(); + + const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); + + m_StaticResCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources); + + // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_StaticResCaches); + (void)Ptr; + + m_ShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, LogicalDevice); + + m_StaticVarsMgrs = MemPool.Allocate(NumShaderStages); + for (Uint32 s = 0; s < NumShaderStages; ++s) + new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; + + std::vector ShaderGroups; + BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool); + InitializePipelineDesc(CreateInfo, ShaderGroupHandleSize, std::move(NameToGroupIndex), MemPool); + + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + + InitResourceLayouts(CreateInfo, ShaderStages); + + // Create shader modules and initialize shader stages + std::vector vkShaderStages; + std::vector ShaderModules; + InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); + + CreateRayTracingPipeline(pDeviceVk, vkShaderStages, ShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline); + + auto err = LogicalDevice.GetRayTracingShaderGroupHandles(m_Pipeline, 0, static_cast(ShaderGroups.size()), ShaderGroupHandleSize, &m_pRayTracingPipelineData->Shaders[0]); + VERIFY(err == VK_SUCCESS, "Failed to get shader group handles"); + (void)err; + } + catch (...) + { + Destruct(); + throw; + } +} PipelineStateVkImpl::~PipelineStateVkImpl() { @@ -562,6 +802,8 @@ PipelineStateVkImpl::~PipelineStateVkImpl() void PipelineStateVkImpl::Destruct() { + TPipelineStateBase::Destruct(); + m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask); m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask); @@ -617,8 +859,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const return false; auto IsSamePipelineLayout = m_PipelineLayout.IsSameAs(pPSOVk->m_PipelineLayout); - -#ifdef DILIGENT_DEBUG +#if 0 //def DILIGENT_DEBUG // AZ TODO { bool IsCompatibleShaders = true; if (GetNumShaderStages() != pPSOVk->GetNumShaderStages()) @@ -736,9 +977,21 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind Layout.CommitDynamicResources(ResourceCache, DynamicDescrSet); } } - // Prepare descriptor sets, and also bind them if there are no dynamic descriptors + VERIFY_EXPR(pDescrSetBindInfo != nullptr); - m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline(), ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); + switch (m_Desc.PipelineType) + { + // clang-format off + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; break; + case PIPELINE_TYPE_COMPUTE: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; break; + case PIPELINE_TYPE_RAY_TRACING: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; break; + default: UNEXPECTED("unknown pipeline type"); + // clang-format on + } + + // Prepare descriptor sets, and also bind them if there are no dynamic descriptors + m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); // Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools // are released at the end of the frame by DeviceContextVkImpl::FinishFrame(). } @@ -783,7 +1036,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY if (LayoutInd < 0) return nullptr; - const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); return StaticVarMgr.GetVariable(Index); } diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index cdcac036..3199a014 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -96,17 +96,18 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* "Main descriptor pool", std::vector { - {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, EngineCI.MainDescriptorPoolSize.NumAccelStructDescriptors} }, EngineCI.MainDescriptorPoolSize.MaxDescriptorSets, true @@ -117,17 +118,18 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* "Dynamic descriptor pool", std::vector { - {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, EngineCI.MainDescriptorPoolSize.NumAccelStructDescriptors} }, EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets, false // Pools can only be reset @@ -160,6 +162,9 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* m_pDxCompiler{CreateDXCompiler(DXCompilerTarget::Vulkan, EngineCI.pDxCompilerPath)} // clang-format on { + static_assert(sizeof(VulkanDescriptorPoolSize) == sizeof(Uint32) * 11, "Please add new descriptors to m_DescriptorSetAllocator and m_DynamicDescriptorPool constructors"); + static_assert(sizeof(DeviceObjectSizes) == sizeof(size_t) * 15, "Please add new objects to DeviceObjectSizes constructor"); + m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_VULKAN; m_DeviceCaps.MajorVersion = 1; m_DeviceCaps.MinorVersion = 0; @@ -573,6 +578,10 @@ void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCr CreatePipelineState(PSOCreateInfo, ppPipelineState); } +void RenderDeviceVkImpl::CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreatePipelineState(PSOCreateInfo, ppPipelineState); +} void RenderDeviceVkImpl::CreateBufferFromVulkanResource(VkBuffer vkBuffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) { diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index caf8ffd2..8a9da14e 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -155,7 +155,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) for (Uint32 res = 0; res < m_TotalResources; ++res) { auto& Res = pResources[res]; - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below"); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); switch (Res.Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: @@ -321,6 +321,36 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } break; + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + { + //auto* pTLASVk = Res.pObject.RawPtr(); + //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; + default: UNEXPECTED("Unexpected resource type"); } } @@ -497,4 +527,20 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetInputAttachmentDescrip return DescrImgInfo; } +VkWriteDescriptorSetAccelerationStructureKHR ShaderResourceCacheVk::Resource::GetAccelerationStructureWriteInfo() const +{ + 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(); + + 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; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index e73ee9aa..16b6bee3 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -93,12 +93,24 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE } } -ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE _Type, - const ShaderVkImpl* _pShader) : - Type{_Type}, - pShader{_pShader}, - SPIRV{pShader->GetSPIRV()} + +ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) : + Type{Stage} +{ + Shaders.push_back(pShader); + SPIRVs.push_back(pShader->GetSPIRV()); +} + +void ShaderResourceLayoutVk::ShaderStageInfo::Append(const ShaderVkImpl* pShader) { + Shaders.push_back(pShader); + SPIRVs.push_back(pShader->GetSPIRV()); +} + +size_t ShaderResourceLayoutVk::ShaderStageInfo::Count() const +{ + VERIFY_EXPR(Shaders.size() == SPIRVs.size()); + return Shaders.size(); } @@ -111,38 +123,53 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk() GetImmutableSampler(s).~ImmutableSamplerPtrType(); } -void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* pShader, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - bool AllocateImmutableSamplers) +void ShaderResourceLayoutVk::AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers) { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); - VERIFY_EXPR(!m_pResources); - m_pResources = pShader->GetShaderResources(); + VERIFY_EXPR(Shaders.size() > 0); + VERIFY_EXPR(m_ShaderType == SHADER_TYPE_UNKNOWN); + + size_t StringPoolSize = 0; + m_ShaderType = Shaders[0]->GetDesc().ShaderType; + m_IsUsingSeparateSamplers = !Shaders[0]->GetShaderResources()->IsUsingCombinedSamplers(); + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - const auto ShaderType = pShader->GetDesc().ShaderType; - VERIFY_EXPR(m_pResources->GetShaderType() == ShaderType); // Count the number of resources to allocate all needed memory + for (size_t s = 0; s < Shaders.size(); ++s) { - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); - m_pResources->ProcessResources( + auto pResources = Shaders[s]->GetShaderResources(); + const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); + VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType); + pResources->ProcessResources( [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { - auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); + auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); if (IsAllowedType(VarType, AllowedTypeBits)) { - // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app + bool IsUniqueName = UniqueNames.emplace(HashMapStringKey{ResAttribs.Name}, ~0u).second; + if (IsUniqueName) + { + StringPoolSize += strlen(ResAttribs.Name) + 1; + + // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app - VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits::max()}, "Number of resources exceeds Uint16 maximum representable value"); - ++m_NumResources[VarType]; + VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits::max()}, "Number of resources exceeds Uint16 maximum representable value"); + ++m_NumResources[VarType]; + } } } // ); + VERIFY_EXPR(m_IsUsingSeparateSamplers == !pResources->IsUsingCombinedSamplers()); } + m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + Uint32 TotalResources = 0; for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) { @@ -157,7 +184,7 @@ void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s) { const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[s]; - if ((ImtblSamDesc.ShaderStages & ShaderType) != 0) + if ((ImtblSamDesc.ShaderStages & m_ShaderType) != 0) ++m_NumImmutableSamplers; } } @@ -194,8 +221,8 @@ static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd) { const auto& Res = Layout.GetResource(ImgVarType, SamplerInd); - if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && - strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0) + if (Res.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + strcmp(Res.Name, SepSampler.Name) == 0) { VERIFY(ImgVarType == Res.GetVariableType(), "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name, @@ -217,62 +244,88 @@ static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, } -void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const ShaderVkImpl* pShader, - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderResourceCacheVk& StaticResourceCache) +void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vector& Shaders, + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderResourceCacheVk& StaticResourceCache) { const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; // We do not need immutable samplers in static shader resource layout as they // are relevant only when the main layout is initialized - constexpr bool AllocateImmutableSamplers = false; - AllocateMemory(pShader, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers); + ResourceNameToIndex_t ResourceNameToIndex; + constexpr bool AllocateImmutableSamplers = false; + AllocateMemory(Shaders, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, ResourceNameToIndex, AllocateImmutableSamplers); std::array CurrResInd = {}; - Uint32 StaticResCacheSize = 0; + Uint32 StaticResCacheSize = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); - const auto ShaderType = pShader->GetDesc().ShaderType; + for (auto* pShader : Shaders) + { + auto pResources = pShader->GetShaderResources(); + const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); + pResources->ProcessResources( + [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // + { + auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); + if (!IsAllowedType(VarType, AllowedTypeBits)) + return; - m_pResources->ProcessResources( - [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // - { - auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); - if (!IsAllowedType(VarType, AllowedTypeBits)) - return; + auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name}); + VERIFY_EXPR(ResIter != ResourceNameToIndex.end()); - Int32 SrcImmutableSamplerInd = -1; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) - { - // Only search for the immutable sampler for combined image samplers and separate samplers - SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); - // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app - } + if (ResIter->second == ~0u) + { + Int32 SrcImmutableSamplerInd = -1; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Only search for the immutable sampler for combined image samplers and separate samplers + SrcImmutableSamplerInd = FindImmutableSampler(m_ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); + // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app + } - Uint32 Binding = Attribs.Type; - Uint32 DescriptorSet = 0; - Uint32 CacheOffset = StaticResCacheSize; - StaticResCacheSize += Attribs.ArraySize; + Uint32 Binding = Attribs.Type; + Uint32 DescriptorSet = 0; + Uint32 CacheOffset = StaticResCacheSize; + StaticResCacheSize += Attribs.ArraySize; - Uint32 SamplerInd = VkResource::InvalidSamplerInd; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) - { - // Separate samplers are enumerated before separate images, so the sampler - // assigned to this separate image must have already been created. - SamplerInd = FindAssignedSampler(*this, *m_pResources, Attribs, CurrResInd[VarType], VarType); - } - ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); - } // - ); + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + { + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must have already been created. + SamplerInd = FindAssignedSampler(*this, *pResources, Attribs, CurrResInd[VarType], VarType); + } + + // add new resource + ResIter->second = CurrResInd[VarType]; + ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, + Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, + Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); + } + else + { + // merge with existing + auto& ExistingRes = GetResource(VarType, ResIter->second); + VERIFY_EXPR(ExistingRes.VariableType == VarType); + VERIFY_EXPR(ExistingRes.Type == Attribs.Type); + VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim); + VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS); + VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize); + } + } // + ); + } #ifdef DILIGENT_DEBUG for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) { VERIFY(CurrResInd[VarType] == m_NumResources[VarType], "Not all resources have been initialized, which will cause a crash when dtor is called"); } + + VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); #endif StaticResourceCache.InitializeSets(GetRawAllocator(), 1, &StaticResCacheSize); @@ -296,14 +349,15 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& const auto ShaderType = Stages & static_cast(~(static_cast(Stages) - 1)); const char* ShaderName = nullptr; - for (const auto& StageInfo : ShaderStages) + // AZ TODO + /*for (const auto& StageInfo : ShaderStages) { if ((Stages & StageInfo.Type) != 0) { ShaderName = StageInfo.pShader->GetDesc().Name; break; } - } + }*/ if (!ShadersStr.empty()) ShadersStr.append(", "); @@ -340,13 +394,17 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& bool VariableFound = false; for (size_t s = 0; s < ShaderStages.size() && !VariableFound; ++s) { - const auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) + auto& Shaders = ShaderStages[s].Shaders; + for (size_t i = 0; i < Shaders.size() && !VariableFound; ++i) { - for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) + const auto& Resources = *Shaders[i]->GetShaderResources(); + if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) { - const auto& ResAttribs = Resources.GetResource(res); - VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); + for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) + { + const auto& ResAttribs = Resources.GetResource(res); + VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); + } } } } @@ -373,28 +431,32 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& bool SamplerFound = false; for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s) { - const auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0) - continue; - - // Irrespective of whether HLSL-style combined image samplers are used, - // an immutable sampler can be assigned to a GLSL sampled image (i.e. sampler2D g_tex) - for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) + auto& Shaders = ShaderStages[s].Shaders; + for (size_t j = 0; j < Shaders.size() && !SamplerFound; ++j) { - const auto& SmplImg = Resources.GetSmpldImg(i); - SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0); - } + const auto& Resources = *Shaders[j]->GetShaderResources(); + if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0) + continue; - if (!SamplerFound) - { - // Check if an immutable sampler is assigned to a separate sampler. - // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler". - // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "". - const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); - for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i) + // Irrespective of whether HLSL-style combined image samplers are used, + // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex) + for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) + { + const auto& SmplImg = Resources.GetSmpldImg(i); + SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0); + } + + if (!SamplerFound) { - const auto& SepSmpl = Resources.GetSepSmplr(i); - SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix); + // Check if static sampler is assigned to a separate sampler. + // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler". + // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "". + const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); + for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i) + { + const auto& SepSmpl = Resources.GetSepSmplr(i); + SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix); + } } } } @@ -423,15 +485,16 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyImmutableSamplers); #endif - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; - const Uint32 NumAllowedTypes = 0; - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - constexpr bool AllocateImmutableSamplers = true; + std::array ResourceNameToIndexArray; + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; + const Uint32 NumAllowedTypes = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + constexpr bool AllocateImmutableSamplers = true; for (size_t s = 0; s < ShaderStages.size(); ++s) { - Layouts[s].AllocateMemory(ShaderStages[s].pShader, LayoutDataAllocator, ResourceLayoutDesc, - AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers); + Layouts[s].AllocateMemory(ShaderStages[s].Shaders, LayoutDataAllocator, ResourceLayoutDesc, + AllowedVarTypes, NumAllowedTypes, ResourceNameToIndexArray[s], AllocateImmutableSamplers); } //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE); @@ -444,74 +507,107 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende auto AddResource = [&](Uint32 ShaderInd, ShaderResourceLayoutVk& ResLayout, const SPIRVShaderResources& Resources, - const SPIRVShaderResourceAttribs& Attribs) // + const SPIRVShaderResourceAttribs& Attribs, + ResourceNameToIndex_t& ResourceNameToIndex, + std::vector& SPIRV) // { const auto ShaderType = Resources.GetShaderType(); const SHADER_RESOURCE_VARIABLE_TYPE VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, Resources.GetCombinedSamplerSuffix()); if (!IsAllowedType(VarType, AllowedTypeBits)) return; - Uint32 Binding = 0; - Uint32 DescriptorSet = 0; - Uint32 CacheOffset = 0; - Uint32 SamplerInd = VkResource::InvalidSamplerInd; + auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name}); + VERIFY_EXPR(ResIter != ResourceNameToIndex.end()); - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + if (ResIter->second == ~0u) { - // Separate samplers are enumerated before separate images, so the sampler - // assigned to this separate image must have already been created. - SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType); - } + // add new resource + Uint32 Binding = 0; + Uint32 DescriptorSet = 0; + Uint32 CacheOffset = 0; + Uint32 SamplerInd = VkResource::InvalidSamplerInd; - VkSampler vkImmutableSampler = VK_NULL_HANDLE; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) - { - // Only search for the immutable sampler for combined image samplers and separate samplers - Int32 SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, Resources.GetCombinedSamplerSuffix()); - if (SrcImmutableSamplerInd >= 0) + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) { - auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++); - VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!"); - const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc; - pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler); - vkImmutableSampler = ImmutableSampler.RawPtr()->GetVkSampler(); + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must have already been created. + SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType); } - } - auto& ShaderSPIRV = ShaderStages[ShaderInd].SPIRV; - PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV); - VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); - VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds maximum representable value"); + VkSampler vkImmutableSampler = VK_NULL_HANDLE; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Only search for the immutable sampler for combined image samplers and separate samplers + Int32 SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, Resources.GetCombinedSamplerSuffix()); + if (SrcImmutableSamplerInd >= 0) + { + auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++); + VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!"); + const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc; + pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler); + vkImmutableSampler = ImmutableSampler.RawPtr()->GetVkSampler(); + } + } + + PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset); + VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); + VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds maximum representable value"); + + SPIRV[Attribs.BindingDecorationOffset] = Binding; + SPIRV[Attribs.DescriptorSetDecorationOffset] = DescriptorSet; #ifdef DILIGENT_DEBUG - // Verify that bindings and cache offsets monotonically increase in every descriptor set - auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet); - if (Binding_OffsetIt != dbgBindings_CacheOffsets.end()) - { - VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic"); - VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic"); - } - dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset); + // Verify that bindings and cache offsets monotonically increase in every descriptor set + auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet); + if (Binding_OffsetIt != dbgBindings_CacheOffsets.end()) + { + VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic"); + VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic"); + } + dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset); #endif - auto& ResInd = CurrResInd[ShaderInd][VarType]; - ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0); + auto& ResInd = CurrResInd[ShaderInd][VarType]; + ResIter->second = ResInd; + ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, ResLayout.m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, + Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, + Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0); + } + else + { + // merge with existing + auto& ExistingRes = ResLayout.GetResource(VarType, ResIter->second); + + VERIFY_EXPR(ExistingRes.VariableType == VarType); + VERIFY_EXPR(ExistingRes.Type == Attribs.Type); + VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim); + VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS); + VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize); + + SPIRV[Attribs.BindingDecorationOffset] = ExistingRes.Binding; + SPIRV[Attribs.DescriptorSetDecorationOffset] = ExistingRes.DescriptorSet; + } }; // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set for (size_t s = 0; s < ShaderStages.size(); ++s) { + auto& Shaders = ShaderStages[s].Shaders; auto& Layout = Layouts[s]; - auto* pShaderVk = ShaderStages[s].pShader; - auto& Resources = *pShaderVk->GetShaderResources(); - for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n) + auto& NameToIdx = ResourceNameToIndexArray[s]; + for (size_t i = 0; i < Shaders.size(); ++i) { - const auto& UB = Resources.GetUB(n); - auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc); - if (IsAllowedType(VarType, AllowedTypeBits)) + auto& SPIRV = ShaderStages[s].SPIRVs[i]; + auto& Resources = *Shaders[i]->GetShaderResources(); + for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n) { - AddResource(static_cast(s), Layout, Resources, UB); + const auto& UB = Resources.GetUB(n); + auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + AddResource(static_cast(s), Layout, Resources, UB, NameToIdx, SPIRV); + } } } } @@ -519,15 +615,21 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende // Second, process all storage buffers for (size_t s = 0; s < ShaderStages.size(); ++s) { + auto& Shaders = ShaderStages[s].Shaders; auto& Layout = Layouts[s]; - auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n) + auto& NameToIdx = ResourceNameToIndexArray[s]; + for (size_t i = 0; i < Shaders.size(); ++i) { - const auto& SB = Resources.GetSB(n); - auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc); - if (IsAllowedType(VarType, AllowedTypeBits)) + auto& Resources = *Shaders[i]->GetShaderResources(); + auto& SPIRV = ShaderStages[s].SPIRVs[i]; + for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n) { - AddResource(static_cast(s), Layout, Resources, SB); + const auto& SB = Resources.GetSB(n); + auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + AddResource(static_cast(s), Layout, Resources, SB, NameToIdx, SPIRV); + } } } } @@ -536,51 +638,62 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende for (size_t s = 0; s < ShaderStages.size(); ++s) { auto& Layout = Layouts[s]; - auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - // clang-format off - Resources.ProcessResources( - [&](const SPIRVShaderResourceAttribs& UB, Uint32) - { - VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); - // Skip - }, - [&](const SPIRVShaderResourceAttribs& SB, Uint32) - { - VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || SB.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer); - // Skip - }, - [&](const SPIRVShaderResourceAttribs& Img, Uint32) - { - VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); - AddResource(static_cast(s), Layout, Resources, Img); - }, - [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) - { - VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); - AddResource(static_cast(s), Layout, Resources, SmplImg); - }, - [&](const SPIRVShaderResourceAttribs& AC, Uint32) - { - VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); - AddResource(static_cast(s), Layout, Resources, AC); - }, - [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) - { - VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); - AddResource(static_cast(s), Layout, Resources, SepSmpl); - }, - [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) - { - VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); - AddResource(static_cast(s), Layout, Resources, SepImg); - }, - [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32) - { - VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment); - AddResource(static_cast(s), Layout, Resources, InputAtt); - } - ); - // clang-format on + auto& Shaders = ShaderStages[s].Shaders; + auto& NameToIdx = ResourceNameToIndexArray[s]; + for (size_t i = 0; i < Shaders.size(); ++i) + { + auto& Resources = *Shaders[i]->GetShaderResources(); + auto& SPIRV = ShaderStages[s].SPIRVs[i]; + // clang-format off + Resources.ProcessResources( + [&](const SPIRVShaderResourceAttribs& UB, Uint32) + { + VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); + // Skip + }, + [&](const SPIRVShaderResourceAttribs& SB, Uint32) + { + VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || SB.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer); + // Skip + }, + [&](const SPIRVShaderResourceAttribs& Img, Uint32) + { + VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); + AddResource(static_cast(s), Layout, Resources, Img, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) + { + VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); + AddResource(static_cast(s), Layout, Resources, SmplImg, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& AC, Uint32) + { + VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); + AddResource(static_cast(s), Layout, Resources, AC, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) + { + VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); + AddResource(static_cast(s), Layout, Resources, SepSmpl, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) + { + VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); + AddResource(static_cast(s), Layout, Resources, SepImg, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32) + { + VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment); + AddResource(static_cast(s), Layout, Resources, InputAtt, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& AccelStruct, Uint32) + { + VERIFY_EXPR(AccelStruct.Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure); + AddResource(static_cast(s), Layout, Resources, AccelStruct, NameToIdx, SPIRV); + } + ); + // clang-format on + } } #ifdef DILIGENT_DEBUG @@ -593,28 +706,32 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende } // Some immutable samplers may never be initialized if they are not present in shaders VERIFY_EXPR(CurrImmutableSamplerInd[s] <= Layout.m_NumImmutableSamplers); + + VERIFY_EXPR(Layout.m_StringPool.GetRemainingSize() == 0); } #endif } -void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, - uint32_t ArrayElement, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView) const + +void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, + uint32_t ArrayElement, + const VkDescriptorImageInfo* pImageInfo, + const VkDescriptorBufferInfo* pBufferInfo, + const VkBufferView* pTexelBufferView, + const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo) const { VERIFY_EXPR(vkDescrSet != VK_NULL_HANDLE); VkWriteDescriptorSet WriteDescrSet; WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescrSet.pNext = nullptr; + WriteDescrSet.pNext = pAccelStructInfo; WriteDescrSet.dstSet = vkDescrSet; WriteDescrSet.dstBinding = Binding; WriteDescrSet.dstArrayElement = ArrayElement; WriteDescrSet.descriptorCount = 1; // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding. // The type of the descriptor also controls which array the descriptors are taken from. (13.2.4) - WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(SpirvAttribs); + WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(Type); WriteDescrSet.pImageInfo = pImageInfo; WriteDescrSet.pBufferInfo = pBufferInfo; WriteDescrSet.pTexelBufferView = pTexelBufferView; @@ -654,10 +771,10 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* Uint32 ArrayInd, Uint16& DynamicBuffersCounter) const { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected"); + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected"); RefCntAutoPtr pBufferVk{pBuffer, IID_BufferVk}; #ifdef DILIGENT_DEVELOPMENT - VerifyConstantBufferBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + VerifyConstantBufferBinding(*this, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); #endif auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) { @@ -691,8 +808,8 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* Uint16& DynamicBuffersCounter) const { // clang-format off - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || + Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer, "Storage buffer resource is expected"); // clang-format on @@ -700,8 +817,8 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* #ifdef DILIGENT_DEVELOPMENT { // HLSL buffer SRVs are mapped to storge buffers in GLSL - auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS; - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS; + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); if (pBufferViewVk != nullptr) { const auto& ViewDesc = pBufferViewVk->GetDesc(); @@ -709,7 +826,7 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW) { LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); + Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); } } } @@ -747,8 +864,8 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* Uint16& DynamicBuffersCounter) const { // clang-format off - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer || + Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer, "Uniform or storage buffer resource is expected"); // clang-format on @@ -756,8 +873,8 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* #ifdef DILIGENT_DEVELOPMENT { // HLSL buffer SRVs are mapped to storge buffers in GLSL - auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE; - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE; + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); if (pBufferViewVk != nullptr) { const auto& ViewDesc = pBufferViewVk->GetDesc(); @@ -765,7 +882,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW)) { LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected."); + Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected."); } } } @@ -805,9 +922,9 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* TCacheSampler CacheSampler) const { // clang-format off - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || + Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || + Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage, "Storage image, separate image or sampled image resource is expected"); // clang-format on @@ -815,8 +932,8 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* #ifdef DILIGENT_DEVELOPMENT { // HLSL buffer SRVs are mapped to storge buffers in GLSL - auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE; - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE; + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); } #endif if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {})) @@ -824,11 +941,11 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* // We can do RawPtr here safely since UpdateCachedResource() returned true auto* pTexViewVk = DstRes.pObject.RawPtr(); #ifdef DILIGENT_DEVELOPMENT - if (SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSamplerAssigned()) + if (Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSamplerAssigned()) { if (pTexViewVk->GetSampler() == nullptr) { - LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '", SpirvAttribs.GetPrintName(ArrayInd), + LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. No sampler is assigned to the view"); } } @@ -844,11 +961,11 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* if (SamplerInd != InvalidSamplerInd) { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, "Only separate images can be assigned separate samplers when using HLSL-style combined samplers."); VERIFY(!IsImmutableSamplerAssigned(), "Separate image can't be assigned an immutable sampler."); const auto& SamplerAttribs = ParentResLayout.GetResource(GetVariableType(), SamplerInd); - VERIFY_EXPR(SamplerAttribs.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); + VERIFY_EXPR(SamplerAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); if (!SamplerAttribs.IsImmutableSamplerAssigned()) { auto* pSampler = pTexViewVk->GetSampler(); @@ -858,8 +975,8 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* } else { - LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name, - "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '", + LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerAttribs.Name, + "' assigned to separate image '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\''); } } @@ -872,20 +989,20 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject* VkDescriptorSet vkDescrSet, Uint32 ArrayInd) const { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected"); + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected"); VERIFY(!IsImmutableSamplerAssigned(), "This separate sampler is assigned an immutable sampler"); RefCntAutoPtr pSamplerVk{pSampler, IID_Sampler}; #ifdef DILIGENT_DEVELOPMENT if (pSampler != nullptr && pSamplerVk == nullptr) { - LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", SpirvAttribs.GetPrintName(ArrayInd), + LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. Unexpected object type: sampler is expected"); } if (GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr && DstRes.pObject != pSamplerVk) { auto VarTypeStr = GetShaderVariableTypeLiteralName(GetVariableType()); - LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", SpirvAttribs.GetPrintName(ArrayInd), + LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. Attempting to bind another sampler or null is an error and may " "cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."); @@ -908,10 +1025,10 @@ void ShaderResourceLayoutVk::VkResource::CacheInputAttachment(IDeviceObject* VkDescriptorSet vkDescrSet, Uint32 ArrayInd) const { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Input attachment resource is expected"); + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Input attachment resource is expected"); RefCntAutoPtr pTexViewVk0{pTexView, IID_TextureViewVk}; #ifdef DILIGENT_DEVELOPMENT - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); #endif if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {})) { @@ -926,9 +1043,32 @@ void ShaderResourceLayoutVk::VkResource::CacheInputAttachment(IDeviceObject* } } +void ShaderResourceLayoutVk::VkResource::CacheAccelerationStructure(IDeviceObject* pTLAS, + ShaderResourceCacheVk::Resource& DstRes, + VkDescriptorSet vkDescrSet, + Uint32 ArrayInd) const +{ + // VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected"); + // RefCntAutoPtr 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 { - VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize); + VERIFY_EXPR(ArrayIndex < ArraySize); auto& DstDescrSet = ResourceCache.GetDescriptorSet(DescriptorSet); auto vkDescrSet = DstDescrSet.GetVkDescriptorSet(); @@ -951,12 +1091,12 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 } #endif auto& DstRes = DstDescrSet.GetResource(CacheOffset + ArrayIndex); - VERIFY(DstRes.Type == SpirvAttribs.Type, "Inconsistent types"); + VERIFY(DstRes.Type == Type, "Inconsistent types"); if (pObj) { - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below"); - switch (SpirvAttribs.Type) + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + switch (Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: CacheUniformBuffer(pObj, DstRes, vkDescrSet, ArrayIndex, ResourceCache.GetDynamicBuffersCounter()); @@ -977,15 +1117,15 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 case SPIRVShaderResourceAttribs::ResourceType::SampledImage: CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex, [&](const VkResource& SeparateSampler, ISampler* pSampler) { - VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.SpirvAttribs.Name, "' is assigned an immutable sampler"); - VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); - DEV_CHECK_ERR(SeparateSampler.SpirvAttribs.ArraySize == 1 || SeparateSampler.SpirvAttribs.ArraySize == SpirvAttribs.ArraySize, - "Array size (", SeparateSampler.SpirvAttribs.ArraySize, + VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.Name, "' is assigned an immutable sampler"); + VERIFY_EXPR(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); + DEV_CHECK_ERR(SeparateSampler.ArraySize == 1 || SeparateSampler.ArraySize == ArraySize, + "Array size (", SeparateSampler.ArraySize, ") of separate sampler variable '", - SeparateSampler.SpirvAttribs.Name, - "' must be one or the same as the array size (", SpirvAttribs.ArraySize, - ") of separate image variable '", SpirvAttribs.Name, "' it is assigned to"); - Uint32 SamplerArrInd = SeparateSampler.SpirvAttribs.ArraySize == 1 ? 0 : ArrayIndex; + SeparateSampler.Name, + "' must be one or the same as the array size (", ArraySize, + ") of separate image variable '", Name, "' it is assigned to"); + Uint32 SamplerArrInd = SeparateSampler.ArraySize == 1 ? 0 : ArrayIndex; SeparateSampler.BindResource(pSampler, SamplerArrInd, ResourceCache); }); break; @@ -999,7 +1139,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 { // Immutable samplers are permanently bound into the set layout; later binding a sampler // into an immutable sampler slot in a descriptor set is not allowed (13.2.1) - LOG_ERROR_MESSAGE("Attempting to assign a sampler to an immutable sampler '", SpirvAttribs.Name, '\''); + LOG_ERROR_MESSAGE("Attempting to assign a sampler to an immutable sampler '", Name, '\''); } break; @@ -1007,14 +1147,18 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 CacheInputAttachment(pObj, DstRes, vkDescrSet, ArrayIndex); break; - default: UNEXPECTED("Unknown resource type ", static_cast(SpirvAttribs.Type)); + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + CacheAccelerationStructure(pObj, DstRes, vkDescrSet, ArrayIndex); + break; + + default: UNEXPECTED("Unknown resource type ", static_cast(Type)); } } else { if (DstRes.pObject && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { - LOG_ERROR_MESSAGE("Shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), + LOG_ERROR_MESSAGE("Shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. " "Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource."); } @@ -1025,7 +1169,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const { - VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize); + VERIFY_EXPR(ArrayIndex < ArraySize); if (DescriptorSet < ResourceCache.GetNumDescriptorSets()) { @@ -1040,6 +1184,72 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const Shader return false; } +ShaderResourceDesc ShaderResourceLayoutVk::VkResource::GetResourceDesc() const +{ + ShaderResourceDesc ResourceDesc; + ResourceDesc.Name = Name; + ResourceDesc.ArraySize = ArraySize; + + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + switch (Type) + { + case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; + break; + + case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer: + // Read-only storage buffers map to buffer SRV + // https://github.com/KhronosGroup/SPIRV-Cross/wiki/Reflection-API-user-guide#read-write-vs-read-only-resources-for-hlsl + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::StorageImage: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::SampledImage: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter: + LOG_WARNING_MESSAGE("There is no appropriate shader resource type for atomic counter resource '", Name, "'"); + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::SeparateImage: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_SAMPLER; + break; + + case SPIRVShaderResourceAttribs::ResourceType::InputAttachment: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT; + break; + + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_ACCEL_STRUCT; + break; + + default: + UNEXPECTED("Unknown SPIRV resource type"); + } + return ResourceDesc; +} + void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout, const ShaderResourceCacheVk& SrcResourceCache, @@ -1055,21 +1265,21 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou // Get resource attributes const auto& DstRes = GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r); const auto& SrcRes = SrcLayout.GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r); - VERIFY(SrcRes.Binding == SrcRes.SpirvAttribs.Type, "Unexpected binding"); - VERIFY(SrcRes.SpirvAttribs.ArraySize == DstRes.SpirvAttribs.ArraySize, "Inconsistent array size"); + VERIFY(SrcRes.Binding == SrcRes.Type, "Unexpected binding"); + VERIFY(SrcRes.ArraySize == DstRes.ArraySize, "Inconsistent array size"); - if (DstRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + if (DstRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && DstRes.IsImmutableSamplerAssigned()) continue; // Skip immutable samplers - for (Uint32 ArrInd = 0; ArrInd < DstRes.SpirvAttribs.ArraySize; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < DstRes.ArraySize; ++ArrInd) { auto SrcOffset = SrcRes.CacheOffset + ArrInd; const auto& SrcCachedSet = SrcResourceCache.GetDescriptorSet(SrcRes.DescriptorSet); const auto& SrcCachedRes = SrcCachedSet.GetResource(SrcOffset); IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr(); if (!pObject) - LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); auto DstOffset = DstRes.CacheOffset + ArrInd; IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject; @@ -1093,15 +1303,15 @@ bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso { const auto& Res = GetResource(VarType, r); VERIFY(Res.GetVariableType() == VarType, "Unexpected variable type"); - for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd) { const auto& CachedDescrSet = ResourceCache.GetDescriptorSet(Res.DescriptorSet); const auto& CachedRes = CachedDescrSet.GetResource(Res.CacheOffset + ArrInd); - VERIFY(CachedRes.Type == Res.SpirvAttribs.Type, "Inconsistent types"); + VERIFY(CachedRes.Type == Res.Type, "Inconsistent types"); if (CachedRes.pObject == nullptr && - !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned())) + !(Res.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned())) { - LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); + LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); BindingsOK = false; } # ifdef DILIGENT_DEBUG @@ -1136,7 +1346,7 @@ void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCache for (Uint32 r = 0; r < TotalResources; ++r) { const auto& Res = GetResource(r); - ResourceCache.InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.SpirvAttribs.ArraySize, Res.SpirvAttribs.Type); + ResourceCache.InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.ArraySize, Res.Type); } } @@ -1151,24 +1361,28 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& static constexpr size_t ImgUpdateBatchSize = 4; static constexpr size_t BuffUpdateBatchSize = 2; static constexpr size_t TexelBuffUpdateBatchSize = 2; + static constexpr size_t AccelStructBatchSize = 2; static constexpr size_t WriteDescriptorSetBatchSize = 2; #else static constexpr size_t ImgUpdateBatchSize = 128; static constexpr size_t BuffUpdateBatchSize = 64; static constexpr size_t TexelBuffUpdateBatchSize = 32; + static constexpr size_t AccelStructBatchSize = 32; static constexpr size_t WriteDescriptorSetBatchSize = 32; #endif // Do not zero-initiaize arrays! - std::array DescrImgInfoArr; - std::array DescrBuffInfoArr; - std::array DescrBuffViewArr; - std::array WriteDescrSetArr; + std::array DescrImgInfoArr; + std::array DescrBuffInfoArr; + std::array DescrBuffViewArr; + std::array DescrAccelStructArr; + std::array WriteDescrSetArr; Uint32 ResNum = 0, ArrElem = 0; auto DescrImgIt = DescrImgInfoArr.begin(); auto DescrBuffIt = DescrBuffInfoArr.begin(); auto BuffViewIt = DescrBuffViewArr.begin(); + auto AccelStructIt = DescrAccelStructArr.begin(); auto WriteDescrSetIt = WriteDescrSetArr.begin(); #ifdef DILIGENT_DEBUG @@ -1195,14 +1409,15 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& WriteDescrSetIt->dstArrayElement = ArrElem; // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding. // The type of the descriptor also controls which array the descriptors are taken from. (13.2.4) - WriteDescrSetIt->descriptorType = PipelineLayout::GetVkDescriptorType(Res.SpirvAttribs); + WriteDescrSetIt->descriptorType = PipelineLayout::GetVkDescriptorType(Res.Type); // For every resource type, try to batch as many descriptor updates as we can - switch (Res.SpirvAttribs.Type) + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + switch (Res.Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrBuffIt = CachedRes.GetUniformBufferDescriptorWriteInfo(); @@ -1214,7 +1429,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer: case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer: WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrBuffIt = CachedRes.GetStorageBufferDescriptorWriteInfo(); @@ -1226,7 +1441,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: WriteDescrSetIt->pTexelBufferView = &(*BuffViewIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && BuffViewIt != DescrBuffViewArr.end()) + while (ArrElem < Res.ArraySize && BuffViewIt != DescrBuffViewArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *BuffViewIt = CachedRes.GetBufferViewWriteInfo(); @@ -1239,7 +1454,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::StorageImage: case SPIRVShaderResourceAttribs::ResourceType::SampledImage: WriteDescrSetIt->pImageInfo = &(*DescrImgIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Res.IsImmutableSamplerAssigned()); @@ -1259,7 +1474,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& if (!Res.IsImmutableSamplerAssigned()) { WriteDescrSetIt->pImageInfo = &(*DescrImgIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrImgIt = CachedRes.GetSamplerDescriptorWriteInfo(); @@ -1269,8 +1484,19 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& } else { - ArrElem = Res.SpirvAttribs.ArraySize; - WriteDescrSetIt->dstArrayElement = Res.SpirvAttribs.ArraySize; + ArrElem = Res.ArraySize; + WriteDescrSetIt->dstArrayElement = Res.ArraySize; + } + break; + + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + WriteDescrSetIt->pNext = &(*AccelStructIt); + while (ArrElem < Res.ArraySize && AccelStructIt != DescrAccelStructArr.end()) + { + const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); + *AccelStructIt = CachedRes.GetAccelerationStructureWriteInfo(); + ++AccelStructIt; + ++ArrElem; } break; @@ -1279,7 +1505,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& } WriteDescrSetIt->descriptorCount = ArrElem - WriteDescrSetIt->dstArrayElement; - if (ArrElem == Res.SpirvAttribs.ArraySize) + if (ArrElem == Res.ArraySize) { ArrElem = 0; ++ResNum; @@ -1294,6 +1520,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& DescrImgIt == DescrImgInfoArr.end() || DescrBuffIt == DescrBuffInfoArr.end() || BuffViewIt == DescrBuffViewArr.end() || + AccelStructIt == DescrAccelStructArr.end() || WriteDescrSetIt == WriteDescrSetArr.end()) { auto DescrWriteCount = static_cast(std::distance(WriteDescrSetArr.begin(), WriteDescrSetIt)); @@ -1303,6 +1530,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& DescrImgIt = DescrImgInfoArr.begin(); DescrBuffIt = DescrBuffInfoArr.begin(); BuffViewIt = DescrBuffViewArr.begin(); + AccelStructIt = DescrAccelStructArr.begin(); WriteDescrSetIt = WriteDescrSetArr.begin(); } } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp index 7e06bd69..062a5725 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp @@ -52,7 +52,7 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayout // When using HLSL-style combined image samplers, we need to skip separate samplers. // Also always skip immutable separate samplers. - if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + if (SrcRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned())) continue; @@ -96,7 +96,7 @@ void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& Sr { const auto& SrcRes = SrcLayout.GetResource(VarType, r); // Skip separate samplers when using combined HLSL-style image samplers. Also always skip immutable separate samplers. - if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + if (SrcRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned())) continue; @@ -132,7 +132,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) con { auto& Var = m_pVariables[v]; const auto& Res = Var.m_Resource; - if (strcmp(Res.SpirvAttribs.Name, Name) == 0) + if (strcmp(Res.Name, Name) == 0) { pVar = &Var; break; @@ -190,18 +190,18 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, const auto& Res = Var.m_Resource; // There should be no immutable separate samplers - VERIFY(Res.SpirvAttribs.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(), + VERIFY(Res.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(), "There must be no shader resource variables for immutable separate samplers"); if ((Flags & (1 << Res.GetVariableType())) == 0) continue; - for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd) { if ((Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, m_ResourceCache)) continue; - const auto* VarName = Res.SpirvAttribs.Name; + const auto* VarName = Res.Name; RefCntAutoPtr pObj; pResourceMapping->GetResource(VarName, &pObj, ArrInd); if (pObj) @@ -212,7 +212,7 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, { if ((Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, m_ResourceCache)) { - LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.SpirvAttribs.GetPrintName(ArrInd), + LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.GetPrintName(ArrInd), "': resource is not found in the resource mapping. " "Do not use BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED flag to suppress the message if this is not an issue."); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp index 65505ad3..66393e9b 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp @@ -122,9 +122,17 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, SourceLength = GLSLSourceString.length(); } + GLSLangUtils::SpirvVersion spvVersion = GLSLangUtils::SpirvVersion::Vk100; + const auto& ExtFeats = GetDevice()->GetLogicalDevice().GetEnabledExtFeatures(); + if (ExtFeats.Spirv15) + spvVersion = GLSLangUtils::SpirvVersion::Vk120; + else if (ExtFeats.Spirv14) + spvVersion = GLSLangUtils::SpirvVersion::Vk110_Spirv14; + m_SPIRV = GLSLangUtils::GLSLtoSPIRV(m_Desc.ShaderType, ShaderSource, static_cast(SourceLength), Macros, ShaderCI.pShaderSourceStreamFactory, + spvVersion, ShaderCI.ppCompilerOutput); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index a03102d0..825bf872 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -73,16 +73,18 @@ bool VulkanInstance::IsExtensionEnabled(const char* ExtensionName) const return false; } -std::shared_ptr VulkanInstance::Create(bool EnableValidation, +std::shared_ptr VulkanInstance::Create(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator) { - auto Instance = new VulkanInstance{EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator}; + auto Instance = new VulkanInstance{ApiVersion, EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator}; return std::shared_ptr{Instance}; } -VulkanInstance::VulkanInstance(bool EnableValidation, +VulkanInstance::VulkanInstance(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator) : @@ -184,6 +186,16 @@ VulkanInstance::VulkanInstance(bool EnableValidation, } } +#if DILIGENT_USE_VOLK + if (vkEnumerateInstanceVersion != nullptr && ApiVersion > VK_API_VERSION_1_0) + { + uint32_t MaxApiVersion = 0; + vkEnumerateInstanceVersion(&MaxApiVersion); + ApiVersion = std::min(ApiVersion, MaxApiVersion); + LOG_INFO_MESSAGE("Used Vulkan API version ", VK_VERSION_MAJOR(ApiVersion), ".", VK_VERSION_MINOR(ApiVersion)); + } +#endif + VkApplicationInfo appInfo = {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; @@ -192,7 +204,7 @@ VulkanInstance::VulkanInstance(bool EnableValidation, appInfo.applicationVersion = 0; // Developer-supplied version number of the application appInfo.pEngineName = "Diligent Engine"; appInfo.engineVersion = 0; // Developer-supplied version number of the engine used to create the application. - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = ApiVersion; VkInstanceCreateInfo InstanceCreateInfo = {}; @@ -229,6 +241,7 @@ VulkanInstance::VulkanInstance(bool EnableValidation, #endif m_EnabledExtensions = std::move(GlobalExtensions); + m_VkVersion = ApiVersion; // If requested, we enable the default validation layers for debugging if (m_DebugUtilsEnabled) diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index f9e190d8..358bdec5 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -36,9 +36,10 @@ namespace VulkanUtilities std::shared_ptr VulkanLogicalDevice::Create(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator) { - auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, vkAllocator}; + auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, EnabledExtFeatures, vkAllocator}; return std::shared_ptr{LogicalDevice}; } @@ -49,9 +50,11 @@ VulkanLogicalDevice::~VulkanLogicalDevice() VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator) : m_VkAllocator{vkAllocator}, - m_EnabledFeatures{*DeviceCI.pEnabledFeatures} + m_EnabledFeatures{*DeviceCI.pEnabledFeatures}, + m_EnabledExtFeatures{EnabledExtFeatures} { auto res = vkCreateDevice(PhysicalDevice.GetVkDeviceHandle(), &DeviceCI, vkAllocator, &m_VkDevice); CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device"); @@ -225,6 +228,29 @@ PipelineWrapper VulkanLogicalDevice::CreateGraphicsPipeline(const VkGraphicsPipe return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)}; } +PipelineWrapper VulkanLogicalDevice::CreateRayTracingPipeline(const VkRayTracingPipelineCreateInfoKHR& PipelineCI, VkPipelineCache cache, const char* DebugName) const +{ +#if DILIGENT_USE_VOLK + VERIFY_EXPR(PipelineCI.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR); + + if (DebugName == nullptr) + DebugName = ""; + + VkPipeline vkPipeline = VK_NULL_HANDLE; + + auto err = vkCreateRayTracingPipelinesKHR(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline); + CHECK_VK_ERROR_AND_THROW(err, "Failed to create ray tracing pipeline '", DebugName, '\''); + + if (*DebugName != 0) + SetPipelineName(m_VkDevice, vkPipeline, DebugName); + + return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)}; +#else + UNSUPPORTED("vkCreateRayTracingPipelinesKHR is only available through Volk"); + return PipelineWrapper{}; +#endif +} + ShaderModuleWrapper VulkanLogicalDevice::CreateShaderModule(const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName) const { VERIFY_EXPR(ShaderModuleCI.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO); @@ -455,6 +481,7 @@ VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkI VkMemoryRequirements VulkanLogicalDevice::GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const { VkMemoryRequirements2 MemReqs = {}; + MemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; #if DILIGENT_USE_VOLK vkGetAccelerationStructureMemoryRequirementsKHR(m_VkDevice, &Info, &MemReqs); #else @@ -571,4 +598,14 @@ VkResult VulkanLogicalDevice::ResetDescriptorPool(VkDescriptorPool vkD return err; } +VkResult VulkanLogicalDevice::GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const +{ +#if DILIGENT_USE_VOLK + return vkGetRayTracingShaderGroupHandlesKHR(m_VkDevice, pipeline, firstGroup, groupCount, dataSize, pData); +#else + UNSUPPORTED("vkGetRayTracingShaderGroupHandlesKHR is only available through Volk"); + return VK_ERROR_FEATURE_NOT_PRESENT; +#endif +} + } // namespace VulkanUtilities diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index 3e5f28d4..b66ac8af 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -166,6 +166,17 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.DescriptorIndexing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; } + // Additional extension that is required for ray tracing shader. + if (IsExtensionSupported(VK_KHR_SPIRV_1_4_EXTENSION_NAME)) + m_ExtFeatures.Spirv14 = true; + + // Some features requires SPIRV 1.4 or 1.5 that added to Vulkan 1.2 core. + if (Instance.GetVkVersion() >= VK_API_VERSION_1_2) + { + m_ExtFeatures.Spirv14 = true; + m_ExtFeatures.Spirv15 = true; + } + // make sure that last pNext is null *NextFeat = nullptr; *NextProp = nullptr; @@ -178,7 +189,6 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, // Emulate KHR extension if (m_ExtFeatures.RayTracingNV) { - //m_ExtFeatures.RayTracing.sType //m_ExtFeatures.RayTracing.rayTracingPrimitiveCulling = true; // AZ TODO m_ExtFeatures.RayTracing.rayTracing = VK_TRUE; @@ -188,7 +198,7 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment; m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount; m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount; - m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount; + m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount / 3; m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures; m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0; } -- cgit v1.2.3 From f8be662d357be9dcbb4b298d93b43d29ae93ce04 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 19:08:28 -0700 Subject: A number of updates/fixes to PSO refactor merge --- .../include/PipelineLayout.hpp | 1 + .../include/PipelineStateVkImpl.hpp | 6 +- .../include/RenderDeviceVkImpl.hpp | 5 + .../include/ShaderResourceBindingVkImpl.hpp | 1 + .../include/ShaderResourceLayoutVk.hpp | 104 ++++---- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 28 ++- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 2 + .../src/PipelineStateVkImpl.cpp | 164 ++++++------- .../src/RenderDeviceVkImpl.cpp | 2 +- .../src/ShaderResourceLayoutVk.cpp | 268 ++++++++++----------- .../src/VulkanUtilities/VulkanInstance.cpp | 2 +- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 2 +- 12 files changed, 286 insertions(+), 299 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp index 8a0fab15..f9f51920 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp @@ -136,6 +136,7 @@ public: // set by the same Vulkan command. If there are no dynamic descriptors, this // function also binds descriptor sets rightaway. void PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, + VkPipelineBindPoint BindPoint, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const; diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index a02c8d74..6aa4e073 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -129,10 +129,11 @@ public: private: using TShaderStages = ShaderResourceLayoutVk::TShaderStages; - template + template void InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& vkShaderStages, - std::vector& ShaderModules); + std::vector& ShaderModules, + InitPSODescType InitPSODesc); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages); @@ -170,6 +171,7 @@ private: // Resource layout index in m_ShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; + static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 9ceed3e4..6abe5213 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -197,6 +197,11 @@ public: IDXCompiler* GetDxCompiler() const { return m_pDxCompiler.get(); } + Uint32 GetShaderGroupHandleSize() const + { + return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; + } + private: template void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState); diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp index 68401f52..0b427640 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp @@ -84,6 +84,7 @@ private: // Resource layout index in m_ShaderResourceCache array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; + static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); bool m_bStaticResourcesInitialized = false; Uint8 m_NumShaders = 0; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index e5cddb0c..a0e40615 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -44,20 +44,9 @@ // d == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] // // +// Every ShaderVariableVkImpl variable managed by ShaderVariableManagerVk keeps a reference to corresponding VkResource. // -// * Every VkResource structure holds a reference to SPIRVShaderResourceAttribs structure from SPIRVShaderResources. -// * ShaderResourceLayoutVk keeps a shared pointer to SPIRVShaderResources instance. -// * Every ShaderVariableVkImpl variable managed by ShaderVariableManagerVk keeps a reference to corresponding VkResource. -// -// -// ______________________ ________________________________________________________________________ -// | | unique_ptr | | | | | | | | -// | SPIRVShaderResources |--------------->| UBs | SBs | StrgImgs | SmplImgs | ACs | SepSamplers | SepImgs | -// |______________________| |________|_________|__________|__________|_______|_____________|_________| -// A A A -// | | | -// |shared_ptr Ref Ref -// ________|__________________ ________\____________________|_____________________________________________ +// ___________________________ ___________________________________________________________________________ // | | unique_ptr | | | | | // | ShaderResourceLayoutVk |--------------->| VkResource[0] | VkResource[1] | ... | VkResource[s+m+d-1] | // |___________________________| |___________________|_________________|_______________|_____________________| @@ -99,13 +88,14 @@ #include #include +#include #include "PipelineState.h" #include "ShaderBase.hpp" #include "HashUtils.hpp" #include "ShaderResourceCacheVk.hpp" -#include "SPIRVShaderResources.hpp" #include "VulkanUtilities/VulkanLogicalDevice.hpp" +#include "StringPool.hpp" namespace Diligent { @@ -113,7 +103,7 @@ namespace Diligent class ShaderVkImpl; /// Diligent::ShaderResourceLayoutVk class -// sizeof(ShaderResourceLayoutVk)==72 (MS compiler, x64) +// sizeof(ShaderResourceLayoutVk)==40 (MS compiler, x64) class ShaderResourceLayoutVk { public: @@ -134,6 +124,9 @@ public: ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) noexcept : m_LogicalDevice{LogicalDevice} { +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(*this) == 40, "Unexpected sizeof(ShaderResourceLayoutVk)."); +#endif } // clang-format off @@ -181,20 +174,27 @@ public: static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1; + static constexpr const Uint32 ResourceDimBits = 7; + static constexpr const Uint32 IsMSFlagBits = 8 - ResourceDimBits; + static_assert(RESOURCE_DIM_NUM_DIMENSIONS <= (1 << ResourceDimBits), "Not enough bits to represent RESOURCE_DIMENSION"); + using ResourceType = SPIRVShaderResourceAttribs::ResourceType; /* 0 */ const Uint16 Binding; -/* 2 */ const Uint16 ArraySize; +/* 2 */ const Uint16 DescriptorSet; + /* 4.0 */ const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set /* 6.5 */ const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler // assigned to separate image /* 7.5 */ const Uint32 VariableType : VariableTypeBits; /* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits; -/* 8 */ const Uint8 DescriptorSet; -/* 9 */ const ResourceType Type; -/* 10.0*/ const Uint8 ResourceDim : 7; -/* 10.7*/ const Uint8 IsMS : 1; +/* 8 */ const Uint16 ArraySize; + +/* 10 */ const ResourceType Type; +/* 11.0*/ const Uint8 ResourceDim : ResourceDimBits; +/* 11.7*/ const Uint8 IsMS : IsMSFlagBits; + /* 16 */ const char* const Name; /* 24 */ const ShaderResourceLayoutVk& ParentResLayout; // clang-format on @@ -203,8 +203,8 @@ public: const char* _Name, Uint16 _ArraySize, ResourceType _Type, - Uint8 _ResourceDim, - Uint8 _IsMS, + RESOURCE_DIMENSION _ResourceDim, + bool _IsMS, SHADER_RESOURCE_VARIABLE_TYPE _VariableType, uint32_t _Binding, uint32_t _DescriptorSet, @@ -218,20 +218,28 @@ public: SamplerInd {_SamplerInd }, VariableType {_VariableType }, ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, - Name {_Name }, - ArraySize {_ArraySize }, - Type {_Type }, - ResourceDim {_ResourceDim }, - IsMS {_IsMS }, - ParentResLayout {_ParentLayout } + ArraySize {_ArraySize }, + Type {_Type }, + ResourceDim {_ResourceDim }, + IsMS {_IsMS ? 1U : 0U}, + Name {_Name }, + ParentResLayout {_ParentLayout } // clang-format on { - VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits)); - VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits)); - VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max()); +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(*this) == 32, "Unexpected sizeof(VkResource)"); +#endif + // clang-format off + VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) ); + VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) ); + VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max() ); VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); + VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type (", Uint32{_VariableType}, ") exceeds max representable value ", (1 << VariableTypeBits) ); + VERIFY(_ResourceDim < (1 << ResourceDimBits), "Resource dimension (", Uint32{_ResourceDim}, ") exceeds max representable value ", (1 << ResourceDimBits) ); + // clang-format on } + // Checks if a resource is bound in ResourceCache at the given ArrayIndex bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const; @@ -273,7 +281,10 @@ public: return Name; } - ShaderResourceDesc GetResourceDesc() const; + ShaderResourceDesc GetResourceDesc() const + { + return ShaderResourceDesc{Name, SPIRVShaderResourceAttribs::GetShaderResourceType(Type), ArraySize}; + } RESOURCE_DIMENSION GetResourceDimension() const { @@ -403,14 +414,16 @@ private: return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } + static constexpr Uint32 InvalidResourceIndex = ~0u; + using ResourceNameToIndex_t = std::unordered_map; - void AllocateMemory(const std::vector& Shaders, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ResourceNameToIndex_t& UniqueNames, - bool AllocateImmutableSamplers); + StringPool AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers); using ImmutableSamplerPtrType = RefCntAutoPtr; ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept @@ -422,16 +435,15 @@ private: // clang-format off /* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; -/* 8 */ std::unique_ptr > m_ResourceBuffer; // AZ TODO: use linear allocator -/*24 */ StringPool m_StringPool; +/* 8 */ std::unique_ptr > m_ResourceBuffer; -/*48 */ std::array m_NumResources = {}; +/*24 */ std::array m_NumResources = {}; -/*56 */ Uint32 m_NumImmutableSamplers = 0; -/*60 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; -/*64 */ bool m_IsUsingSeparateSamplers = false; +/*32 */ Uint16 m_NumImmutableSamplers = 0; +/*34 */ bool m_IsUsingSeparateSamplers = false; +/*36 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; -/*72 */ // End of class +/*40 */ // End of class // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index fcb64973..189b1073 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -252,22 +252,26 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E GetFeatureState(EngineCI.Features.Feature, IsFeatureSupported, FeatureName); \ } while (false) - ENABLE_FEATURE(DeviceExtFeatures.MeshShader.taskShader != VK_FALSE && DeviceExtFeatures.MeshShader.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); + const auto& MeshShaderFeats = DeviceExtFeatures.MeshShader; + ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); + const auto& ShaderFloat16Int8Feats = DeviceExtFeatures.ShaderFloat16Int8; // clang-format off - ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); - ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); + ENABLE_FEATURE(ShaderFloat16Int8Feats.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); + ENABLE_FEATURE(ShaderFloat16Int8Feats.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); // clang-format on + const auto& Storage16BitFeats = DeviceExtFeatures.Storage16Bit; // clang-format off - ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); - ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); - ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); + ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); + ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); + ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); // clang-format on + const auto& Storage8BitFeats = DeviceExtFeatures.Storage8Bit; // clang-format off - ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); - ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); + ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); + ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); // clang-format on ENABLE_FEATURE((DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE && DeviceExtFeatures.Spirv14) || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); @@ -286,7 +290,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // Mesh shader if (EngineCI.Features.MeshShaders != DEVICE_FEATURE_STATE_DISABLED) { - EnabledExtFeats.MeshShader = DeviceExtFeatures.MeshShader; + EnabledExtFeats.MeshShader = MeshShaderFeats; VERIFY_EXPR(EnabledExtFeats.MeshShader.taskShader != VK_FALSE && EnabledExtFeats.MeshShader.meshShader != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME), "VK_NV_mesh_shader extension must be supported as it has already been checked by VulkanPhysicalDevice and " @@ -299,7 +303,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E if (EngineCI.Features.ShaderFloat16 != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.ShaderInt8 != DEVICE_FEATURE_STATE_DISABLED) { - EnabledExtFeats.ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8; + EnabledExtFeats.ShaderFloat16Int8 = ShaderFloat16Int8Feats; VERIFY_EXPR(EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 != VK_FALSE || EnabledExtFeats.ShaderFloat16Int8.shaderInt8 != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME), "VK_KHR_shader_float16_int8 extension must be supported as it has already been checked by VulkanPhysicalDevice " @@ -324,7 +328,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - EnabledExtFeats.Storage16Bit = DeviceExtFeatures.Storage16Bit; + EnabledExtFeats.Storage16Bit = Storage16BitFeats; VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess != VK_FALSE); VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE); VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageInputOutput16 != VK_FALSE); @@ -360,7 +364,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - EnabledExtFeats.Storage8Bit = DeviceExtFeatures.Storage8Bit; + EnabledExtFeats.Storage8Bit = Storage8BitFeats; VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess != VK_FALSE); VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE); // clang-format on diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index d0e37670..c24ed496 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -433,6 +433,7 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl, } void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, + VkPipelineBindPoint BindPoint, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const @@ -478,6 +479,7 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkIm BindInfo.DynamicOffsetCount = TotalDynamicDescriptors; if (TotalDynamicDescriptors > BindInfo.DynamicOffsets.size()) BindInfo.DynamicOffsets.resize(TotalDynamicDescriptors); + BindInfo.BindPoint = BindPoint; BindInfo.pResourceCache = &ResourceCache; #ifdef DILIGENT_DEBUG BindInfo.pDbgPipelineLayout = this; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index c7b9e05f..11be4dba 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -129,11 +129,11 @@ void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& } -void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - VulkanUtilities::PipelineWrapper& Pipeline) +static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + VulkanUtilities::PipelineWrapper& Pipeline) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); @@ -154,13 +154,13 @@ void CreateComputePipeline(RenderDeviceVkImpl* pDevice } -void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - const GraphicsPipelineDesc& GraphicsPipeline, - VulkanUtilities::PipelineWrapper& Pipeline, - RefCntAutoPtr& pRenderPass) +static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const GraphicsPipelineDesc& GraphicsPipeline, + VulkanUtilities::PipelineWrapper& Pipeline, + RefCntAutoPtr& pRenderPass) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); @@ -338,13 +338,13 @@ void CreateGraphicsPipeline(RenderDeviceVkImpl* pDevic } -void CreateRayTracingPipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const std::vector& ShaderGroups, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - const RayTracingPipelineDesc& RayTracingPipeline, - VulkanUtilities::PipelineWrapper& Pipeline) +static void CreateRayTracingPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const std::vector& ShaderGroups, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const RayTracingPipelineDesc& RayTracingPipeline, + VulkanUtilities::PipelineWrapper& Pipeline) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); @@ -410,16 +410,18 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) { + const auto& GeneralShader = CreateInfo.pGeneralShaders[i]; + VkRayTracingShaderGroupCreateInfoKHR Group = {}; Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - Group.generalShader = ShaderToIndex(CreateInfo.pGeneralShaders[i].pShader); + Group.generalShader = ShaderToIndex(GeneralShader.pShader); Group.closestHitShader = VK_SHADER_UNUSED_KHR; Group.anyHitShader = VK_SHADER_UNUSED_KHR; Group.intersectionShader = VK_SHADER_UNUSED_KHR; - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pGeneralShaders[i].Name)}, GroupIndex++).second; + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(GeneralShader.Name)}, GroupIndex++).second; if (!IsUniqueName) LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique"); @@ -428,16 +430,18 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) { + const auto& TriHitShader = CreateInfo.pTriangleHitShaders[i]; + VkRayTracingShaderGroupCreateInfoKHR Group = {}; Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; Group.generalShader = VK_SHADER_UNUSED_KHR; - Group.closestHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pClosestHitShader); - Group.anyHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pAnyHitShader); + Group.closestHitShader = ShaderToIndex(TriHitShader.pClosestHitShader); + Group.anyHitShader = ShaderToIndex(TriHitShader.pAnyHitShader); Group.intersectionShader = VK_SHADER_UNUSED_KHR; - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pTriangleHitShaders[i].Name)}, GroupIndex++).second; + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(TriHitShader.Name)}, GroupIndex++).second; if (!IsUniqueName) LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique"); @@ -446,23 +450,25 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) { + const auto& ProcHitShader = CreateInfo.pProceduralHitShaders[i]; + VkRayTracingShaderGroupCreateInfoKHR Group = {}; Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; Group.generalShader = VK_SHADER_UNUSED_KHR; - Group.intersectionShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pIntersectionShader); - Group.closestHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pClosestHitShader); - Group.anyHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pAnyHitShader); + Group.intersectionShader = ShaderToIndex(ProcHitShader.pIntersectionShader); + Group.closestHitShader = ShaderToIndex(ProcHitShader.pClosestHitShader); + Group.anyHitShader = ShaderToIndex(ProcHitShader.pAnyHitShader); - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pProceduralHitShaders[i].Name)}, GroupIndex++).second; + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(ProcHitShader.Name)}, GroupIndex++).second; if (!IsUniqueName) LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique"); ShaderGroups.push_back(Group); } - VERIFY_EXPR(Uint32(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount) == GroupIndex); + VERIFY_EXPR(Uint32{CreateInfo.GeneralShaderCount} + Uint32{CreateInfo.TriangleHitShaderCount} + Uint32{CreateInfo.ProceduralHitShaderCount} == GroupIndex); #ifdef DILIGENT_DEVELOPMENT Uint32 ShaderIndex2 = 0; @@ -474,7 +480,7 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& if (iter != UniqueShaders.end()) VERIFY_EXPR(iter->second == ShaderIndex2); else - UNEXPECTED("shader is not used in ray tracing shader groups"); + UNEXPECTED("Shader '", pShader->GetDesc().Name, "' is not used in ray tracing shader groups"); ++ShaderIndex2; } @@ -630,10 +636,11 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre m_ShaderResourceLayoutHash = m_PipelineLayout.GetHash(); } -template +template void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& vkShaderStages, - std::vector& ShaderModules) + std::vector& ShaderModules, + InitPSODescType InitPSODesc) { m_ResourceLayoutIndex.fill(-1); @@ -668,7 +675,7 @@ void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& for (Uint32 s = 0; s < NumShaderStages; ++s) new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; - InitializePipelineDesc(CreateInfo, MemPool); + InitPSODesc(CreateInfo, MemPool, ShaderStages); // It is important to construct all objects before initializing them because if an exception is thrown, // destructors will be called for all objects @@ -691,7 +698,12 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* std::vector vkShaderStages; std::vector ShaderModules; - InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, + [this](const GraphicsPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // + { + InitializePipelineDesc(CreateInfo, MemPool); + } // + ); CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); } @@ -714,7 +726,12 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p std::vector vkShaderStages; std::vector ShaderModules; - InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, + [this](const ComputePipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // + { + InitializePipelineDesc(CreateInfo, MemPool); + } // + ); CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); } @@ -733,57 +750,24 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* { try { - m_ResourceLayoutIndex.fill(-1); - - TShaderStages ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); - - const auto ShaderGroupHandleSize = pDeviceVk->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; - TNameToGroupIndexMap NameToGroupIndex; - LinearAllocator MemPool{GetRawAllocator()}; - - const auto NumShaderStages = GetNumShaderStages(); - VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); - - MemPool.AddSpace(NumShaderStages); - MemPool.AddSpace(NumShaderStages * 2); - MemPool.AddSpace(NumShaderStages); - - ReserveSpaceForPipelineDesc(CreateInfo, ShaderGroupHandleSize, MemPool); - - MemPool.Reserve(); - - const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); - - m_StaticResCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources); - - // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). - auto* Ptr = MemPool.ReleaseOwnership(); - VERIFY_EXPR(Ptr == m_StaticResCaches); - (void)Ptr; - - m_ShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, LogicalDevice); - - m_StaticVarsMgrs = MemPool.Allocate(NumShaderStages); - for (Uint32 s = 0; s < NumShaderStages; ++s) - new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; - - std::vector ShaderGroups; - BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool); - InitializePipelineDesc(CreateInfo, ShaderGroupHandleSize, std::move(NameToGroupIndex), MemPool); - - // It is important to construct all objects before initializing them because if an exception is thrown, - // destructors will be called for all objects - - InitResourceLayouts(CreateInfo, ShaderStages); - - // Create shader modules and initialize shader stages std::vector vkShaderStages; std::vector ShaderModules; - InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); + + std::vector ShaderGroups; + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, + [&](const RayTracingPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages& ShaderStages) // + { + TNameToGroupIndexMap NameToGroupIndex; + BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool); + InitializePipelineDesc(CreateInfo, std::move(NameToGroupIndex), MemPool); + } // + ); CreateRayTracingPipeline(pDeviceVk, vkShaderStages, ShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline); + const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); + const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize(); + auto err = LogicalDevice.GetRayTracingShaderGroupHandles(m_Pipeline, 0, static_cast(ShaderGroups.size()), ShaderGroupHandleSize, &m_pRayTracingPipelineData->Shaders[0]); VERIFY(err == VK_SUCCESS, "Failed to get shader group handles"); (void)err; @@ -978,20 +962,22 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind } } - VERIFY_EXPR(pDescrSetBindInfo != nullptr); + + VkPipelineBindPoint BindPoint = VK_PIPELINE_BIND_POINT_MAX_ENUM; switch (m_Desc.PipelineType) { // clang-format off case PIPELINE_TYPE_GRAPHICS: - case PIPELINE_TYPE_MESH: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; break; - case PIPELINE_TYPE_COMPUTE: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; break; - case PIPELINE_TYPE_RAY_TRACING: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; break; - default: UNEXPECTED("unknown pipeline type"); - // clang-format on + case PIPELINE_TYPE_MESH: BindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; break; + case PIPELINE_TYPE_COMPUTE: BindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; break; + case PIPELINE_TYPE_RAY_TRACING: BindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; break; + // clang-format on + default: UNEXPECTED("Unknown pipeline type"); } + VERIFY_EXPR(pDescrSetBindInfo != nullptr); // Prepare descriptor sets, and also bind them if there are no dynamic descriptors - m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); + m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, BindPoint, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); // Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools // are released at the end of the frame by DeviceContextVkImpl::FinishFrame(). } @@ -1036,7 +1022,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY if (LayoutInd < 0) return nullptr; - auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); return StaticVarMgr.GetVariable(Index); } diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 3199a014..4d2c01e3 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -81,7 +81,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* sizeof(FramebufferVkImpl), sizeof(BottomLevelASVkImpl), sizeof(TopLevelASVkImpl), - sizeof(ShaderBindingTableVkImpl) + sizeof(ShaderBindingTableVkImpl), } }, m_VulkanInstance {Instance }, diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 16b6bee3..499c35ef 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -95,10 +95,10 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) : - Type{Stage} + Type{Stage}, + Shaders{{pShader}}, + SPIRVs{{pShader->GetSPIRV()}} { - Shaders.push_back(pShader); - SPIRVs.push_back(pShader->GetSPIRV()); } void ShaderResourceLayoutVk::ShaderStageInfo::Append(const ShaderVkImpl* pShader) @@ -123,13 +123,13 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk() GetImmutableSampler(s).~ImmutableSamplerPtrType(); } -void ShaderResourceLayoutVk::AllocateMemory(const std::vector& Shaders, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ResourceNameToIndex_t& UniqueNames, - bool AllocateImmutableSamplers) +StringPool ShaderResourceLayoutVk::AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers) { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); VERIFY_EXPR(Shaders.size() > 0); @@ -143,16 +143,18 @@ void ShaderResourceLayoutVk::AllocateMemory(const std::vectorGetShaderResources(); - const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); - VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType); - pResources->ProcessResources( + const auto& Resources = *Shaders[s]->GetShaderResources(); + const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); + VERIFY(Resources.GetShaderType() == m_ShaderType, "Unexpected shader type"); + VERIFY(m_IsUsingSeparateSamplers == !Resources.IsUsingCombinedSamplers(), "All shaders in the stage must either use or not use combined image samplers"); + + Resources.ProcessResources( [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); if (IsAllowedType(VarType, AllowedTypeBits)) { - bool IsUniqueName = UniqueNames.emplace(HashMapStringKey{ResAttribs.Name}, ~0u).second; + bool IsUniqueName = UniqueNames.emplace(HashMapStringKey{ResAttribs.Name}, InvalidResourceIndex).second; if (IsUniqueName) { StringPoolSize += strlen(ResAttribs.Name) + 1; @@ -165,11 +167,8 @@ void ShaderResourceLayoutVk::AllocateMemory(const std::vectorIsUsingCombinedSamplers()); } - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - Uint32 TotalResources = 0; for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) { @@ -189,19 +188,26 @@ void ShaderResourceLayoutVk::AllocateMemory(const std::vector>(pRawMem, Allocator); - for (Uint32 s = 0; s < m_NumImmutableSamplers; ++s) - { - // We need to initialize immutable samplers - auto& UninitializedImmutableSampler = GetImmutableSampler(s); - new (std::addressof(UninitializedImmutableSampler)) ImmutableSamplerPtrType; - } + MemPool.AddSpace(TotalResources); + MemPool.AddSpace(m_NumImmutableSamplers); + MemPool.AddSpace(StringPoolSize); + + MemPool.Reserve(); + + auto* pResources = MemPool.Allocate(TotalResources); + auto* pImtblSamplers = MemPool.ConstructArray(m_NumImmutableSamplers); + auto* pStringData = MemPool.ConstructArray(StringPoolSize); + + m_ResourceBuffer = std::unique_ptr>(MemPool.Release(), Allocator); + + VERIFY_EXPR(m_ResourceBuffer.get() == pResources); + VERIFY_EXPR(m_NumImmutableSamplers == 0 || pImtblSamplers == std::addressof(GetImmutableSampler(0))); + + StringPool stringPool; + stringPool.AssignMemory(pStringData, StringPoolSize); + return stringPool; } @@ -254,18 +260,19 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vector CurrResInd = {}; Uint32 StaticResCacheSize = 0; const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - for (auto* pShader : Shaders) + for (const auto* pShader : Shaders) { - auto pResources = pShader->GetShaderResources(); - const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); - pResources->ProcessResources( + const auto& Resources = *pShader->GetShaderResources(); + const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); + Resources.ProcessResources( [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // { auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); @@ -275,7 +282,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vectorsecond == ~0u) + if (ResIter->second == InvalidResourceIndex) { Int32 SrcImmutableSamplerInd = -1; if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || @@ -296,14 +303,26 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vectorsecond = CurrResInd[VarType]; - ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, - Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, - Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); + ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource // + { + *this, + stringPool.CopyString(Attribs.Name), + Attribs.ArraySize, + Attribs.Type, + Attribs.GetResourceDimension(), + Attribs.IsMultisample(), + VarType, + Binding, + DescriptorSet, + CacheOffset, + SamplerInd, + SrcImmutableSamplerInd >= 0 // + }; } else { @@ -325,7 +344,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vectorGetShaderResources(); - if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) + const auto& Resources = *Stage.Shaders[i]->GetShaderResources(); + VERIFY_EXPR(Resources.GetShaderType() == Stage.Type); + + for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) { - for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) - { - const auto& ResAttribs = Resources.GetResource(res); - VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); - } + const auto& ResAttribs = Resources.GetResource(res); + VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); } } } @@ -431,15 +452,17 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& bool SamplerFound = false; for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s) { - auto& Shaders = ShaderStages[s].Shaders; - for (size_t j = 0; j < Shaders.size() && !SamplerFound; ++j) + const auto& Stage = ShaderStages[s]; + if ((Stage.Type & ImtblSamDesc.ShaderStages) == 0) + continue; + + for (size_t j = 0; j < Stage.Shaders.size() && !SamplerFound; ++j) { - const auto& Resources = *Shaders[j]->GetShaderResources(); - if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0) - continue; + const auto& Resources = *Stage.Shaders[j]->GetShaderResources(); + VERIFY_EXPR(Resources.GetShaderType() == Stage.Type); // Irrespective of whether HLSL-style combined image samplers are used, - // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex) + // an immutable sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex) for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) { const auto& SmplImg = Resources.GetSmpldImg(i); @@ -448,7 +471,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& if (!SamplerFound) { - // Check if static sampler is assigned to a separate sampler. + // Check if immutable is assigned to a separate sampler. // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler". // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "". const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); @@ -486,15 +509,21 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende #endif std::array ResourceNameToIndexArray; - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; - const Uint32 NumAllowedTypes = 0; - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - constexpr bool AllocateImmutableSamplers = true; + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; + const Uint32 NumAllowedTypes = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + + constexpr bool AllocateImmutableSamplers = true; + + std::vector stringPools; + stringPools.reserve(ShaderStages.size()); for (size_t s = 0; s < ShaderStages.size(); ++s) { - Layouts[s].AllocateMemory(ShaderStages[s].Shaders, LayoutDataAllocator, ResourceLayoutDesc, - AllowedVarTypes, NumAllowedTypes, ResourceNameToIndexArray[s], AllocateImmutableSamplers); + stringPools.emplace_back( + Layouts[s].AllocateMemory(ShaderStages[s].Shaders, LayoutDataAllocator, ResourceLayoutDesc, + AllowedVarTypes, NumAllowedTypes, ResourceNameToIndexArray[s], + AllocateImmutableSamplers)); } //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE); @@ -504,7 +533,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende std::unordered_map> dbgBindings_CacheOffsets; #endif - auto AddResource = [&](Uint32 ShaderInd, + auto AddResource = [&](const Uint32 ShaderInd, ShaderResourceLayoutVk& ResLayout, const SPIRVShaderResources& Resources, const SPIRVShaderResourceAttribs& Attribs, @@ -519,7 +548,8 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name}); VERIFY_EXPR(ResIter != ResourceNameToIndex.end()); - if (ResIter->second == ~0u) + const VkResource* pResource = nullptr; + if (ResIter->second == InvalidResourceIndex) { // add new resource Uint32 Binding = 0; @@ -554,9 +584,6 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds maximum representable value"); - SPIRV[Attribs.BindingDecorationOffset] = Binding; - SPIRV[Attribs.DescriptorSetDecorationOffset] = DescriptorSet; - #ifdef DILIGENT_DEBUG // Verify that bindings and cache offsets monotonically increase in every descriptor set auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet); @@ -570,24 +597,37 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende auto& ResInd = CurrResInd[ShaderInd][VarType]; ResIter->second = ResInd; - ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, ResLayout.m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, - Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, - Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0); + + pResource = ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource // + { + ResLayout, + stringPools[ShaderInd].CopyString(Attribs.Name), + Attribs.ArraySize, + Attribs.Type, + Attribs.GetResourceDimension(), + Attribs.IsMultisample(), + VarType, + Binding, + DescriptorSet, + CacheOffset, + SamplerInd, + vkImmutableSampler != VK_NULL_HANDLE // + }; } else { // merge with existing - auto& ExistingRes = ResLayout.GetResource(VarType, ResIter->second); + pResource = &ResLayout.GetResource(VarType, ResIter->second); - VERIFY_EXPR(ExistingRes.VariableType == VarType); - VERIFY_EXPR(ExistingRes.Type == Attribs.Type); - VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim); - VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS); - VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize); - - SPIRV[Attribs.BindingDecorationOffset] = ExistingRes.Binding; - SPIRV[Attribs.DescriptorSetDecorationOffset] = ExistingRes.DescriptorSet; + VERIFY_EXPR(pResource->VariableType == VarType); + VERIFY_EXPR(pResource->Type == Attribs.Type); + VERIFY_EXPR(pResource->ResourceDim == Attribs.ResourceDim); + VERIFY_EXPR(pResource->IsMS == Attribs.IsMS); + VERIFY_EXPR(pResource->ArraySize == Attribs.ArraySize); } + VERIFY_EXPR(pResource != nullptr); + SPIRV[Attribs.BindingDecorationOffset] = pResource->Binding; + SPIRV[Attribs.DescriptorSetDecorationOffset] = pResource->DescriptorSet; }; // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set @@ -707,7 +747,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende // Some immutable samplers may never be initialized if they are not present in shaders VERIFY_EXPR(CurrImmutableSamplerInd[s] <= Layout.m_NumImmutableSamplers); - VERIFY_EXPR(Layout.m_StringPool.GetRemainingSize() == 0); + VERIFY_EXPR(stringPools[s].GetRemainingSize() == 0); } #endif } @@ -1184,72 +1224,6 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const Shader return false; } -ShaderResourceDesc ShaderResourceLayoutVk::VkResource::GetResourceDesc() const -{ - ShaderResourceDesc ResourceDesc; - ResourceDesc.Name = Name; - ResourceDesc.ArraySize = ArraySize; - - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); - switch (Type) - { - case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; - break; - - case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer: - // Read-only storage buffers map to buffer SRV - // https://github.com/KhronosGroup/SPIRV-Cross/wiki/Reflection-API-user-guide#read-write-vs-read-only-resources-for-hlsl - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::StorageImage: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::SampledImage: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter: - LOG_WARNING_MESSAGE("There is no appropriate shader resource type for atomic counter resource '", Name, "'"); - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::SeparateImage: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_SAMPLER; - break; - - case SPIRVShaderResourceAttribs::ResourceType::InputAttachment: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT; - break; - - case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_ACCEL_STRUCT; - break; - - default: - UNEXPECTED("Unknown SPIRV resource type"); - } - return ResourceDesc; -} - void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout, const ShaderResourceCacheVk& SrcResourceCache, diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index 825bf872..405149a5 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -192,7 +192,7 @@ VulkanInstance::VulkanInstance(uint32_t ApiVersion, uint32_t MaxApiVersion = 0; vkEnumerateInstanceVersion(&MaxApiVersion); ApiVersion = std::min(ApiVersion, MaxApiVersion); - LOG_INFO_MESSAGE("Used Vulkan API version ", VK_VERSION_MAJOR(ApiVersion), ".", VK_VERSION_MINOR(ApiVersion)); + LOG_INFO_MESSAGE("Using Vulkan API version ", VK_VERSION_MAJOR(ApiVersion), ".", VK_VERSION_MINOR(ApiVersion)); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index b66ac8af..a80d7f73 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -198,7 +198,7 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment; m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount; m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount; - m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount / 3; + m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount; m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures; m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0; } -- cgit v1.2.3 From d829cacd06b2a78708e1e4772a833dad2ade5856 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 19:52:33 -0700 Subject: Fixed two minor merge issues --- Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 98119b2c..8aaee7f7 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -745,7 +745,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const RayTracingPipelineStateCreateInfo& CreateInfo) : - TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, + TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo}, m_SRBMemAllocator{GetRawAllocator()} { try -- cgit v1.2.3 From cbf6f3c8a7e1d4a370d4c9ca2840a143cfbea216 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 20:58:28 -0700 Subject: ShaderResourceLayout{D3D12,Vk}: implemented GetShaderName --- .../GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp | 12 ++++++++++-- Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp | 12 +++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index a0e40615..5406dee3 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -371,7 +371,7 @@ public: const Char* GetShaderName() const { - return ""; // AZ TODO + return GetStringPoolData(); } SHADER_TYPE GetShaderType() const { return m_ShaderType; } @@ -405,7 +405,7 @@ private: const VkResource& GetResource(Uint32 r) const { VERIFY_EXPR(r < GetTotalResourceCount()); - auto* Resources = reinterpret_cast(m_ResourceBuffer.get()); + const auto* Resources = reinterpret_cast(m_ResourceBuffer.get()); return Resources[r]; } @@ -414,8 +414,16 @@ private: return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } + const char* GetStringPoolData() const + { + const auto* ResourceDataEnd = reinterpret_cast(m_ResourceBuffer.get()) + GetTotalResourceCount(); + const auto* SamplerDataEnd = reinterpret_cast(ResourceDataEnd) + m_NumImmutableSamplers; + return reinterpret_cast(SamplerDataEnd); + } + static constexpr Uint32 InvalidResourceIndex = ~0u; + // Maps resource name to its index in m_ResourceBuffer using ResourceNameToIndex_t = std::unordered_map; StringPool AllocateMemory(const std::vector& Shaders, IMemoryAllocator& Allocator, diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 499c35ef..76bd77ee 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -135,11 +135,15 @@ StringPool ShaderResourceLayoutVk::AllocateMemory(const std::vector 0); VERIFY_EXPR(m_ShaderType == SHADER_TYPE_UNKNOWN); - size_t StringPoolSize = 0; m_ShaderType = Shaders[0]->GetDesc().ShaderType; m_IsUsingSeparateSamplers = !Shaders[0]->GetShaderResources()->IsUsingCombinedSamplers(); const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + // Construct shader or shader group name + const auto ShaderName = GetShaderGroupName(Shaders); + + size_t StringPoolSize = ShaderName.length() + 1; + // Count the number of resources to allocate all needed memory for (size_t s = 0; s < Shaders.size(); ++s) { @@ -202,11 +206,13 @@ StringPool ShaderResourceLayoutVk::AllocateMemory(const std::vector>(MemPool.Release(), Allocator); - VERIFY_EXPR(m_ResourceBuffer.get() == pResources); - VERIFY_EXPR(m_NumImmutableSamplers == 0 || pImtblSamplers == std::addressof(GetImmutableSampler(0))); + VERIFY_EXPR(pResources == nullptr || m_ResourceBuffer.get() == pResources); + VERIFY_EXPR(pImtblSamplers == nullptr || pImtblSamplers == std::addressof(GetImmutableSampler(0))); + VERIFY_EXPR(pStringData == GetStringPoolData()); StringPool stringPool; stringPool.AssignMemory(pStringData, StringPoolSize); + stringPool.CopyString(ShaderName); return stringPool; } -- cgit v1.2.3 From 28d240e6135189afa2cf478765c0b774a3c03959 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 21:17:06 -0700 Subject: Fixed Linux build error --- Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 5406dee3..1ad65aa3 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -221,7 +221,7 @@ public: ArraySize {_ArraySize }, Type {_Type }, ResourceDim {_ResourceDim }, - IsMS {_IsMS ? 1U : 0U}, + IsMS {_IsMS ? Uint8{1} : Uint8{0}}, Name {_Name }, ParentResLayout {_ParentLayout } // clang-format on -- cgit v1.2.3 From 8491cede1c2162a18ecd29b6f9bdc53ca5a72ce2 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 23:05:40 -0700 Subject: Fixed vexing gcc/clang liker error --- Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp | 2 +- Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 1ad65aa3..44b75187 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -421,7 +421,7 @@ private: return reinterpret_cast(SamplerDataEnd); } - static constexpr Uint32 InvalidResourceIndex = ~0u; + static constexpr const Uint32 InvalidResourceIndex = ~0u; // Maps resource name to its index in m_ResourceBuffer using ResourceNameToIndex_t = std::unordered_map; diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 76bd77ee..8a48c27c 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -158,7 +158,7 @@ StringPool ShaderResourceLayoutVk::AllocateMemory(const std::vector Date: Wed, 28 Oct 2020 19:33:03 +0300 Subject: added ray tracing implementation for dx12 and vulkan --- .../include/BottomLevelASVkImpl.hpp | 11 + .../include/DescriptorPoolManager.hpp | 18 +- .../include/DeviceContextVkImpl.hpp | 29 ++ .../include/RenderDeviceVkImpl.hpp | 8 +- .../include/ShaderBindingTableVkImpl.hpp | 53 +--- .../include/TopLevelASVkImpl.hpp | 15 +- .../include/VulkanTypeConversions.hpp | 5 +- .../VulkanUtilities/VulkanCommandBuffer.hpp | 67 ++++- .../VulkanUtilities/VulkanLogicalDevice.hpp | 7 +- .../VulkanUtilities/VulkanMemoryManager.hpp | 31 ++- .../interface/BottomLevelASVk.h | 3 +- .../interface/ShaderBindingTableVk.h | 11 +- .../GraphicsEngineVulkan/interface/TopLevelASVk.h | 6 +- .../src/BottomLevelASVkImpl.cpp | 10 +- Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp | 14 +- .../src/CommandPoolManager.cpp | 7 +- .../src/DescriptorPoolManager.cpp | 35 +++ .../src/DeviceContextVkImpl.cpp | 309 +++++++++++++++++---- .../src/PipelineStateVkImpl.cpp | 20 +- .../GraphicsEngineVulkan/src/QueryManagerVk.cpp | 2 +- Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp | 2 +- .../src/ShaderBindingTableVkImpl.cpp | 187 +++++++------ .../src/ShaderResourceCacheVk.cpp | 63 ++--- .../src/ShaderResourceLayoutVk.cpp | 35 +-- .../GraphicsEngineVulkan/src/SwapChainVkImpl.cpp | 31 ++- .../GraphicsEngineVulkan/src/TextureVkImpl.cpp | 16 +- .../GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp | 8 +- .../src/VulkanTypeConversions.cpp | 65 ++++- .../GraphicsEngineVulkan/src/VulkanUploadHeap.cpp | 2 +- .../src/VulkanUtilities/VulkanCommandBuffer.cpp | 87 +++++- .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 12 +- .../src/VulkanUtilities/VulkanMemoryManager.cpp | 30 +- .../VulkanUtilities/VulkanRayTracingKHRviaNV.cpp | 123 ++++---- 33 files changed, 901 insertions(+), 421 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') 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(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 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 m_PoolSizes; - const uint32_t m_MaxSets; - const bool m_AllowFreeing; + std::vector m_PoolSizes; + const uint32_t m_MaxSets; + const bool m_AllowFreeing; std::mutex m_Mutex; std::deque 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 +class ShaderBindingTableVkImpl final : public ShaderBindingTableBase { public: - using TShaderBindingTableBase = ShaderBindingTableBase; + using TShaderBindingTableBase = ShaderBindingTableBase; 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 m_pBuffer; - std::vector 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 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(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 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 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::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 pTexture{Barrier.pResource, IID_TextureVk}; + if (pTexture) { - auto* pTextureVkImpl = ValidatedCast(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 pBuffer{Barrier.pResource, IID_BufferVk}; + if (pBuffer) { - VERIFY_EXPR(Barrier.pBuffer != nullptr); - auto* pBufferVkImpl = ValidatedCast(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(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 Offsets; std::vector 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(src.pVertexBuffer); + auto* pVB = ValidatedCast(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(src.pIndexBuffer); + auto* pIB = ValidatedCast(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(src.pTransformBuffer); + VERIFY_EXPR(BLASDesc.pTriangles[j].AllowsTransforms); + + auto* pTB = ValidatedCast(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(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(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(Attribs.pTLAS); auto* pScratchVk = ValidatedCast(Attribs.pScratchBuffer); - auto* pInstancesVk = ValidatedCast(Attribs.pInstancesBuffer); + auto* pInstancesVk = ValidatedCast(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(pMappedInstances)[i]; - auto* pBLASVk = ValidatedCast(src.pBLAS); + auto* pBLASVk = ValidatedCast(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(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(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 ShaderIndices = {}; std::unordered_map 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(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(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(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()->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(m_RayGenShaderRecord.size()), m_RayGenShaderRecord.data(), TransitionMode); + + if (m_MissShadersRecord.size()) + pContext->UpdateBuffer(m_pBuffer, MissShaderOffset, static_cast(m_MissShadersRecord.size()), m_MissShadersRecord.data(), TransitionMode); + + if (m_HitGroupsRecord.size()) + pContext->UpdateBuffer(m_pBuffer, HitGroupOffset, static_cast(m_HitGroupsRecord.size()), m_HitGroupsRecord.data(), TransitionMode); + + if (m_CallableShadersRecord.size()) + pContext->UpdateBuffer(m_pBuffer, CallableShadersOffset, static_cast(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(); - //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(); + 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(); + auto* pTLASVk = pObject.RawPtr(); - 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 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 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(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(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(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 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(1 << bit)); + FlagBitPosToResourceState[bit] = VkAccessFlagToResourceStates(static_cast(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(PageSize), ParentMemoryMgr.m_Allocator} @@ -53,13 +54,22 @@ VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr, "PageSize (", PageSize, ") exceeds maximum allowed value ", std::numeric_limits::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 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(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(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 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(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 Infos; std::vector 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; -- cgit v1.2.3 From 076e2f20ce80ef9ea6ccb351c2bfdc3b99ac8015 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 30 Oct 2020 14:18:45 -0700 Subject: A number of minor updates --- .../include/DescriptorPoolManager.hpp | 6 +- .../src/CommandPoolManager.cpp | 2 +- .../src/DescriptorPoolManager.cpp | 35 ++-- .../src/DeviceContextVkImpl.cpp | 201 +++++++++++---------- .../src/PipelineStateVkImpl.cpp | 4 +- .../GraphicsEngineVulkan/src/SwapChainVkImpl.cpp | 24 +-- .../src/VulkanTypeConversions.cpp | 13 +- 7 files changed, 148 insertions(+), 137 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp index 41a8cac3..b60f3d89 100644 --- a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp @@ -165,9 +165,9 @@ protected: RenderDeviceVkImpl& m_DeviceVkImpl; const std::string m_PoolName; - std::vector m_PoolSizes; - const uint32_t m_MaxSets; - const bool m_AllowFreeing; + const std::vector m_PoolSizes; + const uint32_t m_MaxSets; + const bool m_AllowFreeing; std::mutex m_Mutex; std::deque m_Pools; diff --git a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp index 6d0e1ab2..cf24d9ea 100644 --- a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp +++ b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp @@ -53,7 +53,7 @@ VulkanUtilities::CommandPoolWrapper CommandPoolManager::AllocateCommandPool(cons { std::lock_guard LockGuard{m_Mutex}; - auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice(); + const auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice(); VulkanUtilities::CommandPoolWrapper CmdPool; if (!m_CmdPools.empty()) diff --git a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp index 6557ac6d..45045cea 100644 --- a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp @@ -59,28 +59,16 @@ VulkanUtilities::DescriptorPoolWrapper DescriptorPoolManager::CreateDescriptorPo return m_DeviceVkImpl.GetLogicalDevice().CreateDescriptorPool(PoolCI, DebugName); } -DescriptorPoolManager::DescriptorPoolManager(RenderDeviceVkImpl& DeviceVkImpl, - std::string PoolName, - std::vector 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 +static std::vector PrunePoolSizes(RenderDeviceVkImpl& DeviceVkImpl, std::vector&& PoolSizes) { - const auto& Feats = m_DeviceVkImpl.GetLogicalDevice().GetEnabledExtFeatures(); - - for (auto iter = m_PoolSizes.begin(); iter != m_PoolSizes.end();) + const auto& Feats = DeviceVkImpl.GetLogicalDevice().GetEnabledExtFeatures(); + for (auto iter = PoolSizes.begin(); iter != PoolSizes.end();) { switch (iter->type) { case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: if (Feats.RayTracing.rayTracing == VK_FALSE) - iter = m_PoolSizes.erase(iter); + iter = PoolSizes.erase(iter); else ++iter; break; @@ -88,7 +76,22 @@ DescriptorPoolManager::DescriptorPoolManager(RenderDeviceVkImpl& D ++iter; } } + return PoolSizes; +} +DescriptorPoolManager::DescriptorPoolManager(RenderDeviceVkImpl& DeviceVkImpl, + std::string PoolName, + std::vector PoolSizes, + uint32_t MaxSets, + bool AllowFreeing) noexcept : + // clang-format off + m_DeviceVkImpl{DeviceVkImpl }, + m_PoolName {std::move(PoolName) }, + m_PoolSizes (PrunePoolSizes(DeviceVkImpl, std::move(PoolSizes))), + m_MaxSets {MaxSets }, + m_AllowFreeing{AllowFreeing } +// clang-format on +{ #ifdef DILIGENT_DEVELOPMENT m_AllocatedPoolCounter = 0; #endif diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 554352ad..69a3a1ba 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2704,8 +2704,7 @@ void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTra } VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type"); - RefCntAutoPtr pTexture{Barrier.pResource, IID_TextureVk}; - if (pTexture) + if (RefCntAutoPtr pTexture{Barrier.pResource, IID_TextureVk}) { VkImageSubresourceRange SubResRange; SubResRange.aspectMask = 0; @@ -2714,17 +2713,23 @@ void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTra SubResRange.baseArrayLayer = Barrier.FirstArraySlice; SubResRange.layerCount = (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES) ? VK_REMAINING_ARRAY_LAYERS : Barrier.ArraySliceCount; TransitionTextureState(*pTexture, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState, &SubResRange); - continue; } - - RefCntAutoPtr pBuffer{Barrier.pResource, IID_BufferVk}; - if (pBuffer) + else if (RefCntAutoPtr pBuffer{Barrier.pResource, IID_BufferVk}) { TransitionBufferState(*pBuffer, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); - continue; } - - UNEXPECTED("unsupported resource type"); + else if (RefCntAutoPtr pBLAS{Barrier.pResource, IID_BottomLevelAS}) + { + TransitionBLASState(*pBLAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); + } + else if (RefCntAutoPtr pTLAS{Barrier.pResource, IID_TopLevelAS}) + { + TransitionTLASState(*pTLAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); + } + else + { + UNEXPECTED("unsupported resource type"); + } } } @@ -2816,61 +2821,61 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) { - auto& src = Attribs.pTriangleData[i]; - Uint32 j = pBLASVk->GetGeometryIndex(src.GeometryName); - auto& dst = Geometries.data()[j]; - auto& tri = dst.geometry.triangles; - auto& off = Offsets.data()[j]; + const auto& SrcTris = Attribs.pTriangleData[i]; + Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcTris.GeometryName); + auto& vkGeo = Geometries[GeoIdx]; + auto& vkTris = vkGeo.geometry.triangles; + auto& off = Offsets[GeoIdx]; - if (j >= Geometries.size()) + if (GeoIdx >= Geometries.size()) { UNEXPECTED("Failed to find geometry by name"); continue; } - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - dst.pNext = nullptr; - dst.flags = GeometryFlagsToVkGeometryFlags(src.Flags); - dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - tri.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; - tri.pNext = nullptr; + vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + vkGeo.pNext = nullptr; + vkGeo.flags = GeometryFlagsToVkGeometryFlags(SrcTris.Flags); + vkGeo.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + vkTris.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + vkTris.pNext = nullptr; - auto* pVB = ValidatedCast(src.pVertexBuffer); - tri.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); - tri.vertexStride = src.VertexStride; - tri.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + src.VertexOffset; + auto* const pVB = ValidatedCast(SrcTris.pVertexBuffer); + vkTris.vertexFormat = TypeToVkFormat(SrcTris.VertexValueType, SrcTris.VertexComponentCount, SrcTris.VertexValueType < VT_FLOAT16); + vkTris.vertexStride = SrcTris.VertexStride; + vkTris.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + SrcTris.VertexOffset; - TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName); + TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, static_cast(0), OpName); - if (src.pIndexBuffer) + if (SrcTris.pIndexBuffer) { - auto* pIB = ValidatedCast(src.pIndexBuffer); - tri.indexType = TypeToVkIndexType(src.IndexType); - tri.indexData.deviceAddress = pIB->GetVkDeviceAddress() + src.IndexOffset; - off.primitiveCount = src.IndexCount / 3; + auto* const pIB = ValidatedCast(SrcTris.pIndexBuffer); + vkTris.indexType = TypeToVkIndexType(SrcTris.IndexType); + vkTris.indexData.deviceAddress = pIB->GetVkDeviceAddress() + SrcTris.IndexOffset; + off.primitiveCount = SrcTris.IndexCount / 3; - TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName); + TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, static_cast(0), OpName); } else { - tri.indexType = VK_INDEX_TYPE_NONE_KHR; - tri.indexData.deviceAddress = 0; - off.primitiveCount = src.VertexCount / 3; + vkTris.indexType = VK_INDEX_TYPE_NONE_KHR; + vkTris.indexData.deviceAddress = 0; + off.primitiveCount = SrcTris.VertexCount / 3; } - if (src.pTransformBuffer) + if (SrcTris.pTransformBuffer) { - VERIFY_EXPR(BLASDesc.pTriangles[j].AllowsTransforms); + VERIFY_EXPR(BLASDesc.pTriangles[GeoIdx].AllowsTransforms); - auto* pTB = ValidatedCast(src.pTransformBuffer); - tri.transformData.deviceAddress = pTB->GetVkDeviceAddress() + src.TransformBufferOffset; + auto* const pTB = ValidatedCast(SrcTris.pTransformBuffer); + vkTris.transformData.deviceAddress = pTB->GetVkDeviceAddress() + SrcTris.TransformBufferOffset; TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName); } else { - VERIFY_EXPR(!BLASDesc.pTriangles[j].AllowsTransforms); - tri.transformData.deviceAddress = 0; + VERIFY_EXPR(!BLASDesc.pTriangles[GeoIdx].AllowsTransforms); + vkTris.transformData.deviceAddress = 0; } off.firstVertex = 0; @@ -2885,35 +2890,35 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) { - auto& src = Attribs.pBoxData[i]; - Uint32 j = pBLASVk->GetGeometryIndex(src.GeometryName); - auto& dst = Geometries.data()[j]; - auto& box = dst.geometry.aabbs; - auto& off = Offsets.data()[j]; + const auto& SrcBoxes = Attribs.pBoxData[i]; + Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcBoxes.GeometryName); + auto& vkGeo = Geometries[GeoIdx]; + auto& vkAABBs = vkGeo.geometry.aabbs; + auto& off = Offsets[GeoIdx]; - if (j >= Geometries.size()) + if (GeoIdx >= Geometries.size()) { UNEXPECTED("Failed to find geometry by name"); continue; } - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; - dst.pNext = nullptr; - dst.flags = GeometryFlagsToVkGeometryFlags(src.Flags); - dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; + vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + vkGeo.pNext = nullptr; + vkGeo.flags = GeometryFlagsToVkGeometryFlags(SrcBoxes.Flags); + vkGeo.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; - auto* pBB = ValidatedCast(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; + auto* const pBB = ValidatedCast(SrcBoxes.pBoxBuffer); + vkAABBs.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR; + vkAABBs.pNext = nullptr; + vkAABBs.stride = SrcBoxes.BoxStride; + vkAABBs.data.deviceAddress = pBB->GetVkDeviceAddress() + SrcBoxes.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; + off.primitiveCount = SrcBoxes.BoxCount; } } @@ -2971,18 +2976,18 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { - auto& src = Attribs.pInstances[i]; - auto& dst = static_cast(pMappedInstances)[i]; - auto* pBLASVk = ValidatedCast(src.pBLAS); + const auto& Inst = Attribs.pInstances[i]; + auto& vkASInst = static_cast(pMappedInstances)[i]; + auto* const pBLASVk = ValidatedCast(Inst.pBLAS); - static_assert(sizeof(dst.transform) == sizeof(src.Transform), "size mismatch"); - std::memcpy(&dst.transform, src.Transform, sizeof(dst.transform)); + static_assert(sizeof(vkASInst.transform) == sizeof(Inst.Transform), "size mismatch"); + std::memcpy(&vkASInst.transform, Inst.Transform, sizeof(vkASInst.transform)); - 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(); + vkASInst.instanceCustomIndex = Inst.CustomId; + vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize + vkASInst.mask = Inst.Mask; + vkASInst.flags = InstanceFlagsToVkGeometryInstanceFlags(Inst.Flags); + vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); } @@ -2991,37 +2996,37 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) } TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName); - VkAccelerationStructureBuildGeometryInfoKHR Info = {}; - VkAccelerationStructureBuildOffsetInfoKHR Offset = {}; - VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = &Offset; - VkAccelerationStructureGeometryKHR Geometry = {}; - VkAccelerationStructureGeometryKHR const* GeometriesPtr = &Geometry; - - Offset.primitiveCount = Attribs.InstanceCount; - - 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.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 - Info.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(TLASDesc.Flags); // flags must be compatible with create info - Info.update = VK_FALSE; - Info.srcAccelerationStructure = VK_NULL_HANDLE; - Info.dstAccelerationStructure = pTLASVk->GetVkTLAS(); - Info.geometryArrayOfPointers = VK_FALSE; - Info.geometryCount = 1; - Info.ppGeometries = &GeometriesPtr; - Info.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset; - - m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr); + VkAccelerationStructureBuildGeometryInfoKHR vkASBuildInfo = {}; + VkAccelerationStructureBuildOffsetInfoKHR vkASBuildOffset = {}; + VkAccelerationStructureBuildOffsetInfoKHR const* vkASBuildOffsetPtr = &vkASBuildOffset; + VkAccelerationStructureGeometryKHR vkASGeometry = {}; + VkAccelerationStructureGeometryKHR const* vkASGeometriesPtr = &vkASGeometry; + + vkASBuildOffset.primitiveCount = Attribs.InstanceCount; + + vkASGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + vkASGeometry.pNext = nullptr; + vkASGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + vkASGeometry.flags = 0; + + auto& vkASInst = vkASGeometry.geometry.instances; + vkASInst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + vkASInst.pNext = nullptr; + vkASInst.arrayOfPointers = VK_FALSE; + vkASInst.data.deviceAddress = pInstancesVk->GetVkDeviceAddress() + Attribs.InstanceBufferOffset; + + vkASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + vkASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; // type must be compatible with create info + vkASBuildInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(TLASDesc.Flags); // flags must be compatible with create info + vkASBuildInfo.update = VK_FALSE; + vkASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; + vkASBuildInfo.dstAccelerationStructure = pTLASVk->GetVkTLAS(); + vkASBuildInfo.geometryArrayOfPointers = VK_FALSE; + vkASBuildInfo.geometryCount = 1; + vkASBuildInfo.ppGeometries = &vkASGeometriesPtr; + vkASBuildInfo.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset; + + m_CommandBuffer.BuildAccelerationStructure(1, &vkASBuildInfo, &vkASBuildOffsetPtr); ++m_State.NumCommands; } diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 548a9cf3..36ca3a42 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -392,8 +392,8 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& Uint32 GroupIndex = 0; - std::array ShaderIndices = {}; - std::unordered_map UniqueShaders; + std::array ShaderIndices = {}; + std::unordered_map UniqueShaders; const auto ShaderToIndex = [&ShaderIndices, &UniqueShaders](const IShader* pShader) -> Uint32 { if (pShader != nullptr) diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp index 27be99fc..d32f9788 100644 --- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp @@ -425,20 +425,22 @@ void SwapChainVkImpl::CreateVulkanSwapChain() DEV_CHECK_ERR(m_SwapChainDesc.Usage != 0, "No swap chain usage flags defined"); 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(UsageBit)) + auto SCUsage = m_SwapChainDesc.Usage; + while (SCUsage != SWAP_CHAIN_USAGE_NONE) { - // 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"); + auto UsageBit = static_cast(1 << PlatformMisc::GetLSB(Uint32{SCUsage})); + switch (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; // clang-format on + default: UNEXPECTED("unknown swapchain usage flag"); + } + SCUsage &= ~UsageBit; } } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index 40882b09..143042b8 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1187,17 +1187,18 @@ static VkPipelineStageFlags ResourceStateFlagToVkPipelineStage(RESOURCE_STATE St } } -VkPipelineStageFlags ResourceStateFlagsToVkPipelineStageFlags(RESOURCE_STATE StateFlags, VkPipelineStageFlags ShaderStages) +VkPipelineStageFlags ResourceStateFlagsToVkPipelineStageFlags(RESOURCE_STATE StateFlags, VkPipelineStageFlags vkShaderStages) { 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) + VkPipelineStageFlags vkPipelineStages = 0; + while (StateFlags != RESOURCE_STATE_UNKNOWN) { - if (StateFlags & Bit) - Stages |= ResourceStateFlagToVkPipelineStage(static_cast(Bit), ShaderStages); + auto StateBit = static_cast(1 << PlatformMisc::GetLSB(Uint32{StateFlags})); + vkPipelineStages |= ResourceStateFlagToVkPipelineStage(StateBit, vkShaderStages); + StateFlags &= ~StateBit; } - return Stages; + return vkPipelineStages; } -- cgit v1.2.3 From 9a8133811d75501ae3d6e4a5c58f821fb38f8e5d Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 30 Oct 2020 14:54:48 -0700 Subject: Fixed clang compiler warning --- Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 45ed73de..f1e8b726 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -97,8 +97,8 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) : Type{Stage}, - Shaders{{pShader}}, - SPIRVs{{{pShader->GetSPIRV()}}} + Shaders{pShader}, + SPIRVs{pShader->GetSPIRV()} { } -- cgit v1.2.3 From efa43e2bd2475a4dec6771bf9759f6a99f7d77ed Mon Sep 17 00:00:00 2001 From: azhirnov Date: Tue, 3 Nov 2020 13:52:24 +0300 Subject: fixed resource state transitions, some improvements for ray tracing --- .../include/RenderDeviceVkImpl.hpp | 4 + .../include/ShaderBindingTableVkImpl.hpp | 7 -- .../include/TopLevelASVkImpl.hpp | 5 +- .../src/DeviceContextVkImpl.cpp | 111 +++++++++++++-------- .../src/PipelineStateVkImpl.cpp | 11 +- .../src/ShaderBindingTableVkImpl.cpp | 45 --------- .../src/ShaderResourceCacheVk.cpp | 40 ++------ .../src/VulkanTypeConversions.cpp | 29 +++--- 8 files changed, 108 insertions(+), 144 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index e13f1a76..5440a6c8 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -201,6 +201,10 @@ public: { return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; } + Uint32 GetMaxShaderRecordStride() const + { + return GetPhysicalDevice().GetExtProperties().RayTracing.maxShaderGroupStride; + } private: template diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp index 1b2db950..cef50a4e 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp @@ -51,10 +51,6 @@ public: bool bIsDeviceInternal = false); ~ShaderBindingTableVkImpl(); - virtual void DILIGENT_CALL_TYPE Verify() const override; - - virtual void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override; - virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override; virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override; @@ -67,9 +63,6 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTableVk, TShaderBindingTableBase); -private: - void ValidateDesc(const ShaderBindingTableDesc& Desc) const; - private: RefCntAutoPtr m_pBuffer; }; diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index b2801eca..0f8a94c8 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -34,15 +34,16 @@ #include "RenderDeviceVkImpl.hpp" #include "TopLevelASVk.h" #include "TopLevelASBase.hpp" +#include "BottomLevelASVkImpl.hpp" #include "VulkanUtilities/VulkanObjectWrappers.hpp" namespace Diligent { -class TopLevelASVkImpl final : public TopLevelASBase +class TopLevelASVkImpl final : public TopLevelASBase { public: - using TTopLevelASBase = TopLevelASBase; + using TTopLevelASBase = TopLevelASBase; TopLevelASVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 69a3a1ba..a77fb96d 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2334,6 +2334,22 @@ void DeviceContextVkImpl::TransitionImageLayout(ITexture* pTexture, VkImageLayou } } +namespace +{ +NODISCARD inline bool ResourceStateHasWriteAccess(RESOURCE_STATE State) +{ + static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "This function must be updated to handle new resource state flag"); + constexpr RESOURCE_STATE WriteAccessStates = + RESOURCE_STATE_RENDER_TARGET | + RESOURCE_STATE_UNORDERED_ACCESS | + RESOURCE_STATE_COPY_DEST | + RESOURCE_STATE_RESOLVE_DEST | + RESOURCE_STATE_BUILD_AS_WRITE; + + return State & WriteAccessStates; +} +} // namespace + void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& TextureVk, RESOURCE_STATE OldState, RESOURCE_STATE NewState, @@ -2396,17 +2412,22 @@ void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& Textur pSubresRange->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; } - // Note that 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. + // Always add barrier after writes. + const bool AfterWrite = ResourceStateHasWriteAccess(OldState); + auto OldLayout = ResourceStateToVkImageLayout(OldState); auto NewLayout = ResourceStateToVkImageLayout(NewState); 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) + + if (((OldState & NewState) != NewState) || OldLayout != NewLayout || AfterWrite) { - TextureVk.SetState(NewState); - VERIFY_EXPR(TextureVk.GetLayout() == NewLayout); + m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange, OldStages, NewStages); + if (UpdateTextureState) + { + TextureVk.SetState(NewState); + VERIFY_EXPR(TextureVk.GetLayout() == NewLayout); + } } } @@ -2421,10 +2442,7 @@ void DeviceContextVkImpl::TransitionOrVerifyTextureState(TextureVkImpl& VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass"); if (Texture.IsInKnownState()) { - if (!Texture.CheckState(RequiredState)) - { - TransitionTextureState(Texture, RESOURCE_STATE_UNKNOWN, RequiredState, true); - } + TransitionTextureState(Texture, RESOURCE_STATE_UNKNOWN, RequiredState, true); VERIFY_EXPR(Texture.GetLayout() == ExpectedLayout); } } @@ -2489,9 +2507,10 @@ 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 || NewState == RESOURCE_STATE_BUILD_AS_WRITE) + // Always add barrier after writes. + const bool AfterWrite = ResourceStateHasWriteAccess(OldState); + + if (((OldState & NewState) != NewState) || AfterWrite) { DEV_CHECK_ERR(BufferVk.m_VulkanBuffer != VK_NULL_HANDLE, "Cannot transition suballocated buffer"); VERIFY_EXPR(BufferVk.GetDynamicOffset(m_ContextId, this) == 0); @@ -2521,10 +2540,7 @@ void DeviceContextVkImpl::TransitionOrVerifyBufferState(BufferVkImpl& VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass"); if (Buffer.IsInKnownState()) { - if (!Buffer.CheckState(RequiredState)) - { - TransitionBufferState(Buffer, RESOURCE_STATE_UNKNOWN, RequiredState, true); - } + TransitionBufferState(Buffer, RESOURCE_STATE_UNKNOWN, RequiredState, true); VERIFY_EXPR(Buffer.CheckAccessFlags(ExpectedAccessFlags)); } } @@ -2564,7 +2580,10 @@ void DeviceContextVkImpl::TransitionBLASState(BottomLevelASVkImpl& BLAS, } } - if ((OldState & NewState) != NewState) + // Always add barrier after writes. + const bool AfterWrite = ResourceStateHasWriteAccess(OldState); + + if ((OldState & NewState) != NewState || AfterWrite) { EnsureVkCmdBuffer(); auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState); @@ -2584,8 +2603,6 @@ void DeviceContextVkImpl::TransitionTLASState(TopLevelASVkImpl& TLAS, 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) { @@ -2609,7 +2626,10 @@ void DeviceContextVkImpl::TransitionTLASState(TopLevelASVkImpl& TLAS, } } - if ((OldState & NewState) != NewState) + // Always add barrier after writes. + const bool AfterWrite = ResourceStateHasWriteAccess(OldState); + + if ((OldState & NewState) != NewState || AfterWrite) { EnsureVkCmdBuffer(); auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState); @@ -2634,10 +2654,7 @@ void DeviceContextVkImpl::TransitionOrVerifyBLASState(BottomLevelASVkImpl& 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); - } + TransitionBLASState(BLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true); } } #ifdef DILIGENT_DEVELOPMENT @@ -2658,10 +2675,7 @@ void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl& 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); - } + TransitionTLASState(TLAS, RESOURCE_STATE_UNKNOWN, RequiredState, true); } } #ifdef DILIGENT_DEVELOPMENT @@ -2669,6 +2683,11 @@ void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl& { DvpVerifyTLASState(TLAS, RequiredState, OperationName); } + + if (RequiredState & RESOURCE_STATE_RAY_TRACING) + { + TLAS.CheckBLASVersion(); + } #endif } @@ -2718,13 +2737,13 @@ void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTra { TransitionBufferState(*pBuffer, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); } - else if (RefCntAutoPtr pBLAS{Barrier.pResource, IID_BottomLevelAS}) + else if (RefCntAutoPtr pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS}) { - TransitionBLASState(*pBLAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); + TransitionBLASState(*pBottomLevelAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); } - else if (RefCntAutoPtr pTLAS{Barrier.pResource, IID_TopLevelAS}) + else if (RefCntAutoPtr pTopLevelAS{Barrier.pResource, IID_TopLevelAS}) { - TransitionTLASState(*pTLAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); + TransitionTLASState(*pTopLevelAS, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState); } else { @@ -2808,7 +2827,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) 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); + TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, OpName); VkAccelerationStructureBuildGeometryInfoKHR Info = {}; std::vector Offsets; @@ -2845,7 +2864,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) vkTris.vertexStride = SrcTris.VertexStride; vkTris.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + SrcTris.VertexOffset; - TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, static_cast(0), OpName); + TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); if (SrcTris.pIndexBuffer) { @@ -2854,7 +2873,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) vkTris.indexData.deviceAddress = pIB->GetVkDeviceAddress() + SrcTris.IndexOffset; off.primitiveCount = SrcTris.IndexCount / 3; - TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, static_cast(0), OpName); + TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); } else { @@ -2870,7 +2889,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) auto* const pTB = ValidatedCast(SrcTris.pTransformBuffer); vkTris.transformData.deviceAddress = pTB->GetVkDeviceAddress() + SrcTris.TransformBufferOffset; - TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName); + TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); } else { @@ -2913,7 +2932,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) vkAABBs.stride = SrcBoxes.BoxStride; vkAABBs.data.deviceAddress = pBB->GetVkDeviceAddress() + SrcBoxes.BoxOffset; - TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName); + TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); off.firstVertex = 0; off.transformOffset = 0; @@ -2939,6 +2958,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) EnsureVkCmdBuffer(); m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr); ++m_State.NumCommands; + +#ifdef DILIGENT_DEVELOPMENT + pBLASVk->UpdateVersion(); +#endif } void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) @@ -2964,7 +2987,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) 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); + TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, OpName); pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.HitShadersPerInstance); @@ -2981,7 +3004,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) auto* const pBLASVk = ValidatedCast(Inst.pBLAS); static_assert(sizeof(vkASInst.transform) == sizeof(Inst.Transform), "size mismatch"); - std::memcpy(&vkASInst.transform, Inst.Transform, sizeof(vkASInst.transform)); + std::memcpy(&vkASInst.transform, Inst.Transform.data, sizeof(vkASInst.transform)); vkASInst.instanceCustomIndex = Inst.CustomId; vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize @@ -2994,7 +3017,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) UpdateBufferRegion(pInstancesVk, Attribs.InstanceBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode); } - TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VkAccessFlagBits(0), OpName); + TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); VkAccelerationStructureBuildGeometryInfoKHR vkASBuildInfo = {}; VkAccelerationStructureBuildOffsetInfoKHR vkASBuildOffset = {}; @@ -3060,6 +3083,10 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) m_CommandBuffer.CopyAccelerationStructure(Info); ++m_State.NumCommands; + +#ifdef DILIGENT_DEVELOPMENT + pDstVk->UpdateVersion(); +#endif } void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs) @@ -3077,6 +3104,8 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs) auto* pSrcVk = ValidatedCast(Attribs.pSrc); auto* pDstVk = ValidatedCast(Attribs.pDst); + pDstVk->CopyInstancceData(*pSrcVk); + VkCopyAccelerationStructureInfoKHR Info = {}; Info.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 36ca3a42..1cac2b6f 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -758,10 +758,16 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* { try { + const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); + const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize(); + + if (LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing == VK_FALSE) + LOG_ERROR_AND_THROW("Ray tracing is not supported by this device"); + std::vector vkShaderStages; std::vector ShaderModules; - std::vector ShaderGroups; + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, [&](const RayTracingPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages& ShaderStages) // { @@ -773,9 +779,6 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* CreateRayTracingPipeline(pDeviceVk, vkShaderStages, ShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline); - const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); - const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize(); - auto err = LogicalDevice.GetRayTracingShaderGroupHandles(m_Pipeline, 0, static_cast(ShaderGroups.size()), ShaderGroupHandleSize, &m_pRayTracingPipelineData->Shaders[0]); VERIFY(err == VK_SUCCESS, "Failed to get shader group handles"); (void)err; diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp index 6f5091e0..3940769f 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp @@ -39,57 +39,12 @@ ShaderBindingTableVkImpl::ShaderBindingTableVkImpl(IReferenceCounters* bool bIsDeviceInternal) : TShaderBindingTableBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal} { - ValidateDesc(Desc); - - const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; - m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize; } ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl() { } -void ShaderBindingTableVkImpl::ValidateDesc(const ShaderBindingTableDesc& Desc) const -{ - const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; - - 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: ", RTLimits.maxShaderGroupStride - RTLimits.shaderGroupHandleSize); - } -} - -void ShaderBindingTableVkImpl::Verify() const -{ - // AZ TODO -} - -void ShaderBindingTableVkImpl::Reset(const ShaderBindingTableDesc& Desc) -{ - m_RayGenShaderRecord.clear(); - m_MissShadersRecord.clear(); - m_CallableShadersRecord.clear(); - m_HitGroupsRecord.clear(); - m_Changed = true; - - try - { - ValidateShaderBindingTableDesc(Desc); - ValidateDesc(Desc); - } - catch (const std::runtime_error&) - { - // AZ TODO - return; - } - - m_Desc = Desc; - - const auto& RTLimits = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing; - m_ShaderRecordStride = m_Desc.ShaderRecordSize + RTLimits.shaderGroupHandleSize; -} - void ShaderBindingTableVkImpl::ResetHitGroups(Uint32 HitShadersPerInstance) { // AZ TODO diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 8101fefc..27e5ee72 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -166,10 +166,9 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) { constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_CONSTANT_BUFFER; VERIFY_EXPR((ResourceStateFlagsToVkAccessFlags(RequiredState) & VK_ACCESS_UNIFORM_READ_BIT) == VK_ACCESS_UNIFORM_READ_BIT); - const bool IsInRequiredState = pBufferVk->CheckState(RequiredState); if (VerifyOnly) { - if (!IsInRequiredState) + if (!pBufferVk->CheckState(RequiredState)) { LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -181,10 +180,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } else { - if (!IsInRequiredState) - { - pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); - } + pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); VERIFY_EXPR(pBufferVk->CheckAccessFlags(VK_ACCESS_UNIFORM_READ_BIT)); } } @@ -211,11 +207,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); VERIFY_EXPR((ResourceStateFlagsToVkAccessFlags(RequiredState) & RequiredAccessFlags) == RequiredAccessFlags); #endif - const bool IsInRequiredState = pBufferVk->CheckState(RequiredState); if (VerifyOnly) { - if (!IsInRequiredState) + if (!pBufferVk->CheckState(RequiredState)) { LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -227,12 +222,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } else { - // 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 (!IsInRequiredState || RequiredState == RESOURCE_STATE_UNORDERED_ACCESS) - { - pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); - } + pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); VERIFY_EXPR(pBufferVk->CheckAccessFlags(RequiredAccessFlags)); } } @@ -275,11 +265,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) VERIFY_EXPR(ResourceStateToVkImageLayout(RequiredState) == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } } - const bool IsInRequiredState = pTextureVk->CheckState(RequiredState); if (VerifyOnly) { - if (!IsInRequiredState) + if (!pTextureVk->CheckState(RequiredState)) { LOG_ERROR_MESSAGE("State of texture '", pTextureVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -291,12 +280,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } else { - // 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 (!IsInRequiredState || RequiredState == RESOURCE_STATE_UNORDERED_ACCESS) - { - pCtxVkImpl->TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); - } + pCtxVkImpl->TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); } } } @@ -327,11 +311,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) auto* pTLASVk = Res.pObject.RawPtr(); if (pTLASVk != nullptr && pTLASVk->IsInKnownState()) { - constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING; - const bool IsInRequiredState = pTLASVk->CheckState(RequiredState); + constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING; if (VerifyOnly) { - if (!IsInRequiredState) + if (!pTLASVk->CheckState(RequiredState)) { LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -340,13 +323,12 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state " "with IDeviceContext::TransitionResourceStates()."); } + + pTLASVk->CheckBLASVersion(); } else { - if (!IsInRequiredState) - { - pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); - } + pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); } } } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index 143042b8..e039311b 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1613,12 +1613,10 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF "Please update the switch below to handle the new ray tracing build flag"); VkBuildAccelerationStructureFlagsKHR Result = 0; - for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + while (Flags != RAYTRACING_BUILD_AS_NONE) { - if ((Flags & Bit) != Bit) - continue; - - switch (static_cast(Bit)) + auto FlagBit = static_cast(1 << PlatformMisc::GetLSB(Uint32{Flags})); + switch (FlagBit) { // clang-format off case RAYTRACING_BUILD_AS_ALLOW_UPDATE: Result |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR; break; @@ -1629,6 +1627,7 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF // clang-format on default: UNEXPECTED("unknown build AS flag"); } + Flags = Flags & ~FlagBit; } return Result; } @@ -1639,12 +1638,10 @@ VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flag "Please update the switch below to handle the new ray tracing geometry flag"); VkGeometryFlagsKHR Result = 0; - for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + while (Flags != RAYTRACING_GEOMETRY_NONE) { - if ((Flags & Bit) != Bit) - continue; - - switch (static_cast(Bit)) + auto FlagBit = static_cast(1 << PlatformMisc::GetLSB(Uint32{Flags})); + switch (FlagBit) { // clang-format off case RAYTRACING_GEOMETRY_OPAQUE: Result |= VK_GEOMETRY_OPAQUE_BIT_KHR; break; @@ -1652,6 +1649,7 @@ VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flag // clang-format on default: UNEXPECTED("unknown geometry flag"); } + Flags = Flags & ~FlagBit; } return Result; } @@ -1662,12 +1660,10 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS "Please update the switch below to handle the new ray tracing instance flag"); VkGeometryInstanceFlagsKHR Result = 0; - for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + while (Flags != RAYTRACING_INSTANCE_NONE) { - if ((Flags & Bit) != Bit) - continue; - - switch (static_cast(Bit)) + auto FlagBit = static_cast(1 << PlatformMisc::GetLSB(Uint32{Flags})); + switch (FlagBit) { // clang-format off case RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE: Result |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; break; @@ -1677,6 +1673,7 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS // clang-format on default: UNEXPECTED("unknown instance flag"); } + Flags = Flags & ~FlagBit; } return Result; } @@ -1693,7 +1690,7 @@ VkCopyAccelerationStructureModeKHR CopyASModeToVkCopyAccelerationStructureMode(C // clang-format on default: UNEXPECTED("unknown AS copy mode"); - return static_cast(0); + return VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR; } } -- cgit v1.2.3 From 5e81b867be771dc7f2add0d7b403af4aeaa744db Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 5 Nov 2020 03:43:05 +0300 Subject: Added AS copy with compacting. Added UB & SB size checks for Vulkan. Some improvements for ray tracing & tests. --- .../include/DeviceContextVkImpl.hpp | 10 + .../include/RenderDeviceVkImpl.hpp | 9 + .../include/ShaderBindingTableVkImpl.hpp | 10 - .../include/ShaderResourceLayoutVk.hpp | 19 +- .../include/TopLevelASVkImpl.hpp | 2 +- .../VulkanUtilities/VulkanCommandBuffer.hpp | 15 ++ .../interface/ShaderBindingTableVk.h | 10 - .../src/BottomLevelASVkImpl.cpp | 123 +++++++------ .../src/DeviceContextVkImpl.cpp | 203 +++++++++++++-------- .../src/ShaderBindingTableVkImpl.cpp | 104 ----------- .../src/ShaderResourceCacheVk.cpp | 4 +- .../src/ShaderResourceLayoutVk.cpp | 23 ++- .../GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp | 49 +++-- .../src/VulkanTypeConversions.cpp | 11 +- .../src/VulkanUtilities/VulkanCommandBuffer.cpp | 4 +- 15 files changed, 303 insertions(+), 293 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index 40e19d80..39dca08d 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -266,6 +266,12 @@ public: /// Implementation of IDeviceContext::CopyTLAS() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CopyTLAS(const CopyTLASAttribs& Attribs) override final; + /// Implementation of IDeviceContext::WriteBLASCompactedSize() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::WriteTLASCompactedSize() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRays() in Vulkan backend. virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; @@ -470,6 +476,8 @@ private: void DvpLogRenderPass_PSOMismatch(); + void CreateASCompactedSizeQueryPool(); + VulkanUtilities::VulkanCommandBuffer m_CommandBuffer; const Uint32 m_NumCommandsToFlush = 192; @@ -551,6 +559,8 @@ private: Int32 m_ActiveQueriesCounter = 0; std::vector m_vkClearValues; + + VulkanUtilities::QueryPoolWrapper m_ASQueryPool; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 5440a6c8..556e3aa5 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -205,6 +205,15 @@ public: { return GetPhysicalDevice().GetExtProperties().RayTracing.maxShaderGroupStride; } + Uint32 GetShaderGroupBaseAlignment() const + { + return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupBaseAlignment; + } + + Uint32 GetMaxDrawMeshTasksCount() const + { + return GetPhysicalDevice().GetExtProperties().MeshShader.maxDrawMeshTasksCount; + } private: template diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp index cef50a4e..ab43ab80 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp @@ -54,17 +54,7 @@ public: virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override; virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) 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); - -private: - RefCntAutoPtr m_pBuffer; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 44b75187..bee3de1f 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -197,6 +197,11 @@ public: /* 16 */ const char* const Name; /* 24 */ const ShaderResourceLayoutVk& ParentResLayout; + +#ifdef DILIGENT_DEBUG +/* 32 */ const Uint32 BufferStaticSize; +/* 36 */ const Uint32 BufferStride; +#endif // clang-format on VkResource(const ShaderResourceLayoutVk& _ParentLayout, @@ -210,7 +215,9 @@ public: uint32_t _DescriptorSet, Uint32 _CacheOffset, Uint32 _SamplerInd, - bool _ImmutableSamplerAssigned = false) noexcept : + bool _ImmutableSamplerAssigned, + Uint32 _BufferStaticSize, + Uint32 _BufferStride) noexcept : // clang-format off Binding {static_cast(_Binding) }, DescriptorSet {static_cast(_DescriptorSet)}, @@ -222,11 +229,15 @@ public: Type {_Type }, ResourceDim {_ResourceDim }, IsMS {_IsMS ? Uint8{1} : Uint8{0}}, - Name {_Name }, - ParentResLayout {_ParentLayout } +#ifdef DILIGENT_DEBUG + BufferStaticSize {_BufferStaticSize}, + BufferStride {_BufferStride }, +#endif + Name {_Name }, + ParentResLayout {_ParentLayout } // clang-format on { -#if defined(_MSC_VER) && defined(_WIN64) +#if defined(_MSC_VER) && defined(_WIN64) && !defined(DILIGENT_DEBUG) static_assert(sizeof(*this) == 32, "Unexpected sizeof(VkResource)"); #endif // clang-format off diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index 0f8a94c8..8f2b42ab 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -58,7 +58,7 @@ public: virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final { auto Handle = GetVkTLAS(); - return reinterpret_cast(Handle); + return reinterpret_cast(Handle); // AZ TODO: fix for 32 bit platform } /// Implementation of ITopLevelASVk::GetVkTLAS(). diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp index 50a4c99f..8a21fb17 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp @@ -637,6 +637,21 @@ public: #endif } + __forceinline void WriteAccelerationStructuresProperties(VkAccelerationStructureKHR accelerationStructure, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery) + { +#if DILIGENT_USE_VOLK + VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); + if (m_State.RenderPass != VK_NULL_HANDLE) + { + // Write AS properties operations must be performed outside of render pass. + EndRenderPass(); + } + vkCmdWriteAccelerationStructuresPropertiesKHR(m_VkCmdBuffer, 1, &accelerationStructure, queryType, queryPool, firstQuery); +#else + UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically"); +#endif + } + __forceinline void TraceRays(const VkStridedBufferRegionKHR& RaygenShaderBindingTable, const VkStridedBufferRegionKHR& MissShaderBindingTable, const VkStridedBufferRegionKHR& HitShaderBindingTable, diff --git a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h index d879faac..ee4ea3c8 100644 --- a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h @@ -50,14 +50,6 @@ static const INTERFACE_ID IID_ShaderBindingTableVk = /// Exposes Vulkan-specific functionality of a Shader binding table object. DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable) { - /// AZ TODO - VIRTUAL void METHOD(GetVkStridedBufferRegions)(THIS_ - 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 @@ -66,8 +58,6 @@ DILIGENT_END_INTERFACE #if DILIGENT_C_INTERFACE -# define IShaderBindingTableVk_GetVkStridedBufferRegions(This, ...) CALL_IFACE_METHOD(ShaderBindingTableVk, GetVkStridedBufferRegions, This, __VA_ARGS__) - #endif DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp index a1172130..cc16c9e4 100644 --- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -45,63 +45,69 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, VkAccelerationStructureCreateInfoKHR CreateInfo = {}; std::vector Geometries; - CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - CreateInfo.maxGeometryCount = std::max(m_Desc.BoxCount, m_Desc.TriangleCount); - CreateInfo.compactedSize = 0; // AZ TODO + CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - VERIFY_EXPR(CreateInfo.maxGeometryCount <= Limits.maxGeometryCount); + if (m_Desc.CompactedSize > 0) + { + CreateInfo.compactedSize = m_Desc.CompactedSize; + } + else + { + CreateInfo.maxGeometryCount = m_Desc.TriangleCount + m_Desc.BoxCount; + Geometries.resize(CreateInfo.maxGeometryCount); + CreateInfo.pGeometryInfos = Geometries.data(); - Geometries.resize(CreateInfo.maxGeometryCount); - CreateInfo.pGeometryInfos = Geometries.data(); + VERIFY_EXPR(CreateInfo.maxGeometryCount <= Limits.maxGeometryCount); - // Specs says: the geometryType member of each geometry in pGeometries must be the same. - if (m_Desc.pTriangles != nullptr) - { - Uint32 MaxPrimitiveCount = 0; - for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i) + if (m_Desc.pTriangles != nullptr) { - auto& src = m_Desc.pTriangles[i]; - auto& dst = Geometries[i]; - - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - dst.pNext = nullptr; - dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - dst.maxPrimitiveCount = (src.IndexType == VT_UNDEFINED ? src.MaxVertexCount : src.MaxIndexCount) / 3; - dst.indexType = TypeToVkIndexType(src.IndexType); - dst.maxVertexCount = src.MaxVertexCount; - dst.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); - dst.allowsTransforms = src.AllowsTransforms; - - MaxPrimitiveCount += dst.maxPrimitiveCount; + + Uint32 MaxPrimitiveCount = 0; + for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i) + { + auto& src = m_Desc.pTriangles[i]; + auto& dst = Geometries[i]; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + dst.maxPrimitiveCount = src.MaxPrimitiveCount; + dst.indexType = TypeToVkIndexType(src.IndexType); + dst.maxVertexCount = src.MaxVertexCount; + dst.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); + dst.allowsTransforms = src.AllowsTransforms; + + MaxPrimitiveCount += dst.maxPrimitiveCount; + } + VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxPrimitiveCount); } - VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxPrimitiveCount); - } - else if (m_Desc.pBoxes != nullptr) - { - Uint32 MaxBoxCount = 0; - for (uint32_t i = 0; i < m_Desc.BoxCount; ++i) + else if (m_Desc.pBoxes != nullptr) { - auto& src = m_Desc.pBoxes[i]; - auto& dst = Geometries[i]; - - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - dst.pNext = nullptr; - dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; - dst.maxPrimitiveCount = src.MaxBoxCount; - dst.indexType = VK_INDEX_TYPE_NONE_KHR; - dst.maxVertexCount = 0; - dst.vertexFormat = VK_FORMAT_UNDEFINED; - dst.allowsTransforms = VK_FALSE; - - MaxBoxCount += dst.maxPrimitiveCount; + Uint32 MaxBoxCount = 0; + for (uint32_t i = 0; i < m_Desc.BoxCount; ++i) + { + auto& src = m_Desc.pBoxes[i]; + auto& dst = Geometries[i]; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; + dst.maxPrimitiveCount = src.MaxBoxCount; + dst.indexType = VK_INDEX_TYPE_NONE_KHR; + dst.maxVertexCount = 0; + dst.vertexFormat = VK_FORMAT_UNDEFINED; + dst.allowsTransforms = VK_FALSE; + + MaxBoxCount += dst.maxPrimitiveCount; + } + VERIFY_EXPR(MaxBoxCount <= Limits.maxPrimitiveCount); + } + else + { + UNEXPECTED("Either pTriangles or pBoxes must not be null"); } - VERIFY_EXPR(MaxBoxCount <= Limits.maxPrimitiveCount); - } - else - { - UNEXPECTED("Either pTriangles or pBoxes must not be null"); } m_VulkanBLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); @@ -132,13 +138,18 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanBLAS); - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Build = static_cast(MemReqs.size); + if (m_Desc.CompactedSize == 0) + { + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Build = static_cast(MemReqs.size); + + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Update = static_cast(MemReqs.size); + } - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Update = static_cast(MemReqs.size); + SetState(RESOURCE_STATE_BUILD_AS_READ); } BottomLevelASVkImpl::~BottomLevelASVkImpl() diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index a77fb96d..a76a901e 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -117,6 +117,8 @@ DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* p m_DummyVB = pDummyVB.RawPtr(); m_vkClearValues.reserve(16); + + CreateASCompactedSizeQueryPool(); } DeviceContextVkImpl::~DeviceContextVkImpl() @@ -592,16 +594,6 @@ void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs) if (!DvpVerifyDrawMeshArguments(Attribs)) return; -#ifdef DILIGENT_DEBUG - { - const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - const auto& MeshShaderFeats = LogicalDevice.GetEnabledExtFeatures().MeshShader; - VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); - VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount); - } -#endif - PrepareForDraw(Attribs.Flags); m_CommandBuffer.DrawMesh(Attribs.ThreadGroupCount, 0); @@ -613,13 +605,6 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib if (!DvpVerifyDrawMeshIndirectArguments(Attribs, pAttribsBuffer)) return; -#ifdef DILIGENT_DEBUG - { - const auto& MeshShaderFeats = m_pDevice->GetLogicalDevice().GetEnabledExtFeatures().MeshShader; - VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); - } -#endif - // We must prepare indirect draw attribs buffer first because state transitions must // be performed outside of render pass, and PrepareForDraw commits render pass BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode); @@ -2684,9 +2669,9 @@ void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl& DvpVerifyTLASState(TLAS, RequiredState, OperationName); } - if (RequiredState & RESOURCE_STATE_RAY_TRACING) + if (RequiredState & (RESOURCE_STATE_RAY_TRACING | RESOURCE_STATE_BUILD_AS_READ)) { - TLAS.CheckBLASVersion(); + TLAS.ValidateContent(); } #endif } @@ -2812,13 +2797,6 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) if (!TDeviceContextBase::BuildBLAS(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG - { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pBLASVk = ValidatedCast(Attribs.pBLAS); auto* pScratchVk = ValidatedCast(Attribs.pScratchBuffer); auto& BLASDesc = pBLASVk->GetDesc(); @@ -2842,9 +2820,6 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) { const auto& SrcTris = Attribs.pTriangleData[i]; Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcTris.GeometryName); - auto& vkGeo = Geometries[GeoIdx]; - auto& vkTris = vkGeo.geometry.triangles; - auto& off = Offsets[GeoIdx]; if (GeoIdx >= Geometries.size()) { @@ -2852,6 +2827,11 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) continue; } + auto& vkGeo = Geometries[GeoIdx]; + auto& vkTris = vkGeo.geometry.triangles; + auto& off = Offsets[GeoIdx]; + const auto& TriDesc = BLASDesc.pTriangles[GeoIdx]; + vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; vkGeo.pNext = nullptr; vkGeo.flags = GeometryFlagsToVkGeometryFlags(SrcTris.Flags); @@ -2859,8 +2839,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) vkTris.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; vkTris.pNext = nullptr; - auto* const pVB = ValidatedCast(SrcTris.pVertexBuffer); - vkTris.vertexFormat = TypeToVkFormat(SrcTris.VertexValueType, SrcTris.VertexComponentCount, SrcTris.VertexValueType < VT_FLOAT16); + auto* const pVB = ValidatedCast(SrcTris.pVertexBuffer); + + // vertex format in SrcTris may be undefined, so use vertex format from description + vkTris.vertexFormat = TypeToVkFormat(TriDesc.VertexValueType, TriDesc.VertexComponentCount, TriDesc.VertexValueType < VT_FLOAT16); vkTris.vertexStride = SrcTris.VertexStride; vkTris.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + SrcTris.VertexOffset; @@ -2868,10 +2850,11 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) if (SrcTris.pIndexBuffer) { - auto* const pIB = ValidatedCast(SrcTris.pIndexBuffer); - vkTris.indexType = TypeToVkIndexType(SrcTris.IndexType); + auto* const pIB = ValidatedCast(SrcTris.pIndexBuffer); + + // index type in SrcTris may be undefined, so use index type from description + vkTris.indexType = TypeToVkIndexType(TriDesc.IndexType); vkTris.indexData.deviceAddress = pIB->GetVkDeviceAddress() + SrcTris.IndexOffset; - off.primitiveCount = SrcTris.IndexCount / 3; TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); } @@ -2879,13 +2862,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) { vkTris.indexType = VK_INDEX_TYPE_NONE_KHR; vkTris.indexData.deviceAddress = 0; - off.primitiveCount = SrcTris.VertexCount / 3; } if (SrcTris.pTransformBuffer) { - VERIFY_EXPR(BLASDesc.pTriangles[GeoIdx].AllowsTransforms); - auto* const pTB = ValidatedCast(SrcTris.pTransformBuffer); vkTris.transformData.deviceAddress = pTB->GetVkDeviceAddress() + SrcTris.TransformBufferOffset; @@ -2893,10 +2873,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) } else { - VERIFY_EXPR(!BLASDesc.pTriangles[GeoIdx].AllowsTransforms); vkTris.transformData.deviceAddress = 0; } + off.primitiveCount = SrcTris.PrimitiveCount; off.firstVertex = 0; off.primitiveOffset = 0; off.transformOffset = 0; @@ -2911,9 +2891,6 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) { const auto& SrcBoxes = Attribs.pBoxData[i]; Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcBoxes.GeometryName); - auto& vkGeo = Geometries[GeoIdx]; - auto& vkAABBs = vkGeo.geometry.aabbs; - auto& off = Offsets[GeoIdx]; if (GeoIdx >= Geometries.size()) { @@ -2921,6 +2898,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) continue; } + auto& vkGeo = Geometries[GeoIdx]; + auto& vkAABBs = vkGeo.geometry.aabbs; + auto& off = Offsets[GeoIdx]; + vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; vkGeo.pNext = nullptr; vkGeo.flags = GeometryFlagsToVkGeometryFlags(SrcBoxes.Flags); @@ -2971,13 +2952,6 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) 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& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pTLASVk = ValidatedCast(Attribs.pTLAS); auto* pScratchVk = ValidatedCast(Attribs.pScratchBuffer); auto* pInstancesVk = ValidatedCast(Attribs.pInstanceBuffer); @@ -3007,7 +2981,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) std::memcpy(&vkASInst.transform, Inst.Transform.data, sizeof(vkASInst.transform)); vkASInst.instanceCustomIndex = Inst.CustomId; - vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize + vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; vkASInst.mask = Inst.Mask; vkASInst.flags = InstanceFlagsToVkGeometryInstanceFlags(Inst.Flags); vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); @@ -3058,16 +3032,13 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) if (!TDeviceContextBase::CopyBLAS(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG - { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pSrcVk = ValidatedCast(Attribs.pSrc); auto* pDstVk = ValidatedCast(Attribs.pDst); + // Dst BLAS description has specified CompactedSize, but doesn't have specified pTriangles and pBoxes. + // We should copy geometries because it required for SBT to map geometry name to hit group. + pDstVk->CopyDescription(*pSrcVk); + VkCopyAccelerationStructureInfoKHR Info = {}; Info.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; @@ -3078,8 +3049,8 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) 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); + TransitionOrVerifyBLASState(*pSrcVk, Attribs.SrcTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBLASState(*pDstVk, Attribs.DstTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); m_CommandBuffer.CopyAccelerationStructure(Info); ++m_State.NumCommands; @@ -3094,16 +3065,11 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs) if (!TDeviceContextBase::CopyTLAS(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG - { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pSrcVk = ValidatedCast(Attribs.pSrc); auto* pDstVk = ValidatedCast(Attribs.pDst); + // Instances specified in BuildTLAS command. + // We should copy instances because it required for SBT to map instance name to hit group. pDstVk->CopyInstancceData(*pSrcVk); VkCopyAccelerationStructureInfoKHR Info = {}; @@ -3116,32 +3082,111 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs) 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); + TransitionOrVerifyTLASState(*pSrcVk, Attribs.SrcTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyTLASState(*pDstVk, Attribs.DstTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); m_CommandBuffer.CopyAccelerationStructure(Info); ++m_State.NumCommands; } -void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) +void DeviceContextVkImpl::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) { - if (!TDeviceContextBase::TraceRays(Attribs, 0)) + if (!TDeviceContextBase::WriteBLASCompactedSize(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG + const Uint32 QueryIndex = 0; + auto* pBLASVk = ValidatedCast(Attribs.pBLAS); + auto* pDestBuffVk = ValidatedCast(Attribs.pDestBuffer); + + EnsureVkCmdBuffer(); + + const char* OpName = "Write AS compacted size (DeviceContextVkImpl::WriteBLASCompactedSize)"; + TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBufferState(*pDestBuffVk, Attribs.BufferTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + + m_CommandBuffer.WriteAccelerationStructuresProperties(pBLASVk->GetVkBLAS(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, m_ASQueryPool, QueryIndex); + m_CommandBuffer.CopyQueryPoolResults(m_ASQueryPool, QueryIndex, 1, pDestBuffVk->GetVkBuffer(), Attribs.DestBufferOffset, sizeof(Uint64), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + m_CommandBuffer.ResetQueryPool(m_ASQueryPool, QueryIndex, 1); + ++m_State.NumCommands; +} + +void DeviceContextVkImpl::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) +{ + if (!TDeviceContextBase::WriteTLASCompactedSize(Attribs, 0)) + return; + + const Uint32 QueryIndex = 0; + auto* pTLASVk = ValidatedCast(Attribs.pTLAS); + auto* pDestBuffVk = ValidatedCast(Attribs.pDestBuffer); + + EnsureVkCmdBuffer(); + + const char* OpName = "Write AS compacted size (DeviceContextVkImpl::WriteTLASCompactedSize)"; + TransitionOrVerifyTLASState(*pTLASVk, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBufferState(*pDestBuffVk, Attribs.BufferTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + + m_CommandBuffer.WriteAccelerationStructuresProperties(pTLASVk->GetVkTLAS(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, m_ASQueryPool, QueryIndex); + m_CommandBuffer.CopyQueryPoolResults(m_ASQueryPool, QueryIndex, 1, pDestBuffVk->GetVkBuffer(), Attribs.DestBufferOffset, sizeof(Uint64), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + m_CommandBuffer.ResetQueryPool(m_ASQueryPool, QueryIndex, 1); + ++m_State.NumCommands; +} + +void DeviceContextVkImpl::CreateASCompactedSizeQueryPool() +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing == DEVICE_FEATURE_STATE_ENABLED) { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); + const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); + VkQueryPoolCreateInfo Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + Info.queryCount = 1; + Info.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; + + m_ASQueryPool = LogicalDevice.CreateQueryPool(Info); } -#endif +} + +void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) +{ + if (!TDeviceContextBase::TraceRays(Attribs, 0)) + return; + + auto* pSBTVk = ValidatedCast(Attribs.pSBT); + IBuffer* pBuffer = nullptr; - VkStridedBufferRegionKHR RaygenShaderBindingTable = {}; - VkStridedBufferRegionKHR MissShaderBindingTable = {}; - VkStridedBufferRegionKHR HitShaderBindingTable = {}; - VkStridedBufferRegionKHR CallableShaderBindingTable = {}; + ShaderBindingTableVkImpl::BindingTable RayGenShaderRecord = {}; + ShaderBindingTableVkImpl::BindingTable MissShaderTable = {}; + ShaderBindingTableVkImpl::BindingTable HitGroupTable = {}; + ShaderBindingTableVkImpl::BindingTable CallableShaderTable = {}; - auto* pSBTVk = ValidatedCast(Attribs.pSBT); - pSBTVk->GetVkStridedBufferRegions(this, Attribs.TransitionMode, RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable); + pSBTVk->GetData(pBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable); + + auto* pBufferVk = ValidatedCast(pBuffer); + + const char* OpName = "Trace rays (DeviceContextVkImpl::TraceRays)"; + TransitionOrVerifyBufferState(*pBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + + // buffer ranges are not intersected, so we don't need to add barriers between them + if (RayGenShaderRecord.pData) + UpdateBuffer(pBuffer, RayGenShaderRecord.Offset, RayGenShaderRecord.Size, RayGenShaderRecord.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (MissShaderTable.pData) + UpdateBuffer(pBuffer, MissShaderTable.Offset, MissShaderTable.Size, MissShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (HitGroupTable.pData) + UpdateBuffer(pBuffer, HitGroupTable.Offset, HitGroupTable.Size, HitGroupTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (CallableShaderTable.pData) + UpdateBuffer(pBuffer, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + TransitionOrVerifyBufferState(*pBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_RAY_TRACING, VK_ACCESS_SHADER_READ_BIT, OpName); + + // clang-format off + VkStridedBufferRegionKHR RaygenShaderBindingTable = {pBufferVk->GetVkBuffer(), RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size }; + VkStridedBufferRegionKHR MissShaderBindingTable = {pBufferVk->GetVkBuffer(), MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size }; + VkStridedBufferRegionKHR HitShaderBindingTable = {pBufferVk->GetVkBuffer(), HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size }; + VkStridedBufferRegionKHR CallableShaderBindingTable = {pBufferVk->GetVkBuffer(), CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size}; + // clang-format on PrepareForRayTracing(); m_CommandBuffer.TraceRays(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable, diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp index 3940769f..c0228146 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp @@ -57,108 +57,4 @@ void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs) // AZ TODO } -void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(IDeviceContextVk* pContext, - RESOURCE_STATE_TRANSITION_MODE TransitionMode, - VkStridedBufferRegionKHR& RaygenShaderBindingTable, - VkStridedBufferRegionKHR& MissShaderBindingTable, - VkStridedBufferRegionKHR& HitShaderBindingTable, - VkStridedBufferRegionKHR& CallableShaderBindingTable) -{ - const auto ShaderGroupBaseAlignment = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupBaseAlignment; - - const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 { - return Align(static_cast(offset), ShaderGroupBaseAlignment); - }; - - 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()); - - // recreate buffer - if (m_pBuffer == nullptr || m_pBuffer->GetDesc().uiSizeInBytes < BufSize) - { - m_pBuffer = nullptr; - - 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 - - VkBuffer BuffHandle = m_pBuffer.RawPtr()->GetVkBuffer(); - - 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_HitGroupsRecord.size()) - { - HitShaderBindingTable.buffer = BuffHandle; - HitShaderBindingTable.offset = HitGroupOffset; - HitShaderBindingTable.size = m_HitGroupsRecord.size(); - HitShaderBindingTable.stride = m_ShaderRecordStride; - } - - if (m_CallableShadersRecord.size()) - { - CallableShaderBindingTable.buffer = BuffHandle; - CallableShaderBindingTable.offset = CallableShadersOffset; - CallableShaderBindingTable.size = m_CallableShadersRecord.size(); - CallableShaderBindingTable.stride = m_ShaderRecordStride; - } - - if (!m_Changed) - return; - - m_Changed = false; - - // update buffer data - if (m_RayGenShaderRecord.size()) - pContext->UpdateBuffer(m_pBuffer, RayGenOffset, static_cast(m_RayGenShaderRecord.size()), m_RayGenShaderRecord.data(), TransitionMode); - - if (m_MissShadersRecord.size()) - pContext->UpdateBuffer(m_pBuffer, MissShaderOffset, static_cast(m_MissShadersRecord.size()), m_MissShadersRecord.data(), TransitionMode); - - if (m_HitGroupsRecord.size()) - pContext->UpdateBuffer(m_pBuffer, HitGroupOffset, static_cast(m_HitGroupsRecord.size()), m_HitGroupsRecord.data(), TransitionMode); - - if (m_CallableShadersRecord.size()) - pContext->UpdateBuffer(m_pBuffer, CallableShadersOffset, static_cast(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) - { - VERIFY_EXPR(m_pBuffer->GetState() == RESOURCE_STATE_RAY_TRACING); - } -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 27e5ee72..0054315f 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -324,7 +324,9 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) "with IDeviceContext::TransitionResourceStates()."); } - pTLASVk->CheckBLASVersion(); +#ifdef DILIGENT_DEVELOPMENT + pTLASVk->ValidateContent(); +#endif } else { diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index f1e8b726..cab26f83 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -328,7 +328,9 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vector= 0 // + SrcImmutableSamplerInd >= 0, + Attribs.BufferStaticSize, + Attribs.BufferStride // }; } else @@ -618,7 +620,9 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende DescriptorSet, CacheOffset, SamplerInd, - vkImmutableSampler != VK_NULL_HANDLE // + vkImmutableSampler != VK_NULL_HANDLE, + Attribs.BufferStaticSize, + Attribs.BufferStride // }; } else @@ -822,6 +826,14 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* RefCntAutoPtr pBufferVk{pBuffer, IID_BufferVk}; #ifdef DILIGENT_DEVELOPMENT VerifyConstantBufferBinding(*this, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + + if (pBufferVk->GetDesc().uiSizeInBytes != BufferStaticSize) + { + std::stringstream ss; + ss << "binding buffer '" << pBufferVk->GetDesc().Name << "' size (" << pBufferVk->GetDesc().uiSizeInBytes + << ") doesn't match buffer size in shader (" << BufferStaticSize << ")"; + LOG_INFO_MESSAGE(ss.str()); + } #endif auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) { @@ -875,6 +887,13 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); } + + if (ViewDesc.ByteWidth < BufferStaticSize || (ViewDesc.ByteWidth - BufferStaticSize) % BufferStride != 0) + { + LOG_INFO_MESSAGE("binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + Name, "' in shader '", ParentResLayout.GetShaderName(), "': size mismatch, in shader buffer has static size (", + BufferStaticSize, ") and array stride (", BufferStride, "), but actual size is (", ViewDesc.ByteWidth, ")."); + } } } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp index ae10b74b..fbef736c 100644 --- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp @@ -40,23 +40,29 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, { const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); - const auto& Limits = PhysicalDevice.GetExtProperties().RayTracing; - - VERIFY_EXPR(m_Desc.MaxInstanceCount <= Limits.maxInstanceCount); + const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracing; VkAccelerationStructureCreateInfoKHR CreateInfo = {}; VkAccelerationStructureCreateGeometryTypeInfoKHR InstanceInfo = {}; - CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - CreateInfo.maxGeometryCount = 1; - CreateInfo.pGeometryInfos = &InstanceInfo; - CreateInfo.compactedSize = 0; // AZ TODO - - InstanceInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - InstanceInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - InstanceInfo.maxPrimitiveCount = m_Desc.MaxInstanceCount; + CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); + + if (m_Desc.CompactedSize > 0) + { + CreateInfo.compactedSize = m_Desc.CompactedSize; + } + else if (m_Desc.MaxInstanceCount > 0) + { + InstanceInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + InstanceInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + InstanceInfo.maxPrimitiveCount = m_Desc.MaxInstanceCount; + + VERIFY_EXPR(m_Desc.MaxInstanceCount <= RTLimits.maxInstanceCount); + CreateInfo.pGeometryInfos = &InstanceInfo; + CreateInfo.maxGeometryCount = 1; + } m_VulkanTLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); @@ -84,13 +90,18 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, auto err = LogicalDevice.BindASMemory(m_VulkanTLAS, Memory, m_MemoryAlignedOffset); CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory"); - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Build = static_cast(MemReqs.size); + if (m_Desc.CompactedSize == 0) + { + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Build = static_cast(MemReqs.size); + + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Update = static_cast(MemReqs.size); + } - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Update = static_cast(MemReqs.size); + SetState(RESOURCE_STATE_BUILD_AS_READ); } TopLevelASVkImpl::~TopLevelASVkImpl() diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index e039311b..53719439 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1241,7 +1241,7 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag) case RESOURCE_STATE_PRESENT: return 0; 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; + case RESOURCE_STATE_RAY_TRACING: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT; // for TLAS & SBT // clang-format on default: @@ -1256,7 +1256,7 @@ public: StateFlagBitPosToVkAccessFlags() { static_assert((1 << MaxFlagBitPos) == RESOURCE_STATE_MAX_BIT, "This function must be updated to handle new resource state flag"); - for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit) + for (Uint32 bit = 0; bit < FlagBitPosToVkAccessFlagsMap.size(); ++bit) { FlagBitPosToVkAccessFlagsMap[bit] = ResourceStateFlagToVkAccessFlags(static_cast(1 << bit)); } @@ -1335,7 +1335,7 @@ class VkAccessFlagBitPosToResourceState public: VkAccessFlagBitPosToResourceState() { - for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit) + for (Uint32 bit = 0; bit < FlagBitPosToResourceState.size(); ++bit) { FlagBitPosToResourceState[bit] = VkAccessFlagToResourceStates(static_cast(1 << bit)); } @@ -1680,13 +1680,14 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS VkCopyAccelerationStructureModeKHR CopyASModeToVkCopyAccelerationStructureMode(COPY_AS_MODE Mode) { - static_assert(COPY_AS_MODE_LAST == COPY_AS_MODE_CLONE, + static_assert(COPY_AS_MODE_LAST == COPY_AS_MODE_COMPACT, "Please update the switch below to handle the new copy AS mode"); switch (Mode) { // clang-format off - case COPY_AS_MODE_CLONE: return VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; + case COPY_AS_MODE_CLONE: return VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; + case COPY_AS_MODE_COMPACT: return VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; // clang-format on default: UNEXPECTED("unknown AS copy mode"); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp index 4d47ca3e..1f81c872 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp @@ -134,12 +134,12 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags case VK_ACCESS_MEMORY_WRITE_BIT: break; - // AZ TODO: comment + // Read access to acceleration structure or vertex/index/instance buffer in a build AS or trace rays operations. 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 + // Write access to acceleration structure or scratch buffer in a build AS operations. case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: Stages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; break; -- cgit v1.2.3 From 8e0218168e2f63812f658298b3571c53879a5780 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 5 Nov 2020 19:58:57 +0300 Subject: Added support for local root signature & shader record. Bug fix for ray tracing. --- .../include/DeviceContextVkImpl.hpp | 4 ++-- .../src/DeviceContextVkImpl.cpp | 11 ++++----- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 28 +++++++++++----------- .../src/PipelineStateVkImpl.cpp | 3 --- .../src/ShaderResourceCacheVk.cpp | 2 +- .../src/ShaderResourceLayoutVk.cpp | 8 +++---- .../VulkanUtilities/VulkanRayTracingKHRviaNV.cpp | 27 +++++++++++++++++++-- 7 files changed, 51 insertions(+), 32 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index 39dca08d..705057e4 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -255,10 +255,10 @@ public: virtual void DILIGENT_CALL_TYPE Flush() override final; /// Implementation of IDeviceContext::BuildBLAS() in Vulkan backend. - virtual void DILIGENT_CALL_TYPE BuildBLAS(const BLASBuildAttribs& Attribs) override final; + virtual void DILIGENT_CALL_TYPE BuildBLAS(const BuildBLASAttribs& Attribs) override final; /// Implementation of IDeviceContext::BuildTLAS() in Vulkan backend. - virtual void DILIGENT_CALL_TYPE BuildTLAS(const TLASBuildAttribs& Attribs) override final; + virtual void DILIGENT_CALL_TYPE BuildTLAS(const BuildTLASAttribs& Attribs) override final; /// Implementation of IDeviceContext::CopyBLAS() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CopyBLAS(const CopyBLASAttribs& Attribs) override final; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index a76a901e..ce9c639c 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2792,7 +2792,7 @@ void DeviceContextVkImpl::ResolveTextureSubresource(ITexture* 1, &ResolveRegion); } -void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) +void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) { if (!TDeviceContextBase::BuildBLAS(Attribs, 0)) return; @@ -2945,7 +2945,7 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) #endif } -void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) +void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) { if (!TDeviceContextBase::BuildTLAS(Attribs, 0)) return; @@ -2967,14 +2967,13 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) // copy instance data into instance buffer { - size_t Size = Attribs.InstanceCount * sizeof(VkAccelerationStructureInstanceKHR); - auto TmpSpace = m_UploadHeap.Allocate(Size, 16); - void* pMappedInstances = TmpSpace.CPUAddress; + size_t Size = Attribs.InstanceCount * sizeof(VkAccelerationStructureInstanceKHR); + auto TmpSpace = m_UploadHeap.Allocate(Size, 16); for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { const auto& Inst = Attribs.pInstances[i]; - auto& vkASInst = static_cast(pMappedInstances)[i]; + auto& vkASInst = static_cast(TmpSpace.CPUAddress)[i]; auto* const pBLASVk = ValidatedCast(Inst.pBLAS); static_assert(sizeof(vkASInst.transform) == sizeof(Inst.Transform), "size mismatch"); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index c24ed496..3840b739 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -45,19 +45,19 @@ class ResourceTypeToVkDescriptorType public: ResourceTypeToVkDescriptorType() { - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please add the corresponding decriptor type"); - m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_MAX_ENUM; // atomic counter doesn't exist in Vulkan - m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::InputAttachment] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - m_Map[SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure] = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + static_assert(Uint32{SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes} == 12, "Please add the corresponding decriptor type"); + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::UniformBuffer}] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer}] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer}] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer}] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer}] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::StorageImage}] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::SampledImage}] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::AtomicCounter}] = VK_DESCRIPTOR_TYPE_MAX_ENUM; // atomic counter doesn't exist in Vulkan + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::SeparateImage}] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::SeparateSampler}] = VK_DESCRIPTOR_TYPE_SAMPLER; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::InputAttachment}] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + m_Map[Uint32{SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure}] = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; } VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType) const @@ -66,7 +66,7 @@ public: } private: - std::array m_Map = {}; + std::array m_Map = {}; }; VkDescriptorType PipelineLayout::GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type) diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 1cac2b6f..a9dcc5cb 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -761,9 +761,6 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize(); - if (LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing == VK_FALSE) - LOG_ERROR_AND_THROW("Ray tracing is not supported by this device"); - std::vector vkShaderStages; std::vector ShaderModules; std::vector ShaderGroups; diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 0054315f..2e1039ba 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -156,7 +156,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) for (Uint32 res = 0; res < m_TotalResources; ++res) { auto& Res = pResources[res]; - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + static_assert(Uint32{SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes} == 12, "Please handle the new resource type below"); switch (Res.Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index cab26f83..7763b480 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -300,7 +300,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vectordescriptorType = PipelineLayout::GetVkDescriptorType(Res.Type); // For every resource type, try to batch as many descriptor updates as we can - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + static_assert(Uint32{SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes} == 12, "Please handle the new resource type below"); switch (Res.Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp index 5b5434d5..451a7cc2 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp @@ -55,14 +55,33 @@ constexpr VkDeviceAddress g_BufferMask = 0xF PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr; PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr; PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr; +PFN_vkAllocateMemory Origin_vkAllocateMemory = nullptr; + VKAPI_ATTR VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) { - const_cast(pCreateInfo)->usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - return Origin_vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer); + VkBufferCreateInfo CreateInfo = *pCreateInfo; + CreateInfo.usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + return Origin_vkCreateBuffer(device, &CreateInfo, pAllocator, pBuffer); +} + +VKAPI_ATTR VkResult VKAPI_PTR Wrap_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) +{ + VkMemoryAllocateInfo AllocInfo = *pAllocateInfo; + + for (auto* pNext = static_cast(const_cast(AllocInfo.pNext)); pNext;) + { + // remove VkMemoryAllocateFlagsInfo because VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is removed from buffer create info. + if (pNext->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) + pNext->pNext = pNext->pNext; + + pNext = pNext->pNext; + } + + return Origin_vkAllocateMemory(device, &AllocInfo, pAllocator, pMemory); } VKAPI_ATTR void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device, @@ -509,6 +528,8 @@ VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkCreateRayTracingPipelinesKHR(VkDevice void EnableRayTracingKHRviaNV() { + LOG_WARNING_MESSAGE("This is fallback implementation, you should use VK_KHR_ray_tracing instead"); + vkCreateAccelerationStructureKHR = &Redirect_vkCreateAccelerationStructureKHR; vkGetAccelerationStructureMemoryRequirementsKHR = &Redirect_vkGetAccelerationStructureMemoryRequirementsKHR; vkBindAccelerationStructureMemoryKHR = &Redirect_vkBindAccelerationStructureMemoryKHR; @@ -523,8 +544,10 @@ void EnableRayTracingKHRviaNV() Origin_vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressKHR; Origin_vkCreateBuffer = vkCreateBuffer; Origin_vkDestroyBuffer = vkDestroyBuffer; + Origin_vkAllocateMemory = vkAllocateMemory; vkCreateBuffer = &Wrap_vkCreateBuffer; vkDestroyBuffer = &Wrap_vkDestroyBuffer; + vkAllocateMemory = Wrap_vkAllocateMemory; vkGetBufferDeviceAddressKHR = &Wrap_vkGetBufferDeviceAddressKHR; vkGetBufferDeviceAddress = &Wrap_vkGetBufferDeviceAddressKHR; vkGetBufferDeviceAddressEXT = &Wrap_vkGetBufferDeviceAddressKHR; -- cgit v1.2.3 From 569fb5a399cdb1cb39fb10d8db1fd78ab56f6c9e Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 17:31:31 -0800 Subject: A number of minor updates/fixes --- .../include/RenderDeviceVkImpl.hpp | 23 ++++++++++------------ .../include/ShaderResourceLayoutVk.hpp | 4 ++-- .../interface/ShaderBindingTableVk.h | 4 ++++ .../src/PipelineStateVkImpl.cpp | 4 ++-- .../src/RenderDeviceVkImpl.cpp | 9 ++++++++- .../src/ShaderResourceLayoutVk.cpp | 14 ++++++------- .../src/VulkanTypeConversions.cpp | 8 ++++---- 7 files changed, 37 insertions(+), 29 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 556e3aa5..bd95d81b 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -197,22 +197,17 @@ public: IDXCompiler* GetDxCompiler() const { return m_pDxCompiler.get(); } - Uint32 GetShaderGroupHandleSize() const + struct Properties { - return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; - } - Uint32 GetMaxShaderRecordStride() const - { - return GetPhysicalDevice().GetExtProperties().RayTracing.maxShaderGroupStride; - } - Uint32 GetShaderGroupBaseAlignment() const - { - return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupBaseAlignment; - } + const Uint32 ShaderGroupHandleSize = 0; + const Uint32 MaxShaderRecordStride = 0; + const Uint32 ShaderGroupBaseAlignment = 0; + const Uint32 MaxDrawMeshTasksCount = 0; + }; - Uint32 GetMaxDrawMeshTasksCount() const + const Properties& GetProperties() const { - return GetPhysicalDevice().GetExtProperties().MeshShader.maxDrawMeshTasksCount; + return m_Properties; } private: @@ -249,6 +244,8 @@ private: VulkanDynamicMemoryManager m_DynamicMemoryManager; std::unique_ptr m_pDxCompiler; + + Properties m_Properties; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index bee3de1f..44a377fd 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -198,7 +198,7 @@ public: /* 16 */ const char* const Name; /* 24 */ const ShaderResourceLayoutVk& ParentResLayout; -#ifdef DILIGENT_DEBUG +#ifdef DILIGENT_DEVELOPMENT /* 32 */ const Uint32 BufferStaticSize; /* 36 */ const Uint32 BufferStride; #endif @@ -229,7 +229,7 @@ public: Type {_Type }, ResourceDim {_ResourceDim }, IsMS {_IsMS ? Uint8{1} : Uint8{0}}, -#ifdef DILIGENT_DEBUG +#ifdef DILIGENT_DEVELOPMENT BufferStaticSize {_BufferStaticSize}, BufferStride {_BufferStride }, #endif diff --git a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h index ee4ea3c8..10970156 100644 --- a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h @@ -46,6 +46,8 @@ static const INTERFACE_ID IID_ShaderBindingTableVk = IShaderBindingTableInclusiveMethods; \ IShaderBindingTableVkMethods ShaderBindingTableVk +#if DILIGENT_CPP_INTERFACE // Empty structs are not allwed in C + // clang-format off /// Exposes Vulkan-specific functionality of a Shader binding table object. DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable) @@ -54,6 +56,8 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable) DILIGENT_END_INTERFACE // clang-format on +#endif + #include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" #if DILIGENT_C_INTERFACE diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index a9dcc5cb..6bfd4eeb 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -758,8 +758,8 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* { try { - const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); - const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize(); + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); + const auto ShaderGroupHandleSize = pDeviceVk->GetProperties().ShaderGroupHandleSize; std::vector vkShaderStages; std::vector ShaderModules; diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 4d2c01e3..addf3440 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -159,7 +159,14 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* EngineCI.DynamicHeapSize, ~Uint64{0} }, - m_pDxCompiler{CreateDXCompiler(DXCompilerTarget::Vulkan, EngineCI.pDxCompilerPath)} + m_pDxCompiler{CreateDXCompiler(DXCompilerTarget::Vulkan, EngineCI.pDxCompilerPath)}, + m_Properties + { + m_PhysicalDevice->GetExtProperties().RayTracing.shaderGroupHandleSize, + m_PhysicalDevice->GetExtProperties().RayTracing.maxShaderGroupStride, + m_PhysicalDevice->GetExtProperties().RayTracing.shaderGroupBaseAlignment, + m_PhysicalDevice->GetExtProperties().MeshShader.maxDrawMeshTasksCount + } // clang-format on { static_assert(sizeof(VulkanDescriptorPoolSize) == sizeof(Uint32) * 11, "Please add new descriptors to m_DescriptorSetAllocator and m_DynamicDescriptorPool constructors"); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 7763b480..ba8d567a 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -827,12 +827,12 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* #ifdef DILIGENT_DEVELOPMENT VerifyConstantBufferBinding(*this, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); - if (pBufferVk->GetDesc().uiSizeInBytes != BufferStaticSize) + if (pBufferVk->GetDesc().uiSizeInBytes < BufferStaticSize) { std::stringstream ss; - ss << "binding buffer '" << pBufferVk->GetDesc().Name << "' size (" << pBufferVk->GetDesc().uiSizeInBytes - << ") doesn't match buffer size in shader (" << BufferStaticSize << ")"; - LOG_INFO_MESSAGE(ss.str()); + ss << "The size of buffer '" << pBufferVk->GetDesc().Name << "' (" << pBufferVk->GetDesc().uiSizeInBytes + << ") is not large enough for what the shader expects (" << BufferStaticSize << ")"; + LOG_ERROR_MESSAGE(ss.str()); } #endif @@ -890,9 +890,9 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* if (ViewDesc.ByteWidth < BufferStaticSize || (ViewDesc.ByteWidth - BufferStaticSize) % BufferStride != 0) { - LOG_INFO_MESSAGE("binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - Name, "' in shader '", ParentResLayout.GetShaderName(), "': size mismatch, in shader buffer has static size (", - BufferStaticSize, ") and array stride (", BufferStride, "), but actual size is (", ViewDesc.ByteWidth, ")."); + LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + Name, "' in shader '", ParentResLayout.GetShaderName(), "': static buffer size in the shader (", + BufferStaticSize, ") and array element stride (", BufferStride, ") are incompatible with the actual buffer size (", ViewDesc.ByteWidth, ")."); } } } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index 53719439..edfa7625 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1634,18 +1634,18 @@ VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureF VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags) { - static_assert(RAYTRACING_GEOMETRY_FLAGS_LAST == RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION, + static_assert(RAYTRACING_GEOMETRY_FLAGS_LAST == RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANY_HIT_INVOCATION, "Please update the switch below to handle the new ray tracing geometry flag"); VkGeometryFlagsKHR Result = 0; - while (Flags != RAYTRACING_GEOMETRY_NONE) + while (Flags != RAYTRACING_GEOMETRY_FLAG_NONE) { auto FlagBit = static_cast(1 << PlatformMisc::GetLSB(Uint32{Flags})); switch (FlagBit) { // clang-format off - case RAYTRACING_GEOMETRY_OPAQUE: Result |= VK_GEOMETRY_OPAQUE_BIT_KHR; break; - case RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION: Result |= VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR; break; + case RAYTRACING_GEOMETRY_FLAG_OPAQUE: Result |= VK_GEOMETRY_OPAQUE_BIT_KHR; break; + case RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANY_HIT_INVOCATION: Result |= VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR; break; // clang-format on default: UNEXPECTED("unknown geometry flag"); } -- cgit v1.2.3 From da9c4e570545d5306a0090662575245c11393a52 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 18:45:33 -0800 Subject: Fixed gcc/clang compiler issue --- Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index bd95d81b..8680b819 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -199,10 +199,10 @@ public: struct Properties { - const Uint32 ShaderGroupHandleSize = 0; - const Uint32 MaxShaderRecordStride = 0; - const Uint32 ShaderGroupBaseAlignment = 0; - const Uint32 MaxDrawMeshTasksCount = 0; + const Uint32 ShaderGroupHandleSize; + const Uint32 MaxShaderRecordStride; + const Uint32 ShaderGroupBaseAlignment; + const Uint32 MaxDrawMeshTasksCount; }; const Properties& GetProperties() const -- cgit v1.2.3 From db5cfe224b9ff00234b29ff097262bc7377b90c4 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 21:43:17 -0800 Subject: Refactored BufferBase --- Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp index ef6685a3..605d1363 100644 --- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp @@ -444,7 +444,7 @@ void BufferVkImpl::CreateViewInternal(const BufferViewDesc& OrigViewDesc, IBuffe VulkanUtilities::BufferViewWrapper BufferVkImpl::CreateView(struct BufferViewDesc& ViewDesc) { VulkanUtilities::BufferViewWrapper BuffView; - CorrectBufferViewDesc(ViewDesc); + ValidateAndCorrectBufferViewDesc(m_Desc, ViewDesc); if ((ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE || ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) && (m_Desc.Mode == BUFFER_MODE_FORMATTED || m_Desc.Mode == BUFFER_MODE_RAW)) { -- cgit v1.2.3 From 4de58520987882e1daa162e31cabca3f334c20a8 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 22:46:17 -0800 Subject: Refactored TextureBase --- Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp index dca627d7..0fb3dd79 100644 --- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp @@ -498,7 +498,7 @@ void TextureVkImpl::CreateViewInternal(const TextureViewDesc& ViewDesc, ITexture VERIFY(&TexViewAllocator == &m_dbgTexViewObjAllocator, "Texture view allocator does not match allocator provided during texture initialization"); auto UpdatedViewDesc = ViewDesc; - CorrectTextureViewDesc(UpdatedViewDesc); + ValidatedAndCorrectTextureViewDesc(m_Desc, UpdatedViewDesc); VulkanUtilities::ImageViewWrapper ImgView = CreateImageView(UpdatedViewDesc); auto pViewVk = NEW_RC_OBJ(TexViewAllocator, "TextureViewVkImpl instance", TextureViewVkImpl, bIsDefaultView ? this : nullptr)(GetDevice(), UpdatedViewDesc, this, std::move(ImgView), bIsDefaultView); -- cgit v1.2.3 From 44bf7cf539949a6f26862201729fce5000b493f0 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Nov 2020 20:25:14 -0800 Subject: Few minor updates to TLAS and BLAS implementations --- Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp | 4 ---- Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp | 6 +----- Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp | 10 +++++----- 3 files changed, 6 insertions(+), 14 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp index e907337d..1a4eb2c1 100644 --- a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp @@ -50,9 +50,6 @@ 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 { @@ -73,7 +70,6 @@ private: VulkanUtilities::AccelStructWrapper m_VulkanBLAS; VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; VkDeviceSize m_MemoryAlignedOffset = 0; - ScratchBufferSizes m_ScratchSize; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index 8f2b42ab..b55223df 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -51,8 +51,7 @@ public: bool bIsDeviceInternal = false); ~TopLevelASVkImpl(); - /// Implementation of ITopLevelAS::GetScratchBufferSizes() in Vulkan backend. - virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; } + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelASVk, TTopLevelASBase); /// Implementation of ITopLevelAS::GetNativeHandle() in Vulkan backend. virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final @@ -64,15 +63,12 @@ public: /// 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: VulkanUtilities::AccelStructWrapper m_VulkanTLAS; VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; VkDeviceSize m_MemoryAlignedOffset = 0; - ScratchBufferSizes m_ScratchSize; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp index cc16c9e4..092da523 100644 --- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -43,7 +43,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, const auto& Limits = PhysicalDevice.GetExtProperties().RayTracing; VkAccelerationStructureCreateInfoKHR CreateInfo = {}; - std::vector Geometries; + std::vector vkGeometries; CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; @@ -56,8 +56,8 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, else { CreateInfo.maxGeometryCount = m_Desc.TriangleCount + m_Desc.BoxCount; - Geometries.resize(CreateInfo.maxGeometryCount); - CreateInfo.pGeometryInfos = Geometries.data(); + vkGeometries.resize(CreateInfo.maxGeometryCount); + CreateInfo.pGeometryInfos = vkGeometries.data(); VERIFY_EXPR(CreateInfo.maxGeometryCount <= Limits.maxGeometryCount); @@ -68,7 +68,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i) { auto& src = m_Desc.pTriangles[i]; - auto& dst = Geometries[i]; + auto& dst = vkGeometries[i]; dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; dst.pNext = nullptr; @@ -89,7 +89,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, for (uint32_t i = 0; i < m_Desc.BoxCount; ++i) { auto& src = m_Desc.pBoxes[i]; - auto& dst = Geometries[i]; + auto& dst = vkGeometries[i]; dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; dst.pNext = nullptr; -- cgit v1.2.3 From 0f35896a60c4de02ccfc91ace18bcef4450fa4d9 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sat, 7 Nov 2020 22:34:49 +0300 Subject: Added ability to update AS. --- .../include/BottomLevelASVkImpl.hpp | 8 ++- .../include/RenderDeviceVkImpl.hpp | 12 ++++ .../include/ShaderBindingTableVkImpl.hpp | 8 +-- .../include/ShaderResourceLayoutVk.hpp | 2 + .../include/TopLevelASVkImpl.hpp | 8 ++- .../interface/RenderDeviceVk.h | 40 +++++++++++++ .../src/BottomLevelASVkImpl.cpp | 17 +++++- .../src/DeviceContextVkImpl.cpp | 56 ++++++++++++------ .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 6 +- .../src/PipelineStateVkImpl.cpp | 6 +- .../src/RenderDeviceVkImpl.cpp | 32 ++++++++++ .../src/ShaderBindingTableVkImpl.cpp | 12 ---- .../src/ShaderResourceCacheVk.cpp | 46 ++++++++++----- .../src/ShaderResourceLayoutVk.cpp | 68 ++++++++++++++++------ .../GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp | 16 ++++- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 1 - 16 files changed, 259 insertions(+), 79 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp index 1a4eb2c1..85665f2c 100644 --- a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp @@ -46,8 +46,12 @@ public: BottomLevelASVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, - const BottomLevelASDesc& Desc, - bool bIsDeviceInternal = false); + const BottomLevelASDesc& Desc); + BottomLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const BottomLevelASDesc& Desc, + RESOURCE_STATE InitialState, + VkAccelerationStructureKHR vkBLAS); ~BottomLevelASVkImpl(); /// Implementation of IBottomLevelAS::GetNativeHandle() in Vulkan backend. diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 8680b819..2aaf4c69 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -151,6 +151,18 @@ public: RESOURCE_STATE InitialState, IBuffer** ppBuffer) override final; + /// Implementation of IRenderDeviceVk::CreateBLASFromVulkanResource(). + virtual void DILIGENT_CALL_TYPE CreateBLASFromVulkanResource(VkAccelerationStructureKHR vkBLAS, + const BottomLevelASDesc& Desc, + RESOURCE_STATE InitialState, + IBottomLevelAS** ppBLAS) override final; + + /// Implementation of IRenderDeviceVk::CreateTLASFromVulkanResource(). + virtual void DILIGENT_CALL_TYPE CreateTLASFromVulkanResource(VkAccelerationStructureKHR vkTLAS, + const TopLevelASDesc& Desc, + RESOURCE_STATE InitialState, + ITopLevelAS** ppTLAS) override final; + /// Implementation of IRenderDevice::IdleGPU() in Vulkan backend. virtual void DILIGENT_CALL_TYPE IdleGPU() override final; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp index ab43ab80..6adc1677 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp @@ -34,16 +34,17 @@ #include "RenderDeviceVkImpl.hpp" #include "ShaderBindingTableVk.h" #include "ShaderBindingTableBase.hpp" +#include "TopLevelASVkImpl.hpp" #include "PipelineStateVkImpl.hpp" #include "VulkanUtilities/VulkanObjectWrappers.hpp" namespace Diligent { -class ShaderBindingTableVkImpl final : public ShaderBindingTableBase +class ShaderBindingTableVkImpl final : public ShaderBindingTableBase { public: - using TShaderBindingTableBase = ShaderBindingTableBase; + using TShaderBindingTableBase = ShaderBindingTableBase; ShaderBindingTableVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, @@ -51,9 +52,6 @@ public: bool bIsDeviceInternal = false); ~ShaderBindingTableVkImpl(); - virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override; - virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override; - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTableVk, TShaderBindingTableBase); }; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 44a377fd..97e3dead 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -396,6 +396,8 @@ public: bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; } + bool IsCompatibleWith(const ShaderResourceLayoutVk& ResLayout) const; + private: Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const { diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index b55223df..a318085e 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -47,8 +47,12 @@ public: TopLevelASVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, - const TopLevelASDesc& Desc, - bool bIsDeviceInternal = false); + const TopLevelASDesc& Desc); + TopLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const TopLevelASDesc& Desc, + RESOURCE_STATE InitialState, + VkAccelerationStructureKHR vkTLAS); ~TopLevelASVkImpl(); IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelASVk, TTopLevelASBase); diff --git a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h b/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h index dfded94f..0d566e70 100644 --- a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h @@ -112,6 +112,44 @@ DILIGENT_BEGIN_INTERFACE(IRenderDeviceVk, IRenderDevice) const BufferDesc REF BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) PURE; + + /// Creates a bottom-level AS object from native Vulkan resource + + /// \param [in] vkBLAS - Vulkan acceleration structure handle. + /// \param [in] Desc - Bottom-level AS description. + /// \param [in] InitialState - Initial BLAS state. Can be RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_BUILD_AS_READ, RESOURCE_STATE_BUILD_AS_WRITE. + /// See Diligent::RESOURCE_STATE. + /// \param [out] ppBLAS - Address of the memory location where the pointer to the + /// bottom-level AS interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. + /// \note Created bottom-level AS object does not take ownership of the Vulkan acceleration structure and will not + /// destroy it once released. The application must not destroy Vulkan acceleration structure while it is + /// in use by the engine. + VIRTUAL void METHOD(CreateBLASFromVulkanResource)(THIS_ + VkAccelerationStructureKHR vkBLAS, + const BottomLevelASDesc REF Desc, + RESOURCE_STATE InitialState, + IBottomLevelAS** ppBLAS) PURE; + + /// Creates a top-level AS object from native Vulkan resource + + /// \param [in] vkTLAS - Vulkan acceleration structure handle. + /// \param [in] Desc - Bottom-level AS description. + /// \param [in] InitialState - Initial TLAS state. Can be RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_BUILD_AS_READ, RESOURCE_STATE_BUILD_AS_WRITE, RESOURCE_STATE_RAY_TRACING. + /// See Diligent::RESOURCE_STATE. + /// \param [out] ppTLAS - Address of the memory location where the pointer to the + /// top-level AS interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. + /// \note Created top-level AS object does not take ownership of the Vulkan acceleration structure and will not + /// destroy it once released. The application must not destroy Vulkan acceleration structure while it is + /// in use by the engine. + VIRTUAL void METHOD(CreateTLASFromVulkanResource)(THIS_ + VkAccelerationStructureKHR vkTLAS, + const TopLevelASDesc REF Desc, + RESOURCE_STATE InitialState, + ITopLevelAS** ppTLAS) PURE; }; DILIGENT_END_INTERFACE @@ -129,6 +167,8 @@ DILIGENT_END_INTERFACE # define IRenderDeviceVk_IsFenceSignaled(This, ...) CALL_IFACE_METHOD(RenderDeviceVk, IsFenceSignaled, This, __VA_ARGS__) # define IRenderDeviceVk_CreateTextureFromVulkanImage(This, ...) CALL_IFACE_METHOD(RenderDeviceVk, CreateTextureFromVulkanImage, This, __VA_ARGS__) # define IRenderDeviceVk_CreateBufferFromVulkanResource(This, ...) CALL_IFACE_METHOD(RenderDeviceVk, CreateBufferFromVulkanResource, This, __VA_ARGS__) +# define IRenderDeviceVk_CreateBLASFromVulkanResource(This, ...) CALL_IFACE_METHOD(RenderDeviceVk, CreateBLASFromVulkanResource, This, __VA_ARGS__) +# define IRenderDeviceVk_CreateTLASFromVulkanResource(This, ...) CALL_IFACE_METHOD(RenderDeviceVk, CreateTLASFromVulkanResource, This, __VA_ARGS__) // clang-format on diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp index 092da523..4e23a13a 100644 --- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -34,9 +34,8 @@ namespace Diligent BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, - const BottomLevelASDesc& Desc, - bool bIsDeviceInternal) : - TBottomLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal} + const BottomLevelASDesc& Desc) : + TBottomLevelASBase{pRefCounters, pRenderDeviceVk, Desc} { const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); @@ -152,6 +151,18 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, SetState(RESOURCE_STATE_BUILD_AS_READ); } +BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const BottomLevelASDesc& Desc, + RESOURCE_STATE InitialState, + VkAccelerationStructureKHR vkBLAS) : + TBottomLevelASBase{pRefCounters, pRenderDeviceVk, Desc}, + m_VulkanBLAS{vkBLAS} +{ + SetState(InitialState); + m_DeviceAddress = pRenderDeviceVk->GetLogicalDevice().GetAccelerationStructureDeviceAddress(m_VulkanBLAS); +} + BottomLevelASVkImpl::~BottomLevelASVkImpl() { // Vk object can only be destroyed when it is no longer used by the GPU diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index ce9c639c..1b8b3e83 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2815,21 +2815,23 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) { Geometries.resize(Attribs.TriangleDataCount); Offsets.resize(Attribs.TriangleDataCount); + pBLASVk->SetActualGeometryCount(Attribs.TriangleDataCount); for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) { const auto& SrcTris = Attribs.pTriangleData[i]; - Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcTris.GeometryName); + Uint32 Idx = i; + Uint32 GeoIdx = pBLASVk->UpdateGeometryIndex(SrcTris.GeometryName, Idx, Attribs.Update); - if (GeoIdx >= Geometries.size()) + if (GeoIdx == INVALID_INDEX || Idx == INVALID_INDEX) { UNEXPECTED("Failed to find geometry by name"); continue; } - auto& vkGeo = Geometries[GeoIdx]; + auto& vkGeo = Geometries[Idx]; auto& vkTris = vkGeo.geometry.triangles; - auto& off = Offsets[GeoIdx]; + auto& off = Offsets[Idx]; const auto& TriDesc = BLASDesc.pTriangles[GeoIdx]; vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; @@ -2886,21 +2888,23 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) { Geometries.resize(Attribs.BoxDataCount); Offsets.resize(Attribs.BoxDataCount); + pBLASVk->SetActualGeometryCount(Attribs.BoxDataCount); for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) { const auto& SrcBoxes = Attribs.pBoxData[i]; - Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcBoxes.GeometryName); + Uint32 Idx = i; + Uint32 GeoIdx = pBLASVk->UpdateGeometryIndex(SrcBoxes.GeometryName, Idx, Attribs.Update); - if (GeoIdx >= Geometries.size()) + if (GeoIdx == INVALID_INDEX || Idx == INVALID_INDEX) { UNEXPECTED("Failed to find geometry by name"); continue; } - auto& vkGeo = Geometries[GeoIdx]; + auto& vkGeo = Geometries[Idx]; auto& vkAABBs = vkGeo.geometry.aabbs; - auto& off = Offsets[GeoIdx]; + auto& off = Offsets[Idx]; vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; vkGeo.pNext = nullptr; @@ -2928,8 +2932,8 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; Info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; // type must be compatible with create info Info.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(BLASDesc.Flags); // flags must be compatible with create info - Info.update = VK_FALSE; - Info.srcAccelerationStructure = VK_NULL_HANDLE; + Info.update = Attribs.Update; + Info.srcAccelerationStructure = Attribs.Update ? pBLASVk->GetVkBLAS() : VK_NULL_HANDLE; Info.dstAccelerationStructure = pBLASVk->GetVkBLAS(); Info.geometryArrayOfPointers = VK_FALSE; Info.geometryCount = static_cast(Geometries.size()); @@ -2963,7 +2967,16 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) TransitionOrVerifyTLASState(*pTLASVk, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, OpName); - pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.HitShadersPerInstance); + if (Attribs.Update) + { + if (!pTLASVk->UpdateInstances(Attribs.pInstances, Attribs.InstanceCount, Attribs.BaseContributionToHitGroupIndex, Attribs.HitShadersPerInstance, Attribs.BindingMode)) + return; + } + else + { + if (!pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.BaseContributionToHitGroupIndex, Attribs.HitShadersPerInstance, Attribs.BindingMode)) + return; + } // copy instance data into instance buffer { @@ -2973,14 +2986,22 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { const auto& Inst = Attribs.pInstances[i]; - auto& vkASInst = static_cast(TmpSpace.CPUAddress)[i]; - auto* const pBLASVk = ValidatedCast(Inst.pBLAS); + const auto InstDesc = pTLASVk->GetInstanceDesc(Inst.InstanceName); + + if (InstDesc.InstanceIndex >= Attribs.InstanceCount) + { + UNEXPECTED("Failed to find instance by name"); + return; + } + + auto& vkASInst = static_cast(TmpSpace.CPUAddress)[InstDesc.InstanceIndex]; + auto* pBLASVk = ValidatedCast(Inst.pBLAS); static_assert(sizeof(vkASInst.transform) == sizeof(Inst.Transform), "size mismatch"); std::memcpy(&vkASInst.transform, Inst.Transform.data, sizeof(vkASInst.transform)); vkASInst.instanceCustomIndex = Inst.CustomId; - vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; + vkASInst.instanceShaderBindingTableRecordOffset = InstDesc.ContributionToHitGroupIndex; vkASInst.mask = Inst.Mask; vkASInst.flags = InstanceFlagsToVkGeometryInstanceFlags(Inst.Flags); vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); @@ -3014,8 +3035,8 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) vkASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; vkASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; // type must be compatible with create info vkASBuildInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(TLASDesc.Flags); // flags must be compatible with create info - vkASBuildInfo.update = VK_FALSE; - vkASBuildInfo.srcAccelerationStructure = VK_NULL_HANDLE; + vkASBuildInfo.update = Attribs.Update; + vkASBuildInfo.srcAccelerationStructure = Attribs.Update ? pTLASVk->GetVkTLAS() : VK_NULL_HANDLE; vkASBuildInfo.dstAccelerationStructure = pTLASVk->GetVkTLAS(); vkASBuildInfo.geometryArrayOfPointers = VK_FALSE; vkASBuildInfo.geometryCount = 1; @@ -3036,7 +3057,8 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) // Dst BLAS description has specified CompactedSize, but doesn't have specified pTriangles and pBoxes. // We should copy geometries because it required for SBT to map geometry name to hit group. - pDstVk->CopyDescription(*pSrcVk); + pDstVk->CopyGeometryDescription(*pSrcVk); + pDstVk->SetActualGeometryCount(pSrcVk->GetActualGeometryCount()); VkCopyAccelerationStructureInfoKHR Info = {}; diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 189b1073..44cf52e3 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -137,8 +137,12 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E try { + Uint32 Version = VK_API_VERSION_1_0; + if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED) + Version = VK_API_VERSION_1_2; + auto Instance = VulkanUtilities::VulkanInstance::Create( - VK_API_VERSION_1_2, // AZ TODO: use 1.2 only for ray tracing, wave ops extensions + Version, EngineCI.EnableValidation, EngineCI.GlobalExtensionCount, EngineCI.ppGlobalExtensionNames, diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 6bfd4eeb..cfde6479 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -851,7 +851,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const return false; auto IsSamePipelineLayout = m_PipelineLayout.IsSameAs(pPSOVk->m_PipelineLayout); -#if 0 //def DILIGENT_DEBUG // AZ TODO +#ifdef DILIGENT_DEBUG { bool IsCompatibleShaders = true; if (GetNumShaderStages() != pPSOVk->GetNumShaderStages()) @@ -867,8 +867,8 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const break; } - const auto& Res0 = GetShaderResLayout(s).GetResources(); - const auto& Res1 = pPSOVk->GetShaderResLayout(s).GetResources(); + const auto& Res0 = GetShaderResLayout(s); + const auto& Res1 = pPSOVk->GetShaderResLayout(s); if (!Res0.IsCompatibleWith(Res1)) { IsCompatibleShaders = false; diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index addf3440..620d29e9 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -754,6 +754,22 @@ void RenderDeviceVkImpl::CreateFramebuffer(const FramebufferDesc& Desc, IFramebu }); } +void RenderDeviceVkImpl::CreateBLASFromVulkanResource(VkAccelerationStructureKHR vkBLAS, + const BottomLevelASDesc& Desc, + RESOURCE_STATE InitialState, + IBottomLevelAS** ppBLAS) +{ + CreateDeviceObject( + "BottomLevelAS", Desc, ppBLAS, + [&]() // + { + BottomLevelASVkImpl* pBottomLevelASVk(NEW_RC_OBJ(m_BLASAllocator, "BottomLevelASVkImpl instance", BottomLevelASVkImpl)(this, Desc, InitialState, vkBLAS)); + pBottomLevelASVk->QueryInterface(IID_BottomLevelAS, reinterpret_cast(ppBLAS)); + OnCreateDeviceObject(pBottomLevelASVk); + } // + ); +} + void RenderDeviceVkImpl::CreateBLAS(const BottomLevelASDesc& Desc, IBottomLevelAS** ppBLAS) { @@ -766,6 +782,22 @@ void RenderDeviceVkImpl::CreateBLAS(const BottomLevelASDesc& Desc, }); } +void RenderDeviceVkImpl::CreateTLASFromVulkanResource(VkAccelerationStructureKHR vkTLAS, + const TopLevelASDesc& Desc, + RESOURCE_STATE InitialState, + ITopLevelAS** ppTLAS) +{ + CreateDeviceObject( + "TopLevelAS", Desc, ppTLAS, + [&]() // + { + TopLevelASVkImpl* pTopLevelASVk(NEW_RC_OBJ(m_BLASAllocator, "TopLevelASVkImpl instance", TopLevelASVkImpl)(this, Desc, InitialState, vkTLAS)); + pTopLevelASVk->QueryInterface(IID_TopLevelAS, reinterpret_cast(ppTLAS)); + OnCreateDeviceObject(pTopLevelASVk); + } // + ); +} + void RenderDeviceVkImpl::CreateTLAS(const TopLevelASDesc& Desc, ITopLevelAS** ppTLAS) { diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp index c0228146..194d15f4 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp @@ -45,16 +45,4 @@ ShaderBindingTableVkImpl::~ShaderBindingTableVkImpl() { } -void ShaderBindingTableVkImpl::ResetHitGroups(Uint32 HitShadersPerInstance) -{ - // AZ TODO - - m_Changed = true; -} - -void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs) -{ - // AZ TODO -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 2e1039ba..26516695 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -166,9 +166,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) { constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_CONSTANT_BUFFER; VERIFY_EXPR((ResourceStateFlagsToVkAccessFlags(RequiredState) & VK_ACCESS_UNIFORM_READ_BIT) == VK_ACCESS_UNIFORM_READ_BIT); + const bool IsInRequiredState = pBufferVk->CheckState(RequiredState); if (VerifyOnly) { - if (!pBufferVk->CheckState(RequiredState)) + if (!IsInRequiredState) { LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -180,7 +181,10 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } else { - pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + if (!IsInRequiredState) + { + pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + } VERIFY_EXPR(pBufferVk->CheckAccessFlags(VK_ACCESS_UNIFORM_READ_BIT)); } } @@ -207,10 +211,11 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT); VERIFY_EXPR((ResourceStateFlagsToVkAccessFlags(RequiredState) & RequiredAccessFlags) == RequiredAccessFlags); #endif + const bool IsInRequiredState = pBufferVk->CheckState(RequiredState); if (VerifyOnly) { - if (!pBufferVk->CheckState(RequiredState)) + if (!IsInRequiredState) { LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -222,7 +227,12 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } else { - pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + // 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 (!IsInRequiredState || RequiredState == RESOURCE_STATE_UNORDERED_ACCESS) + { + pCtxVkImpl->TransitionBufferState(*pBufferVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + } VERIFY_EXPR(pBufferVk->CheckAccessFlags(RequiredAccessFlags)); } } @@ -265,10 +275,11 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) VERIFY_EXPR(ResourceStateToVkImageLayout(RequiredState) == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } } + const bool IsInRequiredState = pTextureVk->CheckState(RequiredState); if (VerifyOnly) { - if (!pTextureVk->CheckState(RequiredState)) + if (!IsInRequiredState) { LOG_ERROR_MESSAGE("State of texture '", pTextureVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -280,7 +291,12 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } else { - pCtxVkImpl->TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + // 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 (!IsInRequiredState || RequiredState == RESOURCE_STATE_UNORDERED_ACCESS) + { + pCtxVkImpl->TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + } } } } @@ -311,10 +327,11 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) auto* pTLASVk = Res.pObject.RawPtr(); if (pTLASVk != nullptr && pTLASVk->IsInKnownState()) { - constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING; + constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING; + const bool IsInRequiredState = pTLASVk->CheckState(RequiredState); if (VerifyOnly) { - if (!pTLASVk->CheckState(RequiredState)) + if (!IsInRequiredState) { LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ", GetResourceStateString(RequiredState), ". Actual state: ", @@ -323,15 +340,18 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state " "with IDeviceContext::TransitionResourceStates()."); } - -#ifdef DILIGENT_DEVELOPMENT - pTLASVk->ValidateContent(); -#endif } else { - pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + if (!IsInRequiredState) + { + pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + } } + +#ifdef DILIGENT_DEVELOPMENT + pTLASVk->ValidateContent(); +#endif } } break; diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index ba8d567a..f45749e2 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -374,27 +374,26 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& std::string ShadersStr; while (Stages != SHADER_TYPE_UNKNOWN) { - const auto ShaderType = Stages & static_cast(~(static_cast(Stages) - 1)); - const char* ShaderName = nullptr; + const auto ShaderType = Stages & static_cast(~(static_cast(Stages) - 1)); + String ShaderName; - // AZ TODO - /*for (const auto& StageInfo : ShaderStages) + for (const auto& StageInfo : ShaderStages) { if ((Stages & StageInfo.Type) != 0) { - ShaderName = StageInfo.pShader->GetDesc().Name; + ShaderName = GetShaderGroupName(StageInfo.Shaders); break; } - }*/ + } if (!ShadersStr.empty()) ShadersStr.append(", "); ShadersStr.append(GetShaderTypeLiteralName(ShaderType)); ShadersStr.append(" ("); - if (ShaderName) + if (ShaderName.size()) { ShadersStr.push_back('\''); - ShadersStr.append(ShaderName ? ShaderName : ""); + ShadersStr.append(ShaderName); ShadersStr.push_back('\''); } else @@ -829,10 +828,10 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* if (pBufferVk->GetDesc().uiSizeInBytes < BufferStaticSize) { - std::stringstream ss; - ss << "The size of buffer '" << pBufferVk->GetDesc().Name << "' (" << pBufferVk->GetDesc().uiSizeInBytes - << ") is not large enough for what the shader expects (" << BufferStaticSize << ")"; - LOG_ERROR_MESSAGE(ss.str()); + // It is OK if enabled robustBufferAccess feature, otherwise access outside of buffer range may lead to crash or undefined behavior. + LOG_WARNING_MESSAGE("Error binding uniform buffer '", pBufferVk->GetDesc().Name, "' to shader variable '", + Name, "' in shader '", ParentResLayout.GetShaderName(), "': buffer size in the shader (", + BufferStaticSize, ") is incompatible with the actual buffer size (", pBufferVk->GetDesc().uiSizeInBytes, ")."); } #endif @@ -888,11 +887,22 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); } - if (ViewDesc.ByteWidth < BufferStaticSize || (ViewDesc.ByteWidth - BufferStaticSize) % BufferStride != 0) + if (BufferStride == 0 && ViewDesc.ByteWidth < BufferStaticSize) { - LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - Name, "' in shader '", ParentResLayout.GetShaderName(), "': static buffer size in the shader (", - BufferStaticSize, ") and array element stride (", BufferStride, ") are incompatible with the actual buffer size (", ViewDesc.ByteWidth, ")."); + // It is OK if enabled robustBufferAccess feature, otherwise access outside of buffer range may lead to crash or undefined behavior. + LOG_WARNING_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + Name, "' in shader '", ParentResLayout.GetShaderName(), "': buffer size in the shader (", + BufferStaticSize, ") is incompatible with the actual buffer view size (", ViewDesc.ByteWidth, ")."); + } + + if (BufferStride > 0 && (ViewDesc.ByteWidth < BufferStaticSize || (ViewDesc.ByteWidth - BufferStaticSize) % BufferStride != 0)) + { + // For buffers with dynamic arrays we know only static part size and array element stride. + // Element stride in shader may be differ than in code. Here we check that buffer size is exactly match to the array with N elements. + LOG_WARNING_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + Name, "' in shader '", ParentResLayout.GetShaderName(), "': static buffer size in the shader (", + BufferStaticSize, ") and array element stride (", BufferStride, ") are incompatible with the actual buffer view size (", ViewDesc.ByteWidth, "),", + " this may be result of array element size mismatch."); } } } @@ -1117,7 +1127,7 @@ void ShaderResourceLayoutVk::VkResource::CacheAccelerationStructure(IDeviceObjec VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected"); RefCntAutoPtr pTLASVk{pTLAS, IID_TopLevelASVk}; #ifdef DILIGENT_DEVELOPMENT - // AZ TODO + VerifyTLASResourceBinding(*this, GetVariableType(), ArrayInd, pTLASVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); #endif if (UpdateCachedResource(DstRes, std::move(pTLASVk), [](const TopLevelASVkImpl*, const TopLevelASVkImpl*) {})) { @@ -1536,4 +1546,28 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& } } +bool ShaderResourceLayoutVk::IsCompatibleWith(const ShaderResourceLayoutVk& ResLayout) const +{ + if (m_NumResources != ResLayout.m_NumResources) + return false; + + bool IsCompatible = true; + for (Uint32 i = 0, Cnt = GetTotalResourceCount(); i < Cnt; ++i) + { + const auto& lhs = this->GetResource(i); + const auto& rhs = ResLayout.GetResource(i); + + // clang-format off + if (lhs.ArraySize != rhs.ArraySize || + lhs.Type != rhs.Type || + lhs.SamplerInd != rhs.SamplerInd) + // clang-format on + { + IsCompatible = false; + } + } + + return IsCompatible; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp index fbef736c..bfde3aa6 100644 --- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp @@ -34,9 +34,8 @@ namespace Diligent TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, - const TopLevelASDesc& Desc, - bool bIsDeviceInternal) : - TTopLevelASBase{pRefCounters, pRenderDeviceVk, Desc, bIsDeviceInternal} + const TopLevelASDesc& Desc) : + TTopLevelASBase{pRefCounters, pRenderDeviceVk, Desc} { const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); @@ -104,6 +103,17 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, SetState(RESOURCE_STATE_BUILD_AS_READ); } +TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const TopLevelASDesc& Desc, + RESOURCE_STATE InitialState, + VkAccelerationStructureKHR vkTLAS) : + TTopLevelASBase{pRefCounters, pRenderDeviceVk, Desc}, + m_VulkanTLAS{vkTLAS} +{ + SetState(InitialState); +} + TopLevelASVkImpl::~TopLevelASVkImpl() { // Vk object can only be destroyed when it is no longer used by the GPU diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index a80d7f73..fd81dcfb 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -189,7 +189,6 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, // Emulate KHR extension if (m_ExtFeatures.RayTracingNV) { - //m_ExtFeatures.RayTracing.rayTracingPrimitiveCulling = true; // AZ TODO m_ExtFeatures.RayTracing.rayTracing = VK_TRUE; m_ExtProperties.RayTracing.shaderGroupHandleSize = RayTracingNV.shaderGroupHandleSize; -- cgit v1.2.3 From 5888241b0f6127c82b64caebb9cb61b933ba4535 Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 9 Nov 2020 21:24:46 -0800 Subject: A bunch of minor updates --- .../include/ShaderResourceLayoutVk.hpp | 10 ++++++++++ .../GraphicsEngineVulkan/interface/RenderDeviceVk.h | 16 ++++++++-------- .../src/ShaderResourceLayoutVk.cpp | 21 +++++++-------------- 3 files changed, 25 insertions(+), 22 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 97e3dead..88885eee 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -307,6 +307,16 @@ public: return IsMS != 0; } + bool IsCompatibleWith(const VkResource& rhs) const + { + // clang-format off + return Binding == rhs.Binding && + DescriptorSet == rhs.DescriptorSet && + ArraySize == rhs.ArraySize && + Type == rhs.Type; + // clang-format on + } + private: void CacheUniformBuffer(IDeviceObject* pBuffer, ShaderResourceCacheVk::Resource& DstRes, diff --git a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h b/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h index 0d566e70..cba7f360 100644 --- a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/RenderDeviceVk.h @@ -127,10 +127,10 @@ DILIGENT_BEGIN_INTERFACE(IRenderDeviceVk, IRenderDevice) /// destroy it once released. The application must not destroy Vulkan acceleration structure while it is /// in use by the engine. VIRTUAL void METHOD(CreateBLASFromVulkanResource)(THIS_ - VkAccelerationStructureKHR vkBLAS, - const BottomLevelASDesc REF Desc, - RESOURCE_STATE InitialState, - IBottomLevelAS** ppBLAS) PURE; + VkAccelerationStructureKHR vkBLAS, + const BottomLevelASDesc REF Desc, + RESOURCE_STATE InitialState, + IBottomLevelAS** ppBLAS) PURE; /// Creates a top-level AS object from native Vulkan resource @@ -146,10 +146,10 @@ DILIGENT_BEGIN_INTERFACE(IRenderDeviceVk, IRenderDevice) /// destroy it once released. The application must not destroy Vulkan acceleration structure while it is /// in use by the engine. VIRTUAL void METHOD(CreateTLASFromVulkanResource)(THIS_ - VkAccelerationStructureKHR vkTLAS, - const TopLevelASDesc REF Desc, - RESOURCE_STATE InitialState, - ITopLevelAS** ppTLAS) PURE; + VkAccelerationStructureKHR vkTLAS, + const TopLevelASDesc REF Desc, + RESOURCE_STATE InitialState, + ITopLevelAS** ppTLAS) PURE; }; DILIGENT_END_INTERFACE diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index f45749e2..9a4caec8 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -828,7 +828,7 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* if (pBufferVk->GetDesc().uiSizeInBytes < BufferStaticSize) { - // It is OK if enabled robustBufferAccess feature, otherwise access outside of buffer range may lead to crash or undefined behavior. + // It is OK if robustBufferAccess feature is enabled, otherwise access outside of buffer range may lead to crash or undefined behavior. LOG_WARNING_MESSAGE("Error binding uniform buffer '", pBufferVk->GetDesc().Name, "' to shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "': buffer size in the shader (", BufferStaticSize, ") is incompatible with the actual buffer size (", pBufferVk->GetDesc().uiSizeInBytes, ")."); @@ -889,7 +889,7 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* if (BufferStride == 0 && ViewDesc.ByteWidth < BufferStaticSize) { - // It is OK if enabled robustBufferAccess feature, otherwise access outside of buffer range may lead to crash or undefined behavior. + // It is OK if robustBufferAccess feature is enabled, otherwise access outside of buffer range may lead to crash or undefined behavior. LOG_WARNING_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "': buffer size in the shader (", BufferStaticSize, ") is incompatible with the actual buffer view size (", ViewDesc.ByteWidth, ")."); @@ -898,11 +898,11 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* if (BufferStride > 0 && (ViewDesc.ByteWidth < BufferStaticSize || (ViewDesc.ByteWidth - BufferStaticSize) % BufferStride != 0)) { // For buffers with dynamic arrays we know only static part size and array element stride. - // Element stride in shader may be differ than in code. Here we check that buffer size is exactly match to the array with N elements. + // Element stride in the shader may be differ than in the code. Here we check that the buffer size is exactly the same as the array with N elements. LOG_WARNING_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "': static buffer size in the shader (", BufferStaticSize, ") and array element stride (", BufferStride, ") are incompatible with the actual buffer view size (", ViewDesc.ByteWidth, "),", - " this may be result of array element size mismatch."); + " this may be the result of the array element size mismatch."); } } } @@ -1551,23 +1551,16 @@ bool ShaderResourceLayoutVk::IsCompatibleWith(const ShaderResourceLayoutVk& ResL if (m_NumResources != ResLayout.m_NumResources) return false; - bool IsCompatible = true; for (Uint32 i = 0, Cnt = GetTotalResourceCount(); i < Cnt; ++i) { const auto& lhs = this->GetResource(i); const auto& rhs = ResLayout.GetResource(i); - // clang-format off - if (lhs.ArraySize != rhs.ArraySize || - lhs.Type != rhs.Type || - lhs.SamplerInd != rhs.SamplerInd) - // clang-format on - { - IsCompatible = false; - } + if (!lhs.IsCompatibleWith(rhs)) + return false; } - return IsCompatible; + return true; } } // namespace Diligent -- cgit v1.2.3 From 0f5eaa1eb5bf6cd85146a29bd988903e22084832 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 12 Nov 2020 18:19:35 +0300 Subject: fixed and improved shader binding --- Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 1b8b3e83..0dd00e6c 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2969,12 +2969,12 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) if (Attribs.Update) { - if (!pTLASVk->UpdateInstances(Attribs.pInstances, Attribs.InstanceCount, Attribs.BaseContributionToHitGroupIndex, Attribs.HitShadersPerInstance, Attribs.BindingMode)) + if (!pTLASVk->UpdateInstances(Attribs.pInstances, Attribs.InstanceCount, Attribs.BaseContributionToHitGroupIndex, Attribs.HitGroupStride, Attribs.BindingMode)) return; } else { - if (!pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.BaseContributionToHitGroupIndex, Attribs.HitShadersPerInstance, Attribs.BindingMode)) + if (!pTLASVk->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.BaseContributionToHitGroupIndex, Attribs.HitGroupStride, Attribs.BindingMode)) return; } @@ -3004,9 +3004,13 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) vkASInst.instanceShaderBindingTableRecordOffset = InstDesc.ContributionToHitGroupIndex; vkASInst.mask = Inst.Mask; vkASInst.flags = InstanceFlagsToVkGeometryInstanceFlags(Inst.Flags); - vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); + vkASInst.accelerationStructureReference = 0; - TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + if (pBLASVk) + { + vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); + TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + } } UpdateBufferRegion(pInstancesVk, Attribs.InstanceBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode); -- cgit v1.2.3 From 53572161c4ee39ff7d66b84e4a9f4979da2f8f0b Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 12 Nov 2020 18:23:43 +0300 Subject: added address alignment checks --- Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 0dd00e6c..d7a0ccb5 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2917,6 +2917,8 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) vkAABBs.stride = SrcBoxes.BoxStride; vkAABBs.data.deviceAddress = pBB->GetVkDeviceAddress() + SrcBoxes.BoxOffset; + VERIFY(vkAABBs.data.deviceAddress % 8 == 0, "AABB start address is not properly aligned"); + TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); off.firstVertex = 0; @@ -3036,6 +3038,8 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) vkASInst.arrayOfPointers = VK_FALSE; vkASInst.data.deviceAddress = pInstancesVk->GetVkDeviceAddress() + Attribs.InstanceBufferOffset; + VERIFY(vkASInst.data.deviceAddress % 16 == 0, "Instance data address is not properly aligned"); + vkASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; vkASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; // type must be compatible with create info vkASBuildInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(TLASDesc.Flags); // flags must be compatible with create info -- cgit v1.2.3 From 275afc41cf421a1a78d8d9c7e46883248689b379 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Fri, 13 Nov 2020 04:11:49 +0300 Subject: bug fix for ray tracing, fixed KHR via NV emulation. --- .../src/DeviceContextVkImpl.cpp | 8 +- .../VulkanUtilities/VulkanRayTracingKHRviaNV.cpp | 100 ++++++++++++++------- 2 files changed, 71 insertions(+), 37 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index d7a0ccb5..3b8f0293 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -3006,13 +3006,9 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) vkASInst.instanceShaderBindingTableRecordOffset = InstDesc.ContributionToHitGroupIndex; vkASInst.mask = Inst.Mask; vkASInst.flags = InstanceFlagsToVkGeometryInstanceFlags(Inst.Flags); - vkASInst.accelerationStructureReference = 0; + vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); - if (pBLASVk) - { - vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); - TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); - } + TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); } UpdateBufferRegion(pInstancesVk, Attribs.InstanceBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp index 451a7cc2..8661f5fe 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp @@ -33,8 +33,8 @@ #include #include -#include "VulkanErrors.hpp" -#include "VulkanUtilities/VulkanLogicalDevice.hpp" +#include "../../include/VulkanErrors.hpp" +#include "../../include/VulkanUtilities/VulkanLogicalDevice.hpp" namespace VulkanUtilities { @@ -46,17 +46,34 @@ static_assert(sizeof(VkDeviceAddress) == 8, "KHR is incompatible with NV extensi namespace { -std::mutex g_BufferDeviceAddressGuard; -std::unordered_map g_DeviceAddressToBuffer; -std::unordered_map g_BufferToDeviceAddress; -uint32_t g_BufferDeviceAddressCounter = 0; -constexpr VkDeviceAddress g_BufferMask = 0xFFFFFFFF00000000ull; - PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr; PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr; PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr; PFN_vkAllocateMemory Origin_vkAllocateMemory = nullptr; +struct DeviceAddressEmulator +{ + std::mutex Guard; + std::unordered_map AddrToBuffer; + std::unordered_map BufferToAddr; + uint32_t Counter = 0; + static constexpr VkDeviceAddress BufferMask = 0xFFFFFFFF00000000ull; + + static DeviceAddressEmulator* GetInstance() + { + static DeviceAddressEmulator inst; + return &inst; + } + + ~DeviceAddressEmulator() + { + vkGetBufferDeviceAddressKHR = Origin_vkGetBufferDeviceAddressKHR; + vkCreateBuffer = Origin_vkCreateBuffer; + vkDestroyBuffer = Origin_vkDestroyBuffer; + vkAllocateMemory = Origin_vkAllocateMemory; + } +}; + VKAPI_ATTR VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, @@ -72,13 +89,13 @@ VKAPI_ATTR VkResult VKAPI_PTR Wrap_vkAllocateMemory(VkDevice device, const VkMem { VkMemoryAllocateInfo AllocInfo = *pAllocateInfo; - for (auto* pNext = static_cast(const_cast(AllocInfo.pNext)); pNext;) + for (auto** ppNext = reinterpret_cast(const_cast(&AllocInfo.pNext)); *ppNext;) { // remove VkMemoryAllocateFlagsInfo because VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is removed from buffer create info. - if (pNext->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) - pNext->pNext = pNext->pNext; - - pNext = pNext->pNext; + if ((*ppNext)->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) + *ppNext = (*ppNext)->pNext; + else + ppNext = &((*ppNext)->pNext); } return Origin_vkAllocateMemory(device, &AllocInfo, pAllocator, pMemory); @@ -90,13 +107,15 @@ VKAPI_ATTR void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice dev { Origin_vkDestroyBuffer(device, buffer, pAllocator); - std::unique_lock lock{g_BufferDeviceAddressGuard}; + auto* inst = DeviceAddressEmulator::GetInstance(); + + std::unique_lock lock{inst->Guard}; - auto iter = g_BufferToDeviceAddress.find(buffer); - if (iter != g_BufferToDeviceAddress.end()) + auto iter = inst->BufferToAddr.find(buffer); + if (iter != inst->BufferToAddr.end()) { - g_DeviceAddressToBuffer.erase(iter->second); - g_BufferToDeviceAddress.erase(iter); + inst->AddrToBuffer.erase(iter->second); + inst->BufferToAddr.erase(iter); } } @@ -106,17 +125,19 @@ VKAPI_ATTR VkDeviceAddress VKAPI_CALL Wrap_vkGetBufferDeviceAddressKHR(VkDevice VERIFY_EXPR(pInfo->sType == VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR); VERIFY_EXPR(pInfo->pNext == nullptr); - std::unique_lock lock{g_BufferDeviceAddressGuard}; + auto* inst = DeviceAddressEmulator::GetInstance(); + + std::unique_lock lock{inst->Guard}; // find in existing buffers - auto iter = g_BufferToDeviceAddress.find(pInfo->buffer); - if (iter != g_BufferToDeviceAddress.end()) + auto iter = inst->BufferToAddr.find(pInfo->buffer); + if (iter != inst->BufferToAddr.end()) return iter->second; // create new device address - VkDeviceAddress Addr = VkDeviceAddress{++g_BufferDeviceAddressCounter} << 32; - g_BufferToDeviceAddress[pInfo->buffer] = Addr; - g_DeviceAddressToBuffer[Addr] = pInfo->buffer; + VkDeviceAddress Addr = VkDeviceAddress{++inst->Counter} << 32; + inst->BufferToAddr[pInfo->buffer] = Addr; + inst->AddrToBuffer[Addr] = pInfo->buffer; return Addr; } @@ -130,16 +151,18 @@ BufferAndOffset DeviceAddressToBuffer(VkDeviceAddress Addr) if (Addr == 0) return {VK_NULL_HANDLE, 0}; - std::unique_lock lock{g_BufferDeviceAddressGuard}; + auto* inst = DeviceAddressEmulator::GetInstance(); + + std::unique_lock lock{inst->Guard}; - auto iter = g_DeviceAddressToBuffer.find(Addr & g_BufferMask); - if (iter == g_DeviceAddressToBuffer.end()) + auto iter = inst->AddrToBuffer.find(Addr & DeviceAddressEmulator::BufferMask); + if (iter == inst->AddrToBuffer.end()) { UNEXPECTED("Failed to map device address to buffer"); return {VK_NULL_HANDLE, 0}; } - return {iter->second, Addr & ~g_BufferMask}; + return {iter->second, Addr & ~DeviceAddressEmulator::BufferMask}; } BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressConstKHR& Addr) @@ -173,9 +196,13 @@ VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevic if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) { - VERIFY_EXPR(pCreateInfo->maxGeometryCount == 1); + VERIFY_EXPR(pCreateInfo->maxGeometryCount == 1 || pCreateInfo->compactedSize > 0); - CreateInfo.info.instanceCount = pCreateInfo->pGeometryInfos->maxPrimitiveCount; + if (pCreateInfo->pGeometryInfos && pCreateInfo->maxGeometryCount == 1) + { + VERIFY_EXPR(pCreateInfo->pGeometryInfos->geometryType == VK_GEOMETRY_TYPE_INSTANCES_KHR); + CreateInfo.info.instanceCount = pCreateInfo->pGeometryInfos->maxPrimitiveCount; + } } else if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) { @@ -234,7 +261,7 @@ VKAPI_ATTR VkResult VKAPI_CALL Redirect_vkCreateAccelerationStructureKHR(VkDevic } CreateInfo.info.geometryCount = static_cast(Geometries.size()); - CreateInfo.info.pGeometries = Geometries.data(); + CreateInfo.info.pGeometries = CreateInfo.info.geometryCount ? Geometries.data() : nullptr; } else { @@ -423,6 +450,16 @@ VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdCopyAccelerationStructureKHR(VkCommandB vkCmdCopyAccelerationStructureNV(commandBuffer, pInfo->dst, pInfo->src, pInfo->mode); } +VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdWriteAccelerationStructuresPropertiesKHR(VkCommandBuffer commandBuffer, + uint32_t accelerationStructureCount, + const VkAccelerationStructureKHR* pAccelerationStructures, + VkQueryType queryType, + VkQueryPool queryPool, + uint32_t firstQuery) +{ + vkCmdWriteAccelerationStructuresPropertiesNV(commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); +} + VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdTraceRaysKHR(VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, @@ -536,6 +573,7 @@ void EnableRayTracingKHRviaNV() vkGetAccelerationStructureDeviceAddressKHR = &Redirect_vkGetAccelerationStructureDeviceAddressKHR; vkCmdBuildAccelerationStructureKHR = &Redirect_vkCmdBuildAccelerationStructureKHR; vkCmdCopyAccelerationStructureKHR = &Redirect_vkCmdCopyAccelerationStructureKHR; + vkCmdWriteAccelerationStructuresPropertiesKHR = &Redirect_vkCmdWriteAccelerationStructuresPropertiesKHR; vkGetRayTracingShaderGroupHandlesKHR = &Redirect_vkGetRayTracingShaderGroupHandlesKHR; vkCreateRayTracingPipelinesKHR = &Redirect_vkCreateRayTracingPipelinesKHR; vkCmdTraceRaysKHR = &Redirect_vkCmdTraceRaysKHR; -- cgit v1.2.3 From 43c3821993cb3d6ec3025fa7156da8544d2a1dac Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 16 Nov 2020 20:30:23 +0300 Subject: D3D12 resource binding refactoring, rename LinearAllocator to FixedLinearAllocator. --- .../src/PipelineStateVkImpl.cpp | 46 +++++++++++----------- .../src/ShaderResourceBindingVkImpl.cpp | 4 +- .../src/ShaderResourceLayoutVk.cpp | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index cfde6479..5609d397 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -382,16 +382,13 @@ static void CreateRayTracingPipeline(RenderDeviceVkImpl* template void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateInfo, - TNameToGroupIndexMap& NameToGroupIndex, + const TNameToGroupIndexMap& NameToGroupIndex, std::vector& ShaderGroups, - const ShaderResourceLayoutVk::TShaderStages& ShaderStages, - LinearAllocator& MemPool) + const ShaderResourceLayoutVk::TShaderStages& ShaderStages) { #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; - std::array ShaderIndices = {}; std::unordered_map UniqueShaders; @@ -429,9 +426,11 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& Group.anyHitShader = VK_SHADER_UNUSED_KHR; Group.intersectionShader = VK_SHADER_UNUSED_KHR; - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(GeneralShader.Name)}, GroupIndex++).second; - if (!IsUniqueName) - LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique"); +#ifdef DILIGENT_DEVELOPMENT + auto Iter = NameToGroupIndex.find(GeneralShader.Name); + CHECK_THROW(Iter != NameToGroupIndex.end()); + CHECK_THROW(Iter->second == ShaderGroups.size()); +#endif ShaderGroups.push_back(Group); } @@ -449,9 +448,11 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& Group.anyHitShader = ShaderToIndex(TriHitShader.pAnyHitShader); Group.intersectionShader = VK_SHADER_UNUSED_KHR; - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(TriHitShader.Name)}, GroupIndex++).second; - if (!IsUniqueName) - LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique"); +#ifdef DILIGENT_DEVELOPMENT + auto Iter = NameToGroupIndex.find(TriHitShader.Name); + CHECK_THROW(Iter != NameToGroupIndex.end()); + CHECK_THROW(Iter->second == ShaderGroups.size()); +#endif ShaderGroups.push_back(Group); } @@ -469,15 +470,15 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& Group.closestHitShader = ShaderToIndex(ProcHitShader.pClosestHitShader); Group.anyHitShader = ShaderToIndex(ProcHitShader.pAnyHitShader); - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(ProcHitShader.Name)}, GroupIndex++).second; - if (!IsUniqueName) - LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique"); +#ifdef DILIGENT_DEVELOPMENT + auto Iter = NameToGroupIndex.find(ProcHitShader.Name); + CHECK_THROW(Iter != NameToGroupIndex.end()); + CHECK_THROW(Iter->second == ShaderGroups.size()); +#endif ShaderGroups.push_back(Group); } - VERIFY_EXPR(Uint32{CreateInfo.GeneralShaderCount} + Uint32{CreateInfo.TriangleHitShaderCount} + Uint32{CreateInfo.ProceduralHitShaderCount} == GroupIndex); - #ifdef DILIGENT_DEVELOPMENT Uint32 ShaderIndex2 = 0; for (auto& Stage : ShaderStages) @@ -655,7 +656,7 @@ void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& TShaderStages ShaderStages; ExtractShaders(CreateInfo, ShaderStages); - LinearAllocator MemPool{GetRawAllocator()}; + FixedLinearAllocator MemPool{GetRawAllocator()}; const auto NumShaderStages = GetNumShaderStages(); VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); @@ -707,7 +708,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* std::vector ShaderModules; InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, - [this](const GraphicsPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // + [this](const GraphicsPipelineStateCreateInfo& CreateInfo, FixedLinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // { InitializePipelineDesc(CreateInfo, MemPool); } // @@ -735,7 +736,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p std::vector ShaderModules; InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, - [this](const ComputePipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // + [this](const ComputePipelineStateCreateInfo& CreateInfo, FixedLinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // { InitializePipelineDesc(CreateInfo, MemPool); } // @@ -766,11 +767,10 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* std::vector ShaderGroups; InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, - [&](const RayTracingPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages& ShaderStages) // + [&](const RayTracingPipelineStateCreateInfo& CreateInfo, FixedLinearAllocator& MemPool, TShaderStages& ShaderStages) // { - TNameToGroupIndexMap NameToGroupIndex; - BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool); - InitializePipelineDesc(CreateInfo, std::move(NameToGroupIndex), MemPool); + InitializePipelineDesc(CreateInfo, MemPool); + BuildRTPipelineDescription(CreateInfo, m_pRayTracingPipelineData->NameToGroupIndex, ShaderGroups, ShaderStages); } // ); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 3e4a65cf..d81fb675 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -30,7 +30,7 @@ #include "PipelineStateVkImpl.hpp" #include "ShaderVkImpl.hpp" #include "RenderDeviceVkImpl.hpp" -#include "LinearAllocator.hpp" +#include "FixedLinearAllocator.hpp" namespace Diligent { @@ -54,7 +54,7 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR m_NumShaders = static_cast(pPSO->GetNumShaderStages()); - LinearAllocator MemPool{GetRawAllocator()}; + FixedLinearAllocator MemPool{GetRawAllocator()}; MemPool.AddSpace(m_NumShaders); MemPool.Reserve(); m_pShaderVarMgrs = MemPool.ConstructArray(m_NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache)); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 9a4caec8..e2ea6cb5 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -193,7 +193,7 @@ StringPool ShaderResourceLayoutVk::AllocateMemory(const std::vector(TotalResources); MemPool.AddSpace(m_NumImmutableSamplers); -- cgit v1.2.3 From a1f696c7b63a9e93bcc7d66a5a6ad9559d799b6a Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 16 Nov 2020 21:42:21 +0300 Subject: update comments --- Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index a318085e..f9e42cab 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -61,7 +61,7 @@ public: virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final { auto Handle = GetVkTLAS(); - return reinterpret_cast(Handle); // AZ TODO: fix for 32 bit platform + return reinterpret_cast(Handle); } /// Implementation of ITopLevelASVk::GetVkTLAS(). -- cgit v1.2.3 From f833f01c4fb6174aed9f90edb1266631a444cecc Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 16 Nov 2020 23:37:39 +0300 Subject: Some fixes for PSO --- Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 5609d397..fe7aa4c6 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -428,8 +428,8 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& #ifdef DILIGENT_DEVELOPMENT auto Iter = NameToGroupIndex.find(GeneralShader.Name); - CHECK_THROW(Iter != NameToGroupIndex.end()); - CHECK_THROW(Iter->second == ShaderGroups.size()); + LOG_PSO_ERROR_AND_THROW(Iter != NameToGroupIndex.end(), "Can't find general shader '", GeneralShader.Name, "'"); + LOG_PSO_ERROR_AND_THROW(Iter->second == ShaderGroups.size(), "General shader group '", GeneralShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); #endif ShaderGroups.push_back(Group); @@ -450,8 +450,8 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& #ifdef DILIGENT_DEVELOPMENT auto Iter = NameToGroupIndex.find(TriHitShader.Name); - CHECK_THROW(Iter != NameToGroupIndex.end()); - CHECK_THROW(Iter->second == ShaderGroups.size()); + LOG_PSO_ERROR_AND_THROW(Iter != NameToGroupIndex.end(), "Can't find triangle hit group '", TriHitShader.Name, "'"); + LOG_PSO_ERROR_AND_THROW(Iter->second == ShaderGroups.size(), "Triangle hit group '", TriHitShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); #endif ShaderGroups.push_back(Group); @@ -472,8 +472,8 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& #ifdef DILIGENT_DEVELOPMENT auto Iter = NameToGroupIndex.find(ProcHitShader.Name); - CHECK_THROW(Iter != NameToGroupIndex.end()); - CHECK_THROW(Iter->second == ShaderGroups.size()); + LOG_PSO_ERROR_AND_THROW(Iter != NameToGroupIndex.end(), "Can't find procedural hit group '", ProcHitShader.Name, "'"); + LOG_PSO_ERROR_AND_THROW(Iter->second == ShaderGroups.size(), "Procedural hit group '", ProcHitShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); #endif ShaderGroups.push_back(Group); -- cgit v1.2.3 From a8d6acd496404dc5b01df997ad9d07504d6ccf1b Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 18 Nov 2020 05:01:18 +0300 Subject: Removed SWAP_CHAIN_USAGE_UNORDERED_ACCESS, fixed shader group checks --- .../src/PipelineStateVkImpl.cpp | 18 ++++++++++----- .../GraphicsEngineVulkan/src/SwapChainVkImpl.cpp | 27 ++++++---------------- 2 files changed, 19 insertions(+), 26 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index fe7aa4c6..2949c928 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -428,8 +428,10 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& #ifdef DILIGENT_DEVELOPMENT auto Iter = NameToGroupIndex.find(GeneralShader.Name); - LOG_PSO_ERROR_AND_THROW(Iter != NameToGroupIndex.end(), "Can't find general shader '", GeneralShader.Name, "'"); - LOG_PSO_ERROR_AND_THROW(Iter->second == ShaderGroups.size(), "General shader group '", GeneralShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); + if (Iter == NameToGroupIndex.end()) + LOG_PSO_ERROR_AND_THROW("Can't find general shader '", GeneralShader.Name, "'"); + if (Iter->second != ShaderGroups.size()) + LOG_PSO_ERROR_AND_THROW("General shader group '", GeneralShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); #endif ShaderGroups.push_back(Group); @@ -450,8 +452,10 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& #ifdef DILIGENT_DEVELOPMENT auto Iter = NameToGroupIndex.find(TriHitShader.Name); - LOG_PSO_ERROR_AND_THROW(Iter != NameToGroupIndex.end(), "Can't find triangle hit group '", TriHitShader.Name, "'"); - LOG_PSO_ERROR_AND_THROW(Iter->second == ShaderGroups.size(), "Triangle hit group '", TriHitShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); + if (Iter == NameToGroupIndex.end()) + LOG_PSO_ERROR_AND_THROW("Can't find triangle hit group '", TriHitShader.Name, "'"); + if (Iter->second != ShaderGroups.size()) + LOG_PSO_ERROR_AND_THROW("Triangle hit group '", TriHitShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); #endif ShaderGroups.push_back(Group); @@ -472,8 +476,10 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& #ifdef DILIGENT_DEVELOPMENT auto Iter = NameToGroupIndex.find(ProcHitShader.Name); - LOG_PSO_ERROR_AND_THROW(Iter != NameToGroupIndex.end(), "Can't find procedural hit group '", ProcHitShader.Name, "'"); - LOG_PSO_ERROR_AND_THROW(Iter->second == ShaderGroups.size(), "Procedural hit group '", ProcHitShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); + if (Iter == NameToGroupIndex.end()) + LOG_PSO_ERROR_AND_THROW("Can't find procedural hit group '", ProcHitShader.Name, "'"); + if (Iter->second != ShaderGroups.size()) + LOG_PSO_ERROR_AND_THROW("Procedural hit group '", ProcHitShader.Name, "' index mismatch: (", Iter->second, ") != (", ShaderGroups.size(), ")"); #endif ShaderGroups.push_back(Group); diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp index d32f9788..7fbe6265 100644 --- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp @@ -423,26 +423,13 @@ void SwapChainVkImpl::CreateVulkanSwapChain() swapchain_ci.imageColorSpace = ColorSpace; DEV_CHECK_ERR(m_SwapChainDesc.Usage != 0, "No swap chain usage flags defined"); - static_assert(SWAP_CHAIN_USAGE_LAST == SWAP_CHAIN_USAGE_UNORDERED_ACCESS, "Please update this function to handle the new swapchain usage"); - - { - auto SCUsage = m_SwapChainDesc.Usage; - while (SCUsage != SWAP_CHAIN_USAGE_NONE) - { - auto UsageBit = static_cast(1 << PlatformMisc::GetLSB(Uint32{SCUsage})); - switch (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; - // clang-format on - default: UNEXPECTED("unknown swapchain usage flag"); - } - SCUsage &= ~UsageBit; - } - } + static_assert(SWAP_CHAIN_USAGE_LAST == SWAP_CHAIN_USAGE_COPY_SOURCE, "Please update this function to handle the new swapchain usage"); + 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; // 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 -- cgit v1.2.3 From 96d39d3be6c2a1e94070f73c62fa85ccf86ddca8 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 25 Nov 2020 19:05:15 +0300 Subject: Added support for VK_KHR_acceleration_structure and VK_KHR_ray_tracing_pipeline --- Graphics/GraphicsEngineVulkan/CMakeLists.txt | 1 - .../include/BottomLevelASVkImpl.hpp | 1 + .../include/TopLevelASVkImpl.hpp | 5 + .../VulkanUtilities/VulkanCommandBuffer.hpp | 22 +- .../include/VulkanUtilities/VulkanHeaders.h | 4 - .../VulkanUtilities/VulkanLogicalDevice.hpp | 3 - .../VulkanUtilities/VulkanPhysicalDevice.hpp | 27 +- .../GraphicsEngineVulkan/interface/TopLevelASVk.h | 6 +- .../src/BottomLevelASVkImpl.cpp | 142 ++--- Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp | 5 +- .../src/DescriptorPoolManager.cpp | 2 +- .../src/DeviceContextVkImpl.cpp | 74 ++- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 62 +-- .../src/PipelineStateVkImpl.cpp | 31 +- .../src/RenderDeviceVkImpl.cpp | 6 +- .../GraphicsEngineVulkan/src/SwapChainVkImpl.cpp | 4 +- .../GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp | 106 ++-- .../src/VulkanUtilities/VulkanDebug.cpp | 1 - .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 38 +- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 49 +- .../VulkanUtilities/VulkanRayTracingKHRviaNV.cpp | 595 --------------------- 21 files changed, 279 insertions(+), 905 deletions(-) delete mode 100644 Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt index 48e0a5c3..e5cd319c 100644 --- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt +++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt @@ -124,7 +124,6 @@ set(VULKAN_UTILS_SRC src/VulkanUtilities/VulkanLogicalDevice.cpp src/VulkanUtilities/VulkanMemoryManager.cpp src/VulkanUtilities/VulkanPhysicalDevice.cpp - src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp ) set(GENERATE_MIPS_SHADER shaders/GenerateMipsCS.csh) diff --git a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp index 85665f2c..d67fe937 100644 --- a/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/BottomLevelASVkImpl.hpp @@ -72,6 +72,7 @@ public: private: VkDeviceAddress m_DeviceAddress = 0; VulkanUtilities::AccelStructWrapper m_VulkanBLAS; + VulkanUtilities::BufferWrapper m_VulkanBuffer; VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; VkDeviceSize m_MemoryAlignedOffset = 0; }; diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index f9e42cab..6eda1339 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -67,10 +67,15 @@ public: /// Implementation of ITopLevelASVk::GetVkTLAS(). virtual VkAccelerationStructureKHR DILIGENT_CALL_TYPE GetVkTLAS() const override { return m_VulkanTLAS; } + /// Implementation of ITopLevelASVk::GetVkDeviceAddress(). + virtual VkDeviceAddress DILIGENT_CALL_TYPE GetVkDeviceAddress() const override { return m_DeviceAddress; } + const VkAccelerationStructureKHR* GetVkTLASPtr() const { return &m_VulkanTLAS; } private: + VkDeviceAddress m_DeviceAddress = 0; VulkanUtilities::AccelStructWrapper m_VulkanTLAS; + VulkanUtilities::BufferWrapper m_VulkanBuffer; VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; VkDeviceSize m_MemoryAlignedOffset = 0; }; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp index 8a21fb17..c0d79648 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp @@ -605,9 +605,9 @@ public: dstBuffer, dstOffset, stride, flags); } - __forceinline void BuildAccelerationStructure(uint32_t infoCount, - const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, - const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos) + __forceinline void BuildAccelerationStructure(uint32_t infoCount, + const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, + const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos) { #if DILIGENT_USE_VOLK VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); @@ -616,7 +616,7 @@ public: // Build AS operations must be performed outside of render pass. EndRenderPass(); } - vkCmdBuildAccelerationStructureKHR(m_VkCmdBuffer, infoCount, pInfos, ppOffsetInfos); + vkCmdBuildAccelerationStructuresKHR(m_VkCmdBuffer, infoCount, pInfos, ppBuildRangeInfos); #else UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically"); #endif @@ -652,13 +652,13 @@ public: #endif } - __forceinline void TraceRays(const VkStridedBufferRegionKHR& RaygenShaderBindingTable, - const VkStridedBufferRegionKHR& MissShaderBindingTable, - const VkStridedBufferRegionKHR& HitShaderBindingTable, - const VkStridedBufferRegionKHR& CallableShaderBindingTable, - uint32_t width, - uint32_t height, - uint32_t depth) + __forceinline void TraceRays(const VkStridedDeviceAddressRegionKHR& RaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR& MissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR& HitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR& CallableShaderBindingTable, + uint32_t width, + uint32_t height, + uint32_t depth) { #if DILIGENT_USE_VOLK VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h index 4b352cd6..bb95a9e4 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanHeaders.h @@ -31,11 +31,7 @@ # define VK_NO_PROTOTYPES #endif -// TODO: remove when ray tracing is released -#define VK_ENABLE_BETA_EXTENSIONS - #include "vulkan/vulkan.h" -#include "vulkan/vulkan_beta.h" #define VK_FORMAT_RANGE_SIZE (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1) diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp index f68d7138..0e309eff 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp @@ -174,13 +174,10 @@ public: VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer vkBuffer) const; VkMemoryRequirements GetImageMemoryRequirements (VkImage vkImage ) const; - - VkMemoryRequirements GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const; VkDeviceAddress GetAccelerationStructureDeviceAddress(VkAccelerationStructureKHR AS) const; VkResult BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const; VkResult BindImageMemory (VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) const; - VkResult BindASMemory (VkAccelerationStructureKHR AS, VkDeviceMemory memory, VkDeviceSize memoryOffset) const; // clang-format on VkResult MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp index b76648a6..404e3eee 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp @@ -39,23 +39,24 @@ class VulkanPhysicalDevice public: struct ExtensionFeatures { - VkPhysicalDeviceMeshShaderFeaturesNV MeshShader = {}; - VkPhysicalDevice16BitStorageFeaturesKHR Storage16Bit = {}; - VkPhysicalDevice8BitStorageFeaturesKHR Storage8Bit = {}; - VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {}; - VkPhysicalDeviceRayTracingFeaturesKHR RayTracing = {}; - bool RayTracingNV = false; // indicates that KHR extension is emulated by NV extension - bool Spirv14 = false; // Ray tracing requires Vulkan 1.2 or SPIRV 1.4 extension - bool Spirv15 = false; // DXC shaders with ray tracing requires Vulkan 1.2 with SPIRV 1.5 - VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {}; - VkPhysicalDeviceDescriptorIndexingFeaturesEXT DescriptorIndexing = {}; + VkPhysicalDeviceMeshShaderFeaturesNV MeshShader = {}; + VkPhysicalDevice16BitStorageFeaturesKHR Storage16Bit = {}; + VkPhysicalDevice8BitStorageFeaturesKHR Storage8Bit = {}; + VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {}; + VkPhysicalDeviceAccelerationStructureFeaturesKHR AccelStruct = {}; + VkPhysicalDeviceRayTracingPipelineFeaturesKHR RayTracingPipeline = {}; + bool Spirv14 = false; // Ray tracing requires Vulkan 1.2 or SPIRV 1.4 extension + bool Spirv15 = false; // DXC shaders with ray tracing requires Vulkan 1.2 with SPIRV 1.5 + VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {}; + VkPhysicalDeviceDescriptorIndexingFeaturesEXT DescriptorIndexing = {}; }; struct ExtensionProperties { - VkPhysicalDeviceMeshShaderPropertiesNV MeshShader = {}; - VkPhysicalDeviceRayTracingPropertiesKHR RayTracing = {}; - VkPhysicalDeviceDescriptorIndexingPropertiesEXT DescriptorIndexing = {}; + VkPhysicalDeviceMeshShaderPropertiesNV MeshShader = {}; + VkPhysicalDeviceAccelerationStructurePropertiesKHR AccelStruct = {}; + VkPhysicalDeviceRayTracingPipelinePropertiesKHR RayTracingPipeline = {}; + VkPhysicalDeviceDescriptorIndexingPropertiesEXT DescriptorIndexing = {}; }; public: diff --git a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h index 161de182..c09f10c0 100644 --- a/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/TopLevelASVk.h @@ -50,6 +50,9 @@ 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 @@ -57,7 +60,8 @@ DILIGENT_END_INTERFACE #if DILIGENT_C_INTERFACE -# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This) +# define ITopLevelASVk_GetVkTLAS(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkTLAS, This) +# define ITopLevelASVk_GetVkDeviceAddress(This) CALL_IFACE_METHOD(TopLevelASVk, GetVkDeviceAddress, This) #endif diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp index 4e23a13a..ffe1eb02 100644 --- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -37,48 +37,44 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, const BottomLevelASDesc& Desc) : TBottomLevelASBase{pRefCounters, pRenderDeviceVk, Desc} { - const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); - const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); - const auto& Limits = PhysicalDevice.GetExtProperties().RayTracing; + const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); + const auto& Limits = PhysicalDevice.GetExtProperties().AccelStruct; + Uint32 AccelStructSize = m_Desc.CompactedSize; - VkAccelerationStructureCreateInfoKHR CreateInfo = {}; - std::vector vkGeometries; - - CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - - if (m_Desc.CompactedSize > 0) + if (AccelStructSize == 0) { - CreateInfo.compactedSize = m_Desc.CompactedSize; - } - else - { - CreateInfo.maxGeometryCount = m_Desc.TriangleCount + m_Desc.BoxCount; - vkGeometries.resize(CreateInfo.maxGeometryCount); - CreateInfo.pGeometryInfos = vkGeometries.data(); + VkAccelerationStructureBuildGeometryInfoKHR vkBuildInfo = {}; + std::vector vkGeometries; + std::vector MaxPrimitiveCounts; + VkAccelerationStructureBuildSizesInfoKHR vkSizeInfo = {VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR}; - VERIFY_EXPR(CreateInfo.maxGeometryCount <= Limits.maxGeometryCount); + vkGeometries.resize(Desc.TriangleCount + Desc.BoxCount); + MaxPrimitiveCounts.resize(vkGeometries.size()); if (m_Desc.pTriangles != nullptr) { - Uint32 MaxPrimitiveCount = 0; for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i) { auto& src = m_Desc.pTriangles[i]; auto& dst = vkGeometries[i]; - - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - dst.pNext = nullptr; - dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - dst.maxPrimitiveCount = src.MaxPrimitiveCount; - dst.indexType = TypeToVkIndexType(src.IndexType); - dst.maxVertexCount = src.MaxVertexCount; - dst.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); - dst.allowsTransforms = src.AllowsTransforms; - - MaxPrimitiveCount += dst.maxPrimitiveCount; + auto& tri = dst.geometry.triangles; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + dst.flags = VkGeometryFlagsKHR(0); + + tri.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + tri.pNext = nullptr; + tri.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); + tri.maxVertex = src.MaxVertexCount; + tri.indexType = TypeToVkIndexType(src.IndexType); + tri.transformData.deviceAddress = src.AllowsTransforms ? 1 : 0; + MaxPrimitiveCounts[i] = src.MaxPrimitiveCount; + + MaxPrimitiveCount += src.MaxPrimitiveCount; } VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxPrimitiveCount); } @@ -89,17 +85,17 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, { auto& src = m_Desc.pBoxes[i]; auto& dst = vkGeometries[i]; + auto& box = dst.geometry.aabbs; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - dst.pNext = nullptr; - dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; - dst.maxPrimitiveCount = src.MaxBoxCount; - dst.indexType = VK_INDEX_TYPE_NONE_KHR; - dst.maxVertexCount = 0; - dst.vertexFormat = VK_FORMAT_UNDEFINED; - dst.allowsTransforms = VK_FALSE; + box.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR; + box.pNext = nullptr; + MaxPrimitiveCounts[i] = src.MaxBoxCount; - MaxBoxCount += dst.maxPrimitiveCount; + MaxBoxCount += src.MaxBoxCount; } VERIFY_EXPR(MaxBoxCount <= Limits.maxPrimitiveCount); } @@ -107,46 +103,58 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, { UNEXPECTED("Either pTriangles or pBoxes must not be null"); } - } - m_VulkanBLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); + vkBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + vkBuildInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); + vkBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + vkBuildInfo.pGeometries = vkGeometries.data(); + vkBuildInfo.geometryCount = static_cast(vkGeometries.size()); - VkAccelerationStructureMemoryRequirementsInfoKHR MemInfo = {}; - VkMemoryRequirements MemReqs = {}; + VERIFY_EXPR(vkBuildInfo.geometryCount <= Limits.maxGeometryCount); - MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; - MemInfo.accelerationStructure = m_VulkanBLAS; - MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; + vkGetAccelerationStructureBuildSizesKHR(LogicalDevice.GetVkDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &vkBuildInfo, MaxPrimitiveCounts.data(), &vkSizeInfo); - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + AccelStructSize = static_cast(vkSizeInfo.accelerationStructureSize); + m_ScratchSize.Build = static_cast(vkSizeInfo.buildScratchSize); + m_ScratchSize.Update = static_cast(vkSizeInfo.updateScratchSize); + } - uint32_t MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + VkBufferCreateInfo vkBuffCI = {}; - if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex) - LOG_ERROR_AND_THROW("Failed to find suitable memory type for BLAS '", m_Desc.Name, '\''); + vkBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + vkBuffCI.flags = 0; + vkBuffCI.size = AccelStructSize; + vkBuffCI.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; + vkBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vkBuffCI.queueFamilyIndexCount = 0; + vkBuffCI.pQueueFamilyIndices = nullptr; + + m_VulkanBuffer = LogicalDevice.CreateBuffer(vkBuffCI, m_Desc.Name); + + VkMemoryRequirements MemReqs = LogicalDevice.GetBufferMemoryRequirements(m_VulkanBuffer); + uint32_t MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 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, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT); + 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, m_MemoryAlignedOffset); - CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory"); + auto err = LogicalDevice.BindBufferMemory(m_VulkanBuffer, Memory, m_MemoryAlignedOffset); + CHECK_VK_ERROR_AND_THROW(err, "Failed to bind buffer memory"); - m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanBLAS); + VkAccelerationStructureCreateInfoKHR vkAccelStrCI = {}; - if (m_Desc.CompactedSize == 0) - { - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Build = static_cast(MemReqs.size); + vkAccelStrCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + vkAccelStrCI.createFlags = 0; + vkAccelStrCI.buffer = m_VulkanBuffer; + vkAccelStrCI.offset = 0; + vkAccelStrCI.size = AccelStructSize; + vkAccelStrCI.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Update = static_cast(MemReqs.size); - } + m_VulkanBLAS = LogicalDevice.CreateAccelStruct(vkAccelStrCI, m_Desc.Name); + + m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanBLAS); SetState(RESOURCE_STATE_BUILD_AS_READ); } @@ -168,6 +176,8 @@ BottomLevelASVkImpl::~BottomLevelASVkImpl() // Vk object can only be destroyed when it is no longer used by the GPU if (m_VulkanBLAS != VK_NULL_HANDLE) m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanBLAS), m_Desc.CommandQueueMask); + if (m_VulkanBuffer != VK_NULL_HANDLE) + m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanBuffer), m_Desc.CommandQueueMask); if (m_MemoryAllocation.Page != nullptr) m_pDevice->SafeReleaseDeviceObject(std::move(m_MemoryAllocation), m_Desc.CommandQueueMask); } diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp index 605d1363..52f586b6 100644 --- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp @@ -159,7 +159,10 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters, } case BIND_RAY_TRACING: { - VkBuffCI.usage |= VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + VkBuffCI.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; // for scratch buffer + VkBuffCI.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + VkBuffCI.usage |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; // acceleration structure build inputs such as vertex, index, transform, aabb, and instance data + VkBuffCI.usage |= VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR; break; } default: diff --git a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp index 45045cea..56a83b85 100644 --- a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp @@ -67,7 +67,7 @@ static std::vector PrunePoolSizes(RenderDeviceVkImpl& Devi switch (iter->type) { case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: - if (Feats.RayTracing.rayTracing == VK_FALSE) + if (Feats.RayTracingPipeline.rayTracingPipeline == VK_FALSE) iter = PoolSizes.erase(iter); else ++iter; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index a38ed072..3cab0ae2 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2750,14 +2750,14 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); TransitionOrVerifyBufferState(*pScratchVk, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, OpName); - VkAccelerationStructureBuildGeometryInfoKHR Info = {}; - std::vector Offsets; - std::vector Geometries; + VkAccelerationStructureBuildGeometryInfoKHR vkASBuildInfo = {}; + std::vector vkRanges; + std::vector vkGeometries; if (Attribs.pTriangleData != nullptr) { - Geometries.resize(Attribs.TriangleDataCount); - Offsets.resize(Attribs.TriangleDataCount); + vkGeometries.resize(Attribs.TriangleDataCount); + vkRanges.resize(Attribs.TriangleDataCount); pBLASVk->SetActualGeometryCount(Attribs.TriangleDataCount); for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) @@ -2772,9 +2772,9 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) continue; } - auto& vkGeo = Geometries[Idx]; + auto& vkGeo = vkGeometries[Idx]; auto& vkTris = vkGeo.geometry.triangles; - auto& off = Offsets[Idx]; + auto& off = vkRanges[Idx]; const auto& TriDesc = BLASDesc.pTriangles[GeoIdx]; vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; @@ -2829,8 +2829,8 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) } else if (Attribs.pBoxData != nullptr) { - Geometries.resize(Attribs.BoxDataCount); - Offsets.resize(Attribs.BoxDataCount); + vkGeometries.resize(Attribs.BoxDataCount); + vkRanges.resize(Attribs.BoxDataCount); pBLASVk->SetActualGeometryCount(Attribs.BoxDataCount); for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) @@ -2845,9 +2845,9 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) continue; } - auto& vkGeo = Geometries[Idx]; + auto& vkGeo = vkGeometries[Idx]; auto& vkAABBs = vkGeo.geometry.aabbs; - auto& off = Offsets[Idx]; + auto& off = vkRanges[Idx]; vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; vkGeo.pNext = nullptr; @@ -2871,22 +2871,21 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) } } - VkAccelerationStructureGeometryKHR const* GeometriesPtr = Geometries.data(); - VkAccelerationStructureBuildOffsetInfoKHR const* OffsetsPtr = Offsets.data(); + VkAccelerationStructureBuildRangeInfoKHR const* VkRangePtr = vkRanges.data(); - Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; - Info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; // type must be compatible with create info - Info.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(BLASDesc.Flags); // flags must be compatible with create info - Info.update = Attribs.Update; - Info.srcAccelerationStructure = Attribs.Update ? pBLASVk->GetVkBLAS() : VK_NULL_HANDLE; - Info.dstAccelerationStructure = pBLASVk->GetVkBLAS(); - Info.geometryArrayOfPointers = VK_FALSE; - Info.geometryCount = static_cast(Geometries.size()); - Info.ppGeometries = &GeometriesPtr; - Info.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset; + vkASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + vkASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; // type must be compatible with create info + vkASBuildInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(BLASDesc.Flags); // flags must be compatible with create info + vkASBuildInfo.mode = Attribs.Update ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + vkASBuildInfo.srcAccelerationStructure = Attribs.Update ? pBLASVk->GetVkBLAS() : VK_NULL_HANDLE; + vkASBuildInfo.dstAccelerationStructure = pBLASVk->GetVkBLAS(); + vkASBuildInfo.geometryCount = static_cast(vkGeometries.size()); + vkASBuildInfo.pGeometries = vkGeometries.data(); + vkASBuildInfo.ppGeometries = nullptr; + vkASBuildInfo.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset; EnsureVkCmdBuffer(); - m_CommandBuffer.BuildAccelerationStructure(1, &Info, &OffsetsPtr); + m_CommandBuffer.BuildAccelerationStructure(1, &vkASBuildInfo, &VkRangePtr); ++m_State.NumCommands; #ifdef DILIGENT_DEVELOPMENT @@ -2958,13 +2957,12 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) } TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); - VkAccelerationStructureBuildGeometryInfoKHR vkASBuildInfo = {}; - VkAccelerationStructureBuildOffsetInfoKHR vkASBuildOffset = {}; - VkAccelerationStructureBuildOffsetInfoKHR const* vkASBuildOffsetPtr = &vkASBuildOffset; - VkAccelerationStructureGeometryKHR vkASGeometry = {}; - VkAccelerationStructureGeometryKHR const* vkASGeometriesPtr = &vkASGeometry; + VkAccelerationStructureBuildGeometryInfoKHR vkASBuildInfo = {}; + VkAccelerationStructureBuildRangeInfoKHR vkRange = {}; + VkAccelerationStructureBuildRangeInfoKHR const* vkRangePtr = &vkRange; + VkAccelerationStructureGeometryKHR vkASGeometry = {}; - vkASBuildOffset.primitiveCount = Attribs.InstanceCount; + vkRange.primitiveCount = Attribs.InstanceCount; vkASGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; vkASGeometry.pNext = nullptr; @@ -2982,15 +2980,15 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) vkASBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; vkASBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; // type must be compatible with create info vkASBuildInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(TLASDesc.Flags); // flags must be compatible with create info - vkASBuildInfo.update = Attribs.Update; + vkASBuildInfo.mode = Attribs.Update ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; vkASBuildInfo.srcAccelerationStructure = Attribs.Update ? pTLASVk->GetVkTLAS() : VK_NULL_HANDLE; vkASBuildInfo.dstAccelerationStructure = pTLASVk->GetVkTLAS(); - vkASBuildInfo.geometryArrayOfPointers = VK_FALSE; vkASBuildInfo.geometryCount = 1; - vkASBuildInfo.ppGeometries = &vkASGeometriesPtr; + vkASBuildInfo.pGeometries = &vkASGeometry; + vkASBuildInfo.ppGeometries = nullptr; vkASBuildInfo.scratchData.deviceAddress = pScratchVk->GetVkDeviceAddress() + Attribs.ScratchBufferOffset; - m_CommandBuffer.BuildAccelerationStructure(1, &vkASBuildInfo, &vkASBuildOffsetPtr); + m_CommandBuffer.BuildAccelerationStructure(1, &vkASBuildInfo, &vkRangePtr); ++m_State.NumCommands; } @@ -3150,10 +3148,10 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) TransitionOrVerifyBufferState(*pBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_RAY_TRACING, VK_ACCESS_SHADER_READ_BIT, OpName); // clang-format off - VkStridedBufferRegionKHR RaygenShaderBindingTable = {pBufferVk->GetVkBuffer(), RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size }; - VkStridedBufferRegionKHR MissShaderBindingTable = {pBufferVk->GetVkBuffer(), MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size }; - VkStridedBufferRegionKHR HitShaderBindingTable = {pBufferVk->GetVkBuffer(), HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size }; - VkStridedBufferRegionKHR CallableShaderBindingTable = {pBufferVk->GetVkBuffer(), CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size}; + VkStridedDeviceAddressRegionKHR RaygenShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size }; + VkStridedDeviceAddressRegionKHR MissShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size }; + VkStridedDeviceAddressRegionKHR HitShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size }; + VkStridedDeviceAddressRegionKHR CallableShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size}; // clang-format on PrepareForRayTracing(); diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 705cdede..93fb9f34 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -278,7 +278,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); // clang-format on - ENABLE_FEATURE((DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE && DeviceExtFeatures.Spirv14) || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); + ENABLE_FEATURE(DeviceExtFeatures.AccelStruct.accelerationStructure != VK_FALSE && DeviceExtFeatures.RayTracingPipeline.rayTracingPipeline != VK_FALSE, RayTracing, "Ray tracing is"); #undef FeatureSupport @@ -405,40 +405,36 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // Ray tracing if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED) { - if (DeviceExtFeatures.RayTracingNV) + // this extensions added to Vulkan 1.2 core + if (!DeviceExtFeatures.Spirv15) { - EnabledExtFeats.RayTracingNV = DeviceExtFeatures.RayTracingNV; - DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME); - } - else if (DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE) - { - DeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // required for VK_EXT_descriptor_indexing - DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); // required for VK_KHR_ray_tracing - DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); // required for VK_KHR_ray_tracing - DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); // required for VK_KHR_ray_tracing - DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // required for VK_KHR_ray_tracing - DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); // required for VK_KHR_ray_tracing - DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME); // required for VK_KHR_ray_tracing - - EnabledExtFeats.RayTracing = DeviceExtFeatures.RayTracing; - EnabledExtFeats.BufferDeviceAddress = DeviceExtFeatures.BufferDeviceAddress; - EnabledExtFeats.DescriptorIndexing = DeviceExtFeatures.DescriptorIndexing; - - if (!DeviceExtFeatures.Spirv15) - { - DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); // required for VK_KHR_spirv_1_4 - DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for ray tracing shaders - EnabledExtFeats.Spirv14 = DeviceExtFeatures.Spirv14; - } - - *NextExt = &EnabledExtFeats.RayTracing; - NextExt = &EnabledExtFeats.RayTracing.pNext; - *NextExt = &EnabledExtFeats.DescriptorIndexing; - NextExt = &EnabledExtFeats.DescriptorIndexing.pNext; - *NextExt = &EnabledExtFeats.BufferDeviceAddress; - NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext; + DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); // required for VK_KHR_spirv_1_4 + DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for VK_KHR_ray_tracing_pipeline + EnabledExtFeats.Spirv14 = DeviceExtFeatures.Spirv14; + VERIFY_EXPR(DeviceExtFeatures.Spirv14); } + + DeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // required for VK_EXT_descriptor_indexing + DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); // required for VK_KHR_acceleration_structure + DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); // required for VK_KHR_acceleration_structure + DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // required for VK_KHR_acceleration_structure + DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); // required for VK_KHR_ray_tracing_pipeline + DeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); // required for ray tracing + DeviceExtensions.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); // required for ray tracing + + EnabledExtFeats.AccelStruct = DeviceExtFeatures.AccelStruct; + EnabledExtFeats.RayTracingPipeline = DeviceExtFeatures.RayTracingPipeline; + EnabledExtFeats.BufferDeviceAddress = DeviceExtFeatures.BufferDeviceAddress; + EnabledExtFeats.DescriptorIndexing = DeviceExtFeatures.DescriptorIndexing; + + *NextExt = &EnabledExtFeats.AccelStruct; + NextExt = &EnabledExtFeats.AccelStruct.pNext; + *NextExt = &EnabledExtFeats.RayTracingPipeline; + NextExt = &EnabledExtFeats.RayTracingPipeline.pNext; + *NextExt = &EnabledExtFeats.DescriptorIndexing; + NextExt = &EnabledExtFeats.DescriptorIndexing.pNext; + *NextExt = &EnabledExtFeats.BufferDeviceAddress; + NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext; } // make sure that last pNext is null diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 2949c928..00bb54d9 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -348,10 +348,10 @@ static void CreateRayTracingPipeline(RenderDeviceVkImpl* { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); - const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracing; + const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracingPipeline; - DEV_CHECK_ERR(RayTracingPipeline.MaxRecursionDepth <= RTLimits.maxRecursionDepth, - "RayTracingPipeline.MaxRecursionDepth must not exceed ", RTLimits.maxRecursionDepth); + DEV_CHECK_ERR(RayTracingPipeline.MaxRecursionDepth <= RTLimits.maxRayRecursionDepth, + "RayTracingPipeline.MaxRecursionDepth must not exceed ", RTLimits.maxRayRecursionDepth); VkRayTracingPipelineCreateInfoKHR PipelineCI = {}; @@ -361,20 +361,17 @@ static void CreateRayTracingPipeline(RenderDeviceVkImpl* PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; #endif - PipelineCI.stageCount = static_cast(Stages.size()); - PipelineCI.pStages = Stages.data(); - PipelineCI.layout = Layout.GetVkPipelineLayout(); - - PipelineCI.groupCount = static_cast(ShaderGroups.size()); - PipelineCI.pGroups = ShaderGroups.data(); - PipelineCI.maxRecursionDepth = RayTracingPipeline.MaxRecursionDepth; - PipelineCI.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; - PipelineCI.libraries.pNext = nullptr; - PipelineCI.libraries.libraryCount = 0; - PipelineCI.libraries.pLibraries = nullptr; - PipelineCI.pLibraryInterface = nullptr; - PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from - PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from + PipelineCI.stageCount = static_cast(Stages.size()); + PipelineCI.pStages = Stages.data(); + PipelineCI.groupCount = static_cast(ShaderGroups.size()); + PipelineCI.pGroups = ShaderGroups.data(); + PipelineCI.maxPipelineRayRecursionDepth = RayTracingPipeline.MaxRecursionDepth; + PipelineCI.pLibraryInfo = nullptr; + PipelineCI.pLibraryInterface = nullptr; + PipelineCI.pDynamicState = nullptr; + PipelineCI.layout = Layout.GetVkPipelineLayout(); + PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from + PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from Pipeline = LogicalDevice.CreateRayTracingPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); } diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 620d29e9..c44d5642 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -162,9 +162,9 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* m_pDxCompiler{CreateDXCompiler(DXCompilerTarget::Vulkan, EngineCI.pDxCompilerPath)}, m_Properties { - m_PhysicalDevice->GetExtProperties().RayTracing.shaderGroupHandleSize, - m_PhysicalDevice->GetExtProperties().RayTracing.maxShaderGroupStride, - m_PhysicalDevice->GetExtProperties().RayTracing.shaderGroupBaseAlignment, + m_PhysicalDevice->GetExtProperties().RayTracingPipeline.shaderGroupHandleSize, + m_PhysicalDevice->GetExtProperties().RayTracingPipeline.maxShaderGroupStride, + m_PhysicalDevice->GetExtProperties().RayTracingPipeline.shaderGroupBaseAlignment, m_PhysicalDevice->GetExtProperties().MeshShader.maxDrawMeshTasksCount } // clang-format on diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp index 7fbe6265..b5f7e041 100644 --- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp @@ -642,8 +642,8 @@ VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk) { // 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); + // Swapchain image may be used as render target or as destination for copy command. + pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT); if (!m_SwapChainImagesInitialized[m_BackBufferIndex]) { // Vulkan validation layers do not like uninitialized memory. diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp index bfde3aa6..d4c771ec 100644 --- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp @@ -37,68 +37,75 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, const TopLevelASDesc& Desc) : TTopLevelASBase{pRefCounters, pRenderDeviceVk, Desc} { - const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); - const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); - const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracing; + const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); + const auto& Limits = PhysicalDevice.GetExtProperties().AccelStruct; + Uint32 AccelStructSize = m_Desc.CompactedSize; - VkAccelerationStructureCreateInfoKHR CreateInfo = {}; - VkAccelerationStructureCreateGeometryTypeInfoKHR InstanceInfo = {}; - - CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - - if (m_Desc.CompactedSize > 0) + if (AccelStructSize == 0) { - CreateInfo.compactedSize = m_Desc.CompactedSize; + VkAccelerationStructureBuildGeometryInfoKHR vkBuildInfo = {}; + VkAccelerationStructureBuildSizesInfoKHR vkSizeInfo = {VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR}; + VkAccelerationStructureGeometryKHR vkGeometry = {}; + VkAccelerationStructureGeometryInstancesDataKHR& vkInstances = vkGeometry.geometry.instances; + const uint32_t MaxPrimitiveCount = m_Desc.MaxInstanceCount; + + vkGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + vkGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + vkInstances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + vkInstances.arrayOfPointers = VK_FALSE; + + vkBuildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + vkBuildInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); + vkBuildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + vkBuildInfo.pGeometries = &vkGeometry; + vkBuildInfo.geometryCount = 1; + + VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxInstanceCount); + + vkGetAccelerationStructureBuildSizesKHR(LogicalDevice.GetVkDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &vkBuildInfo, &MaxPrimitiveCount, &vkSizeInfo); + + AccelStructSize = static_cast(vkSizeInfo.accelerationStructureSize); + m_ScratchSize.Build = static_cast(vkSizeInfo.buildScratchSize); + m_ScratchSize.Update = static_cast(vkSizeInfo.updateScratchSize); } - else if (m_Desc.MaxInstanceCount > 0) - { - InstanceInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - InstanceInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - InstanceInfo.maxPrimitiveCount = m_Desc.MaxInstanceCount; - - VERIFY_EXPR(m_Desc.MaxInstanceCount <= RTLimits.maxInstanceCount); - CreateInfo.pGeometryInfos = &InstanceInfo; - CreateInfo.maxGeometryCount = 1; - } - - m_VulkanTLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); - - VkAccelerationStructureMemoryRequirementsInfoKHR MemInfo = {}; - VkMemoryRequirements MemReqs = {}; - MemInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; - MemInfo.accelerationStructure = m_VulkanTLAS; - MemInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; + VkBufferCreateInfo vkBuffCI = {}; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + vkBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + vkBuffCI.flags = 0; + vkBuffCI.size = AccelStructSize; + vkBuffCI.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; + vkBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vkBuffCI.queueFamilyIndexCount = 0; + vkBuffCI.pQueueFamilyIndices = nullptr; - uint32_t MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + m_VulkanBuffer = LogicalDevice.CreateBuffer(vkBuffCI, m_Desc.Name); - if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex) - LOG_ERROR_AND_THROW("Failed to find suitable memory type for TLAS '", m_Desc.Name, '\''); + VkMemoryRequirements MemReqs = LogicalDevice.GetBufferMemoryRequirements(m_VulkanBuffer); + uint32_t MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 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, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT); + 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, m_MemoryAlignedOffset); - CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory"); + auto err = LogicalDevice.BindBufferMemory(m_VulkanBuffer, Memory, m_MemoryAlignedOffset); + CHECK_VK_ERROR_AND_THROW(err, "Failed to bind buffer memory"); - if (m_Desc.CompactedSize == 0) - { - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Build = static_cast(MemReqs.size); + VkAccelerationStructureCreateInfoKHR vkAccelStrCI = {}; - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Update = static_cast(MemReqs.size); - } + vkAccelStrCI.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + vkAccelStrCI.createFlags = 0; + vkAccelStrCI.buffer = m_VulkanBuffer; + vkAccelStrCI.offset = 0; + vkAccelStrCI.size = AccelStructSize; + vkAccelStrCI.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + + m_VulkanTLAS = LogicalDevice.CreateAccelStruct(vkAccelStrCI, m_Desc.Name); + + m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanTLAS); SetState(RESOURCE_STATE_BUILD_AS_READ); } @@ -112,6 +119,7 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, m_VulkanTLAS{vkTLAS} { SetState(InitialState); + m_DeviceAddress = pRenderDeviceVk->GetLogicalDevice().GetAccelerationStructureDeviceAddress(m_VulkanTLAS); } TopLevelASVkImpl::~TopLevelASVkImpl() @@ -119,6 +127,8 @@ TopLevelASVkImpl::~TopLevelASVkImpl() // Vk object can only be destroyed when it is no longer used by the GPU if (m_VulkanTLAS != VK_NULL_HANDLE) m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanTLAS), m_Desc.CommandQueueMask); + if (m_VulkanBuffer != VK_NULL_HANDLE) + m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanBuffer), m_Desc.CommandQueueMask); if (m_MemoryAllocation.Page != nullptr) m_pDevice->SafeReleaseDeviceObject(std::move(m_MemoryAllocation), m_Desc.CommandQueueMask); } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp index ae1d3f11..c1c20d79 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp @@ -574,7 +574,6 @@ const char* VkResultToString(VkResult errorCode) STR(ERROR_INVALID_EXTERNAL_HANDLE); STR(ERROR_FRAGMENTATION); STR(ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS); - STR(ERROR_INCOMPATIBLE_VERSION_KHR); STR(ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT); STR(ERROR_NOT_PERMITTED_EXT); STR(ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index 7639c309..70bdd20a 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -63,9 +63,6 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe // Since we only use one device at this time, load device function entries // https://github.com/zeux/volk#optimizing-device-calls volkLoadDevice(m_VkDevice); - - if (m_EnabledExtFeatures.RayTracingNV) - EnableRayTracingKHRviaNV(); #endif m_EnabledShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; @@ -75,7 +72,7 @@ VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDe 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) + if (m_EnabledExtFeatures.RayTracingPipeline.rayTracingPipeline != VK_FALSE) m_EnabledShaderStages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; } @@ -242,7 +239,7 @@ PipelineWrapper VulkanLogicalDevice::CreateRayTracingPipeline(const VkRayTracing VkPipeline vkPipeline = VK_NULL_HANDLE; - auto err = vkCreateRayTracingPipelinesKHR(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline); + auto err = vkCreateRayTracingPipelinesKHR(m_VkDevice, VK_NULL_HANDLE, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline); CHECK_VK_ERROR_AND_THROW(err, "Failed to create ray tracing pipeline '", DebugName, '\''); if (*DebugName != 0) @@ -482,18 +479,6 @@ VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkI return MemReqs; } -VkMemoryRequirements VulkanLogicalDevice::GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const -{ - VkMemoryRequirements2 MemReqs = {}; - MemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; -#if DILIGENT_USE_VOLK - vkGetAccelerationStructureMemoryRequirementsKHR(m_VkDevice, &Info, &MemReqs); -#else - UNSUPPORTED("vkGetAccelerationStructureMemoryRequirementsKHR is only available through Volk"); -#endif - return MemReqs.memoryRequirements; -} - VkResult VulkanLogicalDevice::BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const { return vkBindBufferMemory(m_VkDevice, buffer, memory, memoryOffset); @@ -504,25 +489,6 @@ VkResult VulkanLogicalDevice::BindImageMemory(VkImage image, VkDeviceMemory memo return vkBindImageMemory(m_VkDevice, image, memory, memoryOffset); } -VkResult VulkanLogicalDevice::BindASMemory(VkAccelerationStructureKHR AS, VkDeviceMemory memory, VkDeviceSize memoryOffset) const -{ -#if DILIGENT_USE_VOLK - VkBindAccelerationStructureMemoryInfoKHR Info = {}; - - Info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; - Info.memory = memory; - Info.memoryOffset = memoryOffset; - Info.deviceIndexCount = 0; - Info.pDeviceIndices = nullptr; - Info.accelerationStructure = AS; - - return vkBindAccelerationStructureMemoryKHR(m_VkDevice, 1, &Info); -#else - UNSUPPORTED("vkBindAccelerationStructureMemoryKHR is only available through Volk"); - return VK_ERROR_FEATURE_NOT_PRESENT; -#endif -} - VkDeviceAddress VulkanLogicalDevice::GetAccelerationStructureDeviceAddress(VkAccelerationStructureKHR AS) const { #if DILIGENT_USE_VOLK diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index fd81dcfb..61f9f8de 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -71,8 +71,6 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, #if DILIGENT_USE_VOLK if (Instance.IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { - VkPhysicalDeviceRayTracingPropertiesNV RayTracingNV = {}; - VkPhysicalDeviceFeatures2 Feats2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; void** NextFeat = &Feats2.pNext; @@ -120,27 +118,32 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.MeshShader.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV; } - // Get ray tracing features and properties. - if (IsExtensionSupported(VK_KHR_RAY_TRACING_EXTENSION_NAME)) + // Get acceleration structure features and properties. + if (IsExtensionSupported(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) { - *NextFeat = &m_ExtFeatures.RayTracing; - NextFeat = &m_ExtFeatures.RayTracing.pNext; + *NextFeat = &m_ExtFeatures.AccelStruct; + NextFeat = &m_ExtFeatures.AccelStruct.pNext; - m_ExtFeatures.RayTracing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR; + m_ExtFeatures.AccelStruct.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR; - *NextProp = &m_ExtProperties.RayTracing; - NextProp = &m_ExtProperties.RayTracing.pNext; + *NextProp = &m_ExtProperties.AccelStruct; + NextProp = &m_ExtProperties.AccelStruct.pNext; - m_ExtProperties.RayTracing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR; + m_ExtProperties.AccelStruct.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR; } - else if (IsExtensionSupported(VK_NV_RAY_TRACING_EXTENSION_NAME)) + + // Get ray tracing pipeline features and properties. + if (IsExtensionSupported(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME)) { - m_ExtFeatures.RayTracingNV = true; + *NextFeat = &m_ExtFeatures.RayTracingPipeline; + NextFeat = &m_ExtFeatures.RayTracingPipeline.pNext; + + m_ExtFeatures.RayTracingPipeline.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR; - *NextProp = &RayTracingNV; - NextProp = &RayTracingNV.pNext; + *NextProp = &m_ExtProperties.RayTracingPipeline; + NextProp = &m_ExtProperties.RayTracingPipeline.pNext; - RayTracingNV.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV; + m_ExtProperties.RayTracingPipeline.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR; } // Additional extension that is required for ray tracing. @@ -185,22 +188,6 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, // Some flags may not be supported by hardware. vkGetPhysicalDeviceFeatures2KHR(m_VkDevice, &Feats2); vkGetPhysicalDeviceProperties2KHR(m_VkDevice, &Props2); - - // Emulate KHR extension - if (m_ExtFeatures.RayTracingNV) - { - m_ExtFeatures.RayTracing.rayTracing = VK_TRUE; - - m_ExtProperties.RayTracing.shaderGroupHandleSize = RayTracingNV.shaderGroupHandleSize; - m_ExtProperties.RayTracing.maxRecursionDepth = RayTracingNV.maxRecursionDepth; - m_ExtProperties.RayTracing.maxShaderGroupStride = RayTracingNV.maxShaderGroupStride; - m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment; - m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount; - m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount; - m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount; - m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures; - m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0; - } } #endif // DILIGENT_USE_VOLK } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp deleted file mode 100644 index 8661f5fe..00000000 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanRayTracingKHRviaNV.cpp +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright 2019-2020 Diligent Graphics LLC - * Copyright 2015-2019 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - - -// KHR ray tracing emulation through NVidia extension. -// Will be deprecated after the release of KHR extension. - -#include -#include -#include - -#include "../../include/VulkanErrors.hpp" -#include "../../include/VulkanUtilities/VulkanLogicalDevice.hpp" - -namespace VulkanUtilities -{ - -#if DILIGENT_USE_VOLK -static_assert(sizeof(VkAccelerationStructureKHR) == sizeof(VkAccelerationStructureNV), "KHR is incompatible with NV extension"); -static_assert(sizeof(VkDeviceAddress) == 8, "KHR is incompatible with NV extension"); - -namespace -{ - -PFN_vkCreateBuffer Origin_vkCreateBuffer = nullptr; -PFN_vkDestroyBuffer Origin_vkDestroyBuffer = nullptr; -PFN_vkGetBufferDeviceAddressKHR Origin_vkGetBufferDeviceAddressKHR = nullptr; -PFN_vkAllocateMemory Origin_vkAllocateMemory = nullptr; - -struct DeviceAddressEmulator -{ - std::mutex Guard; - std::unordered_map AddrToBuffer; - std::unordered_map BufferToAddr; - uint32_t Counter = 0; - static constexpr VkDeviceAddress BufferMask = 0xFFFFFFFF00000000ull; - - static DeviceAddressEmulator* GetInstance() - { - static DeviceAddressEmulator inst; - return &inst; - } - - ~DeviceAddressEmulator() - { - vkGetBufferDeviceAddressKHR = Origin_vkGetBufferDeviceAddressKHR; - vkCreateBuffer = Origin_vkCreateBuffer; - vkDestroyBuffer = Origin_vkDestroyBuffer; - vkAllocateMemory = Origin_vkAllocateMemory; - } -}; - - -VKAPI_ATTR VkResult VKAPI_CALL Wrap_vkCreateBuffer(VkDevice device, - const VkBufferCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkBuffer* pBuffer) -{ - VkBufferCreateInfo CreateInfo = *pCreateInfo; - CreateInfo.usage &= ~VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - return Origin_vkCreateBuffer(device, &CreateInfo, pAllocator, pBuffer); -} - -VKAPI_ATTR VkResult VKAPI_PTR Wrap_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) -{ - VkMemoryAllocateInfo AllocInfo = *pAllocateInfo; - - for (auto** ppNext = reinterpret_cast(const_cast(&AllocInfo.pNext)); *ppNext;) - { - // remove VkMemoryAllocateFlagsInfo because VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is removed from buffer create info. - if ((*ppNext)->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) - *ppNext = (*ppNext)->pNext; - else - ppNext = &((*ppNext)->pNext); - } - - return Origin_vkAllocateMemory(device, &AllocInfo, pAllocator, pMemory); -} - -VKAPI_ATTR void VKAPI_CALL Wrap_vkDestroyBuffer(VkDevice device, - VkBuffer buffer, - const VkAllocationCallbacks* pAllocator) -{ - Origin_vkDestroyBuffer(device, buffer, pAllocator); - - auto* inst = DeviceAddressEmulator::GetInstance(); - - std::unique_lock lock{inst->Guard}; - - auto iter = inst->BufferToAddr.find(buffer); - if (iter != inst->BufferToAddr.end()) - { - inst->AddrToBuffer.erase(iter->second); - inst->BufferToAddr.erase(iter); - } -} - -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); - - auto* inst = DeviceAddressEmulator::GetInstance(); - - std::unique_lock lock{inst->Guard}; - - // find in existing buffers - auto iter = inst->BufferToAddr.find(pInfo->buffer); - if (iter != inst->BufferToAddr.end()) - return iter->second; - - // create new device address - VkDeviceAddress Addr = VkDeviceAddress{++inst->Counter} << 32; - inst->BufferToAddr[pInfo->buffer] = Addr; - inst->AddrToBuffer[Addr] = pInfo->buffer; - return Addr; -} - -struct BufferAndOffset -{ - VkBuffer Buffer; - VkDeviceSize Offset; -}; -BufferAndOffset DeviceAddressToBuffer(VkDeviceAddress Addr) -{ - if (Addr == 0) - return {VK_NULL_HANDLE, 0}; - - auto* inst = DeviceAddressEmulator::GetInstance(); - - std::unique_lock lock{inst->Guard}; - - auto iter = inst->AddrToBuffer.find(Addr & DeviceAddressEmulator::BufferMask); - if (iter == inst->AddrToBuffer.end()) - { - UNEXPECTED("Failed to map device address to buffer"); - return {VK_NULL_HANDLE, 0}; - } - - return {iter->second, Addr & ~DeviceAddressEmulator::BufferMask}; -} - -BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressConstKHR& Addr) -{ - return DeviceAddressToBuffer(Addr.deviceAddress); -} - -BufferAndOffset DeviceAddressToBuffer(const VkDeviceOrHostAddressKHR& Addr) -{ - return DeviceAddressToBuffer(Addr.deviceAddress); -} - - -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); - VERIFY_EXPR(pCreateInfo->deviceAddress == 0); - - VkAccelerationStructureCreateInfoNV CreateInfo = {}; - std::vector Geometries; - - CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV; - CreateInfo.compactedSize = pCreateInfo->compactedSize; - CreateInfo.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV; - CreateInfo.info.type = pCreateInfo->type; - CreateInfo.info.flags = pCreateInfo->flags; - - if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) - { - VERIFY_EXPR(pCreateInfo->maxGeometryCount == 1 || pCreateInfo->compactedSize > 0); - - if (pCreateInfo->pGeometryInfos && pCreateInfo->maxGeometryCount == 1) - { - VERIFY_EXPR(pCreateInfo->pGeometryInfos->geometryType == VK_GEOMETRY_TYPE_INSTANCES_KHR); - CreateInfo.info.instanceCount = pCreateInfo->pGeometryInfos->maxPrimitiveCount; - } - } - else if (CreateInfo.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) - { - Geometries.resize(pCreateInfo->maxGeometryCount); - - for (uint32_t i = 0; i < pCreateInfo->maxGeometryCount; ++i) - { - auto& src = pCreateInfo->pGeometryInfos[i]; - auto& dst = Geometries[i]; - - VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR); - VERIFY_EXPR(src.pNext == nullptr); - - dst.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV; - dst.pNext = nullptr; - dst.geometryType = src.geometryType; - dst.flags = 0; - - 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) - { - dst.geometry.triangles.vertexData = VK_NULL_HANDLE; - dst.geometry.triangles.vertexOffset = 0; - dst.geometry.triangles.vertexStride = 0; - dst.geometry.triangles.vertexFormat = src.vertexFormat; - dst.geometry.triangles.indexData = VK_NULL_HANDLE; - dst.geometry.triangles.indexOffset = 0; - dst.geometry.triangles.indexCount = 0; - dst.geometry.triangles.indexType = src.indexType; - dst.geometry.triangles.transformData = VK_NULL_HANDLE; - dst.geometry.triangles.transformOffset = 0; - - if (dst.geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR) - { - VERIFY_EXPR(src.maxVertexCount == src.maxPrimitiveCount * 3); - dst.geometry.triangles.vertexCount = src.maxPrimitiveCount * 3; - } - else - { - 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) - { - dst.geometry.aabbs.aabbData = VK_NULL_HANDLE; - dst.geometry.aabbs.numAABBs = src.maxPrimitiveCount; - dst.geometry.aabbs.stride = 0; - dst.geometry.aabbs.offset = 0; - } - } - - CreateInfo.info.geometryCount = static_cast(Geometries.size()); - CreateInfo.info.pGeometries = CreateInfo.info.geometryCount ? Geometries.data() : nullptr; - } - else - { - UNEXPECTED("unknown AS type"); - return VK_RESULT_MAX_ENUM; - } - - return vkCreateAccelerationStructureNV(device, &CreateInfo, pAllocator, reinterpret_cast(pAccelerationStructure)); -} - -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); - - VkAccelerationStructureMemoryRequirementsInfoNV Info = {}; - - Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV; - Info.type = pInfo->type; - Info.accelerationStructure = pInfo->accelerationStructure; - - return vkGetAccelerationStructureMemoryRequirementsNV(device, &Info, pMemoryRequirements); -} - -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); -} - -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); - - VkDeviceAddress result = 0; - vkGetAccelerationStructureHandleNV(device, pInfo->accelerationStructure, sizeof(result), &result); - return result; -} - -VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdBuildAccelerationStructureKHR(VkCommandBuffer commandBuffer, - uint32_t infoCount, - const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, - const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos) -{ - std::vector Geometries; - - for (uint32_t i = 0; i < infoCount; ++i) - { - auto& SrcInfo = pInfos[i]; - auto& SrcOffset = ppOffsetInfos[i]; - - VERIFY_EXPR(SrcInfo.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR); - VERIFY_EXPR(SrcInfo.pNext == nullptr); - - BufferAndOffset Scratch = DeviceAddressToBuffer(SrcInfo.scratchData); - - VkAccelerationStructureInfoNV Info = {}; - - Info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV; - Info.pNext = nullptr; - Info.type = SrcInfo.type; - Info.flags = SrcInfo.flags; - - if (Info.type == VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) - { - VERIFY_EXPR(SrcInfo.geometryCount == 1); - VERIFY_EXPR(SrcInfo.geometryArrayOfPointers == VK_FALSE); - VERIFY_EXPR((*SrcInfo.ppGeometries)[0].geometry.instances.arrayOfPointers == VK_FALSE); - - Info.instanceCount = SrcOffset->primitiveCount; - - BufferAndOffset Instance = DeviceAddressToBuffer((*SrcInfo.ppGeometries)[0].geometry.instances.data); - - vkCmdBuildAccelerationStructureNV(commandBuffer, &Info, - Instance.Buffer, Instance.Offset + SrcOffset[0].primitiveOffset, - SrcInfo.update, - SrcInfo.dstAccelerationStructure, SrcInfo.srcAccelerationStructure, - Scratch.Buffer, Scratch.Offset); - } - else if (Info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) - { - VERIFY_EXPR(SrcInfo.geometryArrayOfPointers == VK_FALSE); - - Geometries.resize(SrcInfo.geometryCount); - - for (uint32_t j = 0; j < SrcInfo.geometryCount; ++j) - { - auto& src = (*SrcInfo.ppGeometries)[j]; - auto& dst = Geometries[j]; - auto& off = SrcOffset[j]; - - VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR); - VERIFY_EXPR(src.pNext == nullptr); - VERIFY_EXPR(src.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR || src.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR); - - dst.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV; - dst.pNext = nullptr; - 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); - VERIFY_EXPR(src.geometry.triangles.pNext == nullptr); - VERIFY_EXPR(off.firstVertex == 0); - - BufferAndOffset VB = DeviceAddressToBuffer(src.geometry.triangles.vertexData); - BufferAndOffset IB = DeviceAddressToBuffer(src.geometry.triangles.indexData); - BufferAndOffset TB = DeviceAddressToBuffer(src.geometry.triangles.transformData); - - dst.geometry.triangles.vertexData = VB.Buffer; - dst.geometry.triangles.vertexOffset = VB.Offset; - dst.geometry.triangles.vertexCount = 0; - dst.geometry.triangles.vertexStride = src.geometry.triangles.vertexStride; - dst.geometry.triangles.vertexFormat = src.geometry.triangles.vertexFormat; - dst.geometry.triangles.indexData = IB.Buffer; - dst.geometry.triangles.indexOffset = IB.Offset; - dst.geometry.triangles.indexCount = 0; - dst.geometry.triangles.indexType = src.geometry.triangles.indexType; - dst.geometry.triangles.transformData = TB.Buffer; - dst.geometry.triangles.transformOffset = TB.Offset + off.transformOffset; - - if (dst.geometry.triangles.indexType == VK_INDEX_TYPE_NONE_KHR) - { - dst.geometry.triangles.vertexOffset += off.primitiveOffset; - dst.geometry.triangles.vertexCount = off.primitiveCount * 3; - } - else - { - dst.geometry.triangles.indexOffset += off.primitiveOffset; - dst.geometry.triangles.indexCount = off.primitiveCount * 3; - dst.geometry.triangles.vertexCount = off.primitiveCount * 6; - } - } - else - { - VERIFY_EXPR(src.geometry.aabbs.sType == VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR); - VERIFY_EXPR(src.geometry.aabbs.pNext == nullptr); - VERIFY_EXPR(src.geometry.aabbs.stride <= std::numeric_limits::max()); - - BufferAndOffset Data = DeviceAddressToBuffer(src.geometry.aabbs.data); - - dst.geometry.aabbs.aabbData = Data.Buffer; - dst.geometry.aabbs.numAABBs = off.primitiveCount; - dst.geometry.aabbs.stride = static_cast(src.geometry.aabbs.stride); - dst.geometry.aabbs.offset = Data.Offset + off.primitiveOffset; - } - } - - Info.geometryCount = static_cast(Geometries.size()); - Info.pGeometries = Geometries.data(); - - vkCmdBuildAccelerationStructureNV(commandBuffer, &Info, - VK_NULL_HANDLE, 0, - SrcInfo.update, - SrcInfo.dstAccelerationStructure, SrcInfo.srcAccelerationStructure, - Scratch.Buffer, Scratch.Offset); - } - else - { - UNEXPECTED("unknown AS type"); - } - } -} - -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); - - vkCmdCopyAccelerationStructureNV(commandBuffer, pInfo->dst, pInfo->src, pInfo->mode); -} - -VKAPI_ATTR void VKAPI_CALL Redirect_vkCmdWriteAccelerationStructuresPropertiesKHR(VkCommandBuffer commandBuffer, - uint32_t accelerationStructureCount, - const VkAccelerationStructureKHR* pAccelerationStructures, - VkQueryType queryType, - VkQueryPool queryPool, - uint32_t firstQuery) -{ - vkCmdWriteAccelerationStructuresPropertiesNV(commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); -} - -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, - pMissShaderBindingTable->buffer, pMissShaderBindingTable->offset, pMissShaderBindingTable->stride, - pHitShaderBindingTable->buffer, pHitShaderBindingTable->offset, pHitShaderBindingTable->stride, - pCallableShaderBindingTable->buffer, pCallableShaderBindingTable->offset, pCallableShaderBindingTable->stride, - width, height, depth); -} - -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); -} - -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 Infos; - std::vector Groups; - Infos.resize(createInfoCount); - - size_t GroupCount = 0; - for (uint32_t i = 0; i < createInfoCount; ++i) - { - GroupCount += pCreateInfos[i].groupCount; - } - Groups.resize(GroupCount); - GroupCount = 0; - - for (uint32_t i = 0; i < createInfoCount; ++i) - { - auto& src = pCreateInfos[i]; - auto& dst = Infos[i]; - - VERIFY_EXPR(src.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR); - VERIFY_EXPR(src.pNext == nullptr); - VERIFY_EXPR(src.libraries.libraryCount == 0); - VERIFY_EXPR(src.libraries.pLibraries == nullptr); - VERIFY_EXPR(src.pLibraryInterface == nullptr); - - // copy groups - for (uint32_t j = 0; j < src.groupCount; ++j) - { - auto& srcg = src.pGroups[j]; - auto& dstg = Groups[GroupCount + j]; - - VERIFY_EXPR(srcg.sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR); - VERIFY_EXPR(srcg.pNext == nullptr); - - dstg.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV; - dstg.pNext = nullptr; - dstg.type = srcg.type; - dstg.generalShader = srcg.generalShader; - dstg.closestHitShader = srcg.closestHitShader; - dstg.anyHitShader = srcg.anyHitShader; - dstg.intersectionShader = srcg.intersectionShader; - - VERIFY_EXPR(srcg.pNext == nullptr); - } - - dst.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV; - dst.pNext = nullptr; - dst.flags = src.flags; - dst.stageCount = src.stageCount; - dst.pStages = src.pStages; - dst.groupCount = src.groupCount; - dst.pGroups = Groups.data() + GroupCount; - dst.maxRecursionDepth = src.maxRecursionDepth; - dst.layout = src.layout; - dst.basePipelineHandle = src.basePipelineHandle; - dst.basePipelineIndex = src.basePipelineIndex; - - GroupCount += src.groupCount; - } - - return vkCreateRayTracingPipelinesNV(device, pipelineCache, createInfoCount, Infos.data(), pAllocator, pPipelines); -} - -} // namespace - -void EnableRayTracingKHRviaNV() -{ - LOG_WARNING_MESSAGE("This is fallback implementation, you should use VK_KHR_ray_tracing instead"); - - vkCreateAccelerationStructureKHR = &Redirect_vkCreateAccelerationStructureKHR; - vkGetAccelerationStructureMemoryRequirementsKHR = &Redirect_vkGetAccelerationStructureMemoryRequirementsKHR; - vkBindAccelerationStructureMemoryKHR = &Redirect_vkBindAccelerationStructureMemoryKHR; - vkGetAccelerationStructureDeviceAddressKHR = &Redirect_vkGetAccelerationStructureDeviceAddressKHR; - vkCmdBuildAccelerationStructureKHR = &Redirect_vkCmdBuildAccelerationStructureKHR; - vkCmdCopyAccelerationStructureKHR = &Redirect_vkCmdCopyAccelerationStructureKHR; - vkCmdWriteAccelerationStructuresPropertiesKHR = &Redirect_vkCmdWriteAccelerationStructuresPropertiesKHR; - vkGetRayTracingShaderGroupHandlesKHR = &Redirect_vkGetRayTracingShaderGroupHandlesKHR; - vkCreateRayTracingPipelinesKHR = &Redirect_vkCreateRayTracingPipelinesKHR; - vkCmdTraceRaysKHR = &Redirect_vkCmdTraceRaysKHR; - vkDestroyAccelerationStructureKHR = &Redirect_vkDestroyAccelerationStructureKHR; - - Origin_vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressKHR; - Origin_vkCreateBuffer = vkCreateBuffer; - Origin_vkDestroyBuffer = vkDestroyBuffer; - Origin_vkAllocateMemory = vkAllocateMemory; - vkCreateBuffer = &Wrap_vkCreateBuffer; - vkDestroyBuffer = &Wrap_vkDestroyBuffer; - vkAllocateMemory = Wrap_vkAllocateMemory; - vkGetBufferDeviceAddressKHR = &Wrap_vkGetBufferDeviceAddressKHR; - vkGetBufferDeviceAddress = &Wrap_vkGetBufferDeviceAddressKHR; - vkGetBufferDeviceAddressEXT = &Wrap_vkGetBufferDeviceAddressKHR; -} -#endif // DILIGENT_USE_VOLK - -} // namespace VulkanUtilities -- cgit v1.2.3 From c3058653add8f8a9d147de652a94c178a6973ac6 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 25 Nov 2020 19:14:57 +0300 Subject: Added RootSignatureBuilder, some fixed for vulkan ray tracing --- Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp | 1 + Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 3cab0ae2..e34f52f2 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2789,6 +2789,7 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) // vertex format in SrcTris may be undefined, so use vertex format from description vkTris.vertexFormat = TypeToVkFormat(TriDesc.VertexValueType, TriDesc.VertexComponentCount, TriDesc.VertexValueType < VT_FLOAT16); vkTris.vertexStride = SrcTris.VertexStride; + vkTris.maxVertex = SrcTris.VertexCount; vkTris.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + SrcTris.VertexOffset; TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 93fb9f34..514ca01d 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -427,6 +427,17 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E EnabledExtFeats.BufferDeviceAddress = DeviceExtFeatures.BufferDeviceAddress; EnabledExtFeats.DescriptorIndexing = DeviceExtFeatures.DescriptorIndexing; + // disable unused features + EnabledExtFeats.AccelStruct.accelerationStructureCaptureReplay = false; + EnabledExtFeats.AccelStruct.accelerationStructureIndirectBuild = false; + EnabledExtFeats.AccelStruct.accelerationStructureHostCommands = false; + EnabledExtFeats.AccelStruct.descriptorBindingAccelerationStructureUpdateAfterBind = false; + + EnabledExtFeats.RayTracingPipeline.rayTracingPipelineShaderGroupHandleCaptureReplay = false; + EnabledExtFeats.RayTracingPipeline.rayTracingPipelineShaderGroupHandleCaptureReplayMixed = false; + EnabledExtFeats.RayTracingPipeline.rayTracingPipelineTraceRaysIndirect = false; + EnabledExtFeats.RayTracingPipeline.rayTraversalPrimitiveCulling = false; // for GLSL_EXT_ray_flags_primitive_culling + *NextExt = &EnabledExtFeats.AccelStruct; NextExt = &EnabledExtFeats.AccelStruct.pNext; *NextExt = &EnabledExtFeats.RayTracingPipeline; -- cgit v1.2.3 From e2dd19e542cee8634aaf1376ba0272c41a89dc2d Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 25 Nov 2020 22:28:38 +0300 Subject: Disable validation layers if they are not compatible with headers, fixed compilation on iOS --- .../include/VulkanUtilities/VulkanInstance.hpp | 2 +- .../VulkanUtilities/VulkanLogicalDevice.hpp | 2 ++ .../src/BottomLevelASVkImpl.cpp | 2 +- .../GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp | 2 +- .../src/VulkanUtilities/VulkanInstance.cpp | 23 +++++++++++++++++----- .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 10 ++++++++++ 6 files changed, 33 insertions(+), 8 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp index c28be56c..e2bb7ad8 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp @@ -62,7 +62,7 @@ public: } // clang-format off - bool IsLayerAvailable (const char* LayerName) const; + bool IsLayerAvailable (const char* LayerName, uint32_t& Version) const; bool IsExtensionAvailable(const char* ExtensionName)const; bool IsExtensionEnabled (const char* ExtensionName)const; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp index 0e309eff..6d2d827c 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp @@ -216,6 +216,8 @@ public: dataSize, pData, stride, flags); } + void GetAccelerationStructureBuildSizes(const VkAccelerationStructureBuildGeometryInfoKHR& BuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR& SizeInfo) const; + VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const; VkPipelineStageFlags GetEnabledShaderStages() const { return m_EnabledShaderStages; } diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp index ffe1eb02..19253b1f 100644 --- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -112,7 +112,7 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, VERIFY_EXPR(vkBuildInfo.geometryCount <= Limits.maxGeometryCount); - vkGetAccelerationStructureBuildSizesKHR(LogicalDevice.GetVkDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &vkBuildInfo, MaxPrimitiveCounts.data(), &vkSizeInfo); + LogicalDevice.GetAccelerationStructureBuildSizes(vkBuildInfo, MaxPrimitiveCounts.data(), vkSizeInfo); AccelStructSize = static_cast(vkSizeInfo.accelerationStructureSize); m_ScratchSize.Build = static_cast(vkSizeInfo.buildScratchSize); diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp index d4c771ec..03724a8a 100644 --- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp @@ -63,7 +63,7 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxInstanceCount); - vkGetAccelerationStructureBuildSizesKHR(LogicalDevice.GetVkDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &vkBuildInfo, &MaxPrimitiveCount, &vkSizeInfo); + LogicalDevice.GetAccelerationStructureBuildSizes(vkBuildInfo, &MaxPrimitiveCount, vkSizeInfo); AccelStructSize = static_cast(vkSizeInfo.accelerationStructureSize); m_ScratchSize.Build = static_cast(vkSizeInfo.buildScratchSize); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index 405149a5..a88a5888 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -46,12 +46,16 @@ namespace VulkanUtilities { -bool VulkanInstance::IsLayerAvailable(const char* LayerName) const +bool VulkanInstance::IsLayerAvailable(const char* LayerName, uint32_t& Version) const { for (const auto& Layer : m_Layers) + { if (strcmp(Layer.layerName, LayerName) == 0) + { + Version = Layer.specVersion; return true; - + } + } return false; } @@ -220,11 +224,20 @@ VulkanInstance::VulkanInstance(uint32_t ApiVersion, bool ValidationLayersPresent = true; for (size_t l = 0; l < _countof(VulkanUtilities::ValidationLayerNames); ++l) { - auto* pLayerName = VulkanUtilities::ValidationLayerNames[l]; - if (!IsLayerAvailable(pLayerName)) + auto* pLayerName = VulkanUtilities::ValidationLayerNames[l]; + uint32_t LayerVer = 0; + if (!IsLayerAvailable(pLayerName, LayerVer)) + { + ValidationLayersPresent = false; + LOG_WARNING_MESSAGE("Failed to find '", pLayerName, "' layer. Validation will be disabled"); + } + if (LayerVer < VK_HEADER_VERSION_COMPLETE) { ValidationLayersPresent = false; - LOG_WARNING_MESSAGE("Failed to find ", pLayerName, " layer. Validation will be disabled"); + LOG_WARNING_MESSAGE("Layer '", pLayerName, "' version (", VK_VERSION_MAJOR(LayerVer), ".", VK_VERSION_MINOR(LayerVer), ".", VK_VERSION_PATCH(LayerVer), + ") is less than header version (", + VK_VERSION_MAJOR(VK_HEADER_VERSION_COMPLETE), ".", VK_VERSION_MINOR(VK_HEADER_VERSION_COMPLETE), ".", VK_VERSION_PATCH(VK_HEADER_VERSION_COMPLETE), + "). Validation will be disabled"); } } if (ValidationLayersPresent) diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index 70bdd20a..0d1534b8 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -504,6 +504,16 @@ VkDeviceAddress VulkanLogicalDevice::GetAccelerationStructureDeviceAddress(VkAcc #endif } +void VulkanLogicalDevice::GetAccelerationStructureBuildSizes(const VkAccelerationStructureBuildGeometryInfoKHR& BuildInfo, const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR& SizeInfo) const +{ +#if DILIGENT_USE_VOLK + vkGetAccelerationStructureBuildSizesKHR(m_VkDevice, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &BuildInfo, pMaxPrimitiveCounts, &SizeInfo); +#else + UNSUPPORTED("vkGetAccelerationStructureDeviceAddressKHR is only available through Volk"); + return VK_ERROR_FEATURE_NOT_PRESENT; +#endif +} + VkResult VulkanLogicalDevice::MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const { return vkMapMemory(m_VkDevice, memory, offset, size, flags, ppData); -- cgit v1.2.3 From 1f9e0a4cd484687c13999d4a6686e104e0a93470 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Tue, 8 Dec 2020 17:56:12 +0300 Subject: some improvements for ray tracing --- .../include/RenderDeviceVkImpl.hpp | 2 ++ .../include/VulkanTypeConversions.hpp | 1 + .../src/DeviceContextVkImpl.cpp | 32 ++++++++++----------- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 1 - .../src/PipelineStateVkImpl.cpp | 9 ++---- .../src/RenderDeviceVkImpl.cpp | 10 ++++++- .../src/VulkanTypeConversions.cpp | 33 +++++++++++++++++++--- 7 files changed, 59 insertions(+), 29 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 2aaf4c69..2b8408ce 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -215,6 +215,8 @@ public: const Uint32 MaxShaderRecordStride; const Uint32 ShaderGroupBaseAlignment; const Uint32 MaxDrawMeshTasksCount; + const Uint32 MaxRayTracingRecursionDepth; + const Uint32 MaxRayGenThreads; }; const Properties& GetProperties() const diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp index 8f90a914..405e9bfa 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp @@ -67,6 +67,7 @@ VkBorderColor BorderColorToVkBorderColor(const Float32 BorderColor[]); VkPipelineStageFlags ResourceStateFlagsToVkPipelineStageFlags(RESOURCE_STATE StateFlags, VkPipelineStageFlags ShaderStages); VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags); +VkAccessFlags AccelStructStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags); VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag, bool IsInsideRenderPass = false); RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags); diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index e34f52f2..48b7df04 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -2514,8 +2514,8 @@ void DeviceContextVkImpl::TransitionBLASState(BottomLevelASVkImpl& BLAS, if ((OldState & NewState) != NewState || AfterWrite) { EnsureVkCmdBuffer(); - auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState); - auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState); + auto OldAccessFlags = AccelStructStateFlagsToVkAccessFlags(OldState); + auto NewAccessFlags = AccelStructStateFlagsToVkAccessFlags(NewState); auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages()); auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages()); m_CommandBuffer.ASMemoryBarrier(OldAccessFlags, NewAccessFlags, OldStages, NewStages); @@ -2560,8 +2560,8 @@ void DeviceContextVkImpl::TransitionTLASState(TopLevelASVkImpl& TLAS, if ((OldState & NewState) != NewState || AfterWrite) { EnsureVkCmdBuffer(); - auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState); - auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState); + auto OldAccessFlags = AccelStructStateFlagsToVkAccessFlags(OldState); + auto NewAccessFlags = AccelStructStateFlagsToVkAccessFlags(NewState); auto OldStages = ResourceStateFlagsToVkPipelineStageFlags(OldState, m_CommandBuffer.GetEnabledShaderStages()); auto NewStages = ResourceStateFlagsToVkPipelineStageFlags(NewState, m_CommandBuffer.GetEnabledShaderStages()); m_CommandBuffer.ASMemoryBarrier(OldAccessFlags, NewAccessFlags, OldStages, NewStages); @@ -2792,7 +2792,7 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) vkTris.maxVertex = SrcTris.VertexCount; vkTris.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + SrcTris.VertexOffset; - TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); + TransitionOrVerifyBufferState(*pVB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_SHADER_READ_BIT, OpName); if (SrcTris.pIndexBuffer) { @@ -2802,7 +2802,7 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) vkTris.indexType = TypeToVkIndexType(TriDesc.IndexType); vkTris.indexData.deviceAddress = pIB->GetVkDeviceAddress() + SrcTris.IndexOffset; - TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); + TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_SHADER_READ_BIT, OpName); } else { @@ -2815,7 +2815,7 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) auto* const pTB = ValidatedCast(SrcTris.pTransformBuffer); vkTris.transformData.deviceAddress = pTB->GetVkDeviceAddress() + SrcTris.TransformBufferOffset; - TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); + TransitionOrVerifyBufferState(*pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_SHADER_READ_BIT, OpName); } else { @@ -2863,7 +2863,7 @@ void DeviceContextVkImpl::BuildBLAS(const BuildBLASAttribs& Attribs) VERIFY(vkAABBs.data.deviceAddress % 8 == 0, "AABB start address is not properly aligned"); - TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); + TransitionOrVerifyBufferState(*pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_SHADER_READ_BIT, OpName); off.firstVertex = 0; off.transformOffset = 0; @@ -2956,7 +2956,7 @@ void DeviceContextVkImpl::BuildTLAS(const BuildTLASAttribs& Attribs) UpdateBufferRegion(pInstancesVk, Attribs.InstanceBufferOffset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, Attribs.InstanceBufferTransitionMode); } - TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); + TransitionOrVerifyBufferState(*pInstancesVk, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_SHADER_READ_BIT, OpName); VkAccelerationStructureBuildGeometryInfoKHR vkASBuildInfo = {}; VkAccelerationStructureBuildRangeInfoKHR vkRange = {}; @@ -3128,10 +3128,10 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) pSBTVk->GetData(pBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable); - auto* pBufferVk = ValidatedCast(pBuffer); + auto* pSBTBufferVk = ValidatedCast(pBuffer); const char* OpName = "Trace rays (DeviceContextVkImpl::TraceRays)"; - TransitionOrVerifyBufferState(*pBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + TransitionOrVerifyBufferState(*pSBTBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); // buffer ranges are not intersected, so we don't need to add barriers between them if (RayGenShaderRecord.pData) @@ -3146,13 +3146,13 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) if (CallableShaderTable.pData) UpdateBuffer(pBuffer, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); - TransitionOrVerifyBufferState(*pBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_RAY_TRACING, VK_ACCESS_SHADER_READ_BIT, OpName); + TransitionOrVerifyBufferState(*pSBTBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_RAY_TRACING, VK_ACCESS_SHADER_READ_BIT, OpName); // clang-format off - VkStridedDeviceAddressRegionKHR RaygenShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size }; - VkStridedDeviceAddressRegionKHR MissShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size }; - VkStridedDeviceAddressRegionKHR HitShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size }; - VkStridedDeviceAddressRegionKHR CallableShaderBindingTable = {pBufferVk->GetVkDeviceAddress() + CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size}; + VkStridedDeviceAddressRegionKHR RaygenShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size }; + VkStridedDeviceAddressRegionKHR MissShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size }; + VkStridedDeviceAddressRegionKHR HitShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size }; + VkStridedDeviceAddressRegionKHR CallableShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size}; // clang-format on PrepareForRayTracing(); diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 514ca01d..ed537333 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -418,7 +418,6 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); // required for VK_KHR_acceleration_structure DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); // required for VK_KHR_acceleration_structure DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // required for VK_KHR_acceleration_structure - DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); // required for VK_KHR_ray_tracing_pipeline DeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); // required for ray tracing DeviceExtensions.push_back(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); // required for ray tracing diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 00bb54d9..7d846b90 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -346,12 +346,7 @@ static void CreateRayTracingPipeline(RenderDeviceVkImpl* const RayTracingPipelineDesc& RayTracingPipeline, VulkanUtilities::PipelineWrapper& Pipeline) { - const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); - const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); - const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracingPipeline; - - DEV_CHECK_ERR(RayTracingPipeline.MaxRecursionDepth <= RTLimits.maxRayRecursionDepth, - "RayTracingPipeline.MaxRecursionDepth must not exceed ", RTLimits.maxRayRecursionDepth); + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); VkRayTracingPipelineCreateInfoKHR PipelineCI = {}; @@ -365,7 +360,7 @@ static void CreateRayTracingPipeline(RenderDeviceVkImpl* PipelineCI.pStages = Stages.data(); PipelineCI.groupCount = static_cast(ShaderGroups.size()); PipelineCI.pGroups = ShaderGroups.data(); - PipelineCI.maxPipelineRayRecursionDepth = RayTracingPipeline.MaxRecursionDepth; + PipelineCI.maxPipelineRayRecursionDepth = std::max(1u, Uint32{RayTracingPipeline.MaxRecursionDepth}) - 1; // for compatibility with D3D12, zero means only one ray tracing depth. PipelineCI.pLibraryInfo = nullptr; PipelineCI.pLibraryInterface = nullptr; PipelineCI.pDynamicState = nullptr; diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index c44d5642..44bc0eb8 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -165,13 +165,21 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* m_PhysicalDevice->GetExtProperties().RayTracingPipeline.shaderGroupHandleSize, m_PhysicalDevice->GetExtProperties().RayTracingPipeline.maxShaderGroupStride, m_PhysicalDevice->GetExtProperties().RayTracingPipeline.shaderGroupBaseAlignment, - m_PhysicalDevice->GetExtProperties().MeshShader.maxDrawMeshTasksCount + m_PhysicalDevice->GetExtProperties().MeshShader.maxDrawMeshTasksCount, + m_PhysicalDevice->GetExtProperties().RayTracingPipeline.maxRayRecursionDepth + 1, // for compatibility with D3D12 + m_PhysicalDevice->GetExtProperties().RayTracingPipeline.maxRayDispatchInvocationCount } // clang-format on { static_assert(sizeof(VulkanDescriptorPoolSize) == sizeof(Uint32) * 11, "Please add new descriptors to m_DescriptorSetAllocator and m_DynamicDescriptorPool constructors"); static_assert(sizeof(DeviceObjectSizes) == sizeof(size_t) * 15, "Please add new objects to DeviceObjectSizes constructor"); + // set device properties + { + static_assert(sizeof(DeviceProperties) == sizeof(Uint32) * 1, "Please set new properties below"); + m_DeviceProperties.MaxRayTracingRecursionDepth = m_Properties.MaxRayTracingRecursionDepth; + } + m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_VULKAN; m_DeviceCaps.MajorVersion = 1; m_DeviceCaps.MinorVersion = 0; diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index edfa7625..17c129c1 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1239,9 +1239,9 @@ 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_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 | VK_ACCESS_SHADER_READ_BIT; // for TLAS & SBT + case RESOURCE_STATE_BUILD_AS_READ: return VK_ACCESS_SHADER_READ_BIT; // for vertex, index, transform, AABB, instance buffers + case RESOURCE_STATE_BUILD_AS_WRITE: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; // for scratch buffer + case RESOURCE_STATE_RAY_TRACING: return VK_ACCESS_SHADER_READ_BIT; // for SBT // clang-format on default: @@ -1290,6 +1290,30 @@ VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags) return AccessFlags; } +VkAccessFlags AccelStructStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags) +{ + VERIFY(Uint32{StateFlags} < (RESOURCE_STATE_MAX_BIT << 1), "Resource state flags are out of range"); + static_assert(RESOURCE_STATE_MAX_BIT == RESOURCE_STATE_RAY_TRACING, "This function must be updated to handle new resource state flag"); + + VkAccessFlags AccessFlags = 0; + Uint32 Bits = StateFlags; + while (Bits != 0) + { + auto Bit = static_cast(1 << PlatformMisc::GetLSB(Bits)); + switch (Bit) + { + // clang-format off + case RESOURCE_STATE_BUILD_AS_READ: AccessFlags |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; break; + case RESOURCE_STATE_BUILD_AS_WRITE: AccessFlags |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; break; + case RESOURCE_STATE_RAY_TRACING: AccessFlags |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; break; + default: UNEXPECTED("Unexpected resource state flag"); + // clang-format on + } + Bits &= ~Bit; + } + return AccessFlags; +} + static RESOURCE_STATE VkAccessFlagToResourceStates(VkAccessFlagBits AccessFlagBit) { VERIFY((AccessFlagBit & (AccessFlagBit - 1)) == 0, "Single access flag bit is expected"); @@ -1302,7 +1326,7 @@ static RESOURCE_STATE VkAccessFlagToResourceStates(VkAccessFlagBits AccessFlagBi case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: return RESOURCE_STATE_VERTEX_BUFFER; case VK_ACCESS_UNIFORM_READ_BIT: return RESOURCE_STATE_CONSTANT_BUFFER; case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: return RESOURCE_STATE_INPUT_ATTACHMENT; - case VK_ACCESS_SHADER_READ_BIT: return RESOURCE_STATE_SHADER_RESOURCE; + case VK_ACCESS_SHADER_READ_BIT: return RESOURCE_STATE_SHADER_RESOURCE; // or RESOURCE_STATE_BUILD_AS_READ case VK_ACCESS_SHADER_WRITE_BIT: return RESOURCE_STATE_UNORDERED_ACCESS; case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: return RESOURCE_STATE_RENDER_TARGET; case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: return RESOURCE_STATE_RENDER_TARGET; @@ -1310,6 +1334,7 @@ static RESOURCE_STATE VkAccessFlagToResourceStates(VkAccessFlagBits AccessFlagBi case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: return RESOURCE_STATE_DEPTH_WRITE; case VK_ACCESS_TRANSFER_READ_BIT: return RESOURCE_STATE_COPY_SOURCE; case VK_ACCESS_TRANSFER_WRITE_BIT: return RESOURCE_STATE_COPY_DEST; + case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: return RESOURCE_STATE_BUILD_AS_WRITE; case VK_ACCESS_HOST_READ_BIT: return RESOURCE_STATE_UNKNOWN; case VK_ACCESS_HOST_WRITE_BIT: return RESOURCE_STATE_UNKNOWN; case VK_ACCESS_MEMORY_READ_BIT: return RESOURCE_STATE_UNKNOWN; -- cgit v1.2.3