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. --- .../include/DeviceContextD3D12Impl.hpp | 15 ++-- .../src/DeviceContextD3D12Impl.cpp | 99 +++++++++++++++++++--- .../src/RenderDeviceD3D12Impl.cpp | 7 +- 3 files changed, 105 insertions(+), 16 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') 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; -- cgit v1.2.3