diff options
| author | azhirnov <zh1dron@gmail.com> | 2020-10-28 16:33:03 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2020-10-28 18:04:08 +0000 |
| commit | 135d5dc6743fc89d7a19c539fa06eca33506f51b (patch) | |
| tree | 9c8ed6e0d40a010f20657e62acbe955fba0757da /Graphics/GraphicsEngineD3D12 | |
| parent | Fixed vexing gcc/clang liker error (diff) | |
| download | DiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.tar.gz DiligentCore-135d5dc6743fc89d7a19c539fa06eca33506f51b.zip | |
added ray tracing implementation for dx12 and vulkan
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
26 files changed, 1512 insertions, 149 deletions
diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt index 9941b62b..611bcbda 100644 --- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt @@ -37,6 +37,9 @@ set(INCLUDE include/SwapChainD3D12Impl.hpp include/TextureD3D12Impl.hpp include/TextureViewD3D12Impl.hpp + include/BottomLevelASD3D12Impl.hpp + include/TopLevelASD3D12Impl.hpp + include/ShaderBindingTableD3D12Impl.hpp ) set(INTERFACE @@ -55,6 +58,9 @@ set(INTERFACE interface/SwapChainD3D12.h interface/TextureD3D12.h interface/TextureViewD3D12.h + interface/BottomLevelASD3D12.h + interface/TopLevelASD3D12.h + interface/ShaderBindingTableD3D12.h ) @@ -89,6 +95,9 @@ set(SRC src/SwapChainD3D12Impl.cpp src/TextureD3D12Impl.cpp src/TextureViewD3D12Impl.cpp + src/BottomLevelASD3D12Impl.cpp + src/TopLevelASD3D12Impl.cpp + src/ShaderBindingTableD3D12Impl.cpp ) if(PLATFORM_WIN32) diff --git a/Graphics/GraphicsEngineD3D12/include/BottomLevelASD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/BottomLevelASD3D12Impl.hpp new file mode 100644 index 00000000..b631bdcc --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/BottomLevelASD3D12Impl.hpp @@ -0,0 +1,74 @@ +/* + * 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 +/// Declaration of Diligent::BottomLevelASD3D12Impl class + +#include "BottomLevelASD3D12.h" +#include "RenderDeviceD3D12.h" +#include "BottomLevelASBase.hpp" +#include "D3D12ResourceBase.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +/// Bottom-level acceleration structure object implementation in Direct3D12 backend. +class BottomLevelASD3D12Impl final : public BottomLevelASBase<IBottomLevelASD3D12, RenderDeviceD3D12Impl>, public D3D12ResourceBase +{ +public: + using TBottomLevelASBase = BottomLevelASBase<IBottomLevelASD3D12, RenderDeviceD3D12Impl>; + + BottomLevelASD3D12Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const BottomLevelASDesc& Desc, + bool bIsDeviceInternal = false); + ~BottomLevelASD3D12Impl(); + + virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of IBottomLevelAS::GetScratchBufferSizes() in DirectX 12 backend. + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; } + + /// Implementation of IBottomLevelASD3D12::GetD3D12BLAS(). + virtual ID3D12Resource* DILIGENT_CALL_TYPE GetD3D12BLAS() override final { return GetD3D12Resource(); } + + /// Implementation of IBottomLevelAS::GetNativeHandle() in Direct3D12 backend. + virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final { return GetD3D12BLAS(); } + + D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress() + { + return GetD3D12Resource()->GetGPUVirtualAddress(); + } + +private: + ScratchBufferSizes m_ScratchSize; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp index ab90dfe7..ad3027a8 100644 --- a/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/BufferD3D12Impl.hpp @@ -103,6 +103,12 @@ public: } } + __forceinline D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress() + { + VERIFY_EXPR(m_Desc.Usage != USAGE_DYNAMIC); + return GetD3D12Resource()->GetGPUVirtualAddress(); + } + D3D12_CPU_DESCRIPTOR_HANDLE GetCBVHandle() { return m_CBVDescriptorAllocation.GetCpuHandle(); } private: diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp index 94f74933..511f1a03 100644 --- a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp +++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp @@ -34,6 +34,8 @@ #include "TextureViewD3D12.h" #include "TextureD3D12.h" #include "BufferD3D12.h" +#include "BottomLevelASD3D12.h" +#include "TopLevelASD3D12.h" #include "DescriptorHeap.hpp" namespace Diligent @@ -114,6 +116,8 @@ public: void TransitionResource(ITextureD3D12* pTexture, RESOURCE_STATE NewState); void TransitionResource(IBufferD3D12* pBuffer, RESOURCE_STATE NewState); + void TransitionResource(IBottomLevelASD3D12* pBLAS, RESOURCE_STATE NewState); + void TransitionResource(ITopLevelASD3D12* pTLAS, RESOURCE_STATE NewState); void TransitionResource(const StateTransitionDesc& Barrier); //void BeginResourceTransition(GpuResource& Resource, D3D12_RESOURCE_STATES NewState, bool FlushImmediate = false); @@ -238,8 +242,25 @@ protected: Uint32 m_MaxInterfaceVer = 0; }; +class ComputeContext : public CommandContext +{ +public: + void SetComputeRootSignature(ID3D12RootSignature* pRootSig) + { + if (pRootSig != m_pCurComputeRootSignature) + { + m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig); + } + } -class GraphicsContext : public CommandContext + void Dispatch(size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1) + { + FlushResourceBarriers(); + m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ); + } +}; + +class GraphicsContext : public ComputeContext { public: void ClearRenderTarget(D3D12_CPU_DESCRIPTOR_HANDLE RTV, const float* Color) @@ -254,7 +275,7 @@ public: m_pCommandList->ClearDepthStencilView(DSV, ClearFlags, Depth, Stencil, 0, nullptr); } - void SetRootSignature(ID3D12RootSignature* pRootSig) + void SetGraphicsRootSignature(ID3D12RootSignature* pRootSig) { if (pRootSig != m_pCurGraphicsRootSignature) { @@ -291,47 +312,6 @@ public: } } - void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants) - { - m_pCommandList->SetGraphicsRoot32BitConstants(RootIndex, NumConstants, pConstants, 0); - } - - void SetConstants(UINT RootIndex, DWParam X) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W) - { - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, Z.Uint, 2); - m_pCommandList->SetGraphicsRoot32BitConstant(RootIndex, W.Uint, 3); - } - - void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV) - { - m_pCommandList->SetGraphicsRootConstantBufferView(RootIndex, CBV); - } - - void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle) - { - m_pCommandList->SetGraphicsRootDescriptorTable(RootIndex, FirstHandle); - } - void SetIndexBuffer(const D3D12_INDEX_BUFFER_VIEW& IBView) { m_pCommandList->IASetIndexBuffer(&IBView); @@ -384,83 +364,62 @@ public: { static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->EndRenderPass(); } -}; -class GraphicsContext5 : public GraphicsContext4 -{ -}; - -class GraphicsContext6 : public GraphicsContext5 -{ -public: - void DrawMesh(UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ) + void SetRayTracingPipelineState(ID3D12StateObject* pPSO) { -#ifdef D3D12_H_HAS_MESH_SHADER - FlushResourceBarriers(); - static_cast<ID3D12GraphicsCommandList6*>(m_pCommandList.p)->DispatchMesh(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ); -#else - UNSUPPORTED("DrawMesh is not supported in current D3D12 header"); -#endif - } -}; - -class ComputeContext : public CommandContext -{ -public: - void SetRootSignature(ID3D12RootSignature* pRootSig) - { - if (pRootSig != m_pCurComputeRootSignature) + if (pPSO != m_pCurPipelineState) { - m_pCommandList->SetComputeRootSignature(m_pCurComputeRootSignature = pRootSig); + static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->SetPipelineState1(pPSO); + m_pCurPipelineState = pPSO; } } - void SetConstants(UINT RootIndex, UINT NumConstants, const void* pConstants) - { - m_pCommandList->SetComputeRoot32BitConstants(RootIndex, NumConstants, pConstants, 0); - } - - void SetConstants(UINT RootIndex, DWParam X) - { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - } - - void SetConstants(UINT RootIndex, DWParam X, DWParam Y) + void BuildRaytracingAccelerationStructure(const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& Desc, + UINT NumPostbuildInfoDescs, + const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC* pPostbuildInfoDescs) { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); + FlushResourceBarriers(); + static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->BuildRaytracingAccelerationStructure(&Desc, NumPostbuildInfoDescs, pPostbuildInfoDescs); } - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z) + void EmitRaytracingAccelerationStructurePostbuildInfo(const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC& Desc, + UINT NumSourceAccelerationStructures, + const D3D12_GPU_VIRTUAL_ADDRESS* pSourceAccelerationStructureData) { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2); + FlushResourceBarriers(); + static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->EmitRaytracingAccelerationStructurePostbuildInfo(&Desc, NumSourceAccelerationStructures, pSourceAccelerationStructureData); } - void SetConstants(UINT RootIndex, DWParam X, DWParam Y, DWParam Z, DWParam W) + void CopyRaytracingAccelerationStructure(D3D12_GPU_VIRTUAL_ADDRESS DestAccelerationStructureData, + D3D12_GPU_VIRTUAL_ADDRESS SourceAccelerationStructureData, + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE Mode) { - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, X.Uint, 0); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Y.Uint, 1); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, Z.Uint, 2); - m_pCommandList->SetComputeRoot32BitConstant(RootIndex, W.Uint, 3); + FlushResourceBarriers(); + static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->CopyRaytracingAccelerationStructure(DestAccelerationStructureData, SourceAccelerationStructureData, Mode); } - - void SetConstantBuffer(UINT RootIndex, D3D12_GPU_VIRTUAL_ADDRESS CBV) + void DispatchRays(const D3D12_DISPATCH_RAYS_DESC& Desc) { - m_pCommandList->SetComputeRootConstantBufferView(RootIndex, CBV); + FlushResourceBarriers(); + static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->DispatchRays(&Desc); } +}; - void SetDescriptorTable(UINT RootIndex, D3D12_GPU_DESCRIPTOR_HANDLE FirstHandle) - { - m_pCommandList->SetComputeRootDescriptorTable(RootIndex, FirstHandle); - } +class GraphicsContext5 : public GraphicsContext4 +{ +}; - void Dispatch(size_t GroupCountX = 1, size_t GroupCountY = 1, size_t GroupCountZ = 1) +class GraphicsContext6 : public GraphicsContext5 +{ +public: + void DrawMesh(UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ) { +#ifdef D3D12_H_HAS_MESH_SHADER FlushResourceBarriers(); - m_pCommandList->Dispatch((UINT)GroupCountX, (UINT)GroupCountY, (UINT)GroupCountZ); + static_cast<ID3D12GraphicsCommandList6*>(m_pCommandList.p)->DispatchMesh(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ); +#else + UNSUPPORTED("DrawMesh is not supported in current D3D12 header"); +#endif } }; diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp index 240ea165..e3a78c6c 100644 --- a/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp +++ b/Graphics/GraphicsEngineD3D12/include/D3D12ResourceBase.hpp @@ -43,7 +43,7 @@ public: ID3D12Resource* GetD3D12Resource() { return m_pd3d12Resource; } protected: - CComPtr<ID3D12Resource> m_pd3d12Resource; ///< D3D12 buffer object + CComPtr<ID3D12Resource> m_pd3d12Resource; ///< D3D12 resource object }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp index c6678ddd..389b76a1 100644 --- a/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp +++ b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp @@ -78,5 +78,9 @@ D3D12_RENDER_PASS_ENDING_ACCESS_TYPE AttachmentStoreOpToD3D12EndingAccessType D3D12_SHADER_VISIBILITY ShaderTypeToD3D12ShaderVisibility(SHADER_TYPE ShaderType); SHADER_TYPE D3D12ShaderVisibilityToShaderType(D3D12_SHADER_VISIBILITY ShaderVisibility); +DXGI_FORMAT ValueTypeToIndexType(VALUE_TYPE Type); + +D3D12_RAYTRACING_GEOMETRY_FLAGS GeometryFlagsToD3D12RTGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags); +D3D12_RAYTRACING_INSTANCE_FLAGS InstanceFlagsToD3D12RTInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags); } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp index 39a354dd..3ac65274 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp @@ -42,6 +42,8 @@ #include "RenderPassD3D12Impl.hpp" #include "PipelineStateD3D12Impl.hpp" #include "D3D12DynamicHeap.hpp" +#include "BottomLevelASD3D12Impl.hpp" +#include "TopLevelASD3D12Impl.hpp" namespace Diligent { @@ -56,6 +58,8 @@ struct DeviceContextD3D12ImplTraits using QueryType = QueryD3D12Impl; using FramebufferType = FramebufferD3D12Impl; using RenderPassType = RenderPassD3D12Impl; + using BottomLevelASType = BottomLevelASD3D12Impl; + using TopLevelASType = TopLevelASD3D12Impl; }; /// Device context implementation in Direct3D12 backend. @@ -125,13 +129,13 @@ public: ITextureView* pDepthStencil, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - /// Implementation of IDeviceContext::BeginRenderPass() in Direct3D11 backend. + /// Implementation of IDeviceContext::BeginRenderPass() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE BeginRenderPass(const BeginRenderPassAttribs& Attribs) override final; - /// Implementation of IDeviceContext::NextSubpass() in Direct3D11 backend. + /// Implementation of IDeviceContext::NextSubpass() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE NextSubpass() override final; - /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend. + /// Implementation of IDeviceContext::EndRenderPass() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE EndRenderPass() override final; // clang-format off @@ -351,12 +355,23 @@ private: RESOURCE_STATE_TRANSITION_MODE TransitionMode, RESOURCE_STATE RequiredState, const char* OperationName); + __forceinline void TransitionOrVerifyBLASState(CommandContext& CmdCtx, + BottomLevelASD3D12Impl& BLAS, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + RESOURCE_STATE RequiredState, + const char* OperationName); + __forceinline void TransitionOrVerifyTLASState(CommandContext& CmdCtx, + TopLevelASD3D12Impl& TLAS, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + RESOURCE_STATE RequiredState, + const char* OperationName); __forceinline void PrepareForDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags); __forceinline void PrepareForIndexedDraw(GraphicsContext& GraphCtx, DRAW_FLAGS Flags, VALUE_TYPE IndexType); __forceinline void PrepareForDispatchCompute(ComputeContext& GraphCtx); + __forceinline void PrepareForDispatchRays(GraphicsContext& GraphCtx); __forceinline void PrepareDrawIndirectBuffer(GraphicsContext& GraphCtx, IBuffer* pAttribsBuffer, diff --git a/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp index 59642660..31b65866 100644 --- a/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/FramebufferD3D12Impl.hpp @@ -39,7 +39,7 @@ namespace Diligent class FixedBlockMemoryAllocator; -/// Render pass implementation in Direct3D11 backend. +/// Render pass implementation in Direct3D12 backend. class FramebufferD3D12Impl final : public FramebufferBase<IFramebuffer, RenderDeviceD3D12Impl> { public: diff --git a/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp index 501e62df..00984731 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RenderPassD3D12Impl.hpp @@ -39,7 +39,7 @@ namespace Diligent class FixedBlockMemoryAllocator; -/// Render pass implementation in Direct3D11 backend. +/// Render pass implementation in Direct3D12 backend. class RenderPassD3D12Impl final : public RenderPassBase<IRenderPass, RenderDeviceD3D12Impl> { public: diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp new file mode 100644 index 00000000..e866c6f2 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp @@ -0,0 +1,79 @@ +/* + * 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 +/// Declaration of Diligent::ShaderBindingTableD3D12Impl class + +#include "ShaderBindingTableD3D12.h" +#include "RenderDeviceD3D12.h" +#include "ShaderBindingTableBase.hpp" +#include "D3D12ResourceBase.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "PipelineStateD3D12Impl.hpp" + +namespace Diligent +{ + +/// Shader binding table object implementation in Direct3D12 backend. +class ShaderBindingTableD3D12Impl final : public ShaderBindingTableBase<IShaderBindingTableD3D12, PipelineStateD3D12Impl, RenderDeviceD3D12Impl>, public D3D12ResourceBase +{ +public: + using TShaderBindingTableBase = ShaderBindingTableBase<IShaderBindingTableD3D12, PipelineStateD3D12Impl, RenderDeviceD3D12Impl>; + + ShaderBindingTableD3D12Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const ShaderBindingTableDesc& Desc, + bool bIsDeviceInternal = false); + ~ShaderBindingTableD3D12Impl(); + + virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + virtual void DILIGENT_CALL_TYPE Verify() const override; + + virtual void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override; + + virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override; + + virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override; + + virtual void DILIGENT_CALL_TYPE GetD3D12AddressRangeAndStride(IDeviceContextD3D12* pContext, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE& RaygenShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& MissShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& HitShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& CallableShaderBindingTable) override; + +private: + void ValidateDesc(const ShaderBindingTableDesc& Desc) const; + +private: + RefCntAutoPtr<IBuffer> m_pBuffer; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp new file mode 100644 index 00000000..8eccf530 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/TopLevelASD3D12Impl.hpp @@ -0,0 +1,83 @@ +/* + * 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 +/// Declaration of Diligent::TopLevelASD3D12Impl class + +#include "TopLevelASD3D12.h" +#include "RenderDeviceD3D12.h" +#include "TopLevelASBase.hpp" +#include "D3D12ResourceBase.hpp" +#include "RenderDeviceD3D12Impl.hpp" + +namespace Diligent +{ + +/// Top-level acceleration structure object implementation in Direct3D12 backend. +class TopLevelASD3D12Impl final : public TopLevelASBase<ITopLevelASD3D12, RenderDeviceD3D12Impl>, public D3D12ResourceBase +{ +public: + using TTopLevelASBase = TopLevelASBase<ITopLevelASD3D12, RenderDeviceD3D12Impl>; + + TopLevelASD3D12Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const TopLevelASDesc& Desc, + bool bIsDeviceInternal = false); + ~TopLevelASD3D12Impl(); + + virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + + /// Implementation of ITopLevelASD3D12::GetScratchBufferSizes() in DirectX 12 backend. + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override { return m_ScratchSize; } + + /// Implementation of ITopLevelASD3D12D3D12::GetD3D12TLAS(). + virtual ID3D12Resource* DILIGENT_CALL_TYPE GetD3D12TLAS() override final { return GetD3D12Resource(); } + + /// Implementation of ITopLevelASD3D12::GetNativeHandle() in Direct3D12 backend. + virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final { return GetD3D12TLAS(); } + + D3D12_GPU_VIRTUAL_ADDRESS GetGPUAddress() + { + return GetD3D12Resource()->GetGPUVirtualAddress(); + } + + /// Implementation of ITopLevelASD3D12::GetCPUDescriptorHandle() in Direct3D12 backend. + virtual D3D12_CPU_DESCRIPTOR_HANDLE DILIGENT_CALL_TYPE GetCPUDescriptorHandle() override final + { + return m_DescriptorHandle.GetCpuHandle(); + } + +private: + ScratchBufferSizes m_ScratchSize; + + // Allocation in a CPU-only descriptor heap + DescriptorHeapAllocation m_DescriptorHandle; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/interface/BottomLevelASD3D12.h b/Graphics/GraphicsEngineD3D12/interface/BottomLevelASD3D12.h new file mode 100644 index 00000000..2b64da57 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/interface/BottomLevelASD3D12.h @@ -0,0 +1,70 @@ +/* + * 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::IBottomLevelASD3D12 interface + +#include "../../GraphicsEngine/interface/BottomLevelAS.h" +#include "../../GraphicsEngine/interface/DeviceContext.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {610228AF-F161-4B12-A00E-71E6E3BB97FE} +static const INTERFACE_ID IID_BottomLevelASD3D12 = + {0x610228af, 0xf161, 0x4b12, {0xa0, 0xe, 0x71, 0xe6, 0xe3, 0xbb, 0x97, 0xfe}}; + +#define DILIGENT_INTERFACE_NAME IBottomLevelASD3D12 +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define IBottomLevelASD3D12InclusiveMethods \ + IBottomLevelASInclusiveMethods; \ + IBottomLevelASD3D12Methods BottomLevelASD3D12 + +// clang-format off + +/// Exposes Direct3D12-specific functionality of a bottom-level acceleration structure object. +DILIGENT_BEGIN_INTERFACE(IBottomLevelASD3D12, IBottomLevelAS) +{ + /// Returns ID3D12Resource interface of the internal D3D12 acceleration structure object. + + /// The method does *NOT* call AddRef() on the returned interface, + /// so Release() must not be called. + VIRTUAL ID3D12Resource* METHOD(GetD3D12BLAS)(THIS) PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +# define IBottomLevelASD3D12_GetD3D12BLAS(This) CALL_IFACE_METHOD(IBottomLevelASD3D12, GetD3D12BLAS, This) + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h new file mode 100644 index 00000000..f33bac1b --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h @@ -0,0 +1,71 @@ +/* + * 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::IShaderBindingTableD3D12 interface + +#include "../../GraphicsEngine/interface/ShaderBindingTable.h" +#include "DeviceContextD3D12.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {DCA2FAD9-2C41-4419-9D16-79731C0ED9D8} +static const INTERFACE_ID IID_ShaderBindingTableD3D12 = + {0xdca2fad9, 0x2c41, 0x4419, {0x9d, 0x16, 0x79, 0x73, 0x1c, 0xe, 0xd9, 0xd8}}; + +#define DILIGENT_INTERFACE_NAME IShaderBindingTableD3D12 +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define IShaderBindingTableD3D12InclusiveMethods \ + IShaderBindingTableInclusiveMethods; \ + IShaderBindingTableD3D12Methods ShaderBindingTable +// clang-format off + +/// Exposes Direct3D12-specific functionality of a shader binding table object. +DILIGENT_BEGIN_INTERFACE(IShaderBindingTableD3D12, IShaderBindingTable) +{ + /// AZ TODO + VIRTUAL void METHOD(GetD3D12AddressRangeAndStride)(THIS_ + IDeviceContextD3D12* pContext, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE REF RaygenShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE REF MissShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE REF HitShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE REF CallableShaderBindingTable) PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/interface/TopLevelASD3D12.h b/Graphics/GraphicsEngineD3D12/interface/TopLevelASD3D12.h new file mode 100644 index 00000000..5b2bd512 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/interface/TopLevelASD3D12.h @@ -0,0 +1,77 @@ +/* + * 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::ITopLevelASD3D12 interface + +#include "../../GraphicsEngine/interface/TopLevelAS.h" +#include "../../GraphicsEngine/interface/DeviceContext.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {46334F12-64CB-4F7C-BB71-31515B6F386D} +static const INTERFACE_ID IID_TopLevelASD3D12 = + {0x46334f12, 0x64cb, 0x4f7c, {0xbb, 0x71, 0x31, 0x51, 0x5b, 0x6f, 0x38, 0x6d}}; + +#define DILIGENT_INTERFACE_NAME ITopLevelASD3D12 +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define ITopLevelASD3D12InclusiveMethods \ + ITopLevelASInclusiveMethods; \ + ITopLevelASD3D12Methods TopLevelASD3D12 + +// clang-format off + +/// Exposes Direct3D12-specific functionality of a top-level acceleration structure object. +DILIGENT_BEGIN_INTERFACE(ITopLevelASD3D12, ITopLevelAS) +{ + /// Returns ID3D12Resource interface of the internal D3D12 acceleration structure object. + + /// The method does *NOT* call AddRef() on the returned interface, + /// so Release() must not be called. + VIRTUAL ID3D12Resource* METHOD(GetD3D12TLAS)(THIS) PURE; + + /// Returns a CPU descriptor handle of the D3D12 acceleration structure + + /// The method does *NOT* call AddRef() on the returned interface, + /// so Release() must not be called. + VIRTUAL D3D12_CPU_DESCRIPTOR_HANDLE METHOD(GetCPUDescriptorHandle)(THIS) PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +# define ITopLevelASD3D12_GetD3D12TLAS(This) CALL_IFACE_METHOD(ITopLevelASD3D12, GetD3D12TLAS, This) +# define ITopLevelASD3D12_GetCPUDescriptorHandle(This) CALL_IFACE_METHOD(ITopLevelASD3D12, GetCPUDescriptorHandle, This) + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp new file mode 100644 index 00000000..31f0e6a3 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp @@ -0,0 +1,152 @@ +/* + * 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 "BottomLevelASD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" +#include "D3D12TypeConversions.hpp" +#include "GraphicsAccessories.hpp" +#include "DXGITypeConversions.hpp" +#include "EngineMemory.h" +#include "StringTools.hpp" + +namespace Diligent +{ + +BottomLevelASD3D12Impl::BottomLevelASD3D12Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const BottomLevelASDesc& Desc, + bool bIsDeviceInternal) : + TBottomLevelASBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal} +{ + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO BottomLevelPrebuildInfo = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS BottomLevelInputs = {}; + std::vector<D3D12_RAYTRACING_GEOMETRY_DESC> Geometries; + + if (m_Desc.pTriangles != nullptr) + { + Geometries.resize(m_Desc.TriangleCount); + Uint32 MaxPrimitiveCount = 0; + for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i) + { + auto& src = m_Desc.pTriangles[i]; + auto& dst = Geometries[i]; + + dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; + dst.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_NONE; + dst.Triangles.VertexBuffer.StartAddress = 0; + dst.Triangles.VertexBuffer.StrideInBytes = 0; + dst.Triangles.VertexFormat = TypeToDXGI_Format(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); + dst.Triangles.VertexCount = src.MaxVertexCount; + dst.Triangles.IndexCount = src.MaxIndexCount; + dst.Triangles.IndexFormat = ValueTypeToIndexType(src.IndexType); + dst.Triangles.IndexBuffer = 0; + dst.Triangles.Transform3x4 = 0; + + MaxPrimitiveCount += src.MaxIndexCount ? src.MaxIndexCount / 3 : src.MaxVertexCount / 3; + } + VERIFY_EXPR(MaxPrimitiveCount <= D3D12_RAYTRACING_MAX_PRIMITIVES_PER_BOTTOM_LEVEL_ACCELERATION_STRUCTURE); + } + else if (m_Desc.pBoxes != nullptr) + { + Geometries.resize(m_Desc.BoxCount); + Uint32 MaxBoxCount = 0; + for (uint32_t i = 0; i < m_Desc.BoxCount; ++i) + { + auto& src = m_Desc.pBoxes[i]; + auto& dst = Geometries[i]; + + dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS; + dst.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_NONE; + dst.AABBs.AABBCount = src.MaxBoxCount; + dst.AABBs.AABBs.StartAddress = 0; + dst.AABBs.AABBs.StrideInBytes = 0; + + MaxBoxCount += src.MaxBoxCount; + } + VERIFY_EXPR(MaxBoxCount <= D3D12_RAYTRACING_MAX_PRIMITIVES_PER_BOTTOM_LEVEL_ACCELERATION_STRUCTURE); + } + + VERIFY_EXPR(Geometries.size() <= D3D12_RAYTRACING_MAX_GEOMETRIES_PER_BOTTOM_LEVEL_ACCELERATION_STRUCTURE); + + BottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL; + BottomLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_NONE; + BottomLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + BottomLevelInputs.pGeometryDescs = Geometries.data(); + BottomLevelInputs.NumDescs = static_cast<UINT>(Geometries.size()); + + auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5(); + + pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&BottomLevelInputs, &BottomLevelPrebuildInfo); + if (BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0) + LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info"); + + D3D12_HEAP_PROPERTIES HeapProps; + HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + HeapProps.CreationNodeMask = 1; + HeapProps.VisibleNodeMask = 1; + + D3D12_RESOURCE_DESC ASDesc = {}; + ASDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + ASDesc.Alignment = 0; + ASDesc.Width = BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes; + ASDesc.Height = 1; + ASDesc.DepthOrArraySize = 1; + ASDesc.MipLevels = 1; + ASDesc.Format = DXGI_FORMAT_UNKNOWN; + ASDesc.SampleDesc.Count = 1; + ASDesc.SampleDesc.Quality = 0; + ASDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + ASDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + + auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, + &ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr, + __uuidof(m_pd3d12Resource), + reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pd3d12Resource))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create D3D12 Bottom-level acceleration structure"); + + if (*m_Desc.Name != 0) + m_pd3d12Resource->SetName(WidenString(m_Desc.Name).c_str()); + + m_ScratchSize.Build = static_cast<Uint32>(BottomLevelPrebuildInfo.ScratchDataSizeInBytes); + m_ScratchSize.Update = static_cast<Uint32>(BottomLevelPrebuildInfo.UpdateScratchDataSizeInBytes); +} + +BottomLevelASD3D12Impl::~BottomLevelASD3D12Impl() +{ + // D3D12 object can only be destroyed when it is no longer used by the GPU + auto* pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice()); + pDeviceD3D12Impl->SafeReleaseDeviceObject(std::move(m_pd3d12Resource), m_Desc.CommandQueueMask); +} + +IMPLEMENT_QUERY_INTERFACE(BottomLevelASD3D12Impl, IID_BottomLevelASD3D12, TBottomLevelASBase) + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp index d7cd54b6..8e84b844 100644 --- a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp @@ -118,9 +118,9 @@ BufferD3D12Impl::BufferD3D12Impl(IReferenceCounters* pRefCounters, // understood by applications and row-major texture data is commonly marshaled through buffers. D3D12BuffDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; D3D12BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE; - if (m_Desc.BindFlags & BIND_UNORDERED_ACCESS) + if ((m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || (m_Desc.BindFlags & BIND_RAY_TRACING)) D3D12BuffDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - if (!(m_Desc.BindFlags & BIND_SHADER_RESOURCE)) + if (!(m_Desc.BindFlags & BIND_SHADER_RESOURCE) && !(m_Desc.BindFlags & BIND_RAY_TRACING)) D3D12BuffDesc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; auto* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device(); diff --git a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp index 389bf3eb..6bc55ac3 100644 --- a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp +++ b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp @@ -30,6 +30,8 @@ #include "CommandContext.hpp" #include "TextureD3D12Impl.hpp" #include "BufferD3D12Impl.hpp" +#include "BottomLevelASD3D12Impl.hpp" +#include "TopLevelASD3D12Impl.hpp" #include "CommandListManager.hpp" #include "D3D12TypeConversions.hpp" @@ -39,9 +41,9 @@ namespace Diligent CommandContext::CommandContext(CommandListManager& CmdListManager) : // clang-format off - m_pCurGraphicsRootSignature {nullptr}, - m_pCurPipelineState {nullptr}, - m_pCurComputeRootSignature {nullptr}, + m_pCurGraphicsRootSignature {nullptr}, + m_pCurPipelineState {nullptr}, + m_pCurComputeRootSignature {nullptr}, m_PendingResourceBarriers (STD_ALLOCATOR_RAW_MEM(D3D12_RESOURCE_BARRIER, GetRawAllocator(), "Allocator for vector<D3D12_RESOURCE_BARRIER>")) // clang-format on { @@ -78,7 +80,7 @@ void CommandContext::Reset(CommandListManager& CmdListManager) m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; #if 0 - BindDescriptorHeaps(); + BindDescriptorHeaps(); #endif } @@ -115,6 +117,24 @@ void CommandContext::TransitionResource(IBufferD3D12* pBuffer, RESOURCE_STATE Ne TransitionResource(BufferBarrier); } +void CommandContext::TransitionResource(IBottomLevelASD3D12* pBLAS, RESOURCE_STATE NewState) +{ + VERIFY_EXPR(pBLAS != nullptr); + auto* pBLASfD3D12 = ValidatedCast<BottomLevelASD3D12Impl>(pBLAS); + VERIFY(pBLASfD3D12->IsInKnownState(), "BLAS state can't be unknown"); + StateTransitionDesc ASBarrier(pBLAS, RESOURCE_STATE_UNKNOWN, NewState, true); + TransitionResource(ASBarrier); +} + +void CommandContext::TransitionResource(ITopLevelASD3D12* pTLAS, RESOURCE_STATE NewState) +{ + VERIFY_EXPR(pTLAS != nullptr); + auto* pTLASfD3D12 = ValidatedCast<TopLevelASD3D12Impl>(pTLAS); + VERIFY(pTLASfD3D12->IsInKnownState(), "TLAS state can't be unknown"); + StateTransitionDesc ASBarrier(pTLAS, RESOURCE_STATE_UNKNOWN, NewState, true); + TransitionResource(ASBarrier); +} + void CommandContext::InsertUAVBarrier(ID3D12Resource* pd3d12Resource) { m_PendingResourceBarriers.emplace_back(); @@ -147,25 +167,23 @@ static D3D12_RESOURCE_BARRIER_FLAGS TransitionTypeToD3D12ResourceBarrierFlag(STA void CommandContext::TransitionResource(const StateTransitionDesc& Barrier) { - DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer must not be null"); - DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown"); - RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; - ID3D12Resource* pd3d12Resource = nullptr; - TextureD3D12Impl* pTextureD3D12Impl = nullptr; - BufferD3D12Impl* pBufferD3D12Impl = nullptr; - if (Barrier.pTexture) + RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; + ID3D12Resource* pd3d12Resource = nullptr; + RefCntAutoPtr<TextureD3D12Impl> pTextureD3D12Impl{Barrier.pResource, IID_TextureD3D12}; + RefCntAutoPtr<BufferD3D12Impl> pBufferD3D12Impl{Barrier.pResource, IID_BufferD3D12}; + RefCntAutoPtr<BottomLevelASD3D12Impl> pBLASD3D12Impl{Barrier.pResource, IID_BottomLevelASD3D12}; + RefCntAutoPtr<TopLevelASD3D12Impl> pTLASD3D12Impl{Barrier.pResource, IID_TopLevelASD3D12}; + + if (pTextureD3D12Impl) { - pTextureD3D12Impl = ValidatedCast<TextureD3D12Impl>(Barrier.pTexture); - pd3d12Resource = pTextureD3D12Impl->GetD3D12Resource(); - OldState = pTextureD3D12Impl->GetState(); + pd3d12Resource = pTextureD3D12Impl->GetD3D12Resource(); + OldState = pTextureD3D12Impl->GetState(); } - else + else if (pBufferD3D12Impl) { - VERIFY_EXPR(Barrier.pBuffer != nullptr); - pBufferD3D12Impl = ValidatedCast<BufferD3D12Impl>(Barrier.pBuffer); - pd3d12Resource = pBufferD3D12Impl->GetD3D12Resource(); - OldState = pBufferD3D12Impl->GetState(); + pd3d12Resource = pBufferD3D12Impl->GetD3D12Resource(); + OldState = pBufferD3D12Impl->GetState(); #ifdef DILIGENT_DEVELOPMENT // Dynamic buffers wtih no SRV/UAV bind flags are suballocated in @@ -178,6 +196,20 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier) } #endif } + else if (pBLASD3D12Impl) + { + pd3d12Resource = pBLASD3D12Impl->GetD3D12Resource(); + OldState = pBLASD3D12Impl->GetState(); + } + else if (pTLASD3D12Impl) + { + pd3d12Resource = pTLASD3D12Impl->GetD3D12Resource(); + OldState = pTLASD3D12Impl->GetState(); + } + else + { + UNEXPECTED("unsupported resource type"); + } if (OldState == RESOURCE_STATE_UNKNOWN) { @@ -243,9 +275,8 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier) } } } - else + else if (pBufferD3D12Impl) { - VERIFY_EXPR(pBufferD3D12Impl); m_PendingResourceBarriers.emplace_back(BarrierDesc); } } @@ -259,10 +290,8 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier) pTextureD3D12Impl->SetState(NewState); } } - else + else if (pBufferD3D12Impl) { - VERIFY_EXPR(pBufferD3D12Impl); - VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END), "Buffer state can't be updated in begin-split barrier"); if (Barrier.UpdateResourceState) @@ -275,9 +304,29 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier) "Dynamic buffers without SRV/UAV bind flag are expected to never " "transition from RESOURCE_STATE_GENERIC_READ state"); } + else if (pBLASD3D12Impl) + { + VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END), + "Bottom-level acceleration structure state can't be updated in begin-split barrier"); + if (Barrier.UpdateResourceState) + { + pBLASD3D12Impl->SetState(NewState); + } + } + else if (pTLASD3D12Impl) + { + VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END), + "Top-level acceleration structure state can't be updated in begin-split barrier"); + if (Barrier.UpdateResourceState) + { + pTLASD3D12Impl->SetState(NewState); + } + } } - if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) + if ((OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) || + (OldState == RESOURCE_STATE_BUILD_AS_WRITE && Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE) || + (OldState == RESOURCE_STATE_RAY_TRACING && Barrier.NewState == RESOURCE_STATE_RAY_TRACING)) { DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "UAV barriers must not be split"); InsertUAVBarrier(pd3d12Resource); diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp index 3ea4bad0..ddab5096 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp @@ -351,8 +351,9 @@ static D3D12_RESOURCE_STATES ResourceStateFlagToD3D12ResourceState(RESOURCE_STAT case RESOURCE_STATE_RESOLVE_SOURCE: return D3D12_RESOURCE_STATE_RESOLVE_SOURCE; case RESOURCE_STATE_INPUT_ATTACHMENT: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; case RESOURCE_STATE_PRESENT: return D3D12_RESOURCE_STATE_PRESENT; - case RESOURCE_STATE_BUILD_AS: return D3D12_RESOURCE_STATES(0); - case RESOURCE_STATE_RAY_TRACING: return D3D12_RESOURCE_STATES(0); // AZ TODO + case RESOURCE_STATE_BUILD_AS_READ: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + case RESOURCE_STATE_BUILD_AS_WRITE: return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + case RESOURCE_STATE_RAY_TRACING: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; // clang-format on default: UNEXPECTED("Unexpected resource state flag"); @@ -379,7 +380,7 @@ public: } private: - static constexpr Uint32 MaxFlagBitPos = 18; + static constexpr Uint32 MaxFlagBitPos = 19; std::array<D3D12_RESOURCE_STATES, MaxFlagBitPos + 1> FlagBitPosToResStateMap; }; @@ -422,7 +423,6 @@ static RESOURCE_STATE D3D12ResourceStateToResourceStateFlags(D3D12_RESOURCE_STAT case D3D12_RESOURCE_STATE_COPY_SOURCE: return RESOURCE_STATE_COPY_SOURCE; case D3D12_RESOURCE_STATE_RESOLVE_DEST: return RESOURCE_STATE_RESOLVE_DEST; case D3D12_RESOURCE_STATE_RESOLVE_SOURCE: return RESOURCE_STATE_RESOLVE_SOURCE; - // AZ TODO // clang-format on default: UNEXPECTED("Unexpected D3D12 resource state"); @@ -592,5 +592,67 @@ SHADER_TYPE D3D12ShaderVisibilityToShaderType(D3D12_SHADER_VISIBILITY ShaderVisi } } +DXGI_FORMAT ValueTypeToIndexType(VALUE_TYPE IndexType) +{ + switch (IndexType) + { + // clang-format off + case VT_UNDEFINED: return DXGI_FORMAT_UNKNOWN; // only for ray tracing + case VT_UINT16: return DXGI_FORMAT_R16_UINT; + case VT_UINT32: return DXGI_FORMAT_R32_UINT; + // clang-format on + default: + UNEXPECTED("Unexpected index type"); + return DXGI_FORMAT_R32_UINT; + } +} + +D3D12_RAYTRACING_GEOMETRY_FLAGS GeometryFlagsToD3D12RTGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags) +{ + static_assert(RAYTRACING_GEOMETRY_FLAGS_LAST == RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION, + "Please update the switch below to handle the new ray tracing geometry flag"); + + Uint32 Result = 0; + for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + { + if ((Flags & Bit) != Bit) + continue; + + switch (static_cast<RAYTRACING_GEOMETRY_FLAGS>(Bit)) + { + // clang-format off + case RAYTRACING_GEOMETRY_OPAQUE: Result |= D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE; break; + case RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION: Result |= D3D12_RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION; break; + // clang-format on + default: UNEXPECTED("unknown geometry flag"); + } + } + return static_cast<D3D12_RAYTRACING_GEOMETRY_FLAGS>(Result); +} + +D3D12_RAYTRACING_INSTANCE_FLAGS InstanceFlagsToD3D12RTInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags) +{ + static_assert(RAYTRACING_INSTANCE_FLAGS_LAST == RAYTRACING_INSTANCE_FORCE_NO_OPAQUE, + "Please update the switch below to handle the new ray tracing instance flag"); + + Uint32 Result = 0; + for (Uint32 Bit = 1; Bit <= Flags; Bit <<= 1) + { + if ((Flags & Bit) != Bit) + continue; + + switch (static_cast<RAYTRACING_INSTANCE_FLAGS>(Bit)) + { + // clang-format off + case RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_TRIANGLE_CULL_DISABLE ; break; + case RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE ; break; + case RAYTRACING_INSTANCE_FORCE_OPAQUE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_FORCE_OPAQUE ; break; + case RAYTRACING_INSTANCE_FORCE_NO_OPAQUE: Result |= D3D12_RAYTRACING_INSTANCE_FLAG_FORCE_NON_OPAQUE ; break; + // clang-format on + default: UNEXPECTED("unknown instance flag"); + } + } + return static_cast<D3D12_RAYTRACING_INSTANCE_FLAGS>(Result); +} } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 6ca74c27..95025c4c 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -39,6 +39,7 @@ #include "D3D12DynamicHeap.hpp" #include "CommandListD3D12Impl.hpp" #include "DXGITypeConversions.hpp" +#include "ShaderBindingTableD3D12Impl.hpp" namespace Diligent { @@ -262,6 +263,8 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) } case PIPELINE_TYPE_RAY_TRACING: { + auto* pd3d12SO = pPipelineStateD3D12->GetD3D12StateObject(); + CmdCtx.AsGraphicsContext4().SetRayTracingPipelineState(pd3d12SO); break; } default: @@ -449,7 +452,7 @@ void DeviceContextD3D12Impl::PrepareForDraw(GraphicsContext& GraphCtx, DRAW_FLAG } #endif - GraphCtx.SetRootSignature(m_pPipelineState->GetD3D12RootSignature()); + GraphCtx.SetGraphicsRootSignature(m_pPipelineState->GetD3D12RootSignature()); if (m_State.pCommittedResourceCache != nullptr) { @@ -605,7 +608,7 @@ void DeviceContextD3D12Impl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Att void DeviceContextD3D12Impl::PrepareForDispatchCompute(ComputeContext& ComputeCtx) { - ComputeCtx.SetRootSignature(m_pPipelineState->GetD3D12RootSignature()); + ComputeCtx.SetComputeRootSignature(m_pPipelineState->GetD3D12RootSignature()); if (m_State.pCommittedResourceCache != nullptr) { if (m_State.pCommittedResourceCache->GetNumDynamicCBsBound() > 0) @@ -634,6 +637,37 @@ void DeviceContextD3D12Impl::PrepareForDispatchCompute(ComputeContext& ComputeCt #endif } +void DeviceContextD3D12Impl::PrepareForDispatchRays(GraphicsContext& GraphCtx) +{ + GraphCtx.SetComputeRootSignature(m_pPipelineState->GetD3D12RootSignature()); + if (m_State.pCommittedResourceCache != nullptr) + { + if (m_State.pCommittedResourceCache->GetNumDynamicCBsBound() > 0) + { + // Only process dynamic buffers. Non-dynamic buffers are committed by CommitShaderResources + m_pPipelineState->GetRootSignature() + .CommitRootViews(*m_State.pCommittedResourceCache, + GraphCtx, + true, // IsCompute + m_ContextId, + this, + true, // CommitViews + true, // ProcessDynamicBuffers + false, // ProcessNonDynamicBuffers + false, // TransitionStates + false // ValidateStates + ); + } + } +#ifdef DILIGENT_DEVELOPMENT + else + { + if (m_pPipelineState->ContainsShaderResources()) + LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called with non-null SRB"); + } +#endif +} + void DeviceContextD3D12Impl::DispatchCompute(const DispatchComputeAttribs& Attribs) { if (!DvpVerifyDispatchArguments(Attribs)) @@ -2139,6 +2173,46 @@ void DeviceContextD3D12Impl::TransitionOrVerifyTextureState(CommandContext& #endif } +void DeviceContextD3D12Impl::TransitionOrVerifyBLASState(CommandContext& CmdCtx, + BottomLevelASD3D12Impl& BLAS, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + RESOURCE_STATE RequiredState, + const char* OperationName) +{ + if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + { + if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState)) + CmdCtx.TransitionResource(&BLAS, RequiredState); + } +#ifdef DILIGENT_DEVELOPMENT + else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY) + { + DvpVerifyBLASState(BLAS, RequiredState, OperationName); + } +#endif +} + +void DeviceContextD3D12Impl::TransitionOrVerifyTLASState(CommandContext& CmdCtx, + TopLevelASD3D12Impl& TLAS, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + RESOURCE_STATE RequiredState, + const char* OperationName) +{ + // AZ TODO: transit BLAS state too? + + if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + { + if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState)) + CmdCtx.TransitionResource(&TLAS, RequiredState); + } +#ifdef DILIGENT_DEVELOPMENT + else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY) + { + DvpVerifyTLASState(TLAS, RequiredState, OperationName); + } +#endif +} + void DeviceContextD3D12Impl::TransitionTextureState(ITexture* pTexture, D3D12_RESOURCE_STATES State) { VERIFY_EXPR(pTexture != nullptr); @@ -2202,22 +2276,218 @@ void DeviceContextD3D12Impl::ResolveTextureSubresource(ITexture* void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) { + if (!TDeviceContextBase::BuildBLAS(Attribs, 0)) + return; + + auto* pBLASD12 = ValidatedCast<BottomLevelASD3D12Impl>(Attribs.pBLAS); + auto* pScratchD12 = ValidatedCast<BufferD3D12Impl>(Attribs.pScratchBuffer); + auto& BLASDesc = pBLASD12->GetDesc(); + + auto& CmdCtx = GetCmdContext(); + const char* OpName = "Build BottomLevelAS (DeviceContextD3D12Impl::BuildBLAS)"; + TransitionOrVerifyBLASState(CmdCtx, *pBLASD12, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + TransitionOrVerifyBufferState(CmdCtx, *pScratchD12, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC Desc = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& Inputs = Desc.Inputs; + std::vector<D3D12_RAYTRACING_GEOMETRY_DESC> Geometries; + + if (Attribs.pTriangleData != nullptr) + { + Geometries.resize(Attribs.TriangleDataCount); + + for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) + { + auto& src = Attribs.pTriangleData[i]; + Uint32 j = pBLASD12->GetGeometryIndex(src.GeometryName); + auto& dst = Geometries.data()[j]; + auto& tri = dst.Triangles; + + if (j >= Geometries.size()) + { + UNEXPECTED("Failed to find geometry by name"); + continue; + } + + dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; + dst.Flags = GeometryFlagsToD3D12RTGeometryFlags(src.Flags); + + auto* pVB = ValidatedCast<BufferD3D12Impl>(src.pVertexBuffer); + tri.VertexFormat = TypeToDXGI_Format(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); + tri.VertexCount = src.VertexCount; + tri.VertexBuffer.StartAddress = pVB->GetGPUAddress() + src.VertexOffset; + tri.VertexBuffer.StrideInBytes = src.VertexStride; + + if (src.pIndexBuffer) + { + auto* pIB = ValidatedCast<BufferD3D12Impl>(src.pIndexBuffer); + tri.IndexBuffer = pIB->GetGPUAddress() + src.IndexOffset; + tri.IndexCount = src.IndexCount; + tri.IndexFormat = ValueTypeToIndexType(src.IndexType); + + TransitionOrVerifyBufferState(CmdCtx, *pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + } + else + { + tri.IndexFormat = DXGI_FORMAT_UNKNOWN; + tri.IndexBuffer = 0; + } + + if (src.pTransformBuffer) + { + VERIFY_EXPR(BLASDesc.pTriangles[j].AllowsTransforms); + + auto* pTB = ValidatedCast<BufferD3D12Impl>(src.pTransformBuffer); + tri.Transform3x4 = pTB->GetGPUAddress() + src.TransformBufferOffset; + + TransitionOrVerifyBufferState(CmdCtx, *pTB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + } + else + { + VERIFY_EXPR(!BLASDesc.pTriangles[j].AllowsTransforms); + tri.Transform3x4 = 0; + } + } + } + else if (Attribs.pBoxData != nullptr) + { + Geometries.resize(Attribs.BoxDataCount); + + for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) + { + auto& src = Attribs.pBoxData[i]; + Uint32 j = pBLASD12->GetGeometryIndex(src.GeometryName); + auto& dst = Geometries.data()[j]; + auto& box = dst.AABBs; + + if (j >= Geometries.size()) + { + UNEXPECTED("Failed to find geometry by name"); + continue; + } + + dst.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS; + dst.Flags = GeometryFlagsToD3D12RTGeometryFlags(src.Flags); + + auto* pBB = ValidatedCast<BufferD3D12Impl>(src.pBoxBuffer); + box.AABBCount = src.BoxCount; + box.AABBs.StartAddress = pBB->GetGPUAddress() + src.BoxOffset; + box.AABBs.StrideInBytes = src.BoxStride; + + TransitionOrVerifyBufferState(CmdCtx, *pBB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + } + } + + Inputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL; + Inputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + Inputs.NumDescs = static_cast<UINT>(Geometries.size()); + Inputs.pGeometryDescs = Geometries.data(); + + Desc.DestAccelerationStructureData = pBLASD12->GetGPUAddress(); + Desc.ScratchAccelerationStructureData = pScratchD12->GetGPUAddress(); + Desc.SourceAccelerationStructureData = 0; + + CmdCtx.AsGraphicsContext4().BuildRaytracingAccelerationStructure(Desc, 0, nullptr); + ++m_State.NumCommands; } void DeviceContextD3D12Impl::BuildTLAS(const TLASBuildAttribs& Attribs) { + if (!TDeviceContextBase::BuildTLAS(Attribs, 0)) + return; + + static_assert(TLAS_INSTANCE_DATA_SIZE == sizeof(D3D12_RAYTRACING_INSTANCE_DESC), "Value in TLAS_INSTANCE_DATA_SIZE doesn't match the actual instance description size"); + + auto* pTLASD12 = ValidatedCast<TopLevelASD3D12Impl>(Attribs.pTLAS); + auto* pScratchD12 = ValidatedCast<BufferD3D12Impl>(Attribs.pScratchBuffer); + auto* pInstancesD12 = ValidatedCast<BufferD3D12Impl>(Attribs.pInstanceBuffer); + //auto& TLASDesc = pTLASD12->GetDesc(); + + auto& CmdCtx = GetCmdContext(); + const char* OpName = "Build TopLevelAS (DeviceContextD3D12Impl::BuildTLAS)"; + TransitionOrVerifyTLASState(CmdCtx, *pTLASD12, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + TransitionOrVerifyBufferState(CmdCtx, *pScratchD12, Attribs.ScratchBufferTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + + pTLASD12->SetInstanceData(Attribs.pInstances, Attribs.InstanceCount, Attribs.HitShadersPerInstance); + + // copy instance data into instance buffer + { + size_t Size = Attribs.InstanceCount * sizeof(D3D12_RAYTRACING_INSTANCE_DESC); + auto TmpSpace = m_DynamicHeap.Allocate(Size, 16, m_ContextFrameNumber); + void* pMappedInstances = TmpSpace.CPUAddress; + + for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) + { + auto& src = Attribs.pInstances[i]; + auto& dst = static_cast<D3D12_RAYTRACING_INSTANCE_DESC*>(pMappedInstances)[i]; + auto* pBLASD12 = ValidatedCast<BottomLevelASD3D12Impl>(src.pBLAS); + + static_assert(sizeof(dst.Transform) == sizeof(src.Transform), "size mismatch"); + std::memcpy(&dst.Transform, src.Transform, sizeof(dst.Transform)); + + dst.InstanceID = src.CustomId; + dst.InstanceContributionToHitGroupIndex = pTLASD12->GetInstanceDesc(src.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize + dst.InstanceMask = src.Mask; + dst.Flags = InstanceFlagsToD3D12RTInstanceFlags(src.Flags); + dst.AccelerationStructure = pBLASD12->GetGPUAddress(); + + TransitionOrVerifyBLASState(CmdCtx, *pBLASD12, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + } + UpdateBufferRegion(pInstancesD12, TmpSpace, Attribs.InstanceBufferOffset, Size, Attribs.InstanceBufferTransitionMode); + } + TransitionOrVerifyBufferState(CmdCtx, *pInstancesD12, Attribs.InstanceBufferTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC Desc = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& Inputs = Desc.Inputs; + + Inputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; + Inputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + Inputs.NumDescs = Attribs.InstanceCount; + Inputs.InstanceDescs = pInstancesD12->GetGPUAddress(); + + Desc.DestAccelerationStructureData = pTLASD12->GetGPUAddress(); + Desc.ScratchAccelerationStructureData = pScratchD12->GetGPUAddress(); + Desc.SourceAccelerationStructureData = 0; + + CmdCtx.AsGraphicsContext4().BuildRaytracingAccelerationStructure(Desc, 0, nullptr); + ++m_State.NumCommands; } void DeviceContextD3D12Impl::CopyBLAS(const CopyBLASAttribs& Attribs) { + if (!TDeviceContextBase::CopyBLAS(Attribs, 0)) + return; + + // AZ TODO } void DeviceContextD3D12Impl::CopyTLAS(const CopyTLASAttribs& Attribs) { + if (!TDeviceContextBase::CopyTLAS(Attribs, 0)) + return; + + // AZ TODO } void DeviceContextD3D12Impl::TraceRays(const TraceRaysAttribs& Attribs) { + if (!TDeviceContextBase::TraceRays(Attribs, 0)) + return; + + D3D12_DISPATCH_RAYS_DESC Desc = {}; + + Desc.Width = Attribs.DimensionX; + Desc.Height = Attribs.DimensionY; + Desc.Depth = Attribs.DimensionZ; + + auto* pSBTD12 = ValidatedCast<ShaderBindingTableD3D12Impl>(Attribs.pSBT); + pSBTD12->GetD3D12AddressRangeAndStride(this, Attribs.TransitionMode, Desc.RayGenerationShaderRecord, Desc.MissShaderTable, Desc.HitGroupTable, Desc.CallableShaderTable); + + auto& CmdCtx = GetCmdContext().AsGraphicsContext4(); + PrepareForDispatchRays(CmdCtx); + + CmdCtx.DispatchRays(Desc); + ++m_State.NumCommands; } } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp index be5c68eb..0da4470b 100644 --- a/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp +++ b/Graphics/GraphicsEngineD3D12/src/GenerateMips.cpp @@ -113,7 +113,7 @@ GenerateMipsHelper::GenerateMipsHelper(ID3D12Device* pd3d12Device) void GenerateMipsHelper::GenerateMips(ID3D12Device* pd3d12Device, TextureViewD3D12Impl* pTexView, CommandContext& Ctx) const { auto& ComputeCtx = Ctx.AsComputeContext(); - ComputeCtx.SetRootSignature(m_pGenerateMipsRS); + ComputeCtx.SetComputeRootSignature(m_pGenerateMipsRS); auto* pTexD3D12 = pTexView->GetTexture<TextureD3D12Impl>(); const auto& TexDesc = pTexD3D12->GetDesc(); const auto& ViewDesc = pTexView->GetDesc(); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index efae7b37..9cc7faa5 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -877,9 +877,9 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou if (Attrib.CommitResources) { if (m_Desc.IsAnyGraphicsPipeline()) - CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature()); + CmdCtx.AsGraphicsContext().SetGraphicsRootSignature(GetD3D12RootSignature()); else - CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature()); + CmdCtx.AsComputeContext().SetComputeRootSignature(GetD3D12RootSignature()); } return nullptr; } @@ -906,9 +906,9 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou if (Attrib.CommitResources) { if (m_Desc.IsAnyGraphicsPipeline()) - CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature()); + CmdCtx.AsGraphicsContext().SetGraphicsRootSignature(GetD3D12RootSignature()); else - CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature()); + CmdCtx.AsComputeContext().SetComputeRootSignature(GetD3D12RootSignature()); if (Attrib.TransitionResources) { diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 9feabb6a..f8f545e7 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -40,6 +40,9 @@ #include "QueryD3D12Impl.hpp" #include "RenderPassD3D12Impl.hpp" #include "FramebufferD3D12Impl.hpp" +#include "BottomLevelASD3D12Impl.hpp" +#include "TopLevelASD3D12Impl.hpp" +#include "ShaderBindingTableD3D12Impl.hpp" #include "EngineMemory.h" namespace Diligent @@ -137,9 +140,9 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo sizeof(QueryD3D12Impl), sizeof(RenderPassD3D12Impl), sizeof(FramebufferD3D12Impl), - 0, - 0, - 0 + sizeof(BottomLevelASD3D12Impl), + sizeof(TopLevelASD3D12Impl), + sizeof(ShaderBindingTableD3D12Impl) } }, m_pd3d12Device {pd3d12Device}, @@ -725,19 +728,37 @@ void RenderDeviceD3D12Impl::CreateFramebuffer(const FramebufferDesc& Desc, IFram void RenderDeviceD3D12Impl::CreateBLAS(const BottomLevelASDesc& Desc, IBottomLevelAS** ppBLAS) { - // AZ TODO + CreateDeviceObject("BottomLevelAS", Desc, ppBLAS, + [&]() // + { + BottomLevelASD3D12Impl* pBottomLevelASVk(NEW_RC_OBJ(m_BLASAllocator, "BottomLevelASD3D12Impl instance", BottomLevelASD3D12Impl)(this, Desc)); + pBottomLevelASVk->QueryInterface(IID_BottomLevelAS, reinterpret_cast<IObject**>(ppBLAS)); + OnCreateDeviceObject(pBottomLevelASVk); + }); } void RenderDeviceD3D12Impl::CreateTLAS(const TopLevelASDesc& Desc, ITopLevelAS** ppTLAS) { - // AZ TODO + CreateDeviceObject("TopLevelAS", Desc, ppTLAS, + [&]() // + { + TopLevelASD3D12Impl* pTopLevelASVk(NEW_RC_OBJ(m_TLASAllocator, "TopLevelASD3D12Impl instance", TopLevelASD3D12Impl)(this, Desc)); + pTopLevelASVk->QueryInterface(IID_TopLevelAS, reinterpret_cast<IObject**>(ppTLAS)); + OnCreateDeviceObject(pTopLevelASVk); + }); } void RenderDeviceD3D12Impl::CreateSBT(const ShaderBindingTableDesc& Desc, IShaderBindingTable** ppSBT) { - // AZ TODO + CreateDeviceObject("ShaderBindingTable", Desc, ppSBT, + [&]() // + { + ShaderBindingTableD3D12Impl* pSBTVk(NEW_RC_OBJ(m_SBTAllocator, "ShaderBindingTableD3D12Impl instance", ShaderBindingTableD3D12Impl)(this, Desc)); + pSBTVk->QueryInterface(IID_ShaderBindingTable, reinterpret_cast<IObject**>(ppSBT)); + OnCreateDeviceObject(pSBTVk); + }); } DescriptorHeapAllocation RenderDeviceD3D12Impl::AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count /*= 1*/) diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 35274af3..d0db2201 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -33,6 +33,7 @@ #include "CommandContext.hpp" #include "RenderDeviceD3D12Impl.hpp" #include "TextureD3D12Impl.hpp" +#include "TopLevelASD3D12Impl.hpp" #include "D3D12TypeConversions.hpp" #include "HashUtils.hpp" @@ -702,6 +703,10 @@ __forceinline void TransitionResource(CommandContext& Ctx, case CachedResourceType::AccelStruct: { + VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); + auto* pTLASD3D12 = Res.pObject.RawPtr<TopLevelASD3D12Impl>(); + if (pTLASD3D12->IsInKnownState() && !pTLASD3D12->CheckState(RESOURCE_STATE_RAY_TRACING)) + Ctx.TransitionResource(pTLASD3D12, RESOURCE_STATE_RAY_TRACING); } break; @@ -806,6 +811,16 @@ void RootSignature::DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resou case CachedResourceType::AccelStruct: { + VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV, "Unexpected descriptor range type"); + const auto* pTLASD3D12 = Res.pObject.RawPtr<const TopLevelASD3D12Impl>(); + if (pTLASD3D12->IsInKnownState() && !pTLASD3D12->CheckState(RESOURCE_STATE_RAY_TRACING)) + { + LOG_ERROR_MESSAGE("TLAS '", pTLASD3D12->GetDesc().Name, "' must be in RESOURCE_STATE_RAY_TRACING state. Actual state: ", + GetResourceStateString(pTLASD3D12->GetState()), + ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state " + "with IDeviceContext::TransitionResourceStates()."); + } } break; diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp new file mode 100644 index 00000000..3727913f --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp @@ -0,0 +1,202 @@ +/* + * 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 "ShaderBindingTableD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" +#include "D3D12TypeConversions.hpp" +#include "GraphicsAccessories.hpp" +#include "DXGITypeConversions.hpp" +#include "EngineMemory.h" +#include "StringTools.hpp" + +namespace Diligent +{ + +ShaderBindingTableD3D12Impl::ShaderBindingTableD3D12Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const ShaderBindingTableDesc& Desc, + bool bIsDeviceInternal) : + TShaderBindingTableBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal} +{ + ValidateDesc(Desc); + + m_ShaderRecordStride = m_Desc.ShaderRecordSize + D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; +} + +ShaderBindingTableD3D12Impl::~ShaderBindingTableD3D12Impl() +{ +} + +IMPLEMENT_QUERY_INTERFACE(ShaderBindingTableD3D12Impl, IID_ShaderBindingTableD3D12, TShaderBindingTableBase) + +void ShaderBindingTableD3D12Impl::ValidateDesc(const ShaderBindingTableDesc& Desc) const +{ + if (Desc.ShaderRecordSize + D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES > D3D12_RAYTRACING_MAX_SHADER_RECORD_STRIDE) + { + LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""), + "' is invalid: ShaderRecordSize is too big, max size is: ", D3D12_RAYTRACING_MAX_SHADER_RECORD_STRIDE - D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES); + } +} + +void ShaderBindingTableD3D12Impl::Verify() const +{ + // AZ TODO +} + +void ShaderBindingTableD3D12Impl::Reset(const ShaderBindingTableDesc& Desc) +{ + m_RayGenShaderRecord.clear(); + m_MissShadersRecord.clear(); + m_CallableShadersRecord.clear(); + m_HitGroupsRecord.clear(); + m_Changed = true; + + try + { + ValidateShaderBindingTableDesc(Desc); + ValidateDesc(Desc); + } + catch (const std::runtime_error&) + { + // AZ TODO + return; + } + + m_Desc = Desc; + m_ShaderRecordStride = m_Desc.ShaderRecordSize + D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; +} + +void ShaderBindingTableD3D12Impl::ResetHitGroups(Uint32 HitShadersPerInstance) +{ + // AZ TODO +} + +void ShaderBindingTableD3D12Impl::BindAll(const BindAllAttribs& Attribs) +{ + // AZ TODO +} + +void ShaderBindingTableD3D12Impl::GetD3D12AddressRangeAndStride(IDeviceContextD3D12* pContext, + RESOURCE_STATE_TRANSITION_MODE TransitionMode, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE& RaygenShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& MissShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& HitShaderBindingTable, + D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE& CallableShaderBindingTable) +{ + const auto AlignToLarger = [](size_t offset) -> Uint32 { + return Align(static_cast<Uint32>(offset), static_cast<Uint32>(D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT)); + }; + + const Uint32 RayGenOffset = 0; + const Uint32 MissShaderOffset = AlignToLarger(m_RayGenShaderRecord.size()); + const Uint32 HitGroupOffset = AlignToLarger(MissShaderOffset + m_MissShadersRecord.size()); + const Uint32 CallableShadersOffset = AlignToLarger(HitGroupOffset + m_HitGroupsRecord.size()); + const Uint32 BufSize = AlignToLarger(CallableShadersOffset + m_CallableShadersRecord.size()); + + // recreate buffer + if (m_pBuffer == nullptr || m_pBuffer->GetDesc().uiSizeInBytes < BufSize) + { + m_pBuffer = nullptr; + + String BuffName = String{GetDesc().Name} + " - internal buffer"; + BufferDesc BuffDesc; + BuffDesc.Name = BuffName.c_str(); + BuffDesc.Usage = USAGE_DEFAULT; + BuffDesc.BindFlags = BIND_RAY_TRACING; + BuffDesc.uiSizeInBytes = BufSize; + + GetDevice()->CreateBuffer(BuffDesc, nullptr, &m_pBuffer); + VERIFY_EXPR(m_pBuffer != nullptr); + } + + if (m_pBuffer == nullptr) + return; // something goes wrong + + const D3D12_GPU_VIRTUAL_ADDRESS BuffHandle = m_pBuffer.RawPtr<BufferD3D12Impl>()->GetGPUAddress(0, ValidatedCast<DeviceContextD3D12Impl>(pContext)); + + if (m_RayGenShaderRecord.size()) + { + RaygenShaderBindingTable.StartAddress = BuffHandle + RayGenOffset; + RaygenShaderBindingTable.SizeInBytes = m_RayGenShaderRecord.size(); + } + + if (m_MissShadersRecord.size()) + { + MissShaderBindingTable.StartAddress = BuffHandle + MissShaderOffset; + MissShaderBindingTable.SizeInBytes = m_MissShadersRecord.size(); + MissShaderBindingTable.StrideInBytes = m_ShaderRecordStride; + } + + if (m_HitGroupsRecord.size()) + { + HitShaderBindingTable.StartAddress = BuffHandle + HitGroupOffset; + HitShaderBindingTable.SizeInBytes = m_HitGroupsRecord.size(); + HitShaderBindingTable.StrideInBytes = m_ShaderRecordStride; + } + + if (m_CallableShadersRecord.size()) + { + CallableShaderBindingTable.StartAddress = BuffHandle + CallableShadersOffset; + CallableShaderBindingTable.SizeInBytes = m_CallableShadersRecord.size(); + CallableShaderBindingTable.StrideInBytes = m_ShaderRecordStride; + } + + if (!m_Changed) + return; + + m_Changed = false; + + // update buffer data + if (m_RayGenShaderRecord.size()) + pContext->UpdateBuffer(m_pBuffer, RayGenOffset, static_cast<Uint32>(m_RayGenShaderRecord.size()), m_RayGenShaderRecord.data(), TransitionMode); + + if (m_MissShadersRecord.size()) + pContext->UpdateBuffer(m_pBuffer, MissShaderOffset, static_cast<Uint32>(m_MissShadersRecord.size()), m_MissShadersRecord.data(), TransitionMode); + + if (m_HitGroupsRecord.size()) + pContext->UpdateBuffer(m_pBuffer, HitGroupOffset, static_cast<Uint32>(m_HitGroupsRecord.size()), m_HitGroupsRecord.data(), TransitionMode); + + if (m_CallableShadersRecord.size()) + pContext->UpdateBuffer(m_pBuffer, CallableShadersOffset, static_cast<Uint32>(m_CallableShadersRecord.size()), m_CallableShadersRecord.data(), TransitionMode); + + if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + { + StateTransitionDesc Barrier; + Barrier.pResource = m_pBuffer; + Barrier.NewState = RESOURCE_STATE_RAY_TRACING; + Barrier.UpdateResourceState = true; + pContext->TransitionResourceStates(1, &Barrier); + } + else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY) + { + VERIFY_EXPR(m_pBuffer->GetState() == RESOURCE_STATE_RAY_TRACING); + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index b4bb1f72..6dbdb97f 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -40,6 +40,7 @@ #include "ShaderResourceVariableBase.hpp" #include "ShaderVariableD3DBase.hpp" #include "LinearAllocator.hpp" +#include "TopLevelASD3D12.h" namespace Diligent { @@ -622,6 +623,35 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheAccelStruct(IDeviceObject* Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const { + VERIFY(Attribs.IsValidBindPoint(), "Invalid bind point"); + VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + + RefCntAutoPtr<ITopLevelASD3D12> pTLASD3D12(pTLAS, IID_TopLevelASD3D12); + if (pTLASD3D12) + { + if (GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr) + { + // Do not update resource if one is already bound unless it is dynamic. This may be + // dangerous as CopyDescriptorsSimple() may interfere with GPU reading the same descriptor. + return; + } + + DstRes.Type = GetResType(); + DstRes.CPUDescriptorHandle = pTLASD3D12->GetCPUDescriptorHandle(); + VERIFY(DstRes.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 resource"); + + if (ShdrVisibleHeapCPUDescriptorHandle.ptr != 0) + { + // Dynamic resources are assigned descriptor in the GPU-visible heap at every draw call, and + // the descriptor is copied by the RootSignature when resources are committed + VERIFY(DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); + + ID3D12Device* pd3d12Device = ParentResLayout.m_pd3d12Device; + pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstRes.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + DstRes.pObject = std::move(pTLASD3D12); + } } const ShaderResourceLayoutD3D12::D3D12Resource& ShaderResourceLayoutD3D12::GetAssignedSampler(const D3D12Resource& TexSrv) const diff --git a/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp new file mode 100644 index 00000000..5f411640 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp @@ -0,0 +1,115 @@ +/* + * 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 "TopLevelASD3D12Impl.hpp" +#include "RenderDeviceD3D12Impl.hpp" +#include "DeviceContextD3D12Impl.hpp" +#include "D3D12TypeConversions.hpp" +#include "GraphicsAccessories.hpp" +#include "DXGITypeConversions.hpp" +#include "EngineMemory.h" +#include "StringTools.hpp" + +namespace Diligent +{ + +TopLevelASD3D12Impl::TopLevelASD3D12Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D12Impl* pDeviceD3D12, + const TopLevelASDesc& Desc, + bool bIsDeviceInternal) : + TTopLevelASBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal} +{ + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO TopLevelPrebuildInfo = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS TopLevelInputs = {}; + + TopLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; + TopLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_NONE; + TopLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + TopLevelInputs.NumDescs = Desc.MaxInstanceCount; + + VERIFY_EXPR(Desc.MaxInstanceCount <= D3D12_RAYTRACING_MAX_INSTANCES_PER_TOP_LEVEL_ACCELERATION_STRUCTURE); + + auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5(); + + pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&TopLevelInputs, &TopLevelPrebuildInfo); + if (TopLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0) + LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info"); + + D3D12_HEAP_PROPERTIES HeapProps; + HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + HeapProps.CreationNodeMask = 1; + HeapProps.VisibleNodeMask = 1; + + D3D12_RESOURCE_DESC ASDesc = {}; + ASDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + ASDesc.Alignment = 0; + ASDesc.Width = TopLevelPrebuildInfo.ResultDataMaxSizeInBytes; + ASDesc.Height = 1; + ASDesc.DepthOrArraySize = 1; + ASDesc.MipLevels = 1; + ASDesc.Format = DXGI_FORMAT_UNKNOWN; + ASDesc.SampleDesc.Count = 1; + ASDesc.SampleDesc.Quality = 0; + ASDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + ASDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + + auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, + &ASDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, nullptr, + __uuidof(m_pd3d12Resource), + reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pd3d12Resource))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create D3D12 Top-level acceleration structure"); + + if (*m_Desc.Name != 0) + m_pd3d12Resource->SetName(WidenString(m_Desc.Name).c_str()); + + m_ScratchSize.Build = static_cast<Uint32>(TopLevelPrebuildInfo.ScratchDataSizeInBytes); + m_ScratchSize.Update = static_cast<Uint32>(TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes); + + m_DescriptorHandle = pDeviceD3D12->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + + D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc; + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; + SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + SRVDesc.Format = DXGI_FORMAT_UNKNOWN; + SRVDesc.RaytracingAccelerationStructure.Location = GetGPUAddress(); + pd3d12Device->CreateShaderResourceView(nullptr, &SRVDesc, m_DescriptorHandle.GetCpuHandle()); +} + +TopLevelASD3D12Impl::~TopLevelASD3D12Impl() +{ + // D3D12 object can only be destroyed when it is no longer used by the GPU + auto* pDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(GetDevice()); + pDeviceD3D12Impl->SafeReleaseDeviceObject(std::move(m_pd3d12Resource), m_Desc.CommandQueueMask); +} + +IMPLEMENT_QUERY_INTERFACE(TopLevelASD3D12Impl, IID_TopLevelASD3D12, TTopLevelASBase) + +} // namespace Diligent |
