diff options
| author | azhirnov <zh1dron@gmail.com> | 2020-11-05 00:43:05 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2020-11-05 00:53:36 +0000 |
| commit | 5e81b867be771dc7f2add0d7b403af4aeaa744db (patch) | |
| tree | 0f1f3835149f8887d80d558203956fcdbb233f60 /Graphics | |
| parent | fixed compilation (diff) | |
| download | DiligentCore-5e81b867be771dc7f2add0d7b403af4aeaa744db.tar.gz DiligentCore-5e81b867be771dc7f2add0d7b403af4aeaa744db.zip | |
Added AS copy with compacting.
Added UB & SB size checks for Vulkan.
Some improvements for ray tracing & tests.
Diffstat (limited to 'Graphics')
47 files changed, 1772 insertions, 971 deletions
diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 2bdd51dc..5a6db4bd 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -36,7 +36,7 @@ #include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" -#include "StringPool.hpp" +#include "LinearAllocator.hpp" #include "HashUtils.hpp" namespace Diligent @@ -67,84 +67,21 @@ public: { ValidateBottomLevelASDesc(Desc); - // Memory must be released if an exception is thrown. - auto RawMemDeleter = [](void* ptr) { - if (ptr != nullptr) - GetRawAllocator().Free(ptr); - }; - - if (Desc.pTriangles != nullptr) + if (Desc.CompactedSize > 0) + {} + else { - size_t StringPoolSize = 0; - for (Uint32 i = 0; i < Desc.TriangleCount; ++i) - { - if (Desc.pTriangles[i].GeometryName == nullptr) - LOG_ERROR_AND_THROW("Geometry name can not be null!"); - - StringPoolSize += strlen(Desc.pTriangles[i].GeometryName) + 1; - } - - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - - std::unique_ptr<BLASTriangleDesc[], decltype(RawMemDeleter)> pTriangles{ - ALLOCATE(GetRawAllocator(), "Memory for BLASTriangleDesc array", BLASTriangleDesc, Desc.TriangleCount), - RawMemDeleter}; - - std::memcpy(pTriangles.get(), Desc.pTriangles, sizeof(*Desc.pTriangles) * Desc.TriangleCount); - this->m_Desc.pBoxes = nullptr; - - // copy strings - for (Uint32 i = 0; i < Desc.TriangleCount; ++i) - { - pTriangles[i].GeometryName = m_StringPool.CopyString(pTriangles[i].GeometryName); - bool IsUniqueName = m_NameToIndex.emplace(pTriangles[i].GeometryName, i).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Geometry name must be unique!"); - } - this->m_Desc.pTriangles = pTriangles.release(); + LinearAllocator MemPool{GetRawAllocator()}; + CopyDescription(Desc, this->m_Desc, MemPool, m_NameToIndex); + this->m_pRawPtr = MemPool.ReleaseOwnership(); } - else if (Desc.pBoxes != nullptr) - { - size_t StringPoolSize = 0; - for (Uint32 i = 0; i < Desc.BoxCount; ++i) - { - if (Desc.pBoxes[i].GeometryName == nullptr) - LOG_ERROR_AND_THROW("Geometry name can not be null!"); - - StringPoolSize += strlen(Desc.pBoxes[i].GeometryName) + 1; - } - - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - - std::unique_ptr<BLASBoundingBoxDesc[], decltype(RawMemDeleter)> pBoxes{ - ALLOCATE(GetRawAllocator(), "Memory for BLASBoundingBoxDesc array", BLASBoundingBoxDesc, Desc.BoxCount), - RawMemDeleter}; - - std::memcpy(pBoxes.get(), Desc.pBoxes, sizeof(*Desc.pBoxes) * Desc.BoxCount); - this->m_Desc.pTriangles = nullptr; - - // copy strings - for (Uint32 i = 0; i < Desc.BoxCount; ++i) - { - pBoxes[i].GeometryName = m_StringPool.CopyString(pBoxes[i].GeometryName); - bool IsUniqueName = m_NameToIndex.emplace(pBoxes[i].GeometryName, i).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Geometry name must be unique!"); - } - this->m_Desc.pBoxes = pBoxes.release(); - } - VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); } ~BottomLevelASBase() { - if (this->m_Desc.pTriangles != nullptr) + if (this->m_pRawPtr) { - GetRawAllocator().Free(const_cast<BLASTriangleDesc*>(this->m_Desc.pTriangles)); - } - if (this->m_Desc.pBoxes != nullptr) - { - GetRawAllocator().Free(const_cast<BLASBoundingBoxDesc*>(this->m_Desc.pBoxes)); + GetRawAllocator().Free(this->m_pRawPtr); } } @@ -164,6 +101,8 @@ public: virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { + VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE, + "Unsupported state for bottom-level acceleration structure"); this->m_State = State; } @@ -184,6 +123,36 @@ public: return (this->m_State & State) == State; } + void CopyDescription(const BottomLevelASBase& Src) + { + const auto& SrcDesc = Src.GetDesc(); + auto& DstDesc = this->m_Desc; + + try + { + if (this->m_pRawPtr) + { + GetRawAllocator().Free(this->m_pRawPtr); + this->m_pRawPtr = nullptr; + } + m_NameToIndex.clear(); + + DstDesc.TriangleCount = SrcDesc.TriangleCount; + DstDesc.BoxCount = SrcDesc.BoxCount; + + LinearAllocator MemPool{GetRawAllocator()}; + CopyDescription(SrcDesc, DstDesc, MemPool, m_NameToIndex); + this->m_pRawPtr = MemPool.ReleaseOwnership(); + } + catch (...) + { + // memory for arrays is not allocated or have been freed + DstDesc.pTriangles = nullptr; + DstDesc.pBoxes = nullptr; + m_NameToIndex.clear(); + } + } + #ifdef DILIGENT_DEVELOPMENT void UpdateVersion() { @@ -194,29 +163,143 @@ public: { return m_Version.load(); } -#endif + + bool ValidateContent() const + { + return true; + } +#endif // DILIGENT_DEVELOPMENT protected: static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) { #define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) - if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) + if (Desc.CompactedSize > 0) { - LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined"); - } + if (Desc.pTriangles != nullptr || Desc.pBoxes != nullptr) + LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then pTriangles and pBoxes must be null"); - if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) + if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) + LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE"); + } + else { - LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0"); + if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) + LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined"); + + if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) + LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0"); + + if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0"); + + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + LOG_BLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); + +#ifdef DILIGENT_DEVELOPMENT + for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + { + const auto& tri = Desc.pTriangles[i]; + + if (tri.GeometryName == nullptr) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].GeometryName must not be null"); + + if (tri.VertexValueType >= VT_NUM_TYPES) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType must be valid type"); + + if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount must be 2 or 3"); + + if (tri.MaxVertexCount == 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must be greater then 0"); + + if (tri.MaxPrimitiveCount == 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxPrimitiveCount must be greater then 0"); + + if (tri.IndexType == VT_UNDEFINED) + { + if (tri.MaxVertexCount != tri.MaxPrimitiveCount * 3) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must equal to (MaxPrimitiveCount * 3)"); + } + else + { + if (tri.IndexType != VT_UINT32 && tri.IndexType != VT_UINT16) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].IndexType must be VT_UINT16 or VT_UINT32"); + } + } + + for (Uint32 i = 0; i < Desc.BoxCount; ++i) + { + const auto& box = Desc.pBoxes[i]; + + if (box.GeometryName == nullptr) + LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].GeometryName must not be null"); + + if (box.MaxBoxCount == 0) + LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].MaxBoxCount must be greater then 0"); + } +#endif // DILIGENT_DEVELOPMENT } - if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) +#undef LOG_BLAS_ERROR_AND_THROW + } + + static void CopyDescription(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>& NameToIndex) + { + if (SrcDesc.pTriangles != nullptr) { - LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0"); + MemPool.AddSpace<decltype(*SrcDesc.pTriangles)>(SrcDesc.TriangleCount); + + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + MemPool.AddSpaceForString(SrcDesc.pTriangles[i].GeometryName); + + MemPool.Reserve(); + + auto* pTriangles = MemPool.CopyArray(SrcDesc.pTriangles, SrcDesc.TriangleCount); + + // copy strings + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + { + pTriangles[i].GeometryName = MemPool.CopyString(SrcDesc.pTriangles[i].GeometryName); + bool IsUniqueName = NameToIndex.emplace(SrcDesc.pTriangles[i].GeometryName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name must be unique!"); + } + DstDesc.pTriangles = pTriangles; + DstDesc.pBoxes = nullptr; + DstDesc.BoxCount = 0; } + else if (SrcDesc.pBoxes != nullptr) + { + MemPool.AddSpace<decltype(*SrcDesc.pBoxes)>(SrcDesc.BoxCount); -#undef LOG_BLAS_ERROR_AND_THROW + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + MemPool.AddSpaceForString(SrcDesc.pBoxes[i].GeometryName); + + MemPool.Reserve(); + + auto* pBoxes = MemPool.CopyArray(SrcDesc.pBoxes, SrcDesc.BoxCount); + + // copy strings + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + { + pBoxes[i].GeometryName = MemPool.CopyString(SrcDesc.pBoxes[i].GeometryName); + bool IsUniqueName = NameToIndex.emplace(SrcDesc.pBoxes[i].GeometryName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name must be unique!"); + } + DstDesc.pBoxes = pBoxes; + DstDesc.pTriangles = nullptr; + DstDesc.TriangleCount = 0; + } + else + { + LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null"); + } } IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) @@ -226,7 +309,7 @@ protected: std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher> m_NameToIndex; - StringPool m_StringPool; + void* m_pRawPtr = nullptr; #ifdef DILIGENT_DEVELOPMENT std::atomic<Uint32> m_Version{0}; diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index ba586f4b..f7abedb8 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -279,11 +279,13 @@ protected: // clang-format on #endif - bool BuildBLAS(const BLASBuildAttribs& Attribs, int); - bool BuildTLAS(const TLASBuildAttribs& Attribs, int); - bool CopyBLAS(const CopyBLASAttribs& Attribs, int); - bool CopyTLAS(const CopyTLASAttribs& Attribs, int); - bool TraceRays(const TraceRaysAttribs& Attribs, int); + bool BuildBLAS(const BLASBuildAttribs& Attribs, int) const; + bool BuildTLAS(const TLASBuildAttribs& Attribs, int) const; + bool CopyBLAS(const CopyBLASAttribs& Attribs, int) const; + bool CopyTLAS(const CopyTLASAttribs& Attribs, int) const; + bool WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const; + bool WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const; + bool TraceRays(const TraceRaysAttribs& Attribs, int) const; /// Strong reference to the device. RefCntAutoPtr<DeviceImplType> m_pDevice; @@ -1503,6 +1505,12 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) return true; + if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device"); + return false; + } + if (!m_pPipelineState) { LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound."); @@ -1521,6 +1529,11 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero."); } + if (Attribs.ThreadGroupCount > m_pDevice->GetMaxDrawMeshTasksCount()) + { + LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch must be less then ", m_pDevice->GetMaxDrawMeshTasksCount()); + } + return true; } @@ -1635,6 +1648,12 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) return true; + if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("DrawMeshIndirect: mesh shaders are not supported by this device"); + return false; + } + if (!m_pPipelineState) { LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: no pipeline state is bound."); @@ -1860,7 +1879,7 @@ void DeviceContextBase<BaseInterface, ImplementationTraits>:: const auto& BLASDesc = pBottomLevelAS->GetDesc(); OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState(); DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING, + DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE, "Invlaid new state specified for BLAS '", BLASDesc.Name, "'"); DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for BLAS"); } @@ -1951,11 +1970,17 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>:: #endif // DILIGENT_DEVELOPMENT template <typename BaseInterface, typename ImplementationTraits> -bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLASBuildAttribs& Attribs, int) +bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLASBuildAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device"); + return false; + } + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("BuildBLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass"); return false; } @@ -1989,22 +2014,51 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA return false; } + const auto& BLASDesc = Attribs.pBLAS->GetDesc(); + + if (Attribs.BoxDataCount > BLASDesc.BoxCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount"); + return false; + } + + if (Attribs.TriangleDataCount > BLASDesc.TriangleCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount"); + return false; + } + #ifdef DILIGENT_DEVELOPMENT for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) { const auto& tri = Attribs.pTriangleData[i]; const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount; const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount; + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName); + + if (GeomIndex == BottomLevelASType::InvalidGeometryIndex) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].GeometryName not found in BLAS description"); + return false; + } + + const auto& TriDesc = BLASDesc.pTriangles[GeomIndex]; + + if (tri.VertexValueType != VT_UNDEFINED && tri.VertexValueType != TriDesc.VertexValueType) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be undefined or match the VertexValueType in geometry description"); + return false; + } - if (tri.VertexValueType >= VT_NUM_TYPES) + if (tri.VertexComponentCount != 0 && tri.VertexComponentCount != TriDesc.VertexComponentCount) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be valid type"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 0 or match the VertexComponentCount in geometry description"); return false; } - if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) + if (tri.VertexCount > TriDesc.MaxVertexCount) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 2 or 3"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must not be greater then MaxVertexCount(", TriDesc.MaxVertexCount, ")"); return false; } @@ -2032,20 +2086,20 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA return false; } - if (tri.IndexType != VT_UNDEFINED) + if (tri.IndexType != VT_UNDEFINED && tri.IndexType != TriDesc.IndexType) { - if (tri.IndexType != VT_UINT16 && tri.IndexType != VT_UINT32) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must not be VT_UNDEFINED, VT_UINT16 or VT_UINT32"); - return false; - } + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must match the IndexType in geometry description"); + return false; + } - if (tri.IndexCount == 0 || (tri.IndexCount % 3 != 0)) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be valid"); - return false; - } + if (tri.PrimitiveCount > TriDesc.MaxPrimitiveCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].PrimitiveCount must not be greater then MaxPrimitiveCount(", TriDesc.MaxPrimitiveCount, ")"); + return false; + } + if (TriDesc.IndexType != VT_UNDEFINED) + { if (tri.pIndexBuffer == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null"); @@ -2058,7 +2112,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA return false; } - const Uint32 IndexDataSize = tri.IndexCount * GetValueSize(tri.IndexType); + const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType); if (tri.IndexOffset + IndexDataSize > tri.pIndexBuffer->GetDesc().uiSizeInBytes) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount"); @@ -2067,10 +2121,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA } else { + if (tri.VertexCount != tri.PrimitiveCount * 3) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must equal to (PrimitiveCount * 3)"); + return false; + } + VERIFY(tri.pIndexBuffer == nullptr, "IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED"); - VERIFY(tri.IndexCount == 0, - "IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be zero if IndexType is VT_UNDEFINED"); } if (tri.pTransformBuffer != nullptr) @@ -2080,13 +2138,34 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag"); return false; } + + if (!TriDesc.AllowsTransforms) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "] use transform buffer but AllowsTransforms is false"); + return false; + } } } for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) { - const auto& box = Attribs.pBoxData[i]; - const Uint32 BoxSize = sizeof(float) * 6; + const auto& box = Attribs.pBoxData[i]; + const Uint32 BoxSize = sizeof(float) * 6; + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName); + + if (GeomIndex == BottomLevelASType::InvalidGeometryIndex) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].GeometryName not found in BLAS description"); + return false; + } + + const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex]; + + if (box.BoxCount > BoxDesc.MaxBoxCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxCount must not be greated then MaxBoxCount (", BoxDesc.MaxBoxCount, ")"); + return false; + } if (box.BoxStride < BoxSize) { @@ -2108,20 +2187,6 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA } #endif // DILIGENT_DEVELOPMENT - const auto& BLASDesc = Attribs.pBLAS->GetDesc(); - - if (Attribs.BoxDataCount > BLASDesc.BoxCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to Attribs.pBLAS->GetDesc().BoxCount"); - return false; - } - - if (Attribs.TriangleDataCount > BLASDesc.TriangleCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to Attribs.pBLAS->GetDesc().TriangleCount"); - return false; - } - const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes) @@ -2146,11 +2211,17 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildBLAS(const BLA } template <typename BaseInterface, typename ImplementationTraits> -bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLASBuildAttribs& Attribs, int) +bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLASBuildAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device"); + return false; + } + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("BuildTLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass"); return false; } @@ -2201,9 +2272,11 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA // calculate instance data size for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { - VERIFY_EXPR((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0); - VERIFY_EXPR(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || - (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0); + VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only first 24 bits are used"); + + VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || + (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0, + "Only first 24 bits are used"); if (Attribs.pInstances[i].InstanceName == nullptr) { @@ -2219,6 +2292,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) ++AutoOffsetCounter; + + + if (TLASDesc.BindingMode != SHADER_BINDING_USER_DEFINED && Attribs.pInstances[i].ContributionToHitGroupIndex != TLAS_INSTANCE_OFFSET_AUTO) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " + "if TLAS created with BindingMode that is not SHADER_BINDING_USER_DEFINED"); + return false; + } } if (AutoOffsetCounter != 0 && AutoOffsetCounter != Attribs.InstanceCount) @@ -2270,8 +2351,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::BuildTLAS(const TLA } template <typename BaseInterface, typename ImplementationTraits> -bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const CopyBLASAttribs& Attribs, int) +bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const CopyBLASAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device"); + return false; + } + if (Attribs.pSrc == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must not be null"); @@ -2286,11 +2373,17 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("CopyBLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass"); return false; } #ifdef DILIGENT_DEVELOPMENT + if (!ValidatedCast<BottomLevelASType>(Attribs.pSrc)->ValidateContent()) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid"); + return false; + } + if (Attribs.Mode == COPY_AS_MODE_CLONE) { auto& SrcDesc = Attribs.pSrc->GetDesc(); @@ -2323,7 +2416,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount || SrcTri.VertexValueType != DstTri.VertexValueType || SrcTri.VertexComponentCount != DstTri.VertexComponentCount || - SrcTri.MaxIndexCount != DstTri.MaxIndexCount || + SrcTri.MaxPrimitiveCount != DstTri.MaxPrimitiveCount || SrcTri.IndexType != DstTri.IndexType || SrcTri.AllowsTransforms != DstTri.AllowsTransforms) // clang-format on @@ -2342,6 +2435,23 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy } } } + else if (Attribs.Mode == COPY_AS_MODE_COMPACT) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (DstDesc.CompactedSize == 0) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must be create with defined CompactedSize"); + return false; + } + } else { LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode"); @@ -2353,8 +2463,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyBLAS(const Copy } template <typename BaseInterface, typename ImplementationTraits> -bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const CopyTLASAttribs& Attribs, int) +bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const CopyTLASAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device"); + return false; + } + if (Attribs.pSrc == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must not be null"); @@ -2369,14 +2485,14 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("CopyTLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass"); return false; } #ifdef DILIGENT_DEVELOPMENT - if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->CheckBLASVersion()) + if (!ValidatedCast<TopLevelASType>(Attribs.pSrc)->ValidateContent()) { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be rebuilded to apply BLAS changes before being copied to another TLAS"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid"); return false; } @@ -2392,6 +2508,23 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy return false; } } + else if (Attribs.Mode == COPY_AS_MODE_COMPACT) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (DstDesc.CompactedSize == 0) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must be create with defined CompactedSize"); + return false; + } + } else { LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode"); @@ -2403,8 +2536,104 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CopyTLAS(const Copy } template <typename BaseInterface, typename ImplementationTraits> -bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const TraceRaysAttribs& Attribs, int) +bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device"); + return false; + } + + if (Attribs.pBLAS == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must not be null"); + return false; + } + if (!(Attribs.pBLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (Attribs.pDestBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must not be null"); + return false; + } + if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer is too small"); + return false; + } + if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 && + !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag"); + return false; + } + + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass"); + return false; + } + return true; +} + +template <typename BaseInterface, typename ImplementationTraits> +bool DeviceContextBase<BaseInterface, ImplementationTraits>::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device"); + return false; + } + + if (Attribs.pTLAS == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must not be null"); + return false; + } + if (!(Attribs.pTLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (Attribs.pDestBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must not be null"); + return false; + } + if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer is too small"); + return false; + } + if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 && + !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag"); + return false; + } + + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass"); + return false; + } + return true; +} + +template <typename BaseInterface, typename ImplementationTraits> +bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const TraceRaysAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device"); + return false; + } + if (Attribs.pSBT == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT must not be null"); @@ -2431,7 +2660,7 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::TraceRays(const Tra return false; } - if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState) + if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState.RawPtr()) { LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name, "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable"); diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 6ce6280b..5a2db2f8 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -228,13 +228,19 @@ public: inline void CopyShaderHandle(const char* Name, void* pData, Uint32 DataSize) const { - VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); const auto ShaderHandleSize = m_pRayTracingPipelineData->ShaderHandleSize; VERIFY_EXPR(ShaderHandleSize <= DataSize); + if (Name == nullptr || Name[0] == '\0') + { + // set shader binding to zero to skip shader execution + std::memset(pData, 0, ShaderHandleSize); + return; + } + auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name); if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end()) { diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index b5642a75..04870876 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -225,10 +225,133 @@ public: Bool DILIGENT_CALL_TYPE Verify() const override final { - // AZ TODO + Uint32 ShCounter = 0; + Uint32 RecCounter = 0; + const auto Stride = this->m_ShaderRecordStride; + const auto ShSize = this->m_pDevice->GetShaderGroupHandleSize(); + const auto FindPattern = [&ShCounter, &RecCounter, Stride, ShSize](const std::vector<Uint8>& Data, const char* Name) -> bool // + { + for (size_t i = 0; i < Data.size(); i += Stride) + { + Uint32 Count = 0; + for (size_t j = 0; j < ShSize; ++j) + Count += (Data[i + j] == EmptyElem); + + if (Count == ShSize) + { + LOG_ERROR_MESSAGE("Shader binding table is not valid: shader in '", Name, "'(", i / Stride, ") is not bound"); + return false; + } + + Count = 0; + for (size_t j = ShSize; j < Stride; ++j) + Count += (Data[i + j] == EmptyElem); + + if (Count > Stride - ShSize) + LOG_WARNING_MESSAGE("Shader binding table is not valid: shader record data in '", Name, "'(", i / Stride, ") is not initialized"); + } + return true; + }; + + if (m_RayGenShaderRecord.empty()) + { + LOG_ERROR_MESSAGE("Shader binding table is not valid: ray generation shader is not bound"); + return false; + } + + if (!FindPattern(m_RayGenShaderRecord, "ray generation") || + !FindPattern(m_MissShadersRecord, "miss") || + !FindPattern(m_CallableShadersRecord, "callable") || + !FindPattern(m_HitGroupsRecord, "hit groups")) + return false; + return true; } + struct BindingTable + { + const void* pData = nullptr; + Uint32 Size = 0; + Uint32 Offset = 0; + Uint32 Stride = 0; + }; + void GetData(IBuffer*& pSBTBuffer, + BindingTable& RaygenShaderBindingTable, + BindingTable& MissShaderBindingTable, + BindingTable& HitShaderBindingTable, + BindingTable& CallableShaderBindingTable) + { + const auto ShaderGroupBaseAlignment = GetDevice()->GetShaderGroupBaseAlignment(); + + const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 { + return Align(static_cast<Uint32>(offset), ShaderGroupBaseAlignment); + }; + + 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 (this->m_pBuffer == nullptr || this->m_pBuffer->GetDesc().uiSizeInBytes < BufSize) + { + this->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, &this->m_pBuffer); + VERIFY_EXPR(this->m_pBuffer != nullptr); + } + + if (this->m_pBuffer == nullptr) + return; // something goes wrong + + pSBTBuffer = this->m_pBuffer; + + if (m_RayGenShaderRecord.size()) + { + RaygenShaderBindingTable.pData = this->m_Changed ? m_RayGenShaderRecord.data() : nullptr; + RaygenShaderBindingTable.Offset = RayGenOffset; + RaygenShaderBindingTable.Size = static_cast<Uint32>(m_RayGenShaderRecord.size()); + RaygenShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (m_MissShadersRecord.size()) + { + MissShaderBindingTable.pData = this->m_Changed ? m_MissShadersRecord.data() : nullptr; + MissShaderBindingTable.Offset = MissShaderOffset; + MissShaderBindingTable.Size = static_cast<Uint32>(m_MissShadersRecord.size()); + MissShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (m_HitGroupsRecord.size()) + { + HitShaderBindingTable.pData = this->m_Changed ? m_HitGroupsRecord.data() : nullptr; + HitShaderBindingTable.Offset = HitGroupOffset; + HitShaderBindingTable.Size = static_cast<Uint32>(m_HitGroupsRecord.size()); + HitShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (m_CallableShadersRecord.size()) + { + CallableShaderBindingTable.pData = this->m_Changed ? m_CallableShadersRecord.data() : nullptr; + CallableShaderBindingTable.Offset = CallableShadersOffset; + CallableShaderBindingTable.Size = static_cast<Uint32>(m_CallableShadersRecord.size()); + CallableShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (!this->m_Changed) + return; + + this->m_Changed = false; + } + protected: void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) const { @@ -270,6 +393,7 @@ protected: std::vector<Uint8> m_HitGroupsRecord; RefCntAutoPtr<PipelineStateImplType> m_pPSO; + RefCntAutoPtr<IBuffer> m_pBuffer; Uint32 m_ShaderRecordSize = 0; Uint32 m_ShaderRecordStride = 0; diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index b03d9e5c..a8896abb 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -33,6 +33,7 @@ #include <unordered_map> #include "TopLevelAS.h" +#include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" @@ -71,59 +72,66 @@ public: { } - void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) + void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) noexcept { - this->m_Instances.clear(); - this->m_StringPool.Release(); - this->m_HitShadersPerInstance = HitShadersPerInstance; - - size_t StringPoolSize = 0; - for (Uint32 i = 0; i < InstanceCount; ++i) + try { - StringPoolSize += strlen(pInstances[i].InstanceName) + 1; - } + this->m_Instances.clear(); + this->m_StringPool.Release(); + this->m_HitShadersPerInstance = HitShadersPerInstance; + + size_t StringPoolSize = 0; + for (Uint32 i = 0; i < InstanceCount; ++i) + { + StringPoolSize += strlen(pInstances[i].InstanceName) + 1; + } - this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - Uint32 InstanceOffset = 0; + Uint32 InstanceOffset = 0; - for (Uint32 i = 0; i < InstanceCount; ++i) - { - auto& inst = pInstances[i]; - const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName); - InstanceDesc Desc = {}; + for (Uint32 i = 0; i < InstanceCount; ++i) + { + auto& inst = pInstances[i]; + const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName); + InstanceDesc Desc = {}; - Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex; - Desc.pBLAS = ValidatedCast<BottomLevelASType>(inst.pBLAS); + Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex; + Desc.pBLAS = ValidatedCast<BottomLevelASType>(inst.pBLAS); #ifdef DILIGENT_DEVELOPMENT - Desc.Version = Desc.pBLAS->GetVersion(); + Desc.Version = Desc.pBLAS->GetVersion(); #endif - if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) - { - Desc.ContributionToHitGroupIndex = InstanceOffset; - auto& BLASDesc = Desc.pBLAS->GetDesc(); - switch (this->m_Desc.BindingMode) + if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) { - // clang-format off - case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break; - case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; - case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; - default: UNEXPECTED("unknown ray tracing shader binding mode"); - // clang-format on + Desc.ContributionToHitGroupIndex = InstanceOffset; + auto& BLASDesc = Desc.pBLAS->GetDesc(); + switch (this->m_Desc.BindingMode) + { + // clang-format off + case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break; + case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; + case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; + default: UNEXPECTED("unknown ray tracing shader binding mode"); + // clang-format on + } } + + bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Instance name must be unique!"); } - bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Instance name must be unique!"); + VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); + } + catch (...) + { + this->m_Instances.clear(); } - - VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); } - void CopyInstancceData(const TopLevelASBase& Src) + void CopyInstancceData(const TopLevelASBase& Src) noexcept { this->m_Instances.clear(); this->m_StringPool.Release(); @@ -162,6 +170,8 @@ public: virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { + VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE || State == RESOURCE_STATE_RAY_TRACING, + "Unsupported state for top-level acceleration structure"); this->m_State = State; } @@ -183,18 +193,42 @@ public: } #ifdef DILIGENT_DEVELOPMENT - bool CheckBLASVersion() const + bool ValidateContent() const { + bool result = true; + + if (m_Instances.empty()) + { + LOG_ERROR_MESSAGE("TLAS with name ('", GetDesc().Name, "') doesn't have instances, use IDeviceContext::BuildTLAS() or IDeviceContext::CopyTLAS() to initialize TLAS content"); + result = false; + } + + // validate instances for (auto& NameAndInst : m_Instances) { - auto& Inst = NameAndInst.second; + const InstanceDesc& Inst = NameAndInst.second; + const BottomLevelASDesc& Desc = Inst.pBLAS->GetDesc(); + if (Inst.Version != Inst.pBLAS->GetVersion()) { - LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS that was changed after TLAS build, you must rebuild TLAS."); - return false; + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that was changed after TLAS build, you must rebuild TLAS"); + result = false; + } + + if (Inst.pBLAS->GetState() != RESOURCE_STATE_BUILD_AS_READ) + { + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that must be in BUILD_AS_READ state, but current state is ", + GetResourceStateFlagString(Inst.pBLAS->GetState())); + result = false; + } + + if (!Inst.pBLAS->ValidateContent()) + { + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that is not valid"); + result = false; } } - return true; + return result; } #endif @@ -203,15 +237,29 @@ protected: { #define LOG_TLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Top-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) - if (Desc.MaxInstanceCount == 0) + if (Desc.CompactedSize > 0) { - LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); - } + if (Desc.MaxInstanceCount != 0) + { + LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then MaxInstanceCount must be zero"); + } - if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) != 0 || - (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD) != 0) + if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) + { + LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE"); + } + } + else { - LOG_TLAS_ERROR_AND_THROW("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD are invalid"); + if (Desc.MaxInstanceCount == 0) + { + LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); + } + + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + { + LOG_TLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); + } } #undef LOG_TLAS_ERROR_AND_THROW diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index d2f1ed0f..ac521756 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -46,39 +46,37 @@ static const INTERFACE_ID IID_BottomLevelAS = /// Defines bottom level acceleration structure triangles description. -/// AZ TODO +/// Triangle geometry description. struct BLASTriangleDesc { /// Geometry name. - /// The name is used to map BLASBuildTriangleData to this geometry. + /// The name is used to map triangles data (BLASBuildTriangleData) to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); /// The maximum vertex count for this geometry. /// Current number of vertices is defined in BLASBuildTriangleData::VertexCount. Uint32 MaxVertexCount DEFAULT_INITIALIZER(0); - /// The type of vertices in this geometry. - /// Float, Int16 are supported. + /// The type of vertices in this geometry, see Diligent::VALUE_TYPE. VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); /// The number of components in vertex. /// 2 and 3 are supported. Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); - /// The maximum index count for this geometry. - /// The current number of indices is defined in BLASBuildTriangleData::IndexCount. - /// It must be 0 if IndexType is VT_UNDEFINED and greater than zero otherwise. - Uint32 MaxIndexCount DEFAULT_INITIALIZER(0); + /// The maximum primitive count of this geometry. + /// The current number of primitives is defined in BLASBuildTriangleData::PrimitiveCount. + Uint32 MaxPrimitiveCount DEFAULT_INITIALIZER(0); - /// Index type of this geometry. + /// Index type of this geometry, see Diligent::VALUE_TYPE. /// Must be VT_UINT16, VT_UINT32 or VT_UNDEFINED. + /// If not defined then used vertex array instead of indexed vertices. VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); - /// AZ TODO + /// Vulkan only, allows to use transformations in BLASBuildTriangleData. Bool AllowsTransforms DEFAULT_INITIALIZER(False); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASTriangleDesc() noexcept {} #endif }; @@ -87,11 +85,11 @@ typedef struct BLASTriangleDesc BLASTriangleDesc; /// Defines bottom level acceleration structure axis aligned bounding boxes description. -/// AZ TODO +/// AABB geometry description. struct BLASBoundingBoxDesc { /// Geometry name. - /// The name is used to map BLASBuildBoundingBoxData to this geometry. + /// The name is used to map AABB data (BLASBuildBoundingBoxData) to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); /// The maximum AABBs count. @@ -99,25 +97,22 @@ struct BLASBoundingBoxDesc Uint32 MaxBoxCount DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBoundingBoxDesc() noexcept {} #endif }; typedef struct BLASBoundingBoxDesc BLASBoundingBoxDesc; -/// AZ TODO - -/// AZ TODO +/// Defines acceleration structures build flags. DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) { - /// AZ TODO RAYTRACING_BUILD_AS_NONE = 0, - /// AZ TODO + /// AZ TODO: not supported yet RAYTRACING_BUILD_AS_ALLOW_UPDATE = 0x01, - /// Indicates that the specified acceleration structure can act as the source for a copy acceleration structure command + /// Indicates that the specified acceleration structure can act as the source for + /// a copy acceleration structure command IDeviceContext::CopyBLAS() or IDeviceContext::CopyTLAS() /// with mode of COPY_AS_MODE_COMPACT to produce a compacted acceleration structure. RAYTRACING_BUILD_AS_ALLOW_COMPACTION = 0x02, @@ -131,15 +126,12 @@ DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) /// result build, potentially at the expense of build time or trace performance. RAYTRACING_BUILD_AS_LOW_MEMORY = 0x10, - RAYTRACING_BUILD_AS_FLAGS_LAST = 0x10 + RAYTRACING_BUILD_AS_FLAGS_LAST = RAYTRACING_BUILD_AS_LOW_MEMORY }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_BUILD_AS_FLAGS) -/// AZ TODO - -// Here we allocate space for geometry data. -// Geometry can be dynamically updated. +/// Bottom-level AS description. struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Array of triangle geometry descriptions. @@ -156,29 +148,37 @@ struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS. RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); + + /// Size from the result of IDeviceContext::WriteBLASCompactedSize() if this acceleration structure + /// is going to be the target of a compacting copy (IDeviceContext::CopyBLAS() with COPY_AS_MODE_COMPACT). + Uint32 CompactedSize DEFAULT_INITIALIZER(0); /// Defines which command queues this BLAS can be used with Uint64 CommandQueueMask DEFAULT_INITIALIZER(1); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BottomLevelASDesc() noexcept {} #endif }; typedef struct BottomLevelASDesc BottomLevelASDesc; + +/// Defines scratch buffer info for acceleration structure. struct ScratchBufferSizes { + /// Scratch buffer size for acceleration structure building. Uint32 Build DEFAULT_INITIALIZER(0); + + /// AZ TODO: not supported yet Uint32 Update DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE - /// AZ TODO ScratchBufferSizes() noexcept {} #endif }; typedef struct ScratchBufferSizes ScratchBufferSizes; + #define DILIGENT_INTERFACE_NAME IBottomLevelAS #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" @@ -186,7 +186,9 @@ typedef struct ScratchBufferSizes ScratchBufferSizes; IDeviceObjectInclusiveMethods; \ IBottomLevelASMethods BottomLevelAS -/// AZ TODO +/// Bottom-level AS interface + +/// Defines the methods to manipulate a BLAS object DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) { #if DILIGENT_CPP_INTERFACE @@ -194,11 +196,16 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) virtual const BottomLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif - /// AZ TODO + /// Returns geometry index that can be used in shader binding table. + + /// \param [in] Name - Geometry name that specified in BLASTriangleDesc or BLASBoundingBoxDesc. + /// \return Geometry index. VIRTUAL Uint32 METHOD(GetGeometryIndex)(THIS_ const char* Name) CONST PURE; - /// AZ TODO + /// Returns scratch buffer info for current acceleration structure. + + /// \return structure object. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; /// Returns native acceleration structure handle specific to the underlying graphics API diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 0cb7fe7d..6c035ded 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -719,10 +719,10 @@ struct BeginRenderPassAttribs }; typedef struct BeginRenderPassAttribs BeginRenderPassAttribs; -/// AZ TODO + +/// TLAS instance flags that used in IDeviceContext::BuildTLAS(). DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) { - /// AZ TODO RAYTRACING_INSTANCE_NONE = 0, /// Disables face culling for this instance. @@ -734,38 +734,40 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x02, /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were specified on all - /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V NoOpaqueKHR ray flag. + /// geometries referenced by this instance. This behavior can be overridden in shader by ray flags. RAYTRACING_INSTANCE_FORCE_OPAQUE = 0x04, - /// causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all - /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V OpaqueKHR ray flag. + /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all + /// geometries referenced by this instance. This behavior can be overridden shader by ray flags. RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08, RAYTRACING_INSTANCE_FLAGS_LAST = RAYTRACING_INSTANCE_FORCE_NO_OPAQUE }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_INSTANCE_FLAGS) -/// AZ TODO + +/// Defines acceleration structure copy mode. + +/// These flags are used by IDeviceContext::CopyBLAS() and IDeviceContext::CopyTLAS(). DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) { - /// Creates a direct copy of the acceleration structure specified in src into the one specified by dst. - /// The dst acceleration structure must have been created with the same parameters as src. + /// Creates a direct copy of the acceleration structure specified in pSrc into the one specified by pDst. + /// The pDst acceleration structure must have been created with the same parameters as pSrc. COPY_AS_MODE_CLONE = 0, - // creates a more compact version of an acceleration structure src into dst. - // The acceleration structure dst must have been created with a compactedSize corresponding to the one returned by vkCmdWriteAccelerationStructuresPropertiesKHR - // after the build of the acceleration structure specified by src. - //COPY_AS_MODE_COMPACT, + /// Creates a more compact version of an acceleration structure pSrc into pDst. + /// The acceleration structure pDst must have been created with a CompactedSize corresponding + /// to the one returned by IDeviceContext::WriteBLASCompactedSize() or IDeviceContext::WriteTLASCompactedSize() + /// after the build of the acceleration structure specified by pSrc. + COPY_AS_MODE_COMPACT, - COPY_AS_MODE_LAST = COPY_AS_MODE_CLONE, + COPY_AS_MODE_LAST = COPY_AS_MODE_COMPACT, }; -/// Defines geometry flags for ray tracing. -/// AZ TODO +/// Defines geometry flags for ray tracing. DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) { - /// AZ TODO RAYTRACING_GEOMETRY_NONE = 0, /// Indicates that this geometry does not invoke the any-hit shaders even if present in a hit group. @@ -779,148 +781,168 @@ DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS) -/// AZ TODO + +/// Triangle geometry data description. struct BLASBuildTriangleData { - // put geometry data to geometry that allocated by BLASTriangleDesc + /// Geometry name used to map geometry to hit group in shader binding table. + /// Put geometry data to geometry that allocated by BLASTriangleDesc with the same name. const char* GeometryName DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr); // specs: Triangles are considered "inactive" (but legal input to acceleration structure build) if the x component of each vertex is NaN + /// Triangle vertices data source. + /// Triangles are considered "inactive" if the x component of each vertex is NaN. + /// Buffer must be created with BIND_RAY_TRACING flag. + IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pVertexBuffer. Uint32 VertexOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Stride in bytes between each vertex. Uint32 VertexStride DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Number of triangle vertices. + /// Must be less than or equal to BLASTriangleDesc::MaxVertexCount. Uint32 VertexCount DEFAULT_INITIALIZER(0); - /// AZ TODO - VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration - Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); // optional, value may be taken from declaration - - // optional + /// The type of vertex and number of components. + /// This is optional values. Must be undefined or same as in BLASTriangleDesc. + VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); + Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Number of triangles. + /// Must equal to VertexCount / 3 if pIndexBuffer is null or must equal to index count / 3. + Uint32 PrimitiveCount DEFAULT_INITIALIZER(0); + + /// Triangle indices data source. + /// Must be null if BLASTriangleDesc::IndexType is undefined. + /// Buffer must be created with BIND_RAY_TRACING flag. IBuffer* pIndexBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pIndexBuffer. Uint32 IndexOffset DEFAULT_INITIALIZER(0); - /// AZ TODO - Uint32 IndexCount DEFAULT_INITIALIZER(0); // AZ TODO: use PrimitveCount ? + /// Type of triangle indices, see Diligent::VALUE_TYPE. + /// This is optional value. Must be undefined or same as in BLASTriangleDesc. + VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); - /// AZ TODO - VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration - - // optional, buffer that contains 3x4 matrix with local transformation for this triangles/mesh - - /// AZ TODO + /// Geometry transformation data source. + /// Buffer must be created with BIND_RAY_TRACING flag. IBuffer* pTransformBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pTransformBuffer. Uint32 TransformBufferOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Geometry flags. RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBuildTriangleData() noexcept {} #endif }; typedef struct BLASBuildTriangleData BLASBuildTriangleData; -/// AZ TODO + +/// AABB geometry data description. struct BLASBuildBoundingBoxData { - /// AZ TODO - // put geometry data to geometry that allocated by BLASBoundingBoxDesc + /// Geometry name used to map geometry to hit group in shader binding table. + /// Put geometry data to geometry that allocated by BLASBoundingBoxDesc with the same name. const char* GeometryName DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBuffer* pBoxBuffer DEFAULT_INITIALIZER(nullptr); // specs: AABBs are considered inactive if AABB.MinX is NaN + /// AABB data source. + /// Each AABB defined as { float3 Min; float3 Max } structure. + /// AABB are considered inactive if AABB.Min.x is NaN. + /// Buffer must be created with BIND_RAY_TRACING flag. + IBuffer* pBoxBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pBoxBuffer. Uint32 BoxOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Stride in bytes between each AABB. Uint32 BoxStride DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Number of AABBs. + /// Must be less than or equal to BLASBoundingBoxDesc::MaxBoxCount. Uint32 BoxCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Geometry flags, see Diligent::RAYTRACING_GEOMETRY_FLAGS. RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBuildBoundingBoxData() noexcept {} #endif }; typedef struct BLASBuildBoundingBoxData BLASBuildBoundingBoxData; -/// AZ TODO +/// This structure is used by IDeviceContext::BuildBLAS(). struct BLASBuildAttribs { - /// AZ TODO + /// Target bottom-level AS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO + + /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// AZ TODO + /// Geometry data source buffers state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// AZ TODO + /// A pointer to an array of TriangleDataCount BLASBuildTriangleData structures that contains triangle geometry data. BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Number of triangle grometries. + /// Must be less than or equal to BottomLevelASDesc::TriangleCount. Uint32 TriangleDataCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// A pointer to an array of BoxDataCount BLASBuildBoundingBoxData structures that contains AABB geometry data. BLASBuildBoundingBoxData const* pBoxData DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Number of AABB geometries. + /// Must be less than or equal to BottomLevelASDesc::BoxCount. Uint32 BoxDataCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Buffer that used for acceleration structure building. + /// Must be created with BIND_RAY_TRACING. + /// Call IBottomLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer. IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Offset from the beginning of the buffer. Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBuildAttribs() noexcept {} #endif }; typedef struct BLASBuildAttribs BLASBuildAttribs; -/// AZ TODO +/// Can be used in TLASBuildInstanceData::ContributionToHitGroupIndex to calculate index +/// depending on geometry count in TLASBuildInstanceData::pBLAS and shader binding mode in TopLevelASDesc::BindingMode. +/// +/// Example: +/// For each instance in TLAS +/// if (Instance.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) +/// Instance.ContributionToHitGroupIndex = InstanceOffset; +/// if (BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY) InstanceOffset += Instance.pBLAS->GeometryCount() * HitShadersPerInstance; +/// if (BindingMode == SHADER_BINDING_MODE_PER_INSTANCE) InstanceOffset += HitShadersPerInstance; static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; -/// AZ TODO -static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; -/// AZ TODO +/// Row-major matrix struct InstanceMatrix { - /// rotation translation - /// (0 1 2) [ 3] - /// (4 5 6) [ 7] - /// (8 9 10) [11] + /// (0.0 1.0 2.0) + /// (0.1 1.1 2.1) - rotation + /// (0.2 1.2 2.2) + /// + /// [0.3 1.3 2.3] - translation float data [3][4]; #if DILIGENT_CPP_INTERFACE - /// AZ TODO + /// Construct identity matrix. InstanceMatrix() noexcept : data{{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, @@ -928,7 +950,8 @@ struct InstanceMatrix {} InstanceMatrix(const InstanceMatrix&) noexcept = default; - + + /// Set matrix translation. InstanceMatrix& SetTranslation(float x, float y, float z) noexcept { data[0][3] = x; @@ -936,151 +959,229 @@ struct InstanceMatrix data[2][3] = z; return *this; } + + /// Set matrix rotation basis. + InstanceMatrix& SetRotation(const float* pMatrix3x3) noexcept + { + data[0][0] = pMatrix3x3[0]; data[1][0] = pMatrix3x3[1]; data[2][0] = pMatrix3x3[2]; + data[0][1] = pMatrix3x3[3]; data[1][1] = pMatrix3x3[4]; data[2][1] = pMatrix3x3[5]; + data[0][2] = pMatrix3x3[6]; data[1][2] = pMatrix3x3[7]; data[2][2] = pMatrix3x3[8]; + return *this; + } #endif }; typedef struct InstanceMatrix InstanceMatrix; -/// AZ TODO + +/// This structure is used by TLASBuildAttribs. struct TLASBuildInstanceData { - /// AZ TODO + /// Instance name that used to map instance to hit group in shader binding table. const char* InstanceName DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); // can be null to deactive instance + /// Bottom-level AS that represents instance geometry. + IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Instace to world transformation. InstanceMatrix Transform; - /// AZ TODO - Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL + /// User-defined value that can be accessed in shader via InstanceID() in HLSL and gl_InstanceCustomIndex in GLSL. + /// Used only first 24 bits. + Uint32 CustomId DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Instance flags, see Diligent::RAYTRACING_INSTANCE_FLAGS. RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE); - /// AZ TODO - Uint8 Mask DEFAULT_INITIALIZER(0xFF); // visibility mask for the geometry, the instance may only be hit if rayMask & instance.mask != 0 + /// Visibility mask for the geometry, the instance may only be hit if rayMask & instance.Mask != 0. + /// (rayMask in GLSL is a cullMask argument of traceRayEXT(), rayMask in HLSL is a InstanceInclusionMask argument of TraceRay()). + Uint8 Mask DEFAULT_INITIALIZER(0xFF); - /// AZ TODO - Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll() + /// Index used to calculate hit group location in shader binding table. + /// Must be TLAS_INSTANCE_OFFSET_AUTO is TLAS created with BindingMode SHADER_BINDING_MODE_PER_GEOMETRY or SHADER_BINDING_MODE_PER_INSTANCE. + /// Used only first 24 bits. + Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TLASBuildInstanceData() noexcept {} #endif }; typedef struct TLASBuildInstanceData TLASBuildInstanceData; -/// AZ TODO +/// Instance size in GPU side. +/// Used to calculate size of TLASBuildAttribs::pInstanceBuffer. +static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; + + +/// This structure is used by IDeviceContext::BuildTLAS(). struct TLASBuildAttribs { - /// AZ TODO + /// Target top-level AS. ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// AZ TODO + /// Bottom-level AS (in TLASBuildInstanceData::pBLAS) state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - - /// AZ TODO + + /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contains instance data. TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Number of instances. + /// Must be less than or equal to TopLevelASDesc::MaxInstanceCount. Uint32 InstanceCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Buffer that will be used to store instance data during AS building. + /// Buffer size must be at least TLAS_INSTANCE_DATA_SIZE * InstanceCount. + /// Buffer must be created with BIND_RAY_TRACING flag. IBuffer* pInstanceBuffer DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO + + /// Offset from the beginning of the buffer to location of instance data. Uint32 InstanceBufferOffset DEFAULT_INITIALIZER(0); - - /// AZ TODO + + /// Instance buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); /// AZ TODO Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); - - /// AZ TODO + + /// Buffer that used for acceleration structure building. + /// Must be created with BIND_RAY_TRACING. + /// Call ITopLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer. IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Offset from the beginning of the buffer. Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TLASBuildAttribs() noexcept {} #endif }; typedef struct TLASBuildAttribs TLASBuildAttribs; -/// AZ TODO +/// This structure is used by IDeviceContext::CopyBLAS(). struct CopyBLASAttribs { - /// AZ TODO - IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); + /// Source bottom-level AS. + IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr); + /// Destination bottom-level AS. + /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize + /// that is greater or equal to size that returned by IDeviceContext::WriteBLASCompactedSize. + IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); + /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE. + COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); - /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// Source bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE SrcTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE DstTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO CopyBLASAttribs() noexcept {} #endif }; typedef struct CopyBLASAttribs CopyBLASAttribs; -/// AZ TODO +/// This structure is used by IDeviceContext::CopyTLAS(). struct CopyTLASAttribs { - /// AZ TODO - ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); + /// Source top-level AS. + ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr); + /// Destination top-level AS. + /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize + /// that is greater or equal to size that returned by IDeviceContext::WriteTLASCompactedSize. + ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); + /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE. + COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); - /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// Source top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE SrcTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE DstTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO CopyTLASAttribs() noexcept {} #endif }; typedef struct CopyTLASAttribs CopyTLASAttribs; -/// AZ TODO +/// This structure is used by IDeviceContext::WriteBLASCompactedSize(). +struct WriteBLASCompactedSizeAttribs +{ + /// Bottom-level AS. + IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); + + /// Command will writes 64 bit value with acceleration structure compacted size into buffer. + IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr); + + /// Offset from the beginning of the buffer to location of AS compacted size. + Uint32 DestBufferOffset DEFAULT_INITIALIZER(0); + + /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + WriteBLASCompactedSizeAttribs() noexcept {} +#endif +}; +typedef struct WriteBLASCompactedSizeAttribs WriteBLASCompactedSizeAttribs; + + +/// This structure is used by IDeviceContext::WriteTLASCompactedSize(). +struct WriteTLASCompactedSizeAttribs +{ + /// Top-level AS. + ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); + + /// Command will writes 64 bit value with acceleration structure compacted size into buffer. + IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr); + + /// Offset from the beginning of the buffer to location of AS compacted size. + Uint32 DestBufferOffset DEFAULT_INITIALIZER(0); + + /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + WriteTLASCompactedSizeAttribs() noexcept {} +#endif +}; +typedef struct WriteTLASCompactedSizeAttribs WriteTLASCompactedSizeAttribs; + + +/// This structure is used by IDeviceContext::TraceRays(). struct TraceRaysAttribs { - /// AZ TODO - IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr); + /// Shader binding table. + IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - Uint32 DimensionX DEFAULT_INITIALIZER(1); - Uint32 DimensionY DEFAULT_INITIALIZER(1); - Uint32 DimensionZ DEFAULT_INITIALIZER(1); + Uint32 DimensionX DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in X direction. + Uint32 DimensionY DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Y direction. + Uint32 DimensionZ DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Z direction. - /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// Shader binding table buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE SBTTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TraceRaysAttribs() noexcept {} #endif }; @@ -1981,23 +2082,52 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) ITexture* pDstTexture, const ResolveTextureSubresourceAttribs REF ResolveAttribs) PURE; - /// AZ TODO + + /// Build Bottom-level acceleration structure with the specified geometries. + + /// \param [in] Attribs - Structure describing build BLAS command attributes, see Diligent::BLASBuildAttribs for details. VIRTUAL void METHOD(BuildBLAS)(THIS_ const BLASBuildAttribs REF Attribs) PURE; - /// AZ TODO + + /// Build Top-level acceleration structure with the specified instances. + + /// \param [in] Attribs - Structure describing build TLAS command attributes, see Diligent::TLASBuildAttribs for details. VIRTUAL void METHOD(BuildTLAS)(THIS_ const TLASBuildAttribs REF Attribs) PURE; - /// AZ TODO + + /// Copies data from one acceleration structure to another. + + /// \param [in] Attribs - Structure describing copy BLAS command attributes, see Diligent::CopyBLASAttribs for details. VIRTUAL void METHOD(CopyBLAS)(THIS_ const CopyBLASAttribs REF Attribs) PURE; - /// AZ TODO + + /// Copies data from one acceleration structure to another. + + /// \param [in] Attribs - Structure describing copy TLAS command attributes, see Diligent::CopyTLASAttribs for details. VIRTUAL void METHOD(CopyTLAS)(THIS_ const CopyTLASAttribs REF Attribs) PURE; - /// AZ TODO + + /// Writes acceleration structure memory size to the buffer for compacting operation. + + /// \param [in] Attribs - Structure describing write BLAS compacted size command attributes, see Diligent::WriteBLASCompactedSizeAttribs for details. + VIRTUAL void METHOD(WriteBLASCompactedSize)(THIS_ + const WriteBLASCompactedSizeAttribs REF Attribs) PURE; + + + /// Writes acceleration structure memory size to the buffer for compacting operation. + + /// \param [in] Attribs - Structure describing write TLAS compacted size command attributes, see Diligent::WriteTLASCompactedSizeAttribs for details. + VIRTUAL void METHOD(WriteTLASCompactedSize)(THIS_ + const WriteTLASCompactedSizeAttribs REF Attribs) PURE; + + + /// Executes a trace rays command. + + /// \param [in] Attribs - Trace rays command attributes, see Diligent::TraceRaysAttribs for details. VIRTUAL void METHOD(TraceRays)(THIS_ const TraceRaysAttribs REF Attribs) PURE; }; @@ -2054,6 +2184,8 @@ DILIGENT_END_INTERFACE # define IDeviceContext_BuildTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, BuildTLAS, This, __VA_ARGS__) # define IDeviceContext_CopyBLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyBLAS, This, __VA_ARGS__) # define IDeviceContext_CopyTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyTLAS, This, __VA_ARGS__) +# define IDeviceContext_WriteBLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteBLASCompactedSize, This, __VA_ARGS__) +# define IDeviceContext_WriteTLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteTLASCompactedSize, This, __VA_ARGS__) # define IDeviceContext_TraceRays(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRays, This, __VA_ARGS__) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 76f8dcd6..cd32efc4 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -2731,9 +2731,14 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) /// The resource is used for present RESOURCE_STATE_PRESENT = 0x10000, - /// AZ TODO + /// The resource is used as vertex/index/instance buffer in a AS building operation + /// or as acceleration structure source in a AS copy operation. RESOURCE_STATE_BUILD_AS_READ = 0x20000, + + /// The resource is used as target in a AS building or AS copy operations. RESOURCE_STATE_BUILD_AS_WRITE = 0x40000, + + /// The resource is used as top-level AS shader resource in a trace rays operation. RESOURCE_STATE_RAY_TRACING = 0x80000, RESOURCE_STATE_MAX_BIT = RESOURCE_STATE_RAY_TRACING, diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index ebec8344..a630b1f1 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -152,7 +152,7 @@ typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc; /// Graphics pipeline state description -/// This structure describes the graphics pipeline state and is part of the PipelineStateDesc structure. +/// This structure describes the graphics pipeline state and is part of the GraphicsPipelineStateCreateInfo structure. struct GraphicsPipelineDesc { /// Blend state description. @@ -215,13 +215,13 @@ struct GraphicsPipelineDesc typedef struct GraphicsPipelineDesc GraphicsPipelineDesc; -/// AZ TODO +/// Ray tracing general shader group description struct RayTracingGeneralShaderGroup { - /// AZ TODO + /// Unique group name. const char* Name DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Shader type must be SHADER_TYPE_RAY_GEN or SHADER_TYPE_RAY_MISS or SHADER_TYPE_CALLABLE. IShader* pShader DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE @@ -237,16 +237,18 @@ struct RayTracingGeneralShaderGroup }; typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; -/// AZ TODO +/// Ray tracing triangle hit shader group description. struct RayTracingTriangleHitShaderGroup { - /// AZ TODO + /// Unique group name. const char* Name DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Closest hit shader. + /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Any-hit shader. Can be null. + /// Shader type must be SHADER_TYPE_RAY_ANY_HIT. IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null #if DILIGENT_CPP_INTERFACE @@ -264,20 +266,23 @@ struct RayTracingTriangleHitShaderGroup }; typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup; -/// AZ TODO +/// Ray tracing procedural hit shader group description. struct RayTracingProceduralHitShaderGroup { - /// AZ TODO + /// Unique group name. const char* Name DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Intersection shader. + /// Shader type must be SHADER_TYPE_RAY_INTERSECTION. IShader* pIntersectionShader DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null - - /// AZ TODO - IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + + /// Closest hit shader. Can be null. + /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. + IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); + + /// Any-hit shader. Can be null. + /// Shader type must be SHADER_TYPE_RAY_ANY_HIT. + IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE RayTracingProceduralHitShaderGroup() noexcept @@ -296,14 +301,16 @@ struct RayTracingProceduralHitShaderGroup }; typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup; -/// AZ TODO +/// This structure describes the ray tracing pipeline state and is part of the RayTracingPipelineStateCreateInfo structure. struct RayTracingPipelineDesc { - // Size of the additional data passed to the shader. - Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0); + /// Size of the additional data passed to the shader. + /// Shader record size plus shader group size (32 bytes) must be aligned to 32 bytes. + /// Shader record size plus shader group size (32 bytes) must not exceed 4096 bytes. + Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0); - /// AZ TODO - Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) + /// Number of recursive call of TraceRay() in HLSL or traceRay() in GLSL. + Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) }; typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; @@ -440,26 +447,28 @@ typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo; /// Ray tracing pipeline state description. struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) - /// AZ TODO + /// Ray tracing pipeline description. RayTracingPipelineDesc RayTracingPipeline; - /// AZ TODO + /// A pointer to an array of GeneralShaderCount RayTracingGeneralShaderGroup structures that contains shader group description. const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + /// Number of general shader groups. + Uint32 GeneralShaderCount DEFAULT_INITIALIZER(0); - /// AZ TODO - const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + /// A pointer to an array of TriangleHitShaderCount RayTracingTriangleHitShaderGroup structures that contains shader group description. + /// Can be null. + const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0); + /// Number of triangle hit shader groups. + Uint32 TriangleHitShaderCount DEFAULT_INITIALIZER(0); - /// AZ TODO - Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0); + /// A pointer to an array of ProceduralHitShaderCount RayTracingProceduralHitShaderGroup structures that contains shader group description. + /// Can be null. + const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); + /// Number of procedural shader groups. + Uint32 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); /// Direct3D12 only: set name of constant buffer that will be used by local root signature. /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero. @@ -575,11 +584,16 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) VIRTUAL bool METHOD(IsCompatibleWith)(THIS_ const struct IPipelineState* pPSO) CONST PURE; - /// AZ TODO + + /// Returns index of shader group that is used by shader binding table. + /// This method must only be called for a ray tracing pipeline. + + /// \param [in] Name - Shader group name. VIRTUAL Uint32 METHOD(GetShaderGroupIndex)(THIS_ const char* Name) CONST PURE; - /// AZ TODO + + /// AZ TODO: remove ? VIRTUAL Uint32 METHOD(GetShaderGroupCount)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index 28e0bb17..fddffeba 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -356,7 +356,7 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8) /// Input attachment in a render pass SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT, - /// AZ TODO + /// Acceleration structure SHADER_RESOURCE_TYPE_ACCEL_STRUCT, SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_ACCEL_STRUCT diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index d6f0740f..da650349 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -46,17 +46,16 @@ static const INTERFACE_ID IID_ShaderBindingTable = // clang-format off -/// AZ TODO +/// Shader binding table description. struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs) - /// AZ TODO + /// Ray tracing pipeline state object from which shaders will be taken. IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr); /// AZ TODO Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); #if DILIGENT_CPP_INTERFACE - /// AZ TODO ShaderBindingTableDesc() noexcept {} #endif }; @@ -89,7 +88,6 @@ struct BindAllAttribs Uint32 HitSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (HitSRDataSize / HitGroupCount) #if DILIGENT_CPP_INTERFACE - /// AZ TODO BindAllAttribs() noexcept {} #endif }; @@ -102,7 +100,9 @@ typedef struct BindAllAttribs BindAllAttribs; IDeviceObjectInclusiveMethods; \ IShaderBindingTableMethods ShaderBindingTable -/// AZ TODO +/// Shader binding table interface + +/// Defines the methods to manipulate a SBT object DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) { #if DILIGENT_CPP_INTERFACE diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 630f8ddd..2efd8518 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -45,7 +45,7 @@ static const INTERFACE_ID IID_TopLevelAS = // clang-format off -/// AZ TODO +/// Defines shader binding mode. DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) { /// Each geometry in each instance can have a unique shader. @@ -58,41 +58,44 @@ DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) SHADER_BINDING_USER_DEFINED, }; -/// AZ TODO + +/// Top-level AS description. struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) - /// Here we allocate space for instances. - /// Instances can be dynamicaly updated. + /// Allocate space for specified number of instances. Uint32 MaxInstanceCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS. RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); + + /// Size from the result of IDeviceContext::WriteTLASCompactedSize() if this acceleration structure + /// is going to be the target of a compacting copy (IDeviceContext::CopyTLAS() with COPY_AS_MODE_COMPACT). + Uint32 CompactedSize DEFAULT_INITIALIZER(0); - // binding mode used for instanceOffset calculation. + /// Binding mode that used for TLASBuildInstanceData::ContributionToHitGroupIndex calculation, + /// see Diligent::SHADER_BINDING_MODE. SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY); - /// Defines which command queues this BLAS can be used with + /// Defines which command queues this BLAS can be used with. Uint64 CommandQueueMask DEFAULT_INITIALIZER(1); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TopLevelASDesc() noexcept {} #endif }; typedef struct TopLevelASDesc TopLevelASDesc; -/// AZ TODO +/// Top-level AS instance description. struct TLASInstanceDesc { - /// AZ TODO + /// Index that specified in TLASBuildInstanceData::ContributionToHitGroupIndex. Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Bottom-level AS that specified in TLASBuildInstanceData::pBLAS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TLASInstanceDesc() noexcept {} #endif }; @@ -106,7 +109,9 @@ typedef struct TLASInstanceDesc TLASInstanceDesc; IDeviceObjectInclusiveMethods; \ ITopLevelASMethods TopLevelAS -/// AZ TODO +/// Top-level AS interface + +/// Defines the methods to manipulate a TLAS object DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) { #if DILIGENT_CPP_INTERFACE @@ -114,11 +119,16 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) virtual const TopLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif - /// AZ TODO + /// Returns instance description that can be used in shader binding table. + + /// \param [in] Name - Instance name that specified in TLASBuildInstanceData::InstanceName. + /// \return structure object. VIRTUAL TLASInstanceDesc METHOD(GetInstanceDesc)(THIS_ const char* Name) CONST PURE; - /// AZ TODO + /// Returns scratch buffer info for current acceleration structure. + + /// \return structure object. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; /// Returns native acceleration structure handle specific to the underlying graphics API diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp index 5be505a1..0eea2efe 100644 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp @@ -262,6 +262,12 @@ public: /// Implementation of IDeviceContext::CopyTLAS(). virtual void DILIGENT_CALL_TYPE CopyTLAS(const CopyTLASAttribs& Attribs) override final; + /// Implementation of IDeviceContext::WriteBLASCompactedSize(). + virtual void DILIGENT_CALL_TYPE WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::WriteTLASCompactedSize(). + virtual void DILIGENT_CALL_TYPE WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRays(). virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index 54c9b3c4..c59f7165 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -2319,6 +2319,16 @@ void DeviceContextD3D11Impl::CopyTLAS(const CopyTLASAttribs& Attribs) UNSUPPORTED("CopyTLAS is not supported in DirectX 11"); } +void DeviceContextD3D11Impl::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) +{ + UNSUPPORTED("CopyTLAS is not supported in DirectX 11"); +} + +void DeviceContextD3D11Impl::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) +{ + UNSUPPORTED("CopyTLAS is not supported in DirectX 11"); +} + void DeviceContextD3D11Impl::TraceRays(const TraceRaysAttribs& Attribs) { UNSUPPORTED("TraceRays is not supported in DirectX 11"); diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp index 511f1a03..1d1f0082 100644 --- a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp +++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp @@ -383,11 +383,10 @@ public: } void EmitRaytracingAccelerationStructurePostbuildInfo(const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC& Desc, - UINT NumSourceAccelerationStructures, - const D3D12_GPU_VIRTUAL_ADDRESS* pSourceAccelerationStructureData) + D3D12_GPU_VIRTUAL_ADDRESS SourceAccelerationStructureAddress) { FlushResourceBarriers(); - static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->EmitRaytracingAccelerationStructurePostbuildInfo(&Desc, NumSourceAccelerationStructures, pSourceAccelerationStructureData); + static_cast<ID3D12GraphicsCommandList4*>(m_pCommandList.p)->EmitRaytracingAccelerationStructurePostbuildInfo(&Desc, 1, &SourceAccelerationStructureAddress); } void CopyRaytracingAccelerationStructure(D3D12_GPU_VIRTUAL_ADDRESS DestAccelerationStructureData, diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp index 389b76a1..8b1818f2 100644 --- a/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp +++ b/Graphics/GraphicsEngineD3D12/include/D3D12TypeConversions.hpp @@ -83,4 +83,7 @@ DXGI_FORMAT ValueTypeToIndexType(VALUE_TYPE Type); D3D12_RAYTRACING_GEOMETRY_FLAGS GeometryFlagsToD3D12RTGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags); D3D12_RAYTRACING_INSTANCE_FLAGS InstanceFlagsToD3D12RTInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags); +D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS BuildASFlagsToD3D12ASBuildFlags(RAYTRACING_BUILD_AS_FLAGS Flags); +D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE CopyASModeToD3D12ASCopyMode(COPY_AS_MODE Mode); + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp index 3ac65274..a112b90e 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp @@ -273,6 +273,12 @@ public: /// Implementation of IDeviceContext::CopyTLAS() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE CopyTLAS(const CopyTLASAttribs& Attribs) override final; + /// Implementation of IDeviceContext::WriteBLASCompactedSize() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::WriteTLASCompactedSize() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRays() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp index 636175d5..619368fd 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp @@ -180,6 +180,9 @@ public: static Uint32 GetShaderGroupHandleSize() { return D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; } static Uint32 GetMaxShaderRecordStride() { return D3D12_RAYTRACING_MAX_SHADER_RECORD_STRIDE; } + static Uint32 GetShaderGroupBaseAlignment() { return D3D12_RAYTRACING_SHADER_TABLE_BYTE_ALIGNMENT; } + + static Uint32 GetMaxDrawMeshTasksCount() { return 64000; } private: template <typename PSOCreateInfoType> diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp index daf84d14..537f240a 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderBindingTableD3D12Impl.hpp @@ -57,16 +57,6 @@ public: 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: - RefCntAutoPtr<IBuffer> m_pBuffer; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h index aa50251a..18ebd984 100644 --- a/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h +++ b/Graphics/GraphicsEngineD3D12/interface/ShaderBindingTableD3D12.h @@ -50,14 +50,6 @@ static const INTERFACE_ID IID_ShaderBindingTableD3D12 = /// 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 @@ -65,8 +57,6 @@ DILIGENT_END_INTERFACE #if DILIGENT_C_INTERFACE -# define IShaderBindingTableD3D12_GetD3D12AddressRangeAndStride(This, ...) CALL_IFACE_METHOD(ShaderBindingTableD3D12, GetD3D12AddressRangeAndStride, This, __VA_ARGS__) - #endif DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp index 31f0e6a3..1fc9f876 100644 --- a/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/BottomLevelASD3D12Impl.cpp @@ -44,67 +44,84 @@ BottomLevelASD3D12Impl::BottomLevelASD3D12Impl(IReferenceCounters* pRef 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; + auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5(); + UINT64 ResultDataMaxSizeInBytes = 0; - if (m_Desc.pTriangles != nullptr) + if (m_Desc.CompactedSize) { - 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); + ResultDataMaxSizeInBytes = m_Desc.CompactedSize; } - else if (m_Desc.pBoxes != nullptr) + else { - 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; + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO d3d12BottomLevelPrebuildInfo = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS d3d12BottomLevelInputs = {}; + std::vector<D3D12_RAYTRACING_GEOMETRY_DESC> Geometries; - MaxBoxCount += src.MaxBoxCount; + 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.IndexType == VT_UNDEFINED ? 0 : src.MaxPrimitiveCount * 3; + dst.Triangles.IndexFormat = ValueTypeToIndexType(src.IndexType); + dst.Triangles.IndexBuffer = 0; + dst.Triangles.Transform3x4 = 0; + + MaxPrimitiveCount += src.MaxPrimitiveCount; + } + 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); + } + else + { + UNEXPECTED("Either pTriangles or pBoxes must not be null"); } - 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); + 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()); + d3d12BottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL; + d3d12BottomLevelInputs.Flags = BuildASFlagsToD3D12ASBuildFlags(m_Desc.Flags); + d3d12BottomLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + d3d12BottomLevelInputs.pGeometryDescs = Geometries.data(); + d3d12BottomLevelInputs.NumDescs = static_cast<UINT>(Geometries.size()); - auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5(); + pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&d3d12BottomLevelInputs, &d3d12BottomLevelPrebuildInfo); + if (d3d12BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0) + LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info"); - pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&BottomLevelInputs, &BottomLevelPrebuildInfo); - if (BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0) - LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info"); + ResultDataMaxSizeInBytes = d3d12BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes; + + m_ScratchSize.Build = static_cast<Uint32>(d3d12BottomLevelPrebuildInfo.ScratchDataSizeInBytes); + m_ScratchSize.Update = static_cast<Uint32>(d3d12BottomLevelPrebuildInfo.UpdateScratchDataSizeInBytes); + } D3D12_HEAP_PROPERTIES HeapProps; HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; @@ -116,7 +133,7 @@ BottomLevelASD3D12Impl::BottomLevelASD3D12Impl(IReferenceCounters* pRef D3D12_RESOURCE_DESC ASDesc = {}; ASDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; ASDesc.Alignment = 0; - ASDesc.Width = BottomLevelPrebuildInfo.ResultDataMaxSizeInBytes; + ASDesc.Width = ResultDataMaxSizeInBytes; ASDesc.Height = 1; ASDesc.DepthOrArraySize = 1; ASDesc.MipLevels = 1; @@ -136,8 +153,9 @@ BottomLevelASD3D12Impl::BottomLevelASD3D12Impl(IReferenceCounters* pRef 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); + VERIFY_EXPR(GetGPUAddress() % D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT == 0); + + SetState(RESOURCE_STATE_BUILD_AS_READ); } BottomLevelASD3D12Impl::~BottomLevelASD3D12Impl() diff --git a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp index 4285e11a..1e301bb2 100644 --- a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp +++ b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp @@ -224,6 +224,12 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier) "RESOURCE_STATE_UNKNOWN to make the engine use current resource state"); } + // RESOURCE_STATE_UNORDERED_ACCESS and RESOURCE_STATE_BUILD_AS_WRITE converted to D3D12_RESOURCE_STATE_UNORDERED_ACCESS. + // UAV barrier must be inserted between D3D12_RESOURCE_STATE_UNORDERED_ACCESS resource usage. + bool RequireUAVBarrier = + (OldState == RESOURCE_STATE_UNORDERED_ACCESS || OldState == RESOURCE_STATE_BUILD_AS_WRITE) && + (Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE); + // Check if required state is already set if ((OldState & Barrier.NewState) != Barrier.NewState) { @@ -306,26 +312,34 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier) } 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); } + + // acceleration structure is always in D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE but requires UAV barrier instead of state transition. + RequireUAVBarrier |= (OldState == RESOURCE_STATE_BUILD_AS_WRITE); } 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); } + + // acceleration structure is always in D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE but requires UAV barrier instead of state transition. + RequireUAVBarrier |= (OldState == RESOURCE_STATE_BUILD_AS_WRITE); + +#ifdef DILIGENT_DEVELOPMENT + if (Barrier.NewState & RESOURCE_STATE_RAY_TRACING) + { + pTLASD3D12Impl->ValidateContent(); + } +#endif } } - if ((OldState == RESOURCE_STATE_UNORDERED_ACCESS || OldState == RESOURCE_STATE_BUILD_AS_WRITE) && - (Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE)) + if (RequireUAVBarrier) { DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "UAV barriers must not be split"); InsertUAVBarrier(pd3d12Resource); diff --git a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp index 74e65559..63d19ce4 100644 --- a/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/CommandQueueD3D12Impl.cpp @@ -94,6 +94,8 @@ Uint64 CommandQueueD3D12Impl::WaitForIdle() Uint64 CommandQueueD3D12Impl::GetCompletedFenceValue() { auto CompletedFenceValue = m_d3d12Fence->GetCompletedValue(); + VERIFY(CompletedFenceValue != UINT64_MAX, "If the device has been removed, the return value will be UINT64_MAX"); + if (CompletedFenceValue > m_LastCompletedFenceValue) m_LastCompletedFenceValue = CompletedFenceValue; return m_LastCompletedFenceValue; diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp index a6d6963e..1f1f621c 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp @@ -367,7 +367,7 @@ public: StateFlagBitPosToD3D12ResourceState() { static_assert((1 << MaxFlagBitPos) == RESOURCE_STATE_MAX_BIT, "This function must be updated to handle new resource state flag"); - for (Uint32 bit = 0; bit <= MaxFlagBitPos; ++bit) + for (Uint32 bit = 0; bit < FlagBitPosToResStateMap.size(); ++bit) { FlagBitPosToResStateMap[bit] = ResourceStateFlagToD3D12ResourceState(static_cast<RESOURCE_STATE>(1 << bit)); } @@ -436,7 +436,7 @@ class D3D12StateFlagBitPosToResourceState public: D3D12StateFlagBitPosToResourceState() { - for (Uint32 bit = 0; bit <= MaxFlagBitPos; ++bit) + for (Uint32 bit = 0; bit < FlagBitPosToResStateMap.size(); ++bit) { FlagBitPosToResStateMap[bit] = D3D12ResourceStateToResourceStateFlags(static_cast<D3D12_RESOURCE_STATES>(1 << bit)); } @@ -653,4 +653,46 @@ D3D12_RAYTRACING_INSTANCE_FLAGS InstanceFlagsToD3D12RTInstanceFlags(RAYTRACING_I return Result; } +D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS BuildASFlagsToD3D12ASBuildFlags(RAYTRACING_BUILD_AS_FLAGS Flags) +{ + static_assert(RAYTRACING_BUILD_AS_FLAGS_LAST == RAYTRACING_BUILD_AS_LOW_MEMORY, + "Please update the switch below to handle the new acceleration structure build flag"); + + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS Result = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_NONE; + while (Flags != RAYTRACING_BUILD_AS_NONE) + { + auto FlagBit = static_cast<RAYTRACING_BUILD_AS_FLAGS>(1 << PlatformMisc::GetLSB(Uint32{Flags})); + switch (FlagBit) + { + // clang-format off + case RAYTRACING_BUILD_AS_ALLOW_UPDATE: Result |= D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_UPDATE; break; + case RAYTRACING_BUILD_AS_ALLOW_COMPACTION: Result |= D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_COMPACTION; break; + case RAYTRACING_BUILD_AS_PREFER_FAST_TRACE: Result |= D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE; break; + case RAYTRACING_BUILD_AS_PREFER_FAST_BUILD: Result |= D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_BUILD; break; + case RAYTRACING_BUILD_AS_LOW_MEMORY: Result |= D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_MINIMIZE_MEMORY; break; + // clang-format on + default: UNEXPECTED("unknown build AS flag"); + } + Flags &= ~FlagBit; + } + return Result; +} + +D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE CopyASModeToD3D12ASCopyMode(COPY_AS_MODE Mode) +{ + static_assert(COPY_AS_MODE_LAST == COPY_AS_MODE_COMPACT, + "Please update the switch below to handle the new copy AS mode"); + + switch (Mode) + { + // clang-format off + case COPY_AS_MODE_CLONE: return D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE; + case COPY_AS_MODE_COMPACT: return D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_COMPACT; + // clang-format on + default: + UNEXPECTED("unknown AS copy mode"); + return static_cast<D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE>(~0u); + } +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 0adcaa59..41de3a47 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -2143,7 +2143,7 @@ void DeviceContextD3D12Impl::TransitionOrVerifyBufferState(CommandContext& { if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { - if (Buffer.IsInKnownState() && !Buffer.CheckState(RequiredState)) + if (Buffer.IsInKnownState()) CmdCtx.TransitionResource(&Buffer, RequiredState); } #ifdef DILIGENT_DEVELOPMENT @@ -2162,7 +2162,7 @@ void DeviceContextD3D12Impl::TransitionOrVerifyTextureState(CommandContext& { if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { - if (Texture.IsInKnownState() && !Texture.CheckState(RequiredState)) + if (Texture.IsInKnownState()) CmdCtx.TransitionResource(&Texture, RequiredState); } #ifdef DILIGENT_DEVELOPMENT @@ -2181,7 +2181,7 @@ void DeviceContextD3D12Impl::TransitionOrVerifyBLASState(CommandContext& { if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { - if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState)) + if (BLAS.IsInKnownState()) CmdCtx.TransitionResource(&BLAS, RequiredState); } #ifdef DILIGENT_DEVELOPMENT @@ -2200,7 +2200,7 @@ void DeviceContextD3D12Impl::TransitionOrVerifyTLASState(CommandContext& { if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { - if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState)) + if (TLAS.IsInKnownState()) CmdCtx.TransitionResource(&TLAS, RequiredState); } #ifdef DILIGENT_DEVELOPMENT @@ -2208,11 +2208,6 @@ void DeviceContextD3D12Impl::TransitionOrVerifyTLASState(CommandContext& { DvpVerifyTLASState(TLAS, RequiredState, OperationName); } - - if (RequiredState & RESOURCE_STATE_RAY_TRACING) - { - TLAS.CheckBLASVersion(); - } #endif } @@ -2291,8 +2286,8 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) 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; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC d3d12BuildASDesc = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& d3d12BuildASInputs = d3d12BuildASDesc.Inputs; std::vector<D3D12_RAYTRACING_GEOMETRY_DESC> Geometries; if (Attribs.pTriangleData != nullptr) @@ -2301,10 +2296,8 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) { - const auto& SrcTris = Attribs.pTriangleData[i]; - Uint32 GeoIdx = pBLASD12->GetGeometryIndex(SrcTris.GeometryName); - auto& d3d12Geo = Geometries[GeoIdx]; - auto& d3d12Tris = d3d12Geo.Triangles; + const auto& SrcTris = Attribs.pTriangleData[i]; + Uint32 GeoIdx = pBLASD12->GetGeometryIndex(SrcTris.GeometryName); if (GeoIdx >= Geometries.size()) { @@ -2312,11 +2305,17 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) continue; } + auto& d3d12Geo = Geometries[GeoIdx]; + auto& d3d12Tris = d3d12Geo.Triangles; + const auto& TriDesc = BLASDesc.pTriangles[GeoIdx]; + d3d12Geo.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; d3d12Geo.Flags = GeometryFlagsToD3D12RTGeometryFlags(SrcTris.Flags); - auto* const pVB = ValidatedCast<BufferD3D12Impl>(SrcTris.pVertexBuffer); - d3d12Tris.VertexFormat = TypeToDXGI_Format(SrcTris.VertexValueType, SrcTris.VertexComponentCount, SrcTris.VertexValueType < VT_FLOAT16); + auto* const pVB = ValidatedCast<BufferD3D12Impl>(SrcTris.pVertexBuffer); + + // vertex format in SrcTris may be undefined, so use vertex format from description + d3d12Tris.VertexFormat = TypeToDXGI_Format(TriDesc.VertexValueType, TriDesc.VertexComponentCount, TriDesc.VertexValueType < VT_FLOAT16); d3d12Tris.VertexCount = SrcTris.VertexCount; d3d12Tris.VertexBuffer.StartAddress = pVB->GetGPUAddress() + SrcTris.VertexOffset; d3d12Tris.VertexBuffer.StrideInBytes = SrcTris.VertexStride; @@ -2325,10 +2324,12 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) if (SrcTris.pIndexBuffer) { - auto* const pIB = ValidatedCast<BufferD3D12Impl>(SrcTris.pIndexBuffer); + auto* const pIB = ValidatedCast<BufferD3D12Impl>(SrcTris.pIndexBuffer); + + // index type in SrcTris may be undefined, so use index type from description + d3d12Tris.IndexFormat = ValueTypeToIndexType(TriDesc.IndexType); d3d12Tris.IndexBuffer = pIB->GetGPUAddress() + SrcTris.IndexOffset; - d3d12Tris.IndexCount = SrcTris.IndexCount; - d3d12Tris.IndexFormat = ValueTypeToIndexType(SrcTris.IndexType); + d3d12Tris.IndexCount = SrcTris.PrimitiveCount * 3; TransitionOrVerifyBufferState(CmdCtx, *pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); } @@ -2340,8 +2341,6 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) if (SrcTris.pTransformBuffer) { - VERIFY_EXPR(BLASDesc.pTriangles[GeoIdx].AllowsTransforms); - auto* const pTB = ValidatedCast<BufferD3D12Impl>(SrcTris.pTransformBuffer); d3d12Tris.Transform3x4 = pTB->GetGPUAddress() + SrcTris.TransformBufferOffset; @@ -2349,7 +2348,6 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) } else { - VERIFY_EXPR(!BLASDesc.pTriangles[GeoIdx].AllowsTransforms); d3d12Tris.Transform3x4 = 0; } } @@ -2360,10 +2358,8 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) { - const auto& SrcBoxes = Attribs.pBoxData[i]; - Uint32 GeoIdx = pBLASD12->GetGeometryIndex(SrcBoxes.GeometryName); - auto& d3d12Geo = Geometries[GeoIdx]; - auto& d3d12AABs = d3d12Geo.AABBs; + const auto& SrcBoxes = Attribs.pBoxData[i]; + Uint32 GeoIdx = pBLASD12->GetGeometryIndex(SrcBoxes.GeometryName); if (GeoIdx >= Geometries.size()) { @@ -2371,6 +2367,9 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) continue; } + auto& d3d12Geo = Geometries[GeoIdx]; + auto& d3d12AABs = d3d12Geo.AABBs; + d3d12Geo.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS; d3d12Geo.Flags = GeometryFlagsToD3D12RTGeometryFlags(SrcBoxes.Flags); @@ -2383,16 +2382,17 @@ void DeviceContextD3D12Impl::BuildBLAS(const BLASBuildAttribs& Attribs) } } - 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(); + d3d12BuildASInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL; + d3d12BuildASInputs.Flags = BuildASFlagsToD3D12ASBuildFlags(BLASDesc.Flags); + d3d12BuildASInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + d3d12BuildASInputs.NumDescs = static_cast<UINT>(Geometries.size()); + d3d12BuildASInputs.pGeometryDescs = Geometries.data(); - Desc.DestAccelerationStructureData = pBLASD12->GetGPUAddress(); - Desc.ScratchAccelerationStructureData = pScratchD12->GetGPUAddress(); - Desc.SourceAccelerationStructureData = 0; + d3d12BuildASDesc.DestAccelerationStructureData = pBLASD12->GetGPUAddress(); + d3d12BuildASDesc.ScratchAccelerationStructureData = pScratchD12->GetGPUAddress(); + d3d12BuildASDesc.SourceAccelerationStructureData = 0; - CmdCtx.AsGraphicsContext4().BuildRaytracingAccelerationStructure(Desc, 0, nullptr); + CmdCtx.AsGraphicsContext4().BuildRaytracingAccelerationStructure(d3d12BuildASDesc, 0, nullptr); ++m_State.NumCommands; #ifdef DILIGENT_DEVELOPMENT @@ -2420,21 +2420,20 @@ void DeviceContextD3D12Impl::BuildTLAS(const TLASBuildAttribs& Attribs) // 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; + size_t Size = Attribs.InstanceCount * sizeof(D3D12_RAYTRACING_INSTANCE_DESC); + auto TmpSpace = m_DynamicHeap.Allocate(Size, 16, m_ContextFrameNumber); for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { const auto& Inst = Attribs.pInstances[i]; - auto& d3d12Inst = static_cast<D3D12_RAYTRACING_INSTANCE_DESC*>(pMappedInstances)[i]; + auto& d3d12Inst = static_cast<D3D12_RAYTRACING_INSTANCE_DESC*>(TmpSpace.CPUAddress)[i]; auto* const pBLASD12 = ValidatedCast<BottomLevelASD3D12Impl>(Inst.pBLAS); static_assert(sizeof(d3d12Inst.Transform) == sizeof(Inst.Transform), "size mismatch"); std::memcpy(&d3d12Inst.Transform, Inst.Transform.data, sizeof(d3d12Inst.Transform)); d3d12Inst.InstanceID = Inst.CustomId; - d3d12Inst.InstanceContributionToHitGroupIndex = pTLASD12->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize + d3d12Inst.InstanceContributionToHitGroupIndex = pTLASD12->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; d3d12Inst.InstanceMask = Inst.Mask; d3d12Inst.Flags = InstanceFlagsToD3D12RTInstanceFlags(Inst.Flags); d3d12Inst.AccelerationStructure = pBLASD12->GetGPUAddress(); @@ -2449,6 +2448,7 @@ void DeviceContextD3D12Impl::BuildTLAS(const TLASBuildAttribs& Attribs) D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS& d3d12BuildASInputs = d3d12BuildASDesc.Inputs; d3d12BuildASInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; + d3d12BuildASInputs.Flags = BuildASFlagsToD3D12ASBuildFlags(pTLASD12->GetDesc().Flags); d3d12BuildASInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; d3d12BuildASInputs.NumDescs = Attribs.InstanceCount; d3d12BuildASInputs.InstanceDescs = pInstancesD12->GetGPUAddress(); @@ -2469,12 +2469,17 @@ void DeviceContextD3D12Impl::CopyBLAS(const CopyBLASAttribs& Attribs) auto* pSrcD3D12 = ValidatedCast<BottomLevelASD3D12Impl>(Attribs.pSrc); auto* pDstD3D12 = ValidatedCast<BottomLevelASD3D12Impl>(Attribs.pDst); auto& CmdCtx = GetCmdContext(); + auto Mode = CopyASModeToD3D12ASCopyMode(Attribs.Mode); + + // Dst BLAS description has specified CompactedSize, but doesn't have specified pTriangles and pBoxes. + // We should copy geometries because it required for SBT to map geometry name to hit group. + pDstD3D12->CopyDescription(*pSrcD3D12); const char* OpName = "Copy BottomLevelAS (DeviceContextD3D12Impl::CopyBLAS)"; - TransitionOrVerifyBLASState(CmdCtx, *pSrcD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); - TransitionOrVerifyBLASState(CmdCtx, *pDstD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + TransitionOrVerifyBLASState(CmdCtx, *pSrcD3D12, Attribs.SrcTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBLASState(CmdCtx, *pDstD3D12, Attribs.DstTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); - CmdCtx.AsGraphicsContext4().CopyRaytracingAccelerationStructure(pSrcD3D12->GetGPUAddress(), pDstD3D12->GetGPUAddress(), D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE); + CmdCtx.AsGraphicsContext4().CopyRaytracingAccelerationStructure(pDstD3D12->GetGPUAddress(), pSrcD3D12->GetGPUAddress(), Mode); ++m_State.NumCommands; #ifdef DILIGENT_DEVELOPMENT @@ -2490,14 +2495,67 @@ void DeviceContextD3D12Impl::CopyTLAS(const CopyTLASAttribs& Attribs) auto* pSrcD3D12 = ValidatedCast<TopLevelASD3D12Impl>(Attribs.pSrc); auto* pDstD3D12 = ValidatedCast<TopLevelASD3D12Impl>(Attribs.pDst); auto& CmdCtx = GetCmdContext(); + auto Mode = CopyASModeToD3D12ASCopyMode(Attribs.Mode); + // Instances specified in BuildTLAS command. + // We should copy instances because it required for SBT to map instance name to hit group. pDstD3D12->CopyInstancceData(*pSrcD3D12); const char* OpName = "Copy BottomLevelAS (DeviceContextD3D12Impl::CopyTLAS)"; - TransitionOrVerifyTLASState(CmdCtx, *pSrcD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); - TransitionOrVerifyTLASState(CmdCtx, *pDstD3D12, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + TransitionOrVerifyTLASState(CmdCtx, *pSrcD3D12, Attribs.SrcTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyTLASState(CmdCtx, *pDstD3D12, Attribs.DstTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); - CmdCtx.AsGraphicsContext4().CopyRaytracingAccelerationStructure(pSrcD3D12->GetGPUAddress(), pDstD3D12->GetGPUAddress(), D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE); + CmdCtx.AsGraphicsContext4().CopyRaytracingAccelerationStructure(pDstD3D12->GetGPUAddress(), pSrcD3D12->GetGPUAddress(), Mode); + ++m_State.NumCommands; +} + +void DeviceContextD3D12Impl::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) +{ + if (!TDeviceContextBase::WriteBLASCompactedSize(Attribs, 0)) + return; + + static_assert(sizeof(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_COMPACTED_SIZE_DESC) == sizeof(Uint64), + "Engine api specifies that compacted size is 64 bits"); + + auto* pBLASD3D12 = ValidatedCast<BottomLevelASD3D12Impl>(Attribs.pBLAS); + auto* pDestBuffD3D12 = ValidatedCast<BufferD3D12Impl>(Attribs.pDestBuffer); + auto& CmdCtx = GetCmdContext(); + + const char* OpName = "Write AS compacted size (DeviceContextD3D12Impl::WriteBLASCompactedSize)"; + TransitionOrVerifyBLASState(CmdCtx, *pBLASD3D12, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBufferState(CmdCtx, *pDestBuffD3D12, Attribs.BufferTransitionMode, RESOURCE_STATE_UNORDERED_ACCESS, OpName); + + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC d3d12Desc = {}; + + d3d12Desc.DestBuffer = pDestBuffD3D12->GetGPUAddress() + Attribs.DestBufferOffset; + d3d12Desc.InfoType = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_COMPACTED_SIZE; + + CmdCtx.AsGraphicsContext4().EmitRaytracingAccelerationStructurePostbuildInfo(d3d12Desc, pBLASD3D12->GetGPUAddress()); + ++m_State.NumCommands; +} + +void DeviceContextD3D12Impl::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) +{ + if (!TDeviceContextBase::WriteTLASCompactedSize(Attribs, 0)) + return; + + static_assert(sizeof(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_COMPACTED_SIZE_DESC) == sizeof(Uint64), + "Engine api specifies that compacted size is 64 bits"); + + auto* pTLASD3D12 = ValidatedCast<TopLevelASD3D12Impl>(Attribs.pTLAS); + auto* pDestBuffD3D12 = ValidatedCast<BufferD3D12Impl>(Attribs.pDestBuffer); + auto& CmdCtx = GetCmdContext(); + + const char* OpName = "Write AS compacted size (DeviceContextD3D12Impl::WriteTLASCompactedSize)"; + TransitionOrVerifyTLASState(CmdCtx, *pTLASD3D12, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBufferState(CmdCtx, *pDestBuffD3D12, Attribs.BufferTransitionMode, RESOURCE_STATE_UNORDERED_ACCESS, OpName); + + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC d3d12Desc = {}; + + d3d12Desc.DestBuffer = pDestBuffD3D12->GetGPUAddress() + Attribs.DestBufferOffset; + d3d12Desc.InfoType = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_COMPACTED_SIZE; + + CmdCtx.AsGraphicsContext4().EmitRaytracingAccelerationStructurePostbuildInfo(d3d12Desc, pTLASD3D12->GetGPUAddress()); ++m_State.NumCommands; } @@ -2506,20 +2564,60 @@ void DeviceContextD3D12Impl::TraceRays(const TraceRaysAttribs& Attribs) if (!TDeviceContextBase::TraceRays(Attribs, 0)) return; + VERIFY_EXPR((Attribs.DimensionX * Attribs.DimensionY * Attribs.DimensionZ) <= D3D12_RAYTRACING_MAX_RAY_GENERATION_SHADER_THREADS); + + auto& CmdCtx = GetCmdContext().AsGraphicsContext4(); + auto* pSBTD12 = ValidatedCast<ShaderBindingTableD3D12Impl>(Attribs.pSBT); + IBuffer* pBuffer = nullptr; + + ShaderBindingTableD3D12Impl::BindingTable RayGenShaderRecord = {}; + ShaderBindingTableD3D12Impl::BindingTable MissShaderTable = {}; + ShaderBindingTableD3D12Impl::BindingTable HitGroupTable = {}; + ShaderBindingTableD3D12Impl::BindingTable CallableShaderTable = {}; + + pSBTD12->GetData(pBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable); + + auto* pBufferD3D12 = ValidatedCast<BufferD3D12Impl>(pBuffer); + + const char* OpName = "Trace rays (DeviceContextD3D12Impl::TraceRays)"; + TransitionOrVerifyBufferState(CmdCtx, *pBufferD3D12, Attribs.SBTTransitionMode, RESOURCE_STATE_COPY_DEST, OpName); + + // buffer ranges are not intersected, so we don't need to add barriers between them + if (RayGenShaderRecord.pData) + UpdateBuffer(pBufferD3D12, RayGenShaderRecord.Offset, RayGenShaderRecord.Size, RayGenShaderRecord.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (MissShaderTable.pData) + UpdateBuffer(pBufferD3D12, MissShaderTable.Offset, MissShaderTable.Size, MissShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (HitGroupTable.pData) + UpdateBuffer(pBufferD3D12, HitGroupTable.Offset, HitGroupTable.Size, HitGroupTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (CallableShaderTable.pData) + UpdateBuffer(pBufferD3D12, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + TransitionOrVerifyBufferState(CmdCtx, *pBufferD3D12, Attribs.SBTTransitionMode, RESOURCE_STATE_RAY_TRACING, OpName); + D3D12_DISPATCH_RAYS_DESC d3d12DispatchDesc = {}; d3d12DispatchDesc.Width = Attribs.DimensionX; d3d12DispatchDesc.Height = Attribs.DimensionY; d3d12DispatchDesc.Depth = Attribs.DimensionZ; - auto* pSBTD12 = ValidatedCast<ShaderBindingTableD3D12Impl>(Attribs.pSBT); - pSBTD12->GetD3D12AddressRangeAndStride(this, Attribs.TransitionMode, - d3d12DispatchDesc.RayGenerationShaderRecord, - d3d12DispatchDesc.MissShaderTable, - d3d12DispatchDesc.HitGroupTable, - d3d12DispatchDesc.CallableShaderTable); + d3d12DispatchDesc.RayGenerationShaderRecord.StartAddress = pBufferD3D12->GetGPUAddress() + RayGenShaderRecord.Offset; + d3d12DispatchDesc.RayGenerationShaderRecord.SizeInBytes = RayGenShaderRecord.Size; + + d3d12DispatchDesc.MissShaderTable.StartAddress = pBufferD3D12->GetGPUAddress() + MissShaderTable.Offset; + d3d12DispatchDesc.MissShaderTable.SizeInBytes = MissShaderTable.Size; + d3d12DispatchDesc.MissShaderTable.StrideInBytes = MissShaderTable.Stride; + + d3d12DispatchDesc.HitGroupTable.StartAddress = pBufferD3D12->GetGPUAddress() + HitGroupTable.Offset; + d3d12DispatchDesc.HitGroupTable.SizeInBytes = HitGroupTable.Size; + d3d12DispatchDesc.HitGroupTable.StrideInBytes = HitGroupTable.Stride; + + d3d12DispatchDesc.CallableShaderTable.StartAddress = pBufferD3D12->GetGPUAddress() + CallableShaderTable.Offset; + d3d12DispatchDesc.CallableShaderTable.SizeInBytes = CallableShaderTable.Size; + d3d12DispatchDesc.CallableShaderTable.StrideInBytes = CallableShaderTable.Stride; - auto& CmdCtx = GetCmdContext().AsGraphicsContext4(); PrepareForDispatchRays(CmdCtx); CmdCtx.DispatchRays(d3d12DispatchDesc); diff --git a/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp index a9e1c7d8..02308ca0 100644 --- a/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/FenceD3D12Impl.cpp @@ -51,7 +51,9 @@ FenceD3D12Impl::~FenceD3D12Impl() Uint64 FenceD3D12Impl::GetCompletedValue() { - return m_pd3d12Fence->GetCompletedValue(); + Uint64 Result = m_pd3d12Fence->GetCompletedValue(); + VERIFY(Result != UINT64_MAX, "If the device has been removed, the return value will be UINT64_MAX"); + return Result; } void FenceD3D12Impl::Reset(Uint64 Value) @@ -61,7 +63,7 @@ void FenceD3D12Impl::Reset(Uint64 Value) void FenceD3D12Impl::WaitForCompletion(Uint64 Value) { - while (m_pd3d12Fence->GetCompletedValue() < Value) + while (GetCompletedValue() < Value) std::this_thread::yield(); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp index d71d98b7..ac67ba57 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderBindingTableD3D12Impl.cpp @@ -62,101 +62,4 @@ 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), 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/TopLevelASD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp index 3bbf3308..2d087d08 100644 --- a/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TopLevelASD3D12Impl.cpp @@ -44,21 +44,34 @@ TopLevelASD3D12Impl::TopLevelASD3D12Impl(IReferenceCounters* pRefCounte bool bIsDeviceInternal) : TTopLevelASBase{pRefCounters, pDeviceD3D12, Desc, bIsDeviceInternal} { - D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO d3d12TopLevelPrebuildInfo = {}; - D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS d3d12TopLevelInputs = {}; + auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5(); + UINT64 ResultDataMaxSizeInBytes = 0; - d3d12TopLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; - d3d12TopLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_NONE; - d3d12TopLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; - d3d12TopLevelInputs.NumDescs = Desc.MaxInstanceCount; + if (m_Desc.CompactedSize > 0) + { + ResultDataMaxSizeInBytes = m_Desc.CompactedSize; + } + else + { + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO d3d12TopLevelPrebuildInfo = {}; + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS d3d12TopLevelInputs = {}; - VERIFY_EXPR(Desc.MaxInstanceCount <= D3D12_RAYTRACING_MAX_INSTANCES_PER_TOP_LEVEL_ACCELERATION_STRUCTURE); + d3d12TopLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; + d3d12TopLevelInputs.Flags = BuildASFlagsToD3D12ASBuildFlags(m_Desc.Flags); + d3d12TopLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + d3d12TopLevelInputs.NumDescs = m_Desc.MaxInstanceCount; - auto* pd3d12Device = pDeviceD3D12->GetD3D12Device5(); + VERIFY_EXPR(m_Desc.MaxInstanceCount <= D3D12_RAYTRACING_MAX_INSTANCES_PER_TOP_LEVEL_ACCELERATION_STRUCTURE); - pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&d3d12TopLevelInputs, &d3d12TopLevelPrebuildInfo); - if (d3d12TopLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0) - LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info"); + pd3d12Device->GetRaytracingAccelerationStructurePrebuildInfo(&d3d12TopLevelInputs, &d3d12TopLevelPrebuildInfo); + if (d3d12TopLevelPrebuildInfo.ResultDataMaxSizeInBytes == 0) + LOG_ERROR_AND_THROW("Failed to get ray tracing acceleration structure prebuild info"); + + ResultDataMaxSizeInBytes = d3d12TopLevelPrebuildInfo.ResultDataMaxSizeInBytes; + + m_ScratchSize.Build = static_cast<Uint32>(d3d12TopLevelPrebuildInfo.ScratchDataSizeInBytes); + m_ScratchSize.Update = static_cast<Uint32>(d3d12TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes); + } D3D12_HEAP_PROPERTIES HeapProps; HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT; @@ -70,7 +83,7 @@ TopLevelASD3D12Impl::TopLevelASD3D12Impl(IReferenceCounters* pRefCounte D3D12_RESOURCE_DESC d3d12ASDesc = {}; d3d12ASDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; d3d12ASDesc.Alignment = 0; - d3d12ASDesc.Width = d3d12TopLevelPrebuildInfo.ResultDataMaxSizeInBytes; + d3d12ASDesc.Width = ResultDataMaxSizeInBytes; d3d12ASDesc.Height = 1; d3d12ASDesc.DepthOrArraySize = 1; d3d12ASDesc.MipLevels = 1; @@ -90,9 +103,6 @@ TopLevelASD3D12Impl::TopLevelASD3D12Impl(IReferenceCounters* pRefCounte if (*m_Desc.Name != 0) m_pd3d12Resource->SetName(WidenString(m_Desc.Name).c_str()); - m_ScratchSize.Build = static_cast<Uint32>(d3d12TopLevelPrebuildInfo.ScratchDataSizeInBytes); - m_ScratchSize.Update = static_cast<Uint32>(d3d12TopLevelPrebuildInfo.UpdateScratchDataSizeInBytes); - m_DescriptorHandle = pDeviceD3D12->AllocateDescriptor(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); D3D12_SHADER_RESOURCE_VIEW_DESC d3d12SRVDesc; @@ -101,6 +111,10 @@ TopLevelASD3D12Impl::TopLevelASD3D12Impl(IReferenceCounters* pRefCounte d3d12SRVDesc.Format = DXGI_FORMAT_UNKNOWN; d3d12SRVDesc.RaytracingAccelerationStructure.Location = GetGPUAddress(); pd3d12Device->CreateShaderResourceView(nullptr, &d3d12SRVDesc, m_DescriptorHandle.GetCpuHandle()); + + VERIFY_EXPR(GetGPUAddress() % D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT == 0); + + SetState(RESOURCE_STATE_BUILD_AS_READ); } TopLevelASD3D12Impl::~TopLevelASD3D12Impl() diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp index 32055367..b851a017 100644 --- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp @@ -259,6 +259,12 @@ public: /// Implementation of IDeviceContext::CopyTLAS() in OpenGL backend. virtual void DILIGENT_CALL_TYPE CopyTLAS(const CopyTLASAttribs& Attribs) override final; + /// Implementation of IDeviceContext::WriteBLASCompactedSize() in OpenGL backend. + virtual void DILIGENT_CALL_TYPE WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::WriteTLASCompactedSize() in OpenGL backend. + virtual void DILIGENT_CALL_TYPE WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRays() in OpenGL backend. virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 7b09f9ce..8fdb05b6 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -1740,6 +1740,16 @@ void DeviceContextGLImpl::CopyTLAS(const CopyTLASAttribs& Attribs) UNSUPPORTED("CopyTLAS is not supported in OpenGL"); } +void DeviceContextGLImpl::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) +{ + UNSUPPORTED("WriteBLASCompactedSize is not supported in OpenGL"); +} + +void DeviceContextGLImpl::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) +{ + UNSUPPORTED("WriteTLASCompactedSize is not supported in OpenGL"); +} + void DeviceContextGLImpl::TraceRays(const TraceRaysAttribs& Attribs) { UNSUPPORTED("TraceRays is not supported in OpenGL"); diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index 40e19d80..39dca08d 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -266,6 +266,12 @@ public: /// Implementation of IDeviceContext::CopyTLAS() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CopyTLAS(const CopyTLASAttribs& Attribs) override final; + /// Implementation of IDeviceContext::WriteBLASCompactedSize() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) override final; + + /// Implementation of IDeviceContext::WriteTLASCompactedSize() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) override final; + /// Implementation of IDeviceContext::TraceRays() in Vulkan backend. virtual void DILIGENT_CALL_TYPE TraceRays(const TraceRaysAttribs& Attribs) override final; @@ -470,6 +476,8 @@ private: void DvpLogRenderPass_PSOMismatch(); + void CreateASCompactedSizeQueryPool(); + VulkanUtilities::VulkanCommandBuffer m_CommandBuffer; const Uint32 m_NumCommandsToFlush = 192; @@ -551,6 +559,8 @@ private: Int32 m_ActiveQueriesCounter = 0; std::vector<VkClearValue> m_vkClearValues; + + VulkanUtilities::QueryPoolWrapper m_ASQueryPool; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 5440a6c8..556e3aa5 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -205,6 +205,15 @@ public: { return GetPhysicalDevice().GetExtProperties().RayTracing.maxShaderGroupStride; } + Uint32 GetShaderGroupBaseAlignment() const + { + return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupBaseAlignment; + } + + Uint32 GetMaxDrawMeshTasksCount() const + { + return GetPhysicalDevice().GetExtProperties().MeshShader.maxDrawMeshTasksCount; + } private: template <typename PSOCreateInfoType> diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp index cef50a4e..ab43ab80 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderBindingTableVkImpl.hpp @@ -54,17 +54,7 @@ public: virtual void DILIGENT_CALL_TYPE ResetHitGroups(Uint32 HitShadersPerInstance) override; virtual void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override; - virtual void DILIGENT_CALL_TYPE GetVkStridedBufferRegions(IDeviceContextVk* pContext, - RESOURCE_STATE_TRANSITION_MODE TransitionMode, - VkStridedBufferRegionKHR& RaygenShaderBindingTable, - VkStridedBufferRegionKHR& MissShaderBindingTable, - VkStridedBufferRegionKHR& HitShaderBindingTable, - VkStridedBufferRegionKHR& CallableShaderBindingTable) override; - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTableVk, TShaderBindingTableBase); - -private: - RefCntAutoPtr<IBuffer> m_pBuffer; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 44b75187..bee3de1f 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -197,6 +197,11 @@ public: /* 16 */ const char* const Name; /* 24 */ const ShaderResourceLayoutVk& ParentResLayout; + +#ifdef DILIGENT_DEBUG +/* 32 */ const Uint32 BufferStaticSize; +/* 36 */ const Uint32 BufferStride; +#endif // clang-format on VkResource(const ShaderResourceLayoutVk& _ParentLayout, @@ -210,7 +215,9 @@ public: uint32_t _DescriptorSet, Uint32 _CacheOffset, Uint32 _SamplerInd, - bool _ImmutableSamplerAssigned = false) noexcept : + bool _ImmutableSamplerAssigned, + Uint32 _BufferStaticSize, + Uint32 _BufferStride) noexcept : // clang-format off Binding {static_cast<decltype(Binding)>(_Binding) }, DescriptorSet {static_cast<decltype(DescriptorSet)>(_DescriptorSet)}, @@ -222,11 +229,15 @@ public: Type {_Type }, ResourceDim {_ResourceDim }, IsMS {_IsMS ? Uint8{1} : Uint8{0}}, - Name {_Name }, - ParentResLayout {_ParentLayout } +#ifdef DILIGENT_DEBUG + BufferStaticSize {_BufferStaticSize}, + BufferStride {_BufferStride }, +#endif + Name {_Name }, + ParentResLayout {_ParentLayout } // clang-format on { -#if defined(_MSC_VER) && defined(_WIN64) +#if defined(_MSC_VER) && defined(_WIN64) && !defined(DILIGENT_DEBUG) static_assert(sizeof(*this) == 32, "Unexpected sizeof(VkResource)"); #endif // clang-format off diff --git a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp index 0f8a94c8..8f2b42ab 100644 --- a/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TopLevelASVkImpl.hpp @@ -58,7 +58,7 @@ public: virtual void* DILIGENT_CALL_TYPE GetNativeHandle() override final { auto Handle = GetVkTLAS(); - return reinterpret_cast<void*>(Handle); + return reinterpret_cast<void*>(Handle); // AZ TODO: fix for 32 bit platform } /// Implementation of ITopLevelASVk::GetVkTLAS(). diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp index 50a4c99f..8a21fb17 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp @@ -637,6 +637,21 @@ public: #endif } + __forceinline void WriteAccelerationStructuresProperties(VkAccelerationStructureKHR accelerationStructure, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery) + { +#if DILIGENT_USE_VOLK + VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE); + if (m_State.RenderPass != VK_NULL_HANDLE) + { + // Write AS properties operations must be performed outside of render pass. + EndRenderPass(); + } + vkCmdWriteAccelerationStructuresPropertiesKHR(m_VkCmdBuffer, 1, &accelerationStructure, queryType, queryPool, firstQuery); +#else + UNSUPPORTED("Ray tracing is not supported when vulkan library is linked statically"); +#endif + } + __forceinline void TraceRays(const VkStridedBufferRegionKHR& RaygenShaderBindingTable, const VkStridedBufferRegionKHR& MissShaderBindingTable, const VkStridedBufferRegionKHR& HitShaderBindingTable, diff --git a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h index d879faac..ee4ea3c8 100644 --- a/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/ShaderBindingTableVk.h @@ -50,14 +50,6 @@ static const INTERFACE_ID IID_ShaderBindingTableVk = /// Exposes Vulkan-specific functionality of a Shader binding table object. DILIGENT_BEGIN_INTERFACE(IShaderBindingTableVk, IShaderBindingTable) { - /// AZ TODO - VIRTUAL void METHOD(GetVkStridedBufferRegions)(THIS_ - IDeviceContextVk* pContext, - RESOURCE_STATE_TRANSITION_MODE TransitionMode, - VkStridedBufferRegionKHR REF RaygenShaderBindingTable, - VkStridedBufferRegionKHR REF MissShaderBindingTable, - VkStridedBufferRegionKHR REF HitShaderBindingTable, - VkStridedBufferRegionKHR REF CallableShaderBindingTable) PURE; }; DILIGENT_END_INTERFACE // clang-format on @@ -66,8 +58,6 @@ DILIGENT_END_INTERFACE #if DILIGENT_C_INTERFACE -# define IShaderBindingTableVk_GetVkStridedBufferRegions(This, ...) CALL_IFACE_METHOD(ShaderBindingTableVk, GetVkStridedBufferRegions, This, __VA_ARGS__) - #endif DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp index a1172130..cc16c9e4 100644 --- a/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BottomLevelASVkImpl.cpp @@ -45,63 +45,69 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, VkAccelerationStructureCreateInfoKHR CreateInfo = {}; std::vector<VkAccelerationStructureCreateGeometryTypeInfoKHR> Geometries; - CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - CreateInfo.maxGeometryCount = std::max(m_Desc.BoxCount, m_Desc.TriangleCount); - CreateInfo.compactedSize = 0; // AZ TODO + CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - VERIFY_EXPR(CreateInfo.maxGeometryCount <= Limits.maxGeometryCount); + if (m_Desc.CompactedSize > 0) + { + CreateInfo.compactedSize = m_Desc.CompactedSize; + } + else + { + CreateInfo.maxGeometryCount = m_Desc.TriangleCount + m_Desc.BoxCount; + Geometries.resize(CreateInfo.maxGeometryCount); + CreateInfo.pGeometryInfos = Geometries.data(); - Geometries.resize(CreateInfo.maxGeometryCount); - CreateInfo.pGeometryInfos = Geometries.data(); + VERIFY_EXPR(CreateInfo.maxGeometryCount <= Limits.maxGeometryCount); - // Specs says: the geometryType member of each geometry in pGeometries must be the same. - if (m_Desc.pTriangles != nullptr) - { - Uint32 MaxPrimitiveCount = 0; - for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i) + if (m_Desc.pTriangles != nullptr) { - auto& src = m_Desc.pTriangles[i]; - auto& dst = Geometries[i]; - - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - dst.pNext = nullptr; - dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; - dst.maxPrimitiveCount = (src.IndexType == VT_UNDEFINED ? src.MaxVertexCount : src.MaxIndexCount) / 3; - dst.indexType = TypeToVkIndexType(src.IndexType); - dst.maxVertexCount = src.MaxVertexCount; - dst.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); - dst.allowsTransforms = src.AllowsTransforms; - - MaxPrimitiveCount += dst.maxPrimitiveCount; + + Uint32 MaxPrimitiveCount = 0; + for (uint32_t i = 0; i < m_Desc.TriangleCount; ++i) + { + auto& src = m_Desc.pTriangles[i]; + auto& dst = Geometries[i]; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + dst.maxPrimitiveCount = src.MaxPrimitiveCount; + dst.indexType = TypeToVkIndexType(src.IndexType); + dst.maxVertexCount = src.MaxVertexCount; + dst.vertexFormat = TypeToVkFormat(src.VertexValueType, src.VertexComponentCount, src.VertexValueType < VT_FLOAT16); + dst.allowsTransforms = src.AllowsTransforms; + + MaxPrimitiveCount += dst.maxPrimitiveCount; + } + VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxPrimitiveCount); } - VERIFY_EXPR(MaxPrimitiveCount <= Limits.maxPrimitiveCount); - } - else if (m_Desc.pBoxes != nullptr) - { - Uint32 MaxBoxCount = 0; - for (uint32_t i = 0; i < m_Desc.BoxCount; ++i) + else if (m_Desc.pBoxes != nullptr) { - auto& src = m_Desc.pBoxes[i]; - auto& dst = Geometries[i]; - - dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - dst.pNext = nullptr; - dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; - dst.maxPrimitiveCount = src.MaxBoxCount; - dst.indexType = VK_INDEX_TYPE_NONE_KHR; - dst.maxVertexCount = 0; - dst.vertexFormat = VK_FORMAT_UNDEFINED; - dst.allowsTransforms = VK_FALSE; - - MaxBoxCount += dst.maxPrimitiveCount; + Uint32 MaxBoxCount = 0; + for (uint32_t i = 0; i < m_Desc.BoxCount; ++i) + { + auto& src = m_Desc.pBoxes[i]; + auto& dst = Geometries[i]; + + dst.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + dst.pNext = nullptr; + dst.geometryType = VK_GEOMETRY_TYPE_AABBS_KHR; + dst.maxPrimitiveCount = src.MaxBoxCount; + dst.indexType = VK_INDEX_TYPE_NONE_KHR; + dst.maxVertexCount = 0; + dst.vertexFormat = VK_FORMAT_UNDEFINED; + dst.allowsTransforms = VK_FALSE; + + MaxBoxCount += dst.maxPrimitiveCount; + } + VERIFY_EXPR(MaxBoxCount <= Limits.maxPrimitiveCount); + } + else + { + UNEXPECTED("Either pTriangles or pBoxes must not be null"); } - VERIFY_EXPR(MaxBoxCount <= Limits.maxPrimitiveCount); - } - else - { - UNEXPECTED("Either pTriangles or pBoxes must not be null"); } m_VulkanBLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); @@ -132,13 +138,18 @@ BottomLevelASVkImpl::BottomLevelASVkImpl(IReferenceCounters* pRefCounters, m_DeviceAddress = LogicalDevice.GetAccelerationStructureDeviceAddress(m_VulkanBLAS); - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Build = static_cast<Uint32>(MemReqs.size); + if (m_Desc.CompactedSize == 0) + { + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Build = static_cast<Uint32>(MemReqs.size); + + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Update = static_cast<Uint32>(MemReqs.size); + } - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Update = static_cast<Uint32>(MemReqs.size); + SetState(RESOURCE_STATE_BUILD_AS_READ); } BottomLevelASVkImpl::~BottomLevelASVkImpl() diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index a77fb96d..a76a901e 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -117,6 +117,8 @@ DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* p m_DummyVB = pDummyVB.RawPtr<BufferVkImpl>(); m_vkClearValues.reserve(16); + + CreateASCompactedSizeQueryPool(); } DeviceContextVkImpl::~DeviceContextVkImpl() @@ -592,16 +594,6 @@ void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs) if (!DvpVerifyDrawMeshArguments(Attribs)) return; -#ifdef DILIGENT_DEBUG - { - const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice(); - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - const auto& MeshShaderFeats = LogicalDevice.GetEnabledExtFeatures().MeshShader; - VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); - VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount); - } -#endif - PrepareForDraw(Attribs.Flags); m_CommandBuffer.DrawMesh(Attribs.ThreadGroupCount, 0); @@ -613,13 +605,6 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib if (!DvpVerifyDrawMeshIndirectArguments(Attribs, pAttribsBuffer)) return; -#ifdef DILIGENT_DEBUG - { - const auto& MeshShaderFeats = m_pDevice->GetLogicalDevice().GetEnabledExtFeatures().MeshShader; - VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); - } -#endif - // We must prepare indirect draw attribs buffer first because state transitions must // be performed outside of render pass, and PrepareForDraw commits render pass BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode); @@ -2684,9 +2669,9 @@ void DeviceContextVkImpl::TransitionOrVerifyTLASState(TopLevelASVkImpl& DvpVerifyTLASState(TLAS, RequiredState, OperationName); } - if (RequiredState & RESOURCE_STATE_RAY_TRACING) + if (RequiredState & (RESOURCE_STATE_RAY_TRACING | RESOURCE_STATE_BUILD_AS_READ)) { - TLAS.CheckBLASVersion(); + TLAS.ValidateContent(); } #endif } @@ -2812,13 +2797,6 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) if (!TDeviceContextBase::BuildBLAS(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG - { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pBLASVk = ValidatedCast<BottomLevelASVkImpl>(Attribs.pBLAS); auto* pScratchVk = ValidatedCast<BufferVkImpl>(Attribs.pScratchBuffer); auto& BLASDesc = pBLASVk->GetDesc(); @@ -2842,9 +2820,6 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) { const auto& SrcTris = Attribs.pTriangleData[i]; Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcTris.GeometryName); - auto& vkGeo = Geometries[GeoIdx]; - auto& vkTris = vkGeo.geometry.triangles; - auto& off = Offsets[GeoIdx]; if (GeoIdx >= Geometries.size()) { @@ -2852,6 +2827,11 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) continue; } + auto& vkGeo = Geometries[GeoIdx]; + auto& vkTris = vkGeo.geometry.triangles; + auto& off = Offsets[GeoIdx]; + const auto& TriDesc = BLASDesc.pTriangles[GeoIdx]; + vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; vkGeo.pNext = nullptr; vkGeo.flags = GeometryFlagsToVkGeometryFlags(SrcTris.Flags); @@ -2859,8 +2839,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) vkTris.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; vkTris.pNext = nullptr; - auto* const pVB = ValidatedCast<BufferVkImpl>(SrcTris.pVertexBuffer); - vkTris.vertexFormat = TypeToVkFormat(SrcTris.VertexValueType, SrcTris.VertexComponentCount, SrcTris.VertexValueType < VT_FLOAT16); + auto* const pVB = ValidatedCast<BufferVkImpl>(SrcTris.pVertexBuffer); + + // vertex format in SrcTris may be undefined, so use vertex format from description + vkTris.vertexFormat = TypeToVkFormat(TriDesc.VertexValueType, TriDesc.VertexComponentCount, TriDesc.VertexValueType < VT_FLOAT16); vkTris.vertexStride = SrcTris.VertexStride; vkTris.vertexData.deviceAddress = pVB->GetVkDeviceAddress() + SrcTris.VertexOffset; @@ -2868,10 +2850,11 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) if (SrcTris.pIndexBuffer) { - auto* const pIB = ValidatedCast<BufferVkImpl>(SrcTris.pIndexBuffer); - vkTris.indexType = TypeToVkIndexType(SrcTris.IndexType); + auto* const pIB = ValidatedCast<BufferVkImpl>(SrcTris.pIndexBuffer); + + // index type in SrcTris may be undefined, so use index type from description + vkTris.indexType = TypeToVkIndexType(TriDesc.IndexType); vkTris.indexData.deviceAddress = pIB->GetVkDeviceAddress() + SrcTris.IndexOffset; - off.primitiveCount = SrcTris.IndexCount / 3; TransitionOrVerifyBufferState(*pIB, Attribs.GeometryTransitionMode, RESOURCE_STATE_BUILD_AS_READ, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, OpName); } @@ -2879,13 +2862,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) { vkTris.indexType = VK_INDEX_TYPE_NONE_KHR; vkTris.indexData.deviceAddress = 0; - off.primitiveCount = SrcTris.VertexCount / 3; } if (SrcTris.pTransformBuffer) { - VERIFY_EXPR(BLASDesc.pTriangles[GeoIdx].AllowsTransforms); - auto* const pTB = ValidatedCast<BufferVkImpl>(SrcTris.pTransformBuffer); vkTris.transformData.deviceAddress = pTB->GetVkDeviceAddress() + SrcTris.TransformBufferOffset; @@ -2893,10 +2873,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) } else { - VERIFY_EXPR(!BLASDesc.pTriangles[GeoIdx].AllowsTransforms); vkTris.transformData.deviceAddress = 0; } + off.primitiveCount = SrcTris.PrimitiveCount; off.firstVertex = 0; off.primitiveOffset = 0; off.transformOffset = 0; @@ -2911,9 +2891,6 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) { const auto& SrcBoxes = Attribs.pBoxData[i]; Uint32 GeoIdx = pBLASVk->GetGeometryIndex(SrcBoxes.GeometryName); - auto& vkGeo = Geometries[GeoIdx]; - auto& vkAABBs = vkGeo.geometry.aabbs; - auto& off = Offsets[GeoIdx]; if (GeoIdx >= Geometries.size()) { @@ -2921,6 +2898,10 @@ void DeviceContextVkImpl::BuildBLAS(const BLASBuildAttribs& Attribs) continue; } + auto& vkGeo = Geometries[GeoIdx]; + auto& vkAABBs = vkGeo.geometry.aabbs; + auto& off = Offsets[GeoIdx]; + vkGeo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; vkGeo.pNext = nullptr; vkGeo.flags = GeometryFlagsToVkGeometryFlags(SrcBoxes.Flags); @@ -2971,13 +2952,6 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) static_assert(TLAS_INSTANCE_DATA_SIZE == sizeof(VkAccelerationStructureInstanceKHR), "Value in TLAS_INSTANCE_DATA_SIZE doesn't match the actual instance description size"); -#ifdef DILIGENT_DEBUG - { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pTLASVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pTLAS); auto* pScratchVk = ValidatedCast<BufferVkImpl>(Attribs.pScratchBuffer); auto* pInstancesVk = ValidatedCast<BufferVkImpl>(Attribs.pInstanceBuffer); @@ -3007,7 +2981,7 @@ void DeviceContextVkImpl::BuildTLAS(const TLASBuildAttribs& Attribs) std::memcpy(&vkASInst.transform, Inst.Transform.data, sizeof(vkASInst.transform)); vkASInst.instanceCustomIndex = Inst.CustomId; - vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; // AZ TODO: optimize + vkASInst.instanceShaderBindingTableRecordOffset = pTLASVk->GetInstanceDesc(Inst.InstanceName).ContributionToHitGroupIndex; vkASInst.mask = Inst.Mask; vkASInst.flags = InstanceFlagsToVkGeometryInstanceFlags(Inst.Flags); vkASInst.accelerationStructureReference = pBLASVk->GetVkDeviceAddress(); @@ -3058,16 +3032,13 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) if (!TDeviceContextBase::CopyBLAS(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG - { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pSrcVk = ValidatedCast<BottomLevelASVkImpl>(Attribs.pSrc); auto* pDstVk = ValidatedCast<BottomLevelASVkImpl>(Attribs.pDst); + // Dst BLAS description has specified CompactedSize, but doesn't have specified pTriangles and pBoxes. + // We should copy geometries because it required for SBT to map geometry name to hit group. + pDstVk->CopyDescription(*pSrcVk); + VkCopyAccelerationStructureInfoKHR Info = {}; Info.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR; @@ -3078,8 +3049,8 @@ void DeviceContextVkImpl::CopyBLAS(const CopyBLASAttribs& Attribs) EnsureVkCmdBuffer(); const char* OpName = "Copy BottomLevelAS (DeviceContextVkImpl::CopyBLAS)"; - TransitionOrVerifyBLASState(*pSrcVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); - TransitionOrVerifyBLASState(*pDstVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + TransitionOrVerifyBLASState(*pSrcVk, Attribs.SrcTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBLASState(*pDstVk, Attribs.DstTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); m_CommandBuffer.CopyAccelerationStructure(Info); ++m_State.NumCommands; @@ -3094,16 +3065,11 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs) if (!TDeviceContextBase::CopyTLAS(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG - { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); - } -#endif - auto* pSrcVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pSrc); auto* pDstVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pDst); + // Instances specified in BuildTLAS command. + // We should copy instances because it required for SBT to map instance name to hit group. pDstVk->CopyInstancceData(*pSrcVk); VkCopyAccelerationStructureInfoKHR Info = {}; @@ -3116,32 +3082,111 @@ void DeviceContextVkImpl::CopyTLAS(const CopyTLASAttribs& Attribs) EnsureVkCmdBuffer(); const char* OpName = "Copy TopLevelAS (DeviceContextVkImpl::CopyTLAS)"; - TransitionOrVerifyTLASState(*pSrcVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); - TransitionOrVerifyTLASState(*pDstVk, Attribs.TransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); + TransitionOrVerifyTLASState(*pSrcVk, Attribs.SrcTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyTLASState(*pDstVk, Attribs.DstTransitionMode, RESOURCE_STATE_BUILD_AS_WRITE, OpName); m_CommandBuffer.CopyAccelerationStructure(Info); ++m_State.NumCommands; } -void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) +void DeviceContextVkImpl::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs) { - if (!TDeviceContextBase::TraceRays(Attribs, 0)) + if (!TDeviceContextBase::WriteBLASCompactedSize(Attribs, 0)) return; -#ifdef DILIGENT_DEBUG + const Uint32 QueryIndex = 0; + auto* pBLASVk = ValidatedCast<BottomLevelASVkImpl>(Attribs.pBLAS); + auto* pDestBuffVk = ValidatedCast<BufferVkImpl>(Attribs.pDestBuffer); + + EnsureVkCmdBuffer(); + + const char* OpName = "Write AS compacted size (DeviceContextVkImpl::WriteBLASCompactedSize)"; + TransitionOrVerifyBLASState(*pBLASVk, Attribs.BLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBufferState(*pDestBuffVk, Attribs.BufferTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + + m_CommandBuffer.WriteAccelerationStructuresProperties(pBLASVk->GetVkBLAS(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, m_ASQueryPool, QueryIndex); + m_CommandBuffer.CopyQueryPoolResults(m_ASQueryPool, QueryIndex, 1, pDestBuffVk->GetVkBuffer(), Attribs.DestBufferOffset, sizeof(Uint64), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + m_CommandBuffer.ResetQueryPool(m_ASQueryPool, QueryIndex, 1); + ++m_State.NumCommands; +} + +void DeviceContextVkImpl::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs) +{ + if (!TDeviceContextBase::WriteTLASCompactedSize(Attribs, 0)) + return; + + const Uint32 QueryIndex = 0; + auto* pTLASVk = ValidatedCast<TopLevelASVkImpl>(Attribs.pTLAS); + auto* pDestBuffVk = ValidatedCast<BufferVkImpl>(Attribs.pDestBuffer); + + EnsureVkCmdBuffer(); + + const char* OpName = "Write AS compacted size (DeviceContextVkImpl::WriteTLASCompactedSize)"; + TransitionOrVerifyTLASState(*pTLASVk, Attribs.TLASTransitionMode, RESOURCE_STATE_BUILD_AS_READ, OpName); + TransitionOrVerifyBufferState(*pDestBuffVk, Attribs.BufferTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + + m_CommandBuffer.WriteAccelerationStructuresProperties(pTLASVk->GetVkTLAS(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, m_ASQueryPool, QueryIndex); + m_CommandBuffer.CopyQueryPoolResults(m_ASQueryPool, QueryIndex, 1, pDestBuffVk->GetVkBuffer(), Attribs.DestBufferOffset, sizeof(Uint64), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); + m_CommandBuffer.ResetQueryPool(m_ASQueryPool, QueryIndex, 1); + ++m_State.NumCommands; +} + +void DeviceContextVkImpl::CreateASCompactedSizeQueryPool() +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing == DEVICE_FEATURE_STATE_ENABLED) { - const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - VERIFY_EXPR(LogicalDevice.GetEnabledExtFeatures().RayTracing.rayTracing != VK_FALSE); + const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); + VkQueryPoolCreateInfo Info = {}; + + Info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + Info.queryCount = 1; + Info.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR; + + m_ASQueryPool = LogicalDevice.CreateQueryPool(Info); } -#endif +} + +void DeviceContextVkImpl::TraceRays(const TraceRaysAttribs& Attribs) +{ + if (!TDeviceContextBase::TraceRays(Attribs, 0)) + return; + + auto* pSBTVk = ValidatedCast<ShaderBindingTableVkImpl>(Attribs.pSBT); + IBuffer* pBuffer = nullptr; - VkStridedBufferRegionKHR RaygenShaderBindingTable = {}; - VkStridedBufferRegionKHR MissShaderBindingTable = {}; - VkStridedBufferRegionKHR HitShaderBindingTable = {}; - VkStridedBufferRegionKHR CallableShaderBindingTable = {}; + ShaderBindingTableVkImpl::BindingTable RayGenShaderRecord = {}; + ShaderBindingTableVkImpl::BindingTable MissShaderTable = {}; + ShaderBindingTableVkImpl::BindingTable HitGroupTable = {}; + ShaderBindingTableVkImpl::BindingTable CallableShaderTable = {}; - auto* pSBTVk = ValidatedCast<ShaderBindingTableVkImpl>(Attribs.pSBT); - pSBTVk->GetVkStridedBufferRegions(this, Attribs.TransitionMode, RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable); + pSBTVk->GetData(pBuffer, RayGenShaderRecord, MissShaderTable, HitGroupTable, CallableShaderTable); + + auto* pBufferVk = ValidatedCast<BufferVkImpl>(pBuffer); + + const char* OpName = "Trace rays (DeviceContextVkImpl::TraceRays)"; + TransitionOrVerifyBufferState(*pBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, OpName); + + // buffer ranges are not intersected, so we don't need to add barriers between them + if (RayGenShaderRecord.pData) + UpdateBuffer(pBuffer, RayGenShaderRecord.Offset, RayGenShaderRecord.Size, RayGenShaderRecord.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (MissShaderTable.pData) + UpdateBuffer(pBuffer, MissShaderTable.Offset, MissShaderTable.Size, MissShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (HitGroupTable.pData) + UpdateBuffer(pBuffer, HitGroupTable.Offset, HitGroupTable.Size, HitGroupTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + if (CallableShaderTable.pData) + UpdateBuffer(pBuffer, CallableShaderTable.Offset, CallableShaderTable.Size, CallableShaderTable.pData, RESOURCE_STATE_TRANSITION_MODE_VERIFY); + + TransitionOrVerifyBufferState(*pBufferVk, Attribs.SBTTransitionMode, RESOURCE_STATE_RAY_TRACING, VK_ACCESS_SHADER_READ_BIT, OpName); + + // clang-format off + VkStridedBufferRegionKHR RaygenShaderBindingTable = {pBufferVk->GetVkBuffer(), RayGenShaderRecord.Offset, RayGenShaderRecord.Stride, RayGenShaderRecord.Size }; + VkStridedBufferRegionKHR MissShaderBindingTable = {pBufferVk->GetVkBuffer(), MissShaderTable.Offset, MissShaderTable.Stride, MissShaderTable.Size }; + VkStridedBufferRegionKHR HitShaderBindingTable = {pBufferVk->GetVkBuffer(), HitGroupTable.Offset, HitGroupTable.Stride, HitGroupTable.Size }; + VkStridedBufferRegionKHR CallableShaderBindingTable = {pBufferVk->GetVkBuffer(), CallableShaderTable.Offset, CallableShaderTable.Stride, CallableShaderTable.Size}; + // clang-format on PrepareForRayTracing(); m_CommandBuffer.TraceRays(RaygenShaderBindingTable, MissShaderBindingTable, HitShaderBindingTable, CallableShaderBindingTable, diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp index 3940769f..c0228146 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderBindingTableVkImpl.cpp @@ -57,108 +57,4 @@ void ShaderBindingTableVkImpl::BindAll(const BindAllAttribs& Attribs) // AZ TODO } -void ShaderBindingTableVkImpl::GetVkStridedBufferRegions(IDeviceContextVk* pContext, - RESOURCE_STATE_TRANSITION_MODE TransitionMode, - VkStridedBufferRegionKHR& RaygenShaderBindingTable, - VkStridedBufferRegionKHR& MissShaderBindingTable, - VkStridedBufferRegionKHR& HitShaderBindingTable, - VkStridedBufferRegionKHR& CallableShaderBindingTable) -{ - const auto ShaderGroupBaseAlignment = GetDevice()->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupBaseAlignment; - - const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 { - return Align(static_cast<Uint32>(offset), ShaderGroupBaseAlignment); - }; - - 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 - - VkBuffer BuffHandle = m_pBuffer.RawPtr<BufferVkImpl>()->GetVkBuffer(); - - if (m_RayGenShaderRecord.size()) - { - RaygenShaderBindingTable.buffer = BuffHandle; - RaygenShaderBindingTable.offset = RayGenOffset; - RaygenShaderBindingTable.size = m_RayGenShaderRecord.size(); - RaygenShaderBindingTable.stride = m_ShaderRecordStride; - } - - if (m_MissShadersRecord.size()) - { - MissShaderBindingTable.buffer = BuffHandle; - MissShaderBindingTable.offset = MissShaderOffset; - MissShaderBindingTable.size = m_MissShadersRecord.size(); - MissShaderBindingTable.stride = m_ShaderRecordStride; - } - - if (m_HitGroupsRecord.size()) - { - HitShaderBindingTable.buffer = BuffHandle; - HitShaderBindingTable.offset = HitGroupOffset; - HitShaderBindingTable.size = m_HitGroupsRecord.size(); - HitShaderBindingTable.stride = m_ShaderRecordStride; - } - - if (m_CallableShadersRecord.size()) - { - CallableShaderBindingTable.buffer = BuffHandle; - CallableShaderBindingTable.offset = CallableShadersOffset; - CallableShaderBindingTable.size = m_CallableShadersRecord.size(); - CallableShaderBindingTable.stride = 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/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 27e5ee72..0054315f 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -324,7 +324,9 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) "with IDeviceContext::TransitionResourceStates()."); } - pTLASVk->CheckBLASVersion(); +#ifdef DILIGENT_DEVELOPMENT + pTLASVk->ValidateContent(); +#endif } else { diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index f1e8b726..cab26f83 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -328,7 +328,9 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vector<co DescriptorSet, CacheOffset, SamplerInd, - SrcImmutableSamplerInd >= 0 // + SrcImmutableSamplerInd >= 0, + Attribs.BufferStaticSize, + Attribs.BufferStride // }; } else @@ -618,7 +620,9 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende DescriptorSet, CacheOffset, SamplerInd, - vkImmutableSampler != VK_NULL_HANDLE // + vkImmutableSampler != VK_NULL_HANDLE, + Attribs.BufferStaticSize, + Attribs.BufferStride // }; } else @@ -822,6 +826,14 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* RefCntAutoPtr<BufferVkImpl> pBufferVk{pBuffer, IID_BufferVk}; #ifdef DILIGENT_DEVELOPMENT VerifyConstantBufferBinding(*this, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + + if (pBufferVk->GetDesc().uiSizeInBytes != BufferStaticSize) + { + std::stringstream ss; + ss << "binding buffer '" << pBufferVk->GetDesc().Name << "' size (" << pBufferVk->GetDesc().uiSizeInBytes + << ") doesn't match buffer size in shader (" << BufferStaticSize << ")"; + LOG_INFO_MESSAGE(ss.str()); + } #endif auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) { @@ -875,6 +887,13 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); } + + if (ViewDesc.ByteWidth < BufferStaticSize || (ViewDesc.ByteWidth - BufferStaticSize) % BufferStride != 0) + { + LOG_INFO_MESSAGE("binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + Name, "' in shader '", ParentResLayout.GetShaderName(), "': size mismatch, in shader buffer has static size (", + BufferStaticSize, ") and array stride (", BufferStride, "), but actual size is (", ViewDesc.ByteWidth, ")."); + } } } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp index ae10b74b..fbef736c 100644 --- a/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TopLevelASVkImpl.cpp @@ -40,23 +40,29 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, { const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); - const auto& Limits = PhysicalDevice.GetExtProperties().RayTracing; - - VERIFY_EXPR(m_Desc.MaxInstanceCount <= Limits.maxInstanceCount); + const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracing; VkAccelerationStructureCreateInfoKHR CreateInfo = {}; VkAccelerationStructureCreateGeometryTypeInfoKHR InstanceInfo = {}; - CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; - CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); - CreateInfo.maxGeometryCount = 1; - CreateInfo.pGeometryInfos = &InstanceInfo; - CreateInfo.compactedSize = 0; // AZ TODO - - InstanceInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; - InstanceInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; - InstanceInfo.maxPrimitiveCount = m_Desc.MaxInstanceCount; + CreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + CreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + CreateInfo.flags = BuildASFlagsToVkBuildAccelerationStructureFlags(m_Desc.Flags); + + if (m_Desc.CompactedSize > 0) + { + CreateInfo.compactedSize = m_Desc.CompactedSize; + } + else if (m_Desc.MaxInstanceCount > 0) + { + InstanceInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + InstanceInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + InstanceInfo.maxPrimitiveCount = m_Desc.MaxInstanceCount; + + VERIFY_EXPR(m_Desc.MaxInstanceCount <= RTLimits.maxInstanceCount); + CreateInfo.pGeometryInfos = &InstanceInfo; + CreateInfo.maxGeometryCount = 1; + } m_VulkanTLAS = LogicalDevice.CreateAccelStruct(CreateInfo, m_Desc.Name); @@ -84,13 +90,18 @@ TopLevelASVkImpl::TopLevelASVkImpl(IReferenceCounters* pRefCounters, auto err = LogicalDevice.BindASMemory(m_VulkanTLAS, Memory, m_MemoryAlignedOffset); CHECK_VK_ERROR_AND_THROW(err, "Failed to bind AS memory"); - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Build = static_cast<Uint32>(MemReqs.size); + if (m_Desc.CompactedSize == 0) + { + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Build = static_cast<Uint32>(MemReqs.size); + + MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; + MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); + m_ScratchSize.Update = static_cast<Uint32>(MemReqs.size); + } - MemInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR; - MemReqs = LogicalDevice.GetASMemoryRequirements(MemInfo); - m_ScratchSize.Update = static_cast<Uint32>(MemReqs.size); + SetState(RESOURCE_STATE_BUILD_AS_READ); } TopLevelASVkImpl::~TopLevelASVkImpl() diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index e039311b..53719439 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1241,7 +1241,7 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag) case RESOURCE_STATE_PRESENT: return 0; case RESOURCE_STATE_BUILD_AS_READ: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; case RESOURCE_STATE_BUILD_AS_WRITE: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; - case RESOURCE_STATE_RAY_TRACING: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + case RESOURCE_STATE_RAY_TRACING: return VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT; // for TLAS & SBT // clang-format on default: @@ -1256,7 +1256,7 @@ public: StateFlagBitPosToVkAccessFlags() { static_assert((1 << MaxFlagBitPos) == RESOURCE_STATE_MAX_BIT, "This function must be updated to handle new resource state flag"); - for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit) + for (Uint32 bit = 0; bit < FlagBitPosToVkAccessFlagsMap.size(); ++bit) { FlagBitPosToVkAccessFlagsMap[bit] = ResourceStateFlagToVkAccessFlags(static_cast<RESOURCE_STATE>(1 << bit)); } @@ -1335,7 +1335,7 @@ class VkAccessFlagBitPosToResourceState public: VkAccessFlagBitPosToResourceState() { - for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit) + for (Uint32 bit = 0; bit < FlagBitPosToResourceState.size(); ++bit) { FlagBitPosToResourceState[bit] = VkAccessFlagToResourceStates(static_cast<VkAccessFlagBits>(1 << bit)); } @@ -1680,13 +1680,14 @@ VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INS VkCopyAccelerationStructureModeKHR CopyASModeToVkCopyAccelerationStructureMode(COPY_AS_MODE Mode) { - static_assert(COPY_AS_MODE_LAST == COPY_AS_MODE_CLONE, + static_assert(COPY_AS_MODE_LAST == COPY_AS_MODE_COMPACT, "Please update the switch below to handle the new copy AS mode"); switch (Mode) { // clang-format off - case COPY_AS_MODE_CLONE: return VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; + case COPY_AS_MODE_CLONE: return VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; + case COPY_AS_MODE_COMPACT: return VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; // clang-format on default: UNEXPECTED("unknown AS copy mode"); diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp index 4d47ca3e..1f81c872 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp @@ -134,12 +134,12 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags case VK_ACCESS_MEMORY_WRITE_BIT: break; - // AZ TODO: comment + // Read access to acceleration structure or vertex/index/instance buffer in a build AS or trace rays operations. case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR: Stages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; break; - // AZ TODO: comment + // Write access to acceleration structure or scratch buffer in a build AS operations. case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR: Stages |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; break; diff --git a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp index 7e75fb07..9385ff3f 100644 --- a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp +++ b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp @@ -55,7 +55,7 @@ struct Resource; namespace Diligent { -// sizeof(SPIRVShaderResourceAttribs) == 24, msvc x64 +// sizeof(SPIRVShaderResourceAttribs) == 32, msvc x64 struct SPIRVShaderResourceAttribs { enum ResourceType : Uint8 @@ -94,7 +94,10 @@ public: // Offset in SPIRV words (uint32_t) of binding & descriptor set decorations in SPIRV binary /* 16 */const uint32_t BindingDecorationOffset; /* 20 */const uint32_t DescriptorSetDecorationOffset; -/* 24 */ // End of structure + +/* 24 */const Uint32 BufferStaticSize; +/* 28 */const Uint32 BufferStride; +/* 32 */ // End of structure // clang-format on @@ -102,7 +105,9 @@ public: const diligent_spirv_cross::Resource& Res, const char* _Name, ResourceType _Type, - Uint32 _SamplerOrSepImgInd = InvalidSepSmplrOrImgInd) noexcept; + Uint32 _SamplerOrSepImgInd = InvalidSepSmplrOrImgInd, + Uint32 _BufferStaticSize = 0, + Uint32 _BufferStride = 0) noexcept; bool IsValidSepSamplerAssigned() const { diff --git a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp index bb15cc06..6c4ce16e 100644 --- a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp +++ b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp @@ -109,7 +109,9 @@ SPIRVShaderResourceAttribs::SPIRVShaderResourceAttribs(const diligent_spirv_cros const diligent_spirv_cross::Resource& Res, const char* _Name, ResourceType _Type, - Uint32 _SepSmplrOrImgInd) noexcept : + Uint32 _SepSmplrOrImgInd, + Uint32 _BufferStaticSize, + Uint32 _BufferStride) noexcept : // clang-format off Name {_Name}, ArraySize {GetResourceArraySize<decltype(ArraySize)>(Compiler, Res)}, @@ -118,7 +120,9 @@ SPIRVShaderResourceAttribs::SPIRVShaderResourceAttribs(const diligent_spirv_cros IsMS {Diligent::IsMultisample(Compiler, Res) ? Uint8{1} : Uint8{0}}, SepSmplrOrImgInd {_SepSmplrOrImgInd}, BindingDecorationOffset {GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationBinding)}, - DescriptorSetDecorationOffset {GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationDescriptorSet)} + DescriptorSetDecorationOffset {GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationDescriptorSet)}, + BufferStaticSize {_BufferStaticSize}, + BufferStride {_BufferStride} // clang-format on { VERIFY(_SepSmplrOrImgInd == SPIRVShaderResourceAttribs::InvalidSepSmplrOrImgInd || @@ -297,10 +301,8 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, &resources.separate_images, &resources.separate_samplers, &resources.subpass_inputs, - &resources.acceleration_structures - // clang-format off - }) - // clang-format on + &resources.acceleration_structures // + }) // { for (const auto& res : *pResType) ResourceNamesPoolSize += res.name.length() + 1; @@ -379,12 +381,16 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, Uint32 CurrUB = 0; for (const auto& UB : resources.uniform_buffers) { - const auto& name = GetUBName(Compiler, UB, ParsedIRSource); + const auto& name = GetUBName(Compiler, UB, ParsedIRSource); + const auto& Type = Compiler.get_type(UB.type_id); + const size_t Size = Compiler.get_declared_struct_size(Type); new (&GetUB(CurrUB++)) SPIRVShaderResourceAttribs(Compiler, UB, ResourceNamesPool.CopyString(name), - SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); + SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, + SPIRVShaderResourceAttribs::InvalidSepSmplrOrImgInd, + Uint32(Size)); } VERIFY_EXPR(CurrUB == GetNumUBs()); } @@ -398,11 +404,17 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, auto ResType = IsReadOnly ? SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer : SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer; + const auto& Type = Compiler.get_type(SB.type_id); + const size_t Size = Compiler.get_declared_struct_size(Type); + const size_t Stride = Compiler.get_declared_struct_size_runtime_array(Type, 1); new (&GetSB(CurrSB++)) SPIRVShaderResourceAttribs(Compiler, SB, ResourceNamesPool.CopyString(SB.name), - ResType); + ResType, + SPIRVShaderResourceAttribs::InvalidSepSmplrOrImgInd, + Uint32(Size), + Uint32(Stride)); } VERIFY_EXPR(CurrSB == GetNumSBs()); } |
