summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-04-21 23:52:56 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-04-21 23:52:56 +0100
commitab5b46dbe58ae0401c24ead55a2627b9a577fc1a (patch)
tree8c2d20920186a636f33c471bd1bfa515ea9de2af
parentSwitch to render trees in bulk through foliage asset rendering (diff)
downloadilt-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.h66
-rw-r--r--test/Jamfile.jam2
-rw-r--r--test/test-assetFactory.cpp5
-rw-r--r--test/test-instancing.cpp15
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());
}