From 85bf771ea6d8d584f1c735cc963e17571ca0a0d1 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 17 Apr 2023 11:54:07 +0100 Subject: First cut of instance vertices and proxy Untested outside unit test, allows the use of a glBuffer as a storage container. To be combined with a vertex array and/or mesh etc for massing drawing with glDrawElementsInstanced --- test/test-instancing.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 test/test-instancing.cpp (limited to 'test/test-instancing.cpp') diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp new file mode 100644 index 0000000..7191567 --- /dev/null +++ b/test/test-instancing.cpp @@ -0,0 +1,76 @@ +#define BOOST_TEST_MODULE instancing + +#include "testHelpers.h" +#include "testMainWindow.h" +#include "ui/applicationBase.h" +#include +#include + +#include + +BOOST_GLOBAL_FIXTURE(ApplicationBase); +BOOST_GLOBAL_FIXTURE(TestMainWindow); + +BOOST_FIXTURE_TEST_SUITE(i, InstanceVertices) + +BOOST_AUTO_TEST_CASE(createDestroy) +{ + BOOST_REQUIRE(data.data()); + BOOST_CHECK_EQUAL(0, next); + BOOST_CHECK(unused.empty()); +} + +BOOST_AUTO_TEST_CASE(storeRetreive) +{ // Read write raw buffer, not normally allowed + std::vector test(data.size()); + std::copy(test.begin(), test.end(), data.begin()); + BOOST_CHECK_EQUAL_COLLECTIONS(test.begin(), test.end(), data.begin(), data.end()); +} + +BOOST_AUTO_TEST_CASE(acquireRelease) +{ + { + auto proxy = acquire(); + *proxy = 20; + BOOST_CHECK_EQUAL(1, next); + } + BOOST_CHECK_EQUAL(1, next); + BOOST_CHECK_EQUAL(1, unused.size()); + BOOST_CHECK_EQUAL(0, unused.front()); +} + +BOOST_AUTO_TEST_CASE(acquireReleaseMove) +{ + { + auto proxy1 = acquire(); + *proxy1 = 20; + BOOST_CHECK_EQUAL(1, next); + auto proxy2 = std::move(proxy1); + *proxy2 = 40; + BOOST_CHECK_EQUAL(1, next); + } + BOOST_CHECK_EQUAL(1, next); + BOOST_CHECK_EQUAL(1, unused.size()); + BOOST_CHECK_EQUAL(0, unused.front()); +} + +BOOST_AUTO_TEST_CASE(initialize) +{ + auto proxy = acquire(5); + BOOST_CHECK_EQUAL(*proxy, 5); +} + +BOOST_AUTO_TEST_CASE(resize) +{ + constexpr auto COUNT = 500; + std::vector proxies; + std::vector expected; + for (auto n = 0; n < COUNT; n++) { + proxies.push_back(acquire(n)); + expected.emplace_back(n); + } + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), data.begin(), data.begin() + COUNT); + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), proxies.begin(), proxies.end()); +} + +BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From ab5b46dbe58ae0401c24ead55a2627b9a577fc1a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 21 Apr 2023 23:52:56 +0100 Subject: Instances buffer data needs to be unmapped before use Here we change quite a bit to support mapping and unmapping the buffer as required. The instance/free referencing is still broken though. We add several instances of tree in the render. --- test/test-instancing.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'test/test-instancing.cpp') diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp index 7191567..2eb3647 100644 --- a/test/test-instancing.cpp +++ b/test/test-instancing.cpp @@ -15,16 +15,21 @@ BOOST_FIXTURE_TEST_SUITE(i, InstanceVertices) BOOST_AUTO_TEST_CASE(createDestroy) { - BOOST_REQUIRE(data.data()); + BOOST_CHECK(!data); + map(); + BOOST_REQUIRE(data); BOOST_CHECK_EQUAL(0, next); BOOST_CHECK(unused.empty()); + unmap(); + BOOST_CHECK(!data); } BOOST_AUTO_TEST_CASE(storeRetreive) { // Read write raw buffer, not normally allowed - std::vector test(data.size()); - std::copy(test.begin(), test.end(), data.begin()); - BOOST_CHECK_EQUAL_COLLECTIONS(test.begin(), test.end(), data.begin(), data.end()); + std::vector test(capacity); + map(); + std::copy(test.begin(), test.end(), data); + BOOST_CHECK_EQUAL_COLLECTIONS(test.begin(), test.end(), data, data + capacity); } BOOST_AUTO_TEST_CASE(acquireRelease) @@ -69,7 +74,7 @@ BOOST_AUTO_TEST_CASE(resize) proxies.push_back(acquire(n)); expected.emplace_back(n); } - BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), data.begin(), data.begin() + COUNT); + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), data, data + COUNT); BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), proxies.begin(), proxies.end()); } -- cgit v1.2.3 From b8889129c6c2b747ff771b711cfbbf91bca93bb6 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 22 Apr 2023 11:44:38 +0100 Subject: Fix the instancing maintenance --- test/test-instancing.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 10 deletions(-) (limited to 'test/test-instancing.cpp') diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp index 2eb3647..8837071 100644 --- a/test/test-instancing.cpp +++ b/test/test-instancing.cpp @@ -1,10 +1,12 @@ #define BOOST_TEST_MODULE instancing +#include "stream_support.hpp" #include "testHelpers.h" #include "testMainWindow.h" #include "ui/applicationBase.h" #include #include +#include #include @@ -20,28 +22,25 @@ BOOST_AUTO_TEST_CASE(createDestroy) BOOST_REQUIRE(data); BOOST_CHECK_EQUAL(0, next); BOOST_CHECK(unused.empty()); + BOOST_CHECK(index.empty()); unmap(); BOOST_CHECK(!data); } -BOOST_AUTO_TEST_CASE(storeRetreive) -{ // Read write raw buffer, not normally allowed - std::vector test(capacity); - map(); - std::copy(test.begin(), test.end(), data); - BOOST_CHECK_EQUAL_COLLECTIONS(test.begin(), test.end(), data, data + capacity); -} - BOOST_AUTO_TEST_CASE(acquireRelease) { { auto proxy = acquire(); *proxy = 20; BOOST_CHECK_EQUAL(1, next); + BOOST_REQUIRE_EQUAL(1, index.size()); + BOOST_CHECK_EQUAL(0, index.front()); + BOOST_CHECK(unused.empty()); } - BOOST_CHECK_EQUAL(1, next); + BOOST_CHECK_EQUAL(0, next); BOOST_CHECK_EQUAL(1, unused.size()); BOOST_CHECK_EQUAL(0, unused.front()); + BOOST_CHECK_EQUAL(1, index.size()); } BOOST_AUTO_TEST_CASE(acquireReleaseMove) @@ -54,9 +53,10 @@ BOOST_AUTO_TEST_CASE(acquireReleaseMove) *proxy2 = 40; BOOST_CHECK_EQUAL(1, next); } - BOOST_CHECK_EQUAL(1, next); + BOOST_CHECK_EQUAL(0, next); BOOST_CHECK_EQUAL(1, unused.size()); BOOST_CHECK_EQUAL(0, unused.front()); + BOOST_CHECK_EQUAL(1, index.size()); } BOOST_AUTO_TEST_CASE(initialize) @@ -78,4 +78,89 @@ BOOST_AUTO_TEST_CASE(resize) BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), proxies.begin(), proxies.end()); } +BOOST_AUTO_TEST_CASE(shuffle) +{ + std::vector proxies; + BOOST_CHECK_EQUAL(0, proxies.emplace_back(acquire(0))); + BOOST_CHECK_EQUAL(1, proxies.emplace_back(acquire(1))); + BOOST_CHECK_EQUAL(2, proxies.emplace_back(acquire(2))); + BOOST_CHECK_EQUAL(3, proxies.emplace_back(acquire(3))); + BOOST_CHECK_EQUAL(4, next); + BOOST_CHECK_EQUAL(data + 0, proxies[0].get()); + BOOST_CHECK_EQUAL(data + 1, proxies[1].get()); + BOOST_CHECK_EQUAL(data + 2, proxies[2].get()); + BOOST_CHECK_EQUAL(data + 3, proxies[3].get()); + BOOST_CHECK(unused.empty()); + BOOST_REQUIRE_EQUAL(4, index.size()); + BOOST_CHECK_EQUAL(0, index[0]); + BOOST_CHECK_EQUAL(1, index[1]); + BOOST_CHECK_EQUAL(2, index[2]); + BOOST_CHECK_EQUAL(3, index[3]); + // Remove 1, 3 moves to [1] + proxies.erase(proxies.begin() + 1); + BOOST_REQUIRE_EQUAL(4, index.size()); + BOOST_REQUIRE_EQUAL(1, unused.size()); + BOOST_CHECK_EQUAL(1, unused[0]); + BOOST_CHECK_EQUAL(data + 0, proxies[0].get()); + BOOST_CHECK_EQUAL(data + 2, proxies[1].get()); + BOOST_CHECK_EQUAL(data + 1, proxies[2].get()); + // Remove 1, 2 moves to [1] + proxies.erase(proxies.begin() + 1); + BOOST_REQUIRE_EQUAL(4, index.size()); + BOOST_REQUIRE_EQUAL(2, unused.size()); + BOOST_CHECK_EQUAL(1, unused[0]); + BOOST_CHECK_EQUAL(2, unused[1]); + BOOST_CHECK_EQUAL(data + 0, proxies[0].get()); + BOOST_CHECK_EQUAL(data + 1, proxies[1].get()); + // Add new, takes 2 at [2] + BOOST_CHECK_EQUAL(4, proxies.emplace_back(acquire(4))); + BOOST_REQUIRE_EQUAL(4, index.size()); + BOOST_REQUIRE_EQUAL(1, unused.size()); + BOOST_CHECK_EQUAL(1, unused[0]); + BOOST_CHECK_EQUAL(data + 0, proxies[0].get()); + BOOST_CHECK_EQUAL(data + 1, proxies[1].get()); + BOOST_CHECK_EQUAL(data + 2, proxies[2].get()); +} + +BOOST_DATA_TEST_CASE(shuffle_random, boost::unit_test::data::xrange(0, 10), x) +{ + std::ignore = x; + std::mt19937 gen(std::random_device {}()); + std::map::InstanceProxy> proxies; + const std::string_view actions = "aaaaaaaarararrraarrrararararaarrrarararararararararraarrrraaaarararaararar"; + int n {}; + for (const auto action : actions) { + switch (action) { + case 'a': + BOOST_REQUIRE_EQUAL(n, proxies.emplace(n, acquire(n)).first->second); + n++; + break; + case 'r': + BOOST_REQUIRE(!proxies.empty()); + auto e = std::next(proxies.begin(), + std::uniform_int_distribution<> {0, static_cast(proxies.size() - 1)}(gen)); + proxies.erase(e); + break; + } + + BOOST_REQUIRE_EQUAL(next, proxies.size()); + for (const auto & [n, p] : proxies) { + BOOST_REQUIRE_EQUAL(n, p); + } + std::set iused; + for (size_t i {}; i < index.size(); i++) { + if (std::find(unused.begin(), unused.end(), i) == unused.end()) { + iused.emplace(index[i]); + } + } + BOOST_TEST_CONTEXT(index) { + BOOST_REQUIRE_EQUAL(iused.size(), next); + if (!iused.empty()) { + BOOST_REQUIRE_EQUAL(*iused.begin(), 0); + BOOST_REQUIRE_EQUAL(*iused.rbegin(), next - 1); + } + } + } +} + BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From bcd0e98739974248e6d29f72e8b281e21fd59657 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 22 Apr 2023 13:17:05 +0100 Subject: Test instancing automatic unmap when count is called, add some nodiscard --- test/test-instancing.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'test/test-instancing.cpp') diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp index 8837071..70b20fa 100644 --- a/test/test-instancing.cpp +++ b/test/test-instancing.cpp @@ -50,8 +50,9 @@ BOOST_AUTO_TEST_CASE(acquireReleaseMove) *proxy1 = 20; BOOST_CHECK_EQUAL(1, next); auto proxy2 = std::move(proxy1); - *proxy2 = 40; + proxy2 = 40; BOOST_CHECK_EQUAL(1, next); + BOOST_CHECK_EQUAL(data[0], 40); } BOOST_CHECK_EQUAL(0, next); BOOST_CHECK_EQUAL(1, unused.size()); @@ -59,10 +60,26 @@ BOOST_AUTO_TEST_CASE(acquireReleaseMove) BOOST_CHECK_EQUAL(1, index.size()); } +BOOST_AUTO_TEST_CASE(autoMapUnmap) +{ + { + auto proxy = acquire(); + BOOST_CHECK(data); + std::ignore = bufferName(); + BOOST_CHECK(data); + BOOST_CHECK_EQUAL(1, count()); + BOOST_CHECK(!data); + } + BOOST_CHECK_EQUAL(0, count()); +} + BOOST_AUTO_TEST_CASE(initialize) { auto proxy = acquire(5); + const auto & constProxy = proxy; BOOST_CHECK_EQUAL(*proxy, 5); + BOOST_CHECK_EQUAL(*constProxy, 5); + BOOST_CHECK_EQUAL(constProxy.get(), constProxy.get()); } BOOST_AUTO_TEST_CASE(resize) -- cgit v1.2.3 From 59d85f9b87fc82b52f2c7438e38768aeddc3cc87 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 22 Apr 2023 14:56:08 +0100 Subject: Don't fill the instances unused vector unnecessarily --- test/test-instancing.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'test/test-instancing.cpp') diff --git a/test/test-instancing.cpp b/test/test-instancing.cpp index 70b20fa..c743ce0 100644 --- a/test/test-instancing.cpp +++ b/test/test-instancing.cpp @@ -38,9 +38,8 @@ BOOST_AUTO_TEST_CASE(acquireRelease) BOOST_CHECK(unused.empty()); } BOOST_CHECK_EQUAL(0, next); - BOOST_CHECK_EQUAL(1, unused.size()); - BOOST_CHECK_EQUAL(0, unused.front()); - BOOST_CHECK_EQUAL(1, index.size()); + BOOST_CHECK(unused.empty()); + BOOST_CHECK(index.empty()); } BOOST_AUTO_TEST_CASE(acquireReleaseMove) @@ -55,9 +54,8 @@ BOOST_AUTO_TEST_CASE(acquireReleaseMove) BOOST_CHECK_EQUAL(data[0], 40); } BOOST_CHECK_EQUAL(0, next); - BOOST_CHECK_EQUAL(1, unused.size()); - BOOST_CHECK_EQUAL(0, unused.front()); - BOOST_CHECK_EQUAL(1, index.size()); + BOOST_CHECK(unused.empty()); + BOOST_CHECK(index.empty()); } BOOST_AUTO_TEST_CASE(autoMapUnmap) -- cgit v1.2.3