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 ++++++++++++++++++ 5 files changed, 133 insertions(+), 4 deletions(-) (limited to 'Graphics/GraphicsEngine') 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 -- cgit v1.2.3