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/GraphicsEngine | |
| 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/GraphicsEngine')
| -rw-r--r-- | Graphics/GraphicsEngine/include/BottomLevelASBase.hpp | 247 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/DeviceContextBase.hpp | 341 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/PipelineStateBase.hpp | 8 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp | 126 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 142 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/BottomLevelAS.h | 67 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/DeviceContext.h | 410 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/GraphicsTypes.h | 7 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/PipelineState.h | 86 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/Shader.h | 2 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/ShaderBindingTable.h | 10 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/TopLevelAS.h | 40 |
12 files changed, 1072 insertions, 414 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 |
