From 3efd89673b48bedffcf36b6b8c66d587512854a1 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 15 Mar 2021 03:14:26 +0300 Subject: Added inline ray tracing & trace rays indirect command. --- .../GraphicsEngine/include/DeviceContextBase.hpp | 46 ++++++++++ Graphics/GraphicsEngine/interface/DeviceContext.h | 37 ++++++++ Graphics/GraphicsEngine/interface/GraphicsTypes.h | 12 ++- Graphics/GraphicsEngine/interface/Shader.h | 4 + Graphics/GraphicsEngine/src/DeviceContextBase.cpp | 38 +++++++++ .../include/DeviceContextD3D11Impl.hpp | 3 + .../src/DeviceContextD3D11Impl.cpp | 5 ++ .../src/RenderDeviceD3D11Impl.cpp | 3 +- .../include/DeviceContextD3D12Impl.hpp | 15 ++-- .../src/DeviceContextD3D12Impl.cpp | 99 +++++++++++++++++++--- .../src/RenderDeviceD3D12Impl.cpp | 7 +- .../include/DeviceContextGLImpl.hpp | 3 + .../src/DeviceContextGLImpl.cpp | 5 ++ .../src/RenderDeviceGLImpl.cpp | 9 +- .../include/DeviceContextVkImpl.hpp | 5 +- .../VulkanUtilities/VulkanCommandBuffer.hpp | 16 ++++ .../VulkanUtilities/VulkanPhysicalDevice.hpp | 1 + .../src/DeviceContextVkImpl.cpp | 64 ++++++++++++-- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 42 +++++++-- .../src/RenderDeviceVkImpl.cpp | 2 +- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 9 ++ Graphics/ShaderTools/src/DXCompiler.cpp | 12 +-- 22 files changed, 391 insertions(+), 46 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 630071f4..87433ea5 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -72,6 +72,7 @@ bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs); bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs); bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs); bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs); +bool VerifyTraceRaysIndirectAttribs(const IRenderDevice* pDevice, const TraceRaysIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer, Uint32 SBTSize); @@ -332,6 +333,10 @@ protected: bool WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const; bool WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const; bool TraceRays(const TraceRaysAttribs& Attribs, int) const; + bool TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer, int) const; + + static constexpr Uint32 TraceRaysIndirectCommandSBTSize = 88; // D3D12: 88 bytes, size of SBT offsets + // Vulkan: 0 bytes, SBT offsets placed directly into function call /// Strong reference to the device. RefCntAutoPtr m_pDevice; @@ -1667,6 +1672,47 @@ bool DeviceContextBase::TraceRays(const TraceRaysAttribs& return true; } +template +bool DeviceContextBase::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer, int) const +{ +#ifdef DILIGENT_DEVELOPMENT + if (m_pDevice->GetDeviceCaps().Features.RayTracing2 != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect: indirect trace rays is not supported by this device"); + return false; + } + + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (!m_pPipelineState->GetDesc().IsRayTracingPipeline()) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline."); + return false; + } + + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect must be performed outside of render pass"); + return false; + } + + if (!VerifyTraceRaysIndirectAttribs(m_pDevice, Attribs, pAttribsBuffer, TraceRaysIndirectCommandSBTSize)) + return false; + + if (!PipelineStateImplType::IsSameObject(m_pPipelineState, ValidatedCast(Attribs.pSBT->GetDesc().pPSO))) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRaysIndirect command arguments are invalid: currently bound pipeline '", m_pPipelineState->GetDesc().Name, + "' doesn't match the pipeline '", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, "' that was used in ShaderBindingTable"); + return false; + } +#endif + + return true; +} diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 411103d7..5800ad76 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -1237,6 +1237,29 @@ struct TraceRaysAttribs typedef struct TraceRaysAttribs TraceRaysAttribs; +/// This structure is used by IDeviceContext::TraceRaysIndirect(). +struct TraceRaysIndirectAttribs +{ + /// Shader binding table. + IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr); + + /// State transition mode for indirect trace rays attributes buffer. + RESOURCE_STATE_TRANSITION_MODE IndirectAttribsBufferStateTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// The offset from the beginning of the buffer to the trace rays command arguments. + Uint32 ArgsByteOffset DEFAULT_INITIALIZER(0); + + /// For Direct3D12 backend size must be 104 bytes, + /// for Vulkan backend size must be 12 bytes (only uint3) or 104 bytes for D3D12 compatibility. + Uint32 ArgsByteSize DEFAULT_INITIALIZER(104); + +#if DILIGENT_CPP_INTERFACE + TraceRaysIndirectAttribs() noexcept {} +#endif +}; +typedef struct TraceRaysIndirectAttribs TraceRaysIndirectAttribs; + + static const Uint32 REMAINING_MIP_LEVELS = ~0u; static const Uint32 REMAINING_ARRAY_SLICES = ~0u; @@ -2202,6 +2225,19 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) /// to the shader binding table passed as an argument to the function. VIRTUAL void METHOD(TraceRays)(THIS_ const TraceRaysAttribs REF Attribs) PURE; + + + /// Executes an indirect trace rays command. + /// + /// \param [in] pAttribsBuffer - Pointer to the buffer containing indirect trace rays attributes. + /// The buffer must contain the following arguments at the specified offset: + /// [88 bytes reserved] - for Direct3D12 backend + /// Uint32 DimensionX; + /// Uint32 DimensionY; + /// Uint32 DimensionZ; + VIRTUAL void METHOD(TraceRaysIndirect)(THIS_ + const TraceRaysIndirectAttribs REF Attribs, + IBuffer* pAttribsBuffer) PURE; }; DILIGENT_END_INTERFACE @@ -2260,6 +2296,7 @@ DILIGENT_END_INTERFACE # define IDeviceContext_WriteBLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteBLASCompactedSize, This, __VA_ARGS__) # define IDeviceContext_WriteTLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteTLASCompactedSize, This, __VA_ARGS__) # define IDeviceContext_TraceRays(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRays, This, __VA_ARGS__) +# define IDeviceContext_TraceRaysIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRaysIndirect, This, __VA_ARGS__) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index ae11a655..456b33e4 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1560,16 +1560,19 @@ struct DeviceFeatures /// Indicates if device supports geometry shaders DEVICE_FEATURE_STATE GeometryShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); - + /// Indicates if device supports tessellation DEVICE_FEATURE_STATE Tessellation DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); - + /// Indicates if device supports mesh and amplification shaders DEVICE_FEATURE_STATE MeshShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); - + /// Indicates if device supports ray tracing shaders DEVICE_FEATURE_STATE RayTracing DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + /// Indicates if device supports inline ray tracing and indirect commands + DEVICE_FEATURE_STATE RayTracing2 DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + /// Indicates if device supports bindless resources DEVICE_FEATURE_STATE BindlessResources DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); @@ -1666,6 +1669,7 @@ struct DeviceFeatures Tessellation {State}, MeshShaders {State}, RayTracing {State}, + RayTracing2 {State}, BindlessResources {State}, OcclusionQueries {State}, BinaryOcclusionQueries {State}, @@ -1691,7 +1695,7 @@ struct DeviceFeatures ShaderResourceRuntimeArray {State} { # if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(*this) == 33, "Did you add a new feature to DeviceFeatures? Please handle its status above."); + static_assert(sizeof(*this) == 34, "Did you add a new feature to DeviceFeatures? Please handle its status above."); # endif } #endif diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index 88c7e223..399f7b6e 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -252,6 +252,10 @@ DILIGENT_TYPED_ENUM(SHADER_COMPILE_FLAGS, Uint32) /// Enable unbounded resource arrays (e.g. Texture2D g_Texture[]). SHADER_COMPILE_FLAG_ENABLE_UNBOUNDED_ARRAYS = 0x01, + /// Enable inline ray tracing for graphics and compute shaders. + /// Requires RayTracing2 device feature. + SHADER_COMPILE_FLAG_ENABLE_INLINE_RAY_TRACING = 0x02, + SHADER_COMPILE_FLAG_LAST = SHADER_COMPILE_FLAG_ENABLE_UNBOUNDED_ARRAYS }; DEFINE_FLAG_ENUM_OPERATORS(SHADER_COMPILE_FLAGS); diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp index 814d1e34..1e0a3b11 100644 --- a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp +++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp @@ -774,4 +774,42 @@ bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs) return true; } +bool VerifyTraceRaysIndirectAttribs(const IRenderDevice* pDevice, const TraceRaysIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer, Uint32 SBTSize) +{ +#define CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Trace rays indirect attribs are invalid: ", __VA_ARGS__) + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.pSBT != nullptr, "pSBT must not be null"); + +#ifdef DILIGENT_DEVELOPMENT + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.pSBT->Verify(VERIFY_SBT_FLAG_SHADER_ONLY | VERIFY_SBT_FLAG_TLAS), + "not all shaders in SBT are bound or instance to shader mapping is incorrect."); +#endif // DILIGENT_DEVELOPMENT + + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect dispatch arguments buffer must not be null."); + + const auto& Desc = pAttribsBuffer->GetDesc(); + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS((Desc.BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0, + "indirect trace rays arguments buffer '", Desc.Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.ArgsByteOffset + Attribs.ArgsByteSize <= Desc.uiSizeInBytes, + "indirect trace rays arguments buffer '", Desc.Name, "' is too small."); + + constexpr Uint32 DimSize = sizeof(Uint32) * 3; + if (pDevice->GetDeviceCaps().IsVulkanDevice()) + { + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS((Desc.BindFlags & BIND_RAY_TRACING) != 0, + "indirect trace rays arguments buffer '", Desc.Name, "' was not created with BIND_RAY_TRACING flag."); + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.ArgsByteSize == DimSize || Attribs.ArgsByteSize == DimSize + SBTSize, + "ArgsByteSize must be (", DimSize, ") or (", DimSize + SBTSize, ") bytes"); + } + else + { + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Attribs.ArgsByteSize == DimSize + SBTSize, "ArgsByteSize must be (", DimSize + SBTSize, ") bytes"); + CHECK_TRACE_RAYS_INDIRECT_ATTRIBS(Desc.Usage == USAGE_DEFAULT, + "pAttribsBuffer will be updated inside TraceRaysIndirect(), buffer must be created only with USAGE_DEFAULT"); + } + +#undef CHECK_TRACE_RAYS_INDIRECT_ATTRIBS + + return true; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp index 7dcde7a0..6b217ed4 100644 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp @@ -260,6 +260,9 @@ public: /// Implementation of IDeviceContext::TraceRays(). virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRaysIndirect(). + virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + /// Implementation of IDeviceContextD3D11::GetD3D11DeviceContext(). virtual ID3D11DeviceContext* DILIGENT_CALL_TYPE GetD3D11DeviceContext() override final { return m_pd3d11DeviceContext; } diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index 90a4c73b..9023d33e 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -2292,6 +2292,11 @@ void DeviceContextD3D11Impl::TraceRays(const TraceRaysAttribs& Attribs) UNSUPPORTED("TraceRays is not supported in DirectX 11"); } +void DeviceContextD3D11Impl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) +{ + UNSUPPORTED("TraceRaysIndirect is not supported in DirectX 11"); +} + // clang-format off #ifdef VERIFY_CONTEXT_BINDINGS DEFINE_D3D11CTX_FUNC_POINTERS(GetCBMethods, GetConstantBuffers) diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index 4ff5502d..858ec96e 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -145,6 +145,7 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo UNSUPPORTED_FEATURE(VertexPipelineUAVWritesAndAtomics, "Vertex pipeline UAV writes and atomics are"); UNSUPPORTED_FEATURE(MeshShaders, "Mesh shaders are"); UNSUPPORTED_FEATURE(RayTracing, "Ray tracing is"); + UNSUPPORTED_FEATURE(RayTracing2, "Inline ray tracing is"); UNSUPPORTED_FEATURE(ShaderResourceRuntimeArray, "Runtime-sized array is"); // clang-format on @@ -176,7 +177,7 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo #undef UNSUPPORTED_FEATURE #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif auto& TexCaps = m_DeviceCaps.TexCaps; diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp index 2edf7677..1f453e6e 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp @@ -276,6 +276,9 @@ public: /// Implementation of IDeviceContext::TraceRays() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRaysIndirect() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + /// Implementation of IDeviceContextD3D12::ID3D12GraphicsCommandList() in Direct3D12 backend. virtual ID3D12GraphicsCommandList* DILIGENT_CALL_TYPE GetD3D12CommandList() override final; @@ -373,11 +376,12 @@ private: __forceinline void PrepareForDispatchCompute(ComputeContext& GraphCtx); __forceinline void PrepareForDispatchRays(GraphicsContext& GraphCtx); - __forceinline void PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx, - IBuffer* pAttribsBuffer, - RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode, - ID3D12Resource*& pd3d12ArgsBuff, - Uint64& BuffDataStartByteOffset); + __forceinline void PrepareIndirectBuffer(GraphicsContext& GraphCtx, + IBuffer* pAttribsBuffer, + RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode, + ID3D12Resource*& pd3d12ArgsBuff, + Uint64& BuffDataStartByteOffset, + const char* OpName); struct RootTableInfo { @@ -458,6 +462,7 @@ private: CComPtr m_pDrawIndexedIndirectSignature; CComPtr m_pDispatchIndirectSignature; CComPtr m_pDrawMeshIndirectSignature; + CComPtr m_pTraceRaysIndirectSignature; D3D12DynamicHeap m_DynamicHeap; diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 78f00768..5dd64710 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -135,6 +135,14 @@ DeviceContextD3D12Impl::DeviceContextD3D12Impl(IReferenceCounters* pRef CHECK_D3D_RESULT_THROW(hr, "Failed to create draw mesh indirect command signature"); } #endif + if (pDeviceD3D12Impl->GetDeviceCaps().Features.RayTracing2 == DEVICE_FEATURE_STATE_ENABLED) + { + CmdSignatureDesc.ByteStride = sizeof(D3D12_DISPATCH_RAYS_DESC); + IndirectArg.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_RAYS; + hr = pd3d12Device->CreateCommandSignature(&CmdSignatureDesc, nullptr, __uuidof(m_pTraceRaysIndirectSignature), reinterpret_cast(static_cast(&m_pTraceRaysIndirectSignature))); + CHECK_D3D_RESULT_THROW(hr, "Failed to create trace rays indirect command signature"); + static_assert(TraceRaysIndirectCommandSBTSize == offsetof(D3D12_DISPATCH_RAYS_DESC, Width), "Invalid SBT offsets size"); + } } DeviceContextD3D12Impl::~DeviceContextD3D12Impl() @@ -619,11 +627,12 @@ void DeviceContextD3D12Impl::DrawIndexed(const DrawIndexedAttribs& Attribs) ++m_State.NumCommands; } -void DeviceContextD3D12Impl::PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx, - IBuffer* pAttribsBuffer, - RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode, - ID3D12Resource*& pd3d12ArgsBuff, - Uint64& BuffDataStartByteOffset) +void DeviceContextD3D12Impl::PrepareIndirectBuffer(GraphicsContext& GraphCtx, + IBuffer* pAttribsBuffer, + RESOURCE_STATE_TRANSITION_MODE BufferStateTransitionMode, + ID3D12Resource*& pd3d12ArgsBuff, + Uint64& BuffDataStartByteOffset, + const char* OpName) { DEV_CHECK_ERR(pAttribsBuffer != nullptr, "Indirect draw attribs buffer must not be null"); @@ -634,8 +643,7 @@ void DeviceContextD3D12Impl::PrepareDrawIndirectBuffer(GraphicsContext& #endif TransitionOrVerifyBufferState(GraphCtx, *pIndirectDrawAttribsD3D12, BufferStateTransitionMode, - RESOURCE_STATE_INDIRECT_ARGUMENT, - "Indirect draw (DeviceContextD3D12Impl::PrepareDrawIndirectBuffer)"); + RESOURCE_STATE_INDIRECT_ARGUMENT, OpName); pd3d12ArgsBuff = pIndirectDrawAttribsD3D12->GetD3D12Buffer(BuffDataStartByteOffset, this); } @@ -650,7 +658,8 @@ void DeviceContextD3D12Impl::DrawIndirect(const DrawIndirectAttribs& Attribs, IB ID3D12Resource* pd3d12ArgsBuff; Uint64 BuffDataStartByteOffset; - PrepareDrawIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset); + PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset, + "Indirect draw (DeviceContextD3D12Impl::DrawIndirect)"); GraphCtx.ExecuteIndirect(m_pDrawIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset); ++m_State.NumCommands; @@ -666,7 +675,8 @@ void DeviceContextD3D12Impl::DrawIndexedIndirect(const DrawIndexedIndirectAttrib ID3D12Resource* pd3d12ArgsBuff; Uint64 BuffDataStartByteOffset; - PrepareDrawIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset); + PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset, + "Indexed indirect draw (DeviceContextD3D12Impl::DrawIndexedIndirect)"); GraphCtx.ExecuteIndirect(m_pDrawIndexedIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset); ++m_State.NumCommands; @@ -694,7 +704,8 @@ void DeviceContextD3D12Impl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Att ID3D12Resource* pd3d12ArgsBuff; Uint64 BuffDataStartByteOffset; - PrepareDrawIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset); + PrepareIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset, + "Indirect draw mesh (DeviceContextD3D12Impl::DrawMeshIndirect)"); GraphCtx.ExecuteIndirect(m_pDrawMeshIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset); ++m_State.NumCommands; @@ -2772,4 +2783,72 @@ void DeviceContextD3D12Impl::TraceRays(const TraceRaysAttribs& Attribs) ++m_State.NumCommands; } +void DeviceContextD3D12Impl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) +{ + if (!TDeviceContextBase::TraceRaysIndirect(Attribs, pAttribsBuffer, 0)) + return; + + auto& CmdCtx = GetCmdContext().AsGraphicsContext4(); + auto* pSBTD3D12 = ValidatedCast(Attribs.pSBT); + IBuffer* pSBTBuffer = nullptr; + + ShaderBindingTableD3D12Impl::BindingTable RayGenShaderRecord = {}; + ShaderBindingTableD3D12Impl::BindingTable MissShaderTable = {}; + ShaderBindingTableD3D12Impl::BindingTable HitGroupTable = {}; + ShaderBindingTableD3D12Impl::BindingTable CallableShaderTable = {}; + + pSBTD3D12->GetData(pSBTBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable); + + auto* pSBTBufferD3D12 = ValidatedCast(pSBTBuffer); + + const char* OpName = "Trace rays indirect (DeviceContextD3D12Impl::TraceRaysIndirect)"; + + if (RayGenShaderRecord.pData || MissShaderTable.pData || HitGroupTable.pData || CallableShaderTable.pData) + { + TransitionOrVerifyBufferState(CmdCtx, *pSBTBufferD3D12, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_COPY_DEST, OpName); + + // buffer ranges are not intersected, so we don't need to add barriers between them + if (RayGenShaderRecord.pData) + UpdateBuffer(pSBTBufferD3D12, RayGenShaderRecord.Offset, RayGenShaderRecord.Size, RayGenShaderRecord.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (MissShaderTable.pData) + UpdateBuffer(pSBTBufferD3D12, MissShaderTable.Offset, MissShaderTable.Size, MissShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (HitGroupTable.pData) + UpdateBuffer(pSBTBufferD3D12, HitGroupTable.Offset, HitGroupTable.Size, HitGroupTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (CallableShaderTable.pData) + UpdateBuffer(pSBTBufferD3D12, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + } + TransitionOrVerifyBufferState(CmdCtx, *pSBTBufferD3D12, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_RAY_TRACING, OpName); + + D3D12_DISPATCH_RAYS_DESC d3d12DispatchDesc = {}; + + d3d12DispatchDesc.RayGenerationShaderRecord.StartAddress = pSBTBufferD3D12->GetGPUAddress() + RayGenShaderRecord.Offset; + d3d12DispatchDesc.RayGenerationShaderRecord.SizeInBytes = RayGenShaderRecord.Size; + + d3d12DispatchDesc.MissShaderTable.StartAddress = pSBTBufferD3D12->GetGPUAddress() + MissShaderTable.Offset; + d3d12DispatchDesc.MissShaderTable.SizeInBytes = MissShaderTable.Size; + d3d12DispatchDesc.MissShaderTable.StrideInBytes = MissShaderTable.Stride; + + d3d12DispatchDesc.HitGroupTable.StartAddress = pSBTBufferD3D12->GetGPUAddress() + HitGroupTable.Offset; + d3d12DispatchDesc.HitGroupTable.SizeInBytes = HitGroupTable.Size; + d3d12DispatchDesc.HitGroupTable.StrideInBytes = HitGroupTable.Stride; + + d3d12DispatchDesc.CallableShaderTable.StartAddress = pSBTBufferD3D12->GetGPUAddress() + CallableShaderTable.Offset; + d3d12DispatchDesc.CallableShaderTable.SizeInBytes = CallableShaderTable.Size; + d3d12DispatchDesc.CallableShaderTable.StrideInBytes = CallableShaderTable.Stride; + + // copy dispath description with shader table data and keep dimension + UpdateBuffer(pAttribsBuffer, Attribs.ArgsByteOffset, offsetof(D3D12_DISPATCH_RAYS_DESC, Width), &d3d12DispatchDesc, Attribs.IndirectAttribsBufferStateTransitionMode); + + auto* pAttribsBufferD3D12 = ValidatedCast(pAttribsBuffer); + TransitionOrVerifyBufferState(CmdCtx, *pAttribsBufferD3D12, Attribs.IndirectAttribsBufferStateTransitionMode, RESOURCE_STATE_INDIRECT_ARGUMENT, OpName); + + PrepareForDispatchRays(CmdCtx); + + CmdCtx.ExecuteIndirect(m_pTraceRaysIndirectSignature, pAttribsBufferD3D12->GetD3D12Resource(), Attribs.ArgsByteOffset); + ++m_State.NumCommands; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 25ce0695..15042442 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -251,6 +251,10 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo { m_DeviceCaps.Features.RayTracing = DEVICE_FEATURE_STATE_ENABLED; } + if (d3d12Features.RaytracingTier >= D3D12_RAYTRACING_TIER_1_1) + { + m_DeviceCaps.Features.RayTracing2 = DEVICE_FEATURE_STATE_ENABLED; + } } } @@ -299,11 +303,12 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo CHECK_REQUIRED_FEATURE(UniformBuffer8BitAccess, "8-bit uniform buffer access is"); CHECK_REQUIRED_FEATURE(RayTracing, "ray tracing is"); + CHECK_REQUIRED_FEATURE(RayTracing2, "inline ray tracing is"); // clang-format on #undef CHECK_REQUIRED_FEATURE #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif auto& TexCaps = m_DeviceCaps.TexCaps; diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp index 867179af..f33b9d2c 100644 --- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp @@ -261,6 +261,9 @@ public: /// Implementation of IDeviceContext::TraceRays() in OpenGL backend. virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRaysIndirect() in OpenGL backend. + virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + /// Implementation of IDeviceContextGL::UpdateCurrentGLContext(). virtual bool DILIGENT_CALL_TYPE UpdateCurrentGLContext() override final; diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index c613ca7d..9958c238 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -1648,4 +1648,9 @@ void DeviceContextGLImpl::TraceRays(const TraceRaysAttribs& Attribs) UNSUPPORTED("TraceRays is not supported in OpenGL"); } +void DeviceContextGLImpl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) +{ + UNSUPPORTED("TraceRaysIndirect is not supported in OpenGL"); +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index 8cf07274..8950671e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -302,9 +302,12 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, } \ } while (false) + // clang-format off SET_FEATURE_STATE(VertexPipelineUAVWritesAndAtomics, false, "Vertex pipeline UAV writes and atomics are"); - SET_FEATURE_STATE(MeshShaders, false, "Mesh shaders are"); - SET_FEATURE_STATE(RayTracing, false, "Ray tracing is"); + SET_FEATURE_STATE(MeshShaders, false, "Mesh shaders are"); + SET_FEATURE_STATE(RayTracing, false, "Ray tracing is"); + SET_FEATURE_STATE(RayTracing2, false, "Inline ray tracing is"); + // clang-format on { bool WireframeFillSupported = (glPolygonMode != nullptr); @@ -457,7 +460,7 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, #undef SET_FEATURE_STATE #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif // get device limits diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index ed2adf11..ee207091 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -269,6 +269,9 @@ public: /// Implementation of IDeviceContext::TraceRays() in Vulkan backend. virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRaysIndirect() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) 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. @@ -451,7 +454,7 @@ private: __forceinline void PrepareForDraw(DRAW_FLAGS Flags); __forceinline void PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType); - __forceinline BufferVkImpl* PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode); + __forceinline BufferVkImpl* PrepareIndirectAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode, const char* OpName); __forceinline void PrepareForDispatchCompute(); __forceinline void PrepareForRayTracing(); diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp index 7f15e642..49a37dc2 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp @@ -670,6 +670,22 @@ public: #endif } + __forceinline void TraceRaysIndirect(const VkStridedDeviceAddressRegionKHR& RaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR& MissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR& HitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR& CallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress) + { +#if DILIGENT_USE_VOLK + VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); + VERIFY(m_State.RayTracingPipeline != VK_NULL_HANDLE, "No ray tracing pipeline bound"); + + vkCmdTraceRaysIndirectKHR(m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, indirectDeviceAddress); +#else + UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically"); +#endif + } + void FlushBarriers(); __forceinline void SetVkCmdBuffer(VkCommandBuffer VkCmdBuffer) diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp index 38813f20..5f17d666 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp @@ -45,6 +45,7 @@ public: VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {}; VkPhysicalDeviceAccelerationStructureFeaturesKHR AccelStruct = {}; VkPhysicalDeviceRayTracingPipelineFeaturesKHR RayTracingPipeline = {}; + VkPhysicalDeviceRayQueryFeaturesKHR RayQuery = {}; bool Spirv14 = false; // Ray tracing requires Vulkan 1.2 or SPIRV 1.4 extension bool Spirv15 = false; // DXC shaders with ray tracing requires Vulkan 1.2 with SPIRV 1.5 VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {}; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 723e2c7c..0707a989 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -792,7 +792,9 @@ void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags) #endif } -BufferVkImpl* DeviceContextVkImpl::PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode) +BufferVkImpl* DeviceContextVkImpl::PrepareIndirectAttribsBuffer(IBuffer* pAttribsBuffer, + RESOURCE_STATE_TRANSITION_MODE TransitonMode, + const char* OpName) { DEV_CHECK_ERR(pAttribsBuffer, "Indirect draw attribs buffer must not be null"); auto* pIndirectDrawAttribsVk = ValidatedCast(pAttribsBuffer); @@ -804,7 +806,7 @@ BufferVkImpl* DeviceContextVkImpl::PrepareIndirectDrawAttribsBuffer(IBuffer* pAt // Buffer memory barries must be executed outside of render pass TransitionOrVerifyBufferState(*pIndirectDrawAttribsVk, TransitonMode, RESOURCE_STATE_INDIRECT_ARGUMENT, - VK_ACCESS_INDIRECT_COMMAND_READ_BIT, "Indirect draw (DeviceContextVkImpl::Draw)"); + VK_ACCESS_INDIRECT_COMMAND_READ_BIT, OpName); return pIndirectDrawAttribsVk; } @@ -852,7 +854,7 @@ void DeviceContextVkImpl::DrawIndirect(const DrawIndirectAttribs& Attribs, IBuff // 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); + BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, "Indirect draw (DeviceContextVkImpl::DrawIndirect)"); PrepareForDraw(Attribs.Flags); @@ -867,7 +869,7 @@ void DeviceContextVkImpl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs& // 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); + BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, "Indirect draw (DeviceContextVkImpl::DrawIndexedIndirect)"); PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType); @@ -893,7 +895,7 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib // 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); + BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, "Indirect draw (DeviceContextVkImpl::DrawMeshIndirect)"); PrepareForDraw(Attribs.Flags); @@ -3471,4 +3473,56 @@ void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) ++m_State.NumCommands; } +void DeviceContextVkImpl::TraceRaysIndirect(const TraceRaysIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) +{ + if (!TDeviceContextBase::TraceRaysIndirect(Attribs, pAttribsBuffer, 0)) + return; + + auto* pSBTVk = ValidatedCast(Attribs.pSBT); + IBuffer* pBuffer = nullptr; + + ShaderBindingTableVkImpl::BindingTable RayGenShaderRecord = {}; + ShaderBindingTableVkImpl::BindingTable MissShaderTable = {}; + ShaderBindingTableVkImpl::BindingTable HitGroupTable = {}; + ShaderBindingTableVkImpl::BindingTable CallableShaderTable = {}; + + pSBTVk->GetData(pBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable); + + const char* OpName = "Trace rays indirect (DeviceContextVkImpl::TraceRaysIndirect)"; + auto* const pSBTBufferVk = ValidatedCast(pBuffer); + auto* const pIndirectAttribsVk = PrepareIndirectAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, OpName); + const auto IndirectBuffOffset = Attribs.ArgsByteOffset + (Attribs.ArgsByteSize == sizeof(Uint32) * 3 ? 0 : TraceRaysIndirectCommandSBTSize); + + if (RayGenShaderRecord.pData || MissShaderTable.pData || HitGroupTable.pData || CallableShaderTable.pData) + { + TransitionOrVerifyBufferState(*pSBTBufferVk, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + + // buffer ranges are not intersected, so we don't need to add barriers between them + if (RayGenShaderRecord.pData) + UpdateBuffer(pBuffer, RayGenShaderRecord.Offset, RayGenShaderRecord.Size, RayGenShaderRecord.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (MissShaderTable.pData) + UpdateBuffer(pBuffer, MissShaderTable.Offset, MissShaderTable.Size, MissShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (HitGroupTable.pData) + UpdateBuffer(pBuffer, HitGroupTable.Offset, HitGroupTable.Size, HitGroupTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (CallableShaderTable.pData) + UpdateBuffer(pBuffer, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + } + TransitionOrVerifyBufferState(*pSBTBufferVk, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_RAY_TRACING, VK_ACCESS_SHADER_READ_BIT, OpName); + + // clang-format off + VkStridedDeviceAddressRegionKHR RaygenShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size }; + VkStridedDeviceAddressRegionKHR MissShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size }; + VkStridedDeviceAddressRegionKHR HitShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size }; + VkStridedDeviceAddressRegionKHR CallableShaderBindingTable = {pSBTBufferVk->GetVkDeviceAddress() + CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size}; + // clang-format on + + PrepareForRayTracing(); + m_CommandBuffer.TraceRaysIndirect(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable, + pIndirectAttribsVk->GetVkDeviceAddress() + IndirectBuffOffset); + ++m_State.NumCommands; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 7e08a361..027fa892 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -138,7 +138,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E try { Uint32 Version = VK_API_VERSION_1_0; - if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED) + if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.RayTracing2 != DEVICE_FEATURE_STATE_DISABLED) Version = VK_API_VERSION_1_2; auto Instance = VulkanUtilities::VulkanInstance::Create( @@ -280,8 +280,18 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E const auto& DescrIndexingFeats = DeviceExtFeatures.DescriptorIndexing; ENABLE_FEATURE(DescrIndexingFeats.runtimeDescriptorArray != VK_FALSE, ShaderResourceRuntimeArray, "Shader resource runtime array is"); - - ENABLE_FEATURE(DeviceExtFeatures.AccelStruct.accelerationStructure != VK_FALSE && DeviceExtFeatures.RayTracingPipeline.rayTracingPipeline != VK_FALSE, RayTracing, "Ray tracing is"); + const auto& AccelStructFeats = DeviceExtFeatures.AccelStruct; + const auto& RayTracingFeats = DeviceExtFeatures.RayTracingPipeline; + const auto& RayQueryFeats = DeviceExtFeatures.RayQuery; + // clang-format off + ENABLE_FEATURE(AccelStructFeats.accelerationStructure != VK_FALSE && + RayTracingFeats.rayTracingPipeline != VK_FALSE, RayTracing, "Ray tracing is"); + ENABLE_FEATURE(AccelStructFeats.accelerationStructure != VK_FALSE && + RayTracingFeats.rayTracingPipeline != VK_FALSE && + RayTracingFeats.rayTracingPipelineTraceRaysIndirect != VK_FALSE && + RayTracingFeats.rayTraversalPrimitiveCulling != VK_FALSE && + RayQueryFeats.rayQuery != VK_FALSE, RayTracing2, "Inline ray tracing is"); + // clang-format on #undef FeatureSupport @@ -417,13 +427,13 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E } // Ray tracing - if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED) + if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.RayTracing2 != DEVICE_FEATURE_STATE_DISABLED) { // this extensions added to Vulkan 1.2 core if (!DeviceExtFeatures.Spirv15) { DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); // required for VK_KHR_spirv_1_4 - DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for VK_KHR_ray_tracing_pipeline + DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for VK_KHR_ray_tracing_pipeline or VK_KHR_ray_query EnabledExtFeats.Spirv14 = DeviceExtFeatures.Spirv14; VERIFY_EXPR(DeviceExtFeatures.Spirv14); } @@ -439,14 +449,11 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // disable unused features EnabledExtFeats.AccelStruct.accelerationStructureCaptureReplay = false; - EnabledExtFeats.AccelStruct.accelerationStructureIndirectBuild = false; EnabledExtFeats.AccelStruct.accelerationStructureHostCommands = false; EnabledExtFeats.AccelStruct.descriptorBindingAccelerationStructureUpdateAfterBind = false; EnabledExtFeats.RayTracingPipeline.rayTracingPipelineShaderGroupHandleCaptureReplay = false; EnabledExtFeats.RayTracingPipeline.rayTracingPipelineShaderGroupHandleCaptureReplayMixed = false; - EnabledExtFeats.RayTracingPipeline.rayTracingPipelineTraceRaysIndirect = false; - EnabledExtFeats.RayTracingPipeline.rayTraversalPrimitiveCulling = false; // for GLSL_EXT_ray_flags_primitive_culling *NextExt = &EnabledExtFeats.AccelStruct; NextExt = &EnabledExtFeats.AccelStruct.pNext; @@ -454,6 +461,23 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E NextExt = &EnabledExtFeats.RayTracingPipeline.pNext; *NextExt = &EnabledExtFeats.BufferDeviceAddress; NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext; + + // Inline ray tracing from any shader. + if (EngineCI.Features.RayTracing2 != DEVICE_FEATURE_STATE_DISABLED) + { + DeviceExtensions.push_back(VK_KHR_RAY_QUERY_EXTENSION_NAME); + + EnabledExtFeats.RayQuery = RayQueryFeats; + + *NextExt = &EnabledExtFeats.RayQuery; + NextExt = &EnabledExtFeats.RayQuery.pNext; + } + else + { + EnabledExtFeats.AccelStruct.accelerationStructureIndirectBuild = false; + EnabledExtFeats.RayTracingPipeline.rayTracingPipelineTraceRaysIndirect = false; + EnabledExtFeats.RayTracingPipeline.rayTraversalPrimitiveCulling = false; // for GLSL_EXT_ray_flags_primitive_culling + } } // make sure that last pNext is null @@ -461,7 +485,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E } #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 8debcd97..e1ce9efa 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -234,7 +234,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED; #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary)."); + static_assert(sizeof(DeviceFeatures) == 34, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary)."); #endif const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits; diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index 343893e9..cf1cbd3f 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -146,6 +146,15 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.RayTracingPipeline.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR; } + // Get inline ray tracing features. + if (IsExtensionSupported(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + { + *NextFeat = &m_ExtFeatures.RayQuery; + NextFeat = &m_ExtFeatures.RayQuery.pNext; + + m_ExtFeatures.RayQuery.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR; + } + // Additional extension that is required for ray tracing. if (IsExtensionSupported(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) { diff --git a/Graphics/ShaderTools/src/DXCompiler.cpp b/Graphics/ShaderTools/src/DXCompiler.cpp index 549c5b48..488a1e00 100644 --- a/Graphics/ShaderTools/src/DXCompiler.cpp +++ b/Graphics/ShaderTools/src/DXCompiler.cpp @@ -725,13 +725,12 @@ void DXCompilerImpl::Compile(const ShaderCreateInfo& ShaderCI, else DxilArgs.push_back(L"-Od"); // TODO: something goes wrong if optimization is enabled #endif + DEV_CHECK_ERR((ShaderCI.CompileFlags & SHADER_COMPILE_FLAG_ENABLE_INLINE_RAY_TRACING) == 0 || + (ShaderModel.Major > 6 || (ShaderModel.Major == 6 && ShaderModel.Minor >= 5)), + "Inline ray tracing requires Shader Model 6.5 and above"); } else if (m_Target == DXCompilerTarget::Vulkan) { - const Uint32 RayTracingStages = - SHADER_TYPE_RAY_GEN | SHADER_TYPE_RAY_MISS | SHADER_TYPE_RAY_CLOSEST_HIT | - SHADER_TYPE_RAY_ANY_HIT | SHADER_TYPE_RAY_INTERSECTION | SHADER_TYPE_CALLABLE; - DxilArgs.assign( { L"-spirv", @@ -740,9 +739,10 @@ void DXCompilerImpl::Compile(const ShaderCreateInfo& ShaderCI, L"-O3", // Optimization level 3 }); - if (ShaderCI.Desc.ShaderType & RayTracingStages) + if ((ShaderCI.Desc.ShaderType & SHADER_TYPE_ALL_RAY_TRACING) != 0 || + (ShaderCI.CompileFlags & SHADER_COMPILE_FLAG_ENABLE_INLINE_RAY_TRACING) != 0) { - DxilArgs.push_back(L"-fspv-target-env=vulkan1.2"); // required for SPV_KHR_ray_tracing + DxilArgs.push_back(L"-fspv-target-env=vulkan1.2"); // required for SPV_KHR_ray_tracing and SPV_KHR_ray_query } } else -- cgit v1.2.3