summaryrefslogtreecommitdiff
path: root/gfx/gl/instanceVertices.h
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-04-22 11:44:38 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-04-22 11:44:38 +0100
commitb8889129c6c2b747ff771b711cfbbf91bca93bb6 (patch)
tree8d16362d9adb71c0d8af43a9819e6ac3a66cfba1 /gfx/gl/instanceVertices.h
parentInstances buffer data needs to be unmapped before use (diff)
downloadilt-b8889129c6c2b747ff771b711cfbbf91bca93bb6.tar.bz2
ilt-b8889129c6c2b747ff771b711cfbbf91bca93bb6.tar.xz
ilt-b8889129c6c2b747ff771b711cfbbf91bca93bb6.zip
Fix the instancing maintenance
Diffstat (limited to 'gfx/gl/instanceVertices.h')
-rw-r--r--gfx/gl/instanceVertices.h83
1 files changed, 57 insertions, 26 deletions
diff --git a/gfx/gl/instanceVertices.h b/gfx/gl/instanceVertices.h
index c2ddb1d..036b48e 100644
--- a/gfx/gl/instanceVertices.h
+++ b/gfx/gl/instanceVertices.h
@@ -32,37 +32,38 @@ public:
InstanceProxy &
operator=(InstanceProxy && other)
{
+ if (instances) {
+ instances->release(*this);
+ }
instances = std::exchange(other.instances, nullptr);
index = other.index;
+ return *this;
+ }
+ template<typename U>
+ T &
+ operator=(U && v)
+ {
+ return instances->at(index) = std::forward<U>(v);
}
operator T &()
{
- return *get();
+ return instances->at(index);
}
operator const T &() const
{
- return *get();
- }
- template<typename U>
- T &
- operator=(U && v)
- {
- instances->map();
- return instances->data[index] = std::forward<U>(v);
+ return instances->at(index);
}
T *
get()
{
- instances->map();
- return &instances->data[index];
+ return &instances->at(index);
}
const T *
get() const
{
- instances->map();
- return &instances->data[index];
+ return &instances->at(index);
}
T *
operator->()
@@ -77,12 +78,12 @@ public:
T &
operator*()
{
- return *get();
+ return instances->at(index);
}
const T &
operator*() const
{
- return *get();
+ return instances->at(index);
}
private:
@@ -100,22 +101,16 @@ public:
if (!unused.empty()) {
auto idx = unused.back();
unused.pop_back();
- new (data + idx) T(std::forward<Params>(params)...);
+ index[idx] = next++;
+ new (&at(idx)) T(std::forward<Params>(params)...);
return InstanceProxy {this, idx};
}
if (next >= capacity) {
resize(capacity * 2);
}
- 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);
+ index.emplace_back(next++);
+ new (data + index.back()) T(std::forward<Params>(params)...);
+ return InstanceProxy {this, index.size() - 1};
}
const auto &
@@ -136,6 +131,30 @@ protected:
friend InstanceProxy;
void
+ release(const InstanceProxy & p)
+ {
+ // Destroy p's object
+ at(p.index).~T();
+ if (next-- > index[p.index]) {
+ // Remember p.index is free index now
+ unused.push_back(p.index);
+ // Move last object into p's slot
+ new (&at(p.index)) T {std::move(data[next])};
+ (data[next]).~T();
+ for (auto & i : index) {
+ if (i == next) {
+ i = index[p.index];
+ break;
+ }
+ }
+ index[p.index] = 100000;
+ }
+ else {
+ index.pop_back();
+ }
+ }
+
+ void
allocBuffer(std::size_t newCapacity)
{
glBindBuffer(GL_ARRAY_BUFFER, buffer);
@@ -160,6 +179,13 @@ protected:
capacity = newCapacity;
}
+ T &
+ at(size_t pindex)
+ {
+ map();
+ return data[index[pindex]];
+ }
+
void
map() const
{
@@ -179,7 +205,12 @@ protected:
glBuffer buffer;
mutable T * data {};
+ // Size of buffer
std::size_t capacity {};
+ // # used of capacity
std::size_t next {};
+ // Index into buffer given to nth proxy
+ std::vector<size_t> index;
+ // List of free spaces in index
std::vector<size_t> unused;
};