diff --git a/src/Magnum/MeshTools/Test/CMakeLists.txt b/src/Magnum/MeshTools/Test/CMakeLists.txt index ae64ea45f..767e6305f 100644 --- a/src/Magnum/MeshTools/Test/CMakeLists.txt +++ b/src/Magnum/MeshTools/Test/CMakeLists.txt @@ -32,10 +32,9 @@ corrade_add_test(MeshToolsGenerateIndicesTest GenerateIndicesTest.cpp LIBRARIES corrade_add_test(MeshToolsGenerateNormalsTest GenerateNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib MagnumPrimitives) corrade_add_test(MeshToolsInterleaveTest InterleaveTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsRemoveDuplicatesTest RemoveDuplicatesTest.cpp LIBRARIES MagnumMeshToolsTestLib) -corrade_add_test(MeshToolsSubdivideTest SubdivideTest.cpp LIBRARIES Magnum) +corrade_add_test(MeshToolsSubdivideTest SubdivideTest.cpp LIBRARIES Magnum MagnumPrimitives) corrade_add_test(MeshToolsTipsifyTest TipsifyTest.cpp LIBRARIES MagnumMeshTools) corrade_add_test(MeshToolsTransformTest TransformTest.cpp LIBRARIES MagnumMeshTools) -corrade_add_test(MeshToolsSubdivideRemov___Benchmark SubdivideRemoveDuplicatesBenchmark.cpp LIBRARIES MagnumMeshTools MagnumPrimitives) # Graceful assert for testing set_property(TARGET @@ -59,7 +58,6 @@ set_target_properties( MeshToolsSubdivideTest MeshToolsTipsifyTest MeshToolsTransformTest - MeshToolsSubdivideRemov___Benchmark PROPERTIES FOLDER "Magnum/MeshTools/Test") if(BUILD_DEPRECATED) diff --git a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp index d301c2751..67fc2c64d 100644 --- a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp +++ b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp @@ -31,7 +31,7 @@ #include #include -#include "Magnum/Math/Vector2.h" +#include "Magnum/Math/Vector3.h" #include "Magnum/MeshTools/RemoveDuplicates.h" #include "Magnum/Trade/MeshData.h" @@ -75,6 +75,9 @@ struct RemoveDuplicatesTest: TestSuite::Tester { void soakTest(); void soakTestFuzzy(); + + void benchmark(); + void benchmarkFuzzy(); }; const struct { @@ -136,6 +139,9 @@ RemoveDuplicatesTest::RemoveDuplicatesTest() { addRepeatedTests({&RemoveDuplicatesTest::soakTest, &RemoveDuplicatesTest::soakTestFuzzy}, 10); + + addBenchmarks({&RemoveDuplicatesTest::benchmark, + &RemoveDuplicatesTest::benchmarkFuzzy}, 10); } void RemoveDuplicatesTest::removeDuplicates() { @@ -672,6 +678,40 @@ void RemoveDuplicatesTest::soakTestFuzzy() { 100); } +void RemoveDuplicatesTest::benchmark() { + /* Array of 100 unique items with 100 duplicates each, shuffled */ + Vector3i data[10000]; + for(std::size_t i = 0; i != Containers::arraySize(data); ++i) + data[i].x() = i/100; + std::shuffle(std::begin(data), std::end(data), std::minstd_rand{std::random_device{}()}); + + std::size_t count; + UnsignedInt indices[10000]; + CORRADE_BENCHMARK(1) + count = MeshTools::removeDuplicatesInPlaceInto( + Containers::arrayCast<2, char>(Containers::arrayView(data)), + indices); + + CORRADE_COMPARE(count, 100); +} + +void RemoveDuplicatesTest::benchmarkFuzzy() { + /* Array of 100 unique items with 100 duplicates each, shuffled */ + Vector3 data[10000]; + for(std::size_t i = 0; i != Containers::arraySize(data); ++i) + data[i].x() = i/100; + std::shuffle(std::begin(data), std::end(data), std::minstd_rand{std::random_device{}()}); + + std::size_t count; + UnsignedInt indices[10000]; + CORRADE_BENCHMARK(1) + count = MeshTools::removeDuplicatesFuzzyInPlaceInto( + Containers::arrayCast<2, Float>(Containers::arrayView(data)), + indices); + + CORRADE_COMPARE(count, 100); +} + }}}} CORRADE_TEST_MAIN(Magnum::MeshTools::Test::RemoveDuplicatesTest) diff --git a/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.cpp b/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.cpp deleted file mode 100644 index dec138860..000000000 --- a/src/Magnum/MeshTools/Test/SubdivideRemoveDuplicatesBenchmark.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - This file is part of Magnum. - - Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 - Vladimír Vondruš - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ - -#include -#include -#include - -#include "Magnum/Math/Vector4.h" -#include "Magnum/MeshTools/Duplicate.h" -#include "Magnum/MeshTools/RemoveDuplicates.h" -#include "Magnum/MeshTools/Subdivide.h" -#include "Magnum/Primitives/Icosphere.h" -#include "Magnum/Trade/MeshData.h" - -namespace Magnum { namespace MeshTools { namespace Test { namespace { - -struct SubdivideRemoveDuplicatesBenchmark: TestSuite::Tester { - explicit SubdivideRemoveDuplicatesBenchmark(); - - void subdivide(); - void subdivideAndRemoveDuplicatesAfter(); - void subdivideAndRemoveDuplicatesAfterInPlace(); - void subdivideAndRemoveDuplicatesInBetween(); -}; - -SubdivideRemoveDuplicatesBenchmark::SubdivideRemoveDuplicatesBenchmark() { - addBenchmarks({&SubdivideRemoveDuplicatesBenchmark::subdivide, - &SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesAfter, - &SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesAfterInPlace, - &SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesInBetween}, 4); -} - -namespace { - static Vector3 interpolator(const Vector3& a, const Vector3& b) { - return (a+b).normalized(); - } -} - -void SubdivideRemoveDuplicatesBenchmark::subdivide() { - Trade::MeshData icosphere = Primitives::icosphereSolid(0); - - CORRADE_BENCHMARK(3) { - Containers::Array indices; - arrayResize(indices, Containers::NoInit, icosphere.indexCount()); - Utility::copy(icosphere.indices(), indices); - - Containers::Array positions; - arrayResize(positions, Containers::NoInit, icosphere.vertexCount()); - Utility::copy(icosphere.attribute(Trade::MeshAttribute::Position), positions); - - /* Subdivide 5 times */ - for(std::size_t i = 0; i != 5; ++i) - MeshTools::subdivide(indices, positions, interpolator); - } -} - -void SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesAfter() { - Trade::MeshData icosphere = Primitives::icosphereSolid(0); - - CORRADE_BENCHMARK(3) { - Containers::Array indices; - arrayResize(indices, Containers::NoInit, icosphere.indexCount()); - Utility::copy(icosphere.indices(), indices); - - Containers::Array positions; - arrayResize(positions, Containers::NoInit, icosphere.vertexCount()); - Utility::copy(icosphere.attribute(Trade::MeshAttribute::Position), positions); - - /* Subdivide 5 times */ - for(std::size_t i = 0; i != 5; ++i) - MeshTools::subdivide(indices, positions, interpolator); - - /* Remove duplicates after */ - arrayResize(positions, MeshTools::removeDuplicatesFuzzyIndexedInPlace( - stridedArrayView(indices), - Containers::arrayCast<2, Float>(stridedArrayView(positions)))); - } -} - -void SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesAfterInPlace() { - CORRADE_BENCHMARK(3) { - /* Because that's what this thing does */ - Trade::MeshData icosphere = Primitives::icosphereSolid(5); - } -} - -void SubdivideRemoveDuplicatesBenchmark::subdivideAndRemoveDuplicatesInBetween() { - Trade::MeshData icosphere = Primitives::icosphereSolid(0); - - CORRADE_BENCHMARK(3) { - Containers::Array indices; - arrayResize(indices, Containers::NoInit, icosphere.indexCount()); - Utility::copy(icosphere.indices(), indices); - - Containers::Array positions; - arrayResize(positions, Containers::NoInit, icosphere.vertexCount()); - Utility::copy(icosphere.attribute(Trade::MeshAttribute::Position), positions); - - /* Subdivide 5 times and remove duplicates during the operation */ - for(std::size_t i = 0; i != 5; ++i) { - MeshTools::subdivide(indices, positions, interpolator); - arrayResize(positions, MeshTools::removeDuplicatesFuzzyIndexedInPlace( - stridedArrayView(indices), - Containers::arrayCast<2, Float>(stridedArrayView(positions)))); - } - } -} - -}}}} - -CORRADE_TEST_MAIN(Magnum::MeshTools::Test::SubdivideRemoveDuplicatesBenchmark) - diff --git a/src/Magnum/MeshTools/Test/SubdivideTest.cpp b/src/Magnum/MeshTools/Test/SubdivideTest.cpp index 826ca9dc1..45c6af1e8 100644 --- a/src/Magnum/MeshTools/Test/SubdivideTest.cpp +++ b/src/Magnum/MeshTools/Test/SubdivideTest.cpp @@ -24,13 +24,17 @@ */ #include +#include #include #include +#include #include -#include "Magnum/Math/Vector.h" +#include "Magnum/Math/Vector3.h" #include "Magnum/MeshTools/RemoveDuplicates.h" #include "Magnum/MeshTools/Subdivide.h" +#include "Magnum/Primitives/Icosphere.h" +#include "Magnum/Trade/MeshData.h" namespace Magnum { namespace MeshTools { namespace Test { namespace { @@ -47,11 +51,17 @@ struct SubdivideTest: TestSuite::Tester { void subdivideInPlaceSmallIndexType(); /* this is additionally regression-tested in PrimitivesIcosphereTest */ + + void benchmark(); }; typedef Math::Vector<1, Int> Vector1; -inline Vector1 interpolator(Vector1 a, Vector1 b) { return (a[0]+b[0])/2; } +inline Vector1 interpolator1(Vector1 a, Vector1 b) { return (a[0]+b[0])/2; } + +Vector3 interpolator3(const Vector3& a, const Vector3& b) { + return (a+b).normalized(); +} SubdivideTest::SubdivideTest() { addTests({&SubdivideTest::subdivide, @@ -64,12 +74,14 @@ SubdivideTest::SubdivideTest() { &SubdivideTest::subdivideInPlace, &SubdivideTest::subdivideInPlaceWrongIndexCount, &SubdivideTest::subdivideInPlaceSmallIndexType}); + + addBenchmarks({&SubdivideTest::benchmark}, 4); } void SubdivideTest::subdivide() { auto positions = Containers::array({0, 2, 6, 8}); auto indices = Containers::array({0, 1, 2, 1, 2, 3}); - MeshTools::subdivide(indices, positions, interpolator); + MeshTools::subdivide(indices, positions, interpolator1); CORRADE_COMPARE_AS(indices, Containers::arrayView({ 4, 5, 6, 7, 8, 9, 0, 4, 6, 4, 1, 5, 6, 5, 2, 1, 7, 9, 7, 2, 8, 9, 8, 3 @@ -84,7 +96,7 @@ void SubdivideTest::subdivideStl() { std::vector positions{0, 2, 6, 8}; std::vector indices{0, 1, 2, 1, 2, 3}; CORRADE_IGNORE_DEPRECATED_PUSH - MeshTools::subdivide(indices, positions, interpolator); + MeshTools::subdivide(indices, positions, interpolator1); CORRADE_IGNORE_DEPRECATED_POP CORRADE_COMPARE_AS(indices, @@ -106,7 +118,7 @@ void SubdivideTest::subdivideWrongIndexCount() { Containers::Array positions; Containers::Array indices{2}; - MeshTools::subdivide(indices, positions, interpolator); + MeshTools::subdivide(indices, positions, interpolator1); CORRADE_COMPARE(out.str(), "MeshTools::subdivide(): index count is not divisible by 3\n"); } @@ -116,7 +128,7 @@ template void SubdivideTest::subdivideInPlace() { T indices[6*4]{0, 1, 2, 1, 2, 3, /* and 18 more */}; Vector1 positions[4 + 6]{0, 2, 6, 8, /* and 6 more */}; MeshTools::subdivideInPlace(Containers::stridedArrayView(indices), - Containers::stridedArrayView(positions), interpolator); + Containers::stridedArrayView(positions), interpolator1); CORRADE_COMPARE_AS(Containers::arrayView(indices), Containers::arrayView({4, 5, 6, 7, 8, 9, 0, 4, 6, 4, 1, 5, 6, 5, 2, 1, 7, 9, 7, 2, 8, 9, 8, 3}), @@ -137,7 +149,7 @@ void SubdivideTest::subdivideInPlaceWrongIndexCount() { UnsignedInt indices[6*4 + 1]{0, 1, 2, 1, 2, 3, /* and 18+1 more */}; Vector1 positions[]{0}; MeshTools::subdivideInPlace(Containers::stridedArrayView(indices), - Containers::stridedArrayView(positions), interpolator); + Containers::stridedArrayView(positions), interpolator1); CORRADE_COMPARE(out.str(), "MeshTools::subdivideInPlace(): can't divide 25 indices to four parts with each having triangle faces\n"); } @@ -152,10 +164,28 @@ void SubdivideTest::subdivideInPlaceSmallIndexType() { UnsignedByte indices[6*4]{0, 1, 2, 1, 2, 3, /* and 18 more */}; Vector1 positions[256]{}; MeshTools::subdivideInPlace(Containers::stridedArrayView(indices), - Containers::stridedArrayView(positions), interpolator); + Containers::stridedArrayView(positions), interpolator1); CORRADE_COMPARE(out.str(), "MeshTools::subdivideInPlace(): a 1-byte index type is too small for 256 vertices\n"); } +void SubdivideTest::benchmark() { + Trade::MeshData icosphere = Primitives::icosphereSolid(0); + + CORRADE_BENCHMARK(3) { + Containers::Array indices; + arrayResize(indices, Containers::NoInit, icosphere.indexCount()); + Utility::copy(icosphere.indices(), indices); + + Containers::Array positions; + arrayResize(positions, Containers::NoInit, icosphere.vertexCount()); + Utility::copy(icosphere.attribute(Trade::MeshAttribute::Position), positions); + + /* Subdivide 5 times */ + for(std::size_t i = 0; i != 5; ++i) + MeshTools::subdivide(indices, positions, interpolator3); + } +} + }}}} CORRADE_TEST_MAIN(Magnum::MeshTools::Test::SubdivideTest)