diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2023-04-21 23:52:56 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2023-04-21 23:52:56 +0100 |
commit | ab5b46dbe58ae0401c24ead55a2627b9a577fc1a (patch) | |
tree | 8c2d20920186a636f33c471bd1bfa515ea9de2af | |
parent | Switch to render trees in bulk through foliage asset rendering (diff) | |
download | ilt-ab5b46dbe58ae0401c24ead55a2627b9a577fc1a.tar.bz2 ilt-ab5b46dbe58ae0401c24ead55a2627b9a577fc1a.tar.xz ilt-ab5b46dbe58ae0401c24ead55a2627b9a577fc1a.zip |
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.
-rw-r--r-- | gfx/gl/instanceVertices.h | 66 | ||||
-rw-r--r-- | test/Jamfile.jam | 2 | ||||
-rw-r--r-- | test/test-assetFactory.cpp | 5 | ||||
-rw-r--r-- | test/test-instancing.cpp | 15 |
4 files changed, 61 insertions, 27 deletions
diff --git a/gfx/gl/instanceVertices.h b/gfx/gl/instanceVertices.h index dc28a4d..c2ddb1d 100644 --- a/gfx/gl/instanceVertices.h +++ b/gfx/gl/instanceVertices.h @@ -9,11 +9,9 @@ template<typename T> class InstanceVertices { public: - InstanceVertices(size_t initialSize = 16) : data {allocBuffer(buffer, initialSize)}, next {} { } - - ~InstanceVertices() + InstanceVertices(size_t initialSize = 16) { - glUnmapNamedBuffer(buffer); + allocBuffer(initialSize); } class InstanceProxy { @@ -50,17 +48,20 @@ public: T & operator=(U && v) { + instances->map(); return instances->data[index] = std::forward<U>(v); } T * get() { + instances->map(); return &instances->data[index]; } const T * get() const { + instances->map(); return &instances->data[index]; } T * @@ -95,22 +96,24 @@ public: InstanceProxy acquire(Params &&... params) { + map(); if (!unused.empty()) { auto idx = unused.back(); unused.pop_back(); - new (&data[idx]) T(std::forward<Params>(params)...); + new (data + idx) T(std::forward<Params>(params)...); return InstanceProxy {this, idx}; } - if (next >= data.size()) { - resize(data.size() * 2); + if (next >= capacity) { + resize(capacity * 2); } - new (&data[next]) T(std::forward<Params>(params)...); + new (data + next) T(std::forward<Params>(params)...); return InstanceProxy {this, next++}; } void release(const InstanceProxy & p) { + map(); data[p.index].~T(); unused.push_back(p.index); } @@ -118,42 +121,65 @@ public: const auto & bufferName() const { + unmap(); return buffer; } auto count() const { + unmap(); return next; } protected: friend InstanceProxy; - static std::span<T> - allocBuffer(const glBuffer & buffer, std::size_t count) + void + allocBuffer(std::size_t newCapacity) { glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(sizeof(T) * count), nullptr, GL_DYNAMIC_DRAW); - auto data = static_cast<T *>(glMapNamedBuffer(buffer, GL_READ_WRITE)); + glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(sizeof(T) * newCapacity), nullptr, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); - return {data, count}; + capacity = newCapacity; + data = nullptr; } void resize(size_t newCapacity) { - const auto maintain = std::min(newCapacity, data.size()); - const auto maintaind = static_cast<typename decltype(data)::difference_type>(maintain); + const auto maintain = std::min(newCapacity, capacity); std::vector<T> existing; + const auto maintaind = static_cast<typename decltype(existing)::difference_type>(maintain); existing.reserve(maintain); - std::move(data.begin(), data.begin() + maintaind, std::back_inserter(existing)); - data = allocBuffer(buffer, newCapacity); - std::move(existing.begin(), existing.begin() + maintaind, data.begin()); + map(); + std::move(data, data + maintain, std::back_inserter(existing)); + allocBuffer(newCapacity); + map(); + std::move(existing.begin(), existing.begin() + maintaind, data); + capacity = newCapacity; + } + + void + map() const + { + if (!data) { + data = static_cast<T *>(glMapNamedBuffer(buffer, GL_READ_WRITE)); + } + } + + void + unmap() const + { + if (data) { + glUnmapNamedBuffer(buffer); + data = nullptr; + } } glBuffer buffer; - std::span<T> data; - std::size_t next; + mutable T * data {}; + std::size_t capacity {}; + std::size_t next {}; std::vector<size_t> unused; }; diff --git a/test/Jamfile.jam b/test/Jamfile.jam index 9cdcef4..1ce73b7 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -53,7 +53,7 @@ run test-text.cpp ; run test-enumDetails.cpp ; run test-render.cpp : -- : test-assetFactory : <library>test ; run test-glContextBhvr.cpp ; -run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.* ] fixtures/rgb.txt ] : <library>test ; +run test-assetFactory.cpp : -- : [ sequence.insertion-sort [ glob-tree $(res) : *.* ] fixtures/rgb.txt test-instancing ] : <library>test ; run perf-assetFactory.cpp : -- : test-assetFactory : <library>benchmark <library>test ; run perf-persistence.cpp : -- : test-persistence : <library>benchmark <library>test ; run test-worker.cpp ; diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 817654b..82a1825 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -107,7 +107,10 @@ BOOST_AUTO_TEST_CASE(foliage, *boost::unit_test::timeout(5)) auto tree_01_1_f = std::dynamic_pointer_cast<Foliage>(tree_01_1); BOOST_REQUIRE(tree_01_1_f); - auto plant = std::make_shared<Plant>(tree_01_1_f, Location {{-2, 2, 0}, {}}); + auto plant1 = std::make_shared<Plant>(tree_01_1_f, Location {{-2, 2, 0}, {0, 0, 0}}); + auto plant2 = std::make_shared<Plant>(tree_01_1_f, Location {{3, -4, 0}, {0, 1, 0}}); + auto plant3 = std::make_shared<Plant>(tree_01_1_f, Location {{-2, -4, 0}, {0, 2, 0}}); + auto plant4 = std::make_shared<Plant>(tree_01_1_f, Location {{3, 2, 0}, {0, 3, 0}}); objects.objects.push_back(tree_01_1_f); render(5); 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<int>) 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<int> 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<int> 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()); } |