From 394d165d6877afe6490bad49f8b957492c5ac3e4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 2 Feb 2024 01:25:38 +0000 Subject: Fix warnings in test-glContainer Also updates static asserts to requirements --- lib/glContainer.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/glContainer.h') diff --git a/lib/glContainer.h b/lib/glContainer.h index 2ccc1c2..b4238d5 100644 --- a/lib/glContainer.h +++ b/lib/glContainer.h @@ -272,6 +272,7 @@ public: void resize(size_type newSize) + requires std::is_default_constructible_v { if (newSize == size_) { return; @@ -327,6 +328,7 @@ public: template reference_type emplace_back(P &&... ps) + requires std::is_constructible_v { auto newSize = size_ + 1; reserve(newSize); @@ -339,8 +341,8 @@ public: template iterator emplace(iterator pos, P &&... ps) + requires std::is_nothrow_constructible_v { - static_assert(std::is_nothrow_constructible_v); auto newSize = size_ + 1; const auto idx = pos - begin(); reserve(newSize); @@ -355,6 +357,7 @@ public: reference_type push_back(T p) + requires std::is_move_constructible_v { auto newSize = size_ + 1; reserve(newSize); @@ -366,8 +369,8 @@ public: iterator insert(iterator pos, T p) + requires std::is_nothrow_move_constructible_v { - static_assert(std::is_nothrow_move_constructible_v); auto newSize = size_ + 1; const auto idx = pos - begin(); reserve(newSize); -- cgit v1.2.3 From 9a106a6906d6a9718541633525de540e667b7625 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 2 Feb 2024 02:02:19 +0000 Subject: Don't keep a span, create as needed Removes the error prone issue where data/size get out of sync. Fixes overflow issues leading to memory corruption of GPU data. --- lib/glContainer.h | 106 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 46 deletions(-) (limited to 'lib/glContainer.h') diff --git a/lib/glContainer.h b/lib/glContainer.h index b4238d5..1cdeee0 100644 --- a/lib/glContainer.h +++ b/lib/glContainer.h @@ -50,84 +50,84 @@ public: begin() { map(); - return data_.begin(); + return mkspan().begin(); } [[nodiscard]] iterator end() { map(); - return data_.end(); + return mkspan().end(); } [[nodiscard]] const_iterator begin() const { map(); - return const_span {data_}.begin(); + return mkcspan().begin(); } [[nodiscard]] const_iterator end() const { map(); - return const_span {data_}.end(); + return mkcspan().end(); } [[nodiscard]] const_iterator cbegin() const { map(); - return const_span {data_}.begin(); + return mkcspan().begin(); } [[nodiscard]] const_iterator cend() const { map(); - return const_span {data_}.end(); + return mkcspan().end(); } [[nodiscard]] reverse_iterator rbegin() { map(); - return data_.rbegin(); + return mkspan().rbegin(); } [[nodiscard]] reverse_iterator rend() { map(); - return data_.rend(); + return mkspan().rend(); } [[nodiscard]] const_reverse_iterator rbegin() const { map(); - return const_span {data_}.rbegin(); + return mkcspan().rbegin(); } [[nodiscard]] const_reverse_iterator rend() const { map(); - return const_span {data_}.rend(); + return mkcspan().rend(); } [[nodiscard]] const_reverse_iterator crbegin() const { map(); - return const_span {data_}.rbegin(); + return mkcspan().rbegin(); } [[nodiscard]] const_reverse_iterator crend() const { map(); - return const_span {data_}.rend(); + return mkcspan().rend(); } [[nodiscard]] const auto & @@ -148,8 +148,8 @@ public: if (pos >= size()) { throw std::out_of_range {__FUNCTION__}; } - if (data_.data()) { - data_[pos] = value; + if (data_) { + mkspan()[pos] = value; } else { glBindBuffer(GL_ARRAY_BUFFER, buffer_); @@ -165,7 +165,7 @@ public: throw std::out_of_range {__FUNCTION__}; } map(); - return data_[pos]; + return mkspan()[pos]; } [[nodiscard]] const_reference_type @@ -175,63 +175,63 @@ public: throw std::out_of_range {__FUNCTION__}; } map(); - return data_[pos]; + return mkcspan()[pos]; } [[nodiscard]] reference_type operator[](size_type pos) { map(); - return data_[pos]; + return mkspan()[pos]; } [[nodiscard]] const_reference_type operator[](size_type pos) const { map(); - return data_[pos]; + return mkcspan()[pos]; } [[nodiscard]] pointer_type data() { map(); - return data_.data(); + return data_; } [[nodiscard]] const_pointer_type data() const { map(); - return data_.data(); + return data_; } [[nodiscard]] reference_type front() { map(); - return data_.front(); + return mkspan().front(); } [[nodiscard]] reference_type back() { map(); - return data_.back(); + return mkspan().back(); } [[nodiscard]] const_reference_type front() const { map(); - return data_.front(); + return mkcspan().front(); } [[nodiscard]] const_reference_type back() const { map(); - return data_.back(); + return mkcspan().back(); } [[nodiscard]] bool @@ -249,7 +249,7 @@ public: void unmap() const { - if (data_.data()) { + if (data_) { glUnmapNamedBuffer(buffer_); data_ = {}; } @@ -291,8 +291,10 @@ public: allocBuffer(newSize); mapForAdd(); } - for (auto uninitialised = data_.data() + size_; uninitialised < data_.data() + newSize; ++uninitialised) { - new (uninitialised) T {}; + if (newSize > size_) { + for (auto & uninitialised : mkspan().subspan(size_, newSize - size_)) { + new (&uninitialised) T {}; + } } setSize(newSize); } @@ -333,7 +335,7 @@ public: auto newSize = size_ + 1; reserve(newSize); mapForAdd(); - new (&data_[size_]) T {std::forward

(ps)...}; + new (&*end()) T {std::forward

(ps)...}; setSize(newSize); return back(); } @@ -347,10 +349,10 @@ public: const auto idx = pos - begin(); reserve(newSize); mapForAdd(); - auto newT = begin() + idx; - std::move_backward(newT, end(), end() + 1); - newT->~T(); - new (&*newT) T {std::forward

(ps)...}; + pos = begin() + idx; + std::move_backward(pos, end(), end() + 1); + pos->~T(); + new (&*pos) T {std::forward

(ps)...}; setSize(newSize); return pos; } @@ -362,7 +364,7 @@ public: auto newSize = size_ + 1; reserve(newSize); mapForAdd(); - new (&data_[size_]) T {std::move(p)}; + new (&*end()) T {std::move(p)}; setSize(newSize); return back(); } @@ -375,10 +377,10 @@ public: const auto idx = pos - begin(); reserve(newSize); mapForAdd(); - auto newT = begin() + idx; - std::move_backward(newT, end(), end() + 1); - newT->~T(); - new (&*newT) T {std::move(p)}; + pos = begin() + idx; + std::move_backward(pos, end(), end() + 1); + pos->~T(); + new (&*pos) T {std::move(p)}; setSize(newSize); return pos; } @@ -388,11 +390,9 @@ public: { if constexpr (!is_trivial_dest) { map(); - data_[--size_].~T(); - } - else { - --size_; + back().~T(); } + --size_; } void @@ -419,7 +419,7 @@ protected: void setSize(size_type s) { - data_ = {data_.data(), size_ = s}; + size_ = s; } void @@ -446,14 +446,28 @@ protected: void mapForAdd() const { - if (!data_.data()) { - data_ = {static_cast(glMapNamedBuffer(buffer_, GL_READ_WRITE)), size_}; - assert(data_.data()); + if (!data_) { + data_ = static_cast(glMapNamedBuffer(buffer_, GL_READ_WRITE)); + assert(data_); } } + span + mkspan() const + { + assert(!size_ || data_); + return span {data_, size_}; + } + + const_span + mkcspan() const + { + assert(!size_ || data_); + return const_span {data_, size_}; + } + glBuffer buffer_; std::size_t capacity_ {}; std::size_t size_ {}; - mutable span data_; + mutable T * data_; }; -- cgit v1.2.3 From b85297334ee3b59a738eec4dd8560979b0591c37 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 2 Feb 2024 20:49:09 +0000 Subject: Map buffers RO if const operations, upgrade to RW as required --- lib/glContainer.h | 78 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 30 deletions(-) (limited to 'lib/glContainer.h') diff --git a/lib/glContainer.h b/lib/glContainer.h index 1cdeee0..4960e3c 100644 --- a/lib/glContainer.h +++ b/lib/glContainer.h @@ -7,6 +7,9 @@ #include #include +static_assert(GL_READ_ONLY < GL_READ_WRITE); +static_assert(GL_WRITE_ONLY < GL_READ_WRITE); + template class glContainer { public: using span = std::span; @@ -49,84 +52,84 @@ public: [[nodiscard]] iterator begin() { - map(); + map(GL_READ_WRITE); return mkspan().begin(); } [[nodiscard]] iterator end() { - map(); + map(GL_READ_WRITE); return mkspan().end(); } [[nodiscard]] const_iterator begin() const { - map(); + map(GL_READ_ONLY); return mkcspan().begin(); } [[nodiscard]] const_iterator end() const { - map(); + map(GL_READ_ONLY); return mkcspan().end(); } [[nodiscard]] const_iterator cbegin() const { - map(); + map(GL_READ_ONLY); return mkcspan().begin(); } [[nodiscard]] const_iterator cend() const { - map(); + map(GL_READ_ONLY); return mkcspan().end(); } [[nodiscard]] reverse_iterator rbegin() { - map(); + map(GL_READ_WRITE); return mkspan().rbegin(); } [[nodiscard]] reverse_iterator rend() { - map(); + map(GL_READ_WRITE); return mkspan().rend(); } [[nodiscard]] const_reverse_iterator rbegin() const { - map(); + map(GL_READ_ONLY); return mkcspan().rbegin(); } [[nodiscard]] const_reverse_iterator rend() const { - map(); + map(GL_READ_ONLY); return mkcspan().rend(); } [[nodiscard]] const_reverse_iterator crbegin() const { - map(); + map(GL_READ_ONLY); return mkcspan().rbegin(); } [[nodiscard]] const_reverse_iterator crend() const { - map(); + map(GL_READ_ONLY); return mkcspan().rend(); } @@ -164,7 +167,7 @@ public: if (pos >= size()) { throw std::out_of_range {__FUNCTION__}; } - map(); + map(GL_READ_WRITE); return mkspan()[pos]; } @@ -174,63 +177,63 @@ public: if (pos >= size()) { throw std::out_of_range {__FUNCTION__}; } - map(); + map(GL_READ_ONLY); return mkcspan()[pos]; } [[nodiscard]] reference_type operator[](size_type pos) { - map(); + map(GL_READ_WRITE); return mkspan()[pos]; } [[nodiscard]] const_reference_type operator[](size_type pos) const { - map(); + map(GL_READ_ONLY); return mkcspan()[pos]; } [[nodiscard]] pointer_type data() { - map(); + map(GL_READ_WRITE); return data_; } [[nodiscard]] const_pointer_type data() const { - map(); + map(GL_READ_ONLY); return data_; } [[nodiscard]] reference_type front() { - map(); + map(GL_READ_WRITE); return mkspan().front(); } [[nodiscard]] reference_type back() { - map(); + map(GL_READ_WRITE); return mkspan().back(); } [[nodiscard]] const_reference_type front() const { - map(); + map(GL_READ_ONLY); return mkcspan().front(); } [[nodiscard]] const_reference_type back() const { - map(); + map(GL_READ_ONLY); return mkcspan().back(); } @@ -252,6 +255,7 @@ public: if (data_) { glUnmapNamedBuffer(buffer_); data_ = {}; + access_ = {}; } } @@ -308,10 +312,10 @@ public: std::vector existing; existing.reserve(size_); - map(); + map(is_trivial_dest ? GL_READ_ONLY : GL_READ_WRITE); std::move(begin(), end(), std::back_inserter(existing)); allocBuffer(size_); - map(); + map(GL_READ_WRITE); std::move(existing.begin(), existing.end(), begin()); } @@ -319,7 +323,7 @@ public: clear() noexcept(is_trivial_dest) { if constexpr (!is_trivial_dest) { - map(); + map(GL_READ_WRITE); std::for_each(begin(), end(), [](auto && v) { v.~T(); }); @@ -389,7 +393,7 @@ public: pop_back() { if constexpr (!is_trivial_dest) { - map(); + map(GL_READ_WRITE); back().~T(); } --size_; @@ -405,7 +409,7 @@ public: erase(iterator pos, iterator to) { const auto eraseSize = to - pos; - map(); + map(GL_READ_WRITE); std::move(to, end(), pos); if constexpr (!is_trivial_dest) { std::for_each(end() - eraseSize, end(), [](auto && v) { @@ -433,13 +437,14 @@ protected: glBindBuffer(GL_ARRAY_BUFFER, 0); capacity_ = newCapacity; data_ = {}; + access_ = {}; } void - map() const + map(GLenum access) const { if (size_ > 0) { - mapForAdd(); + mapMode(access); } } @@ -447,8 +452,20 @@ protected: mapForAdd() const { if (!data_) { - data_ = static_cast(glMapNamedBuffer(buffer_, GL_READ_WRITE)); + mapMode(GL_READ_WRITE); + } + } + + void + mapMode(GLenum access) const + { + if (data_ && access_ < access) { + unmap(); + } + if (!data_) { + data_ = static_cast(glMapNamedBuffer(buffer_, access)); assert(data_); + access_ = access; } } @@ -470,4 +487,5 @@ protected: std::size_t capacity_ {}; std::size_t size_ {}; mutable T * data_; + mutable GLenum access_ {}; }; -- cgit v1.2.3 From 017ca4691f84281c0a1ec4da36e7cf81e38dbbbc Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 2 Feb 2024 21:07:23 +0000 Subject: Allow specifying a target other than array buffer GL_ARRAY_BUFFER is the default. Also removes accidental use for OpenGL 4.x functions. --- lib/glContainer.h | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'lib/glContainer.h') diff --git a/lib/glContainer.h b/lib/glContainer.h index 4960e3c..5cbb038 100644 --- a/lib/glContainer.h +++ b/lib/glContainer.h @@ -26,7 +26,7 @@ public: using const_reverse_iterator = const_span::reverse_iterator; static constexpr bool is_trivial_dest = std::is_trivially_destructible_v; - glContainer() + explicit glContainer(GLenum target = GL_ARRAY_BUFFER) : target_ {target} { allocBuffer(1); } @@ -41,7 +41,8 @@ public: clear(); } - template typename C> explicit glContainer(const C & src) + template typename C> + explicit glContainer(const C & src, GLenum target = GL_ARRAY_BUFFER) : target_ {target} { reserve(src.size()); std::copy(src.begin(), src.end(), std::back_inserter(*this)); @@ -155,9 +156,9 @@ public: mkspan()[pos] = value; } else { - glBindBuffer(GL_ARRAY_BUFFER, buffer_); - glBufferSubData(GL_ARRAY_BUFFER, static_cast(pos * sizeof(T)), sizeof(value), &value); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(target_, buffer_); + glBufferSubData(target_, static_cast(pos * sizeof(T)), sizeof(value), &value); + glBindBuffer(target_, 0); } } @@ -253,7 +254,9 @@ public: unmap() const { if (data_) { - glUnmapNamedBuffer(buffer_); + glBindBuffer(target_, buffer_); + glUnmapBuffer(target_); + glBindBuffer(target_, 0); data_ = {}; access_ = {}; } @@ -432,9 +435,9 @@ protected: if (newCapacity == 0) { return allocBuffer(1); } - glBindBuffer(GL_ARRAY_BUFFER, buffer_); - glBufferData(GL_ARRAY_BUFFER, static_cast(sizeof(T) * newCapacity), nullptr, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(target_, buffer_); + glBufferData(target_, static_cast(sizeof(T) * newCapacity), nullptr, GL_DYNAMIC_DRAW); + glBindBuffer(target_, 0); capacity_ = newCapacity; data_ = {}; access_ = {}; @@ -463,7 +466,9 @@ protected: unmap(); } if (!data_) { - data_ = static_cast(glMapNamedBuffer(buffer_, access)); + glBindBuffer(target_, buffer_); + data_ = static_cast(glMapBuffer(target_, access)); + glBindBuffer(target_, 0); assert(data_); access_ = access; } @@ -484,6 +489,7 @@ protected: } glBuffer buffer_; + GLenum target_; std::size_t capacity_ {}; std::size_t size_ {}; mutable T * data_; -- cgit v1.2.3