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