From 01efea6331ae92a2cda01e41610e61bc6384b5ba Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 20:22:40 -0800 Subject: Refactored BottomLevelASBase --- Graphics/GraphicsEngine/CMakeLists.txt | 1 + .../GraphicsEngine/include/BottomLevelASBase.hpp | 206 +++++---------------- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 170 +++++++++++++++++ 3 files changed, 215 insertions(+), 162 deletions(-) create mode 100644 Graphics/GraphicsEngine/src/BottomLevelASBase.cpp (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index 47692deb..db339e11 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -68,6 +68,7 @@ set(INTERFACE set(SOURCE src/APIInfo.cpp + src/BottomLevelASBase.cpp src/BufferBase.cpp src/DefaultShaderSourceStreamFactory.cpp src/EngineMemory.cpp diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 08fc4243..ddb5dd22 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -31,7 +31,7 @@ /// Implementation of the Diligent::BottomLevelASBase template class #include -#include +#include #include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" @@ -42,6 +42,16 @@ namespace Diligent { +/// Validates bottom-level AS description and throws and exception in case of an error. +void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false); + +/// Copies bottom-level AS description (except for the Name) using MemPool to allocate required dynamic space. +void CopyBottomLevelASDesc(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + std::unordered_map& NameToIndex) noexcept(false); + + /// Template class implementing base functionality for a bottom-level acceleration structure object. /// \tparam BaseInterface - base interface that this class will inheret @@ -65,26 +75,24 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { - ValidateBottomLevelASDesc(Desc); + ValidateBottomLevelASDesc(this->m_Desc); if (Desc.CompactedSize > 0) - {} + { + } else { - LinearAllocator MemPool{GetRawAllocator()}; - CopyDescription(Desc, this->m_Desc, MemPool, m_NameToIndex); - this->m_pRawPtr = MemPool.ReleaseOwnership(); + CopyDescriptionUnsafe(Desc); } } ~BottomLevelASBase() { - if (this->m_pRawPtr) - { - GetRawAllocator().Free(this->m_pRawPtr); - } + Clear(); } + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) + static constexpr Uint32 InvalidGeometryIndex = ~0u; virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final @@ -95,14 +103,14 @@ public: if (iter != m_NameToIndex.end()) return iter->second; - UNEXPECTED("Can't find geometry with specified name"); + LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\''); return InvalidGeometryIndex; } 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"); + "Unsupported state for a bottom-level acceleration structure"); this->m_State = State; } @@ -123,36 +131,6 @@ 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() { @@ -171,139 +149,43 @@ public: } #endif // DILIGENT_DEVELOPMENT -protected: - static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) + void CopyDescription(const BottomLevelASBase& SrcBLAS) noexcept { -#define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + Clear(); - if (Desc.CompactedSize > 0) + try { - 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.Flags != RAYTRACING_BUILD_AS_NONE) - LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE"); + CopyDescriptionUnsafe(SrcBLAS.GetDesc()); } - else + catch (...) { - 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 + Clear(); } + } -#undef LOG_BLAS_ERROR_AND_THROW +private: + void CopyDescriptionUnsafe(const BottomLevelASDesc& SrcDesc) noexcept(false) + { + LinearAllocator MemPool{GetRawAllocator()}; + CopyBottomLevelASDesc(SrcDesc, this->m_Desc, MemPool, m_NameToIndex); + this->m_pRawPtr = MemPool.Release(); } - static void CopyDescription(const BottomLevelASDesc& SrcDesc, - BottomLevelASDesc& DstDesc, - LinearAllocator& MemPool, - std::unordered_map& NameToIndex) + void Clear() noexcept { - if (SrcDesc.pTriangles != nullptr) - { - MemPool.AddSpace(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(SrcDesc.BoxCount); - - 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 + if (this->m_pRawPtr != nullptr) { - LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null"); + GetRawAllocator().Free(this->m_pRawPtr); + this->m_pRawPtr = nullptr; } - } - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) + // Preserve original name - it was allocated by DeviceObjectBase + auto* Name = this->m_Desc.Name; + this->m_Desc = BottomLevelASDesc{}; + this->m_Desc.Name = Name; + + m_NameToIndex.clear(); + } protected: RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp new file mode 100644 index 00000000..fec51592 --- /dev/null +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -0,0 +1,170 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "BottomLevelASBase.hpp" + +namespace Diligent +{ + +void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false) +{ +#define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of a bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.CompactedSize > 0) + { + if (Desc.pTriangles != nullptr || Desc.pBoxes != nullptr) + LOG_BLAS_ERROR_AND_THROW("If non-zero CompactedSize is specified, pTriangles and pBoxes must both be null"); + + if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) + LOG_BLAS_ERROR_AND_THROW("If non-zero CompactedSize is specified, Flags must be RAYTRACING_BUILD_AS_NONE"); + } + else + { + 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("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD flags are mutually exclusive"); + + 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 a 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 than 0"); + + if (tri.MaxPrimitiveCount == 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxPrimitiveCount must be greater than 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 than 0"); + } + } + +#undef LOG_BLAS_ERROR_AND_THROW +} + +void CopyBottomLevelASDesc(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + std::unordered_map& NameToIndex) noexcept(false) +{ + // Preserve original name + const auto* Name = DstDesc.Name; + DstDesc = SrcDesc; + DstDesc.Name = Name; + + if (SrcDesc.pTriangles != nullptr) + { + MemPool.AddSpace(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) + { + const auto* SrcGeoName = SrcDesc.pTriangles[i].GeometryName; + pTriangles[i].GeometryName = MemPool.CopyString(SrcGeoName); + bool IsUniqueName = NameToIndex.emplace(SrcGeoName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); + } + DstDesc.pTriangles = pTriangles; + DstDesc.pBoxes = nullptr; + DstDesc.BoxCount = 0; + } + else if (SrcDesc.pBoxes != nullptr) + { + MemPool.AddSpace(SrcDesc.BoxCount); + + 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) + { + const auto* SrcGeoName = SrcDesc.pBoxes[i].GeometryName; + pBoxes[i].GeometryName = MemPool.CopyString(SrcGeoName); + bool IsUniqueName = NameToIndex.emplace(SrcGeoName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); + } + DstDesc.pBoxes = pBoxes; + DstDesc.pTriangles = nullptr; + DstDesc.TriangleCount = 0; + } + else + { + LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null"); + } +} + +} // namespace Diligent -- cgit v1.2.3