/* * Copyright 2019-2021 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 "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.BoxCount != 0) ^ (Desc.TriangleCount != 0))) LOG_BLAS_ERROR_AND_THROW("Exactly one of BoxCount (", Desc.BoxCount, ") and TriangleCount (", Desc.TriangleCount, ") must be non-zero."); if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) LOG_BLAS_ERROR_AND_THROW("BoxCount is ", Desc.BoxCount, ", but pBoxes is null."); if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) LOG_BLAS_ERROR_AND_THROW("TriangleCount is ", Desc.TriangleCount, ", but pTriangles is null."); if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) != 0 && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD) != 0) 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_FLOAT32 && tri.VertexValueType != VT_FLOAT16 && tri.VertexValueType != VT_INT16) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType (", GetValueTypeString(tri.VertexValueType), ") is invalid. Only the following values are allowed: VT_FLOAT32, VT_FLOAT16, VT_INT16."); if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount (", Uint32{tri.VertexComponentCount}, ") is invalid. Only 2 or 3 are allowed."); 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 (", tri.MaxVertexCount, ") must be equal to MaxPrimitiveCount * 3 (", tri.MaxPrimitiveCount * 3, ")."); } else { if (tri.IndexType != VT_UINT32 && tri.IndexType != VT_UINT16) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].IndexType (", GetValueTypeString(tri.VertexValueType), ") 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 CopyBLASGeometryDesc(const BottomLevelASDesc& SrcDesc, BottomLevelASDesc& DstDesc, FixedLinearAllocator& MemPool, const BLASNameToIndex* pSrcNameToIndex, BLASNameToIndex& DstNameToIndex) noexcept(false) { 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); Uint32 ActualIndex = INVALID_INDEX; if (pSrcNameToIndex) { auto iter = pSrcNameToIndex->find(SrcGeoName); VERIFY_EXPR(iter != pSrcNameToIndex->end()); ActualIndex = iter->second.ActualIndex; } bool IsUniqueName = DstNameToIndex.emplace(SrcGeoName, BLASGeomIndex{i, ActualIndex}).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); } DstDesc.pTriangles = pTriangles; DstDesc.TriangleCount = SrcDesc.TriangleCount; 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); Uint32 ActualIndex = INVALID_INDEX; if (pSrcNameToIndex) { auto iter = pSrcNameToIndex->find(SrcGeoName); VERIFY_EXPR(iter != pSrcNameToIndex->end()); ActualIndex = iter->second.ActualIndex; } bool IsUniqueName = DstNameToIndex.emplace(SrcGeoName, BLASGeomIndex{i, ActualIndex}).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); } DstDesc.pBoxes = pBoxes; DstDesc.BoxCount = SrcDesc.BoxCount; DstDesc.pTriangles = nullptr; DstDesc.TriangleCount = 0; } else { LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null"); } } } // namespace Diligent