diff options
Diffstat (limited to 'lib/glAllocator.h')
| -rw-r--r-- | lib/glAllocator.h | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/lib/glAllocator.h b/lib/glAllocator.h new file mode 100644 index 0000000..02690c3 --- /dev/null +++ b/lib/glAllocator.h @@ -0,0 +1,163 @@ +#include "special_members.h" +#include <glad/gl.h> +#include <iterator> +#include <memory> +#include <vector> + +namespace Detail { + template<typename T> class glPointer { + public: + constexpr glPointer(const glPointer<std::remove_const_t<T>> & other) + requires(std::is_const_v<T>) + : ptr {other.get()}, name {other.bufferName()} + { + } + + DEFAULT_MOVE_COPY(glPointer); + + constexpr glPointer() : ptr {nullptr}, name {0} { } + + constexpr glPointer(T * ptr, GLuint name) : ptr {ptr}, name {name} { } + + auto operator<=>(const glPointer &) const noexcept = default; + + operator T *() const noexcept + { + return ptr; + } + + operator bool() const noexcept + { + return ptr; + } + + std::ptrdiff_t + operator-(const glPointer & other) const noexcept + { + return ptr - other.ptr; + } + + T * + get() const noexcept + { + return ptr; + } + + T & + operator*() const noexcept + { + return *ptr; + } + + [[nodiscard]] + T & + operator[](std::unsigned_integral auto index) const noexcept + { + return ptr[index]; + } + + T * + operator->() const noexcept + { + return ptr; + } + + glPointer<T> & + operator++() noexcept + { + ++ptr; + return *this; + } + + glPointer<T> & + operator--() noexcept + { + --ptr; + return *this; + } + + [[nodiscard]] glPointer<T> + operator+(std::integral auto offset) const noexcept + { + return {ptr + offset, name}; + } + + [[nodiscard]] glPointer<T> + operator-(std::integral auto offset) const noexcept + { + return {ptr - offset, name}; + } + + [[nodiscard]] glPointer<T> + operator+=(std::integral auto offset) const noexcept + { + return {ptr += offset, name}; + } + + [[nodiscard]] glPointer<T> + operator-=(std::integral auto offset) const noexcept + { + return {ptr -= offset, name}; + } + + [[nodiscard]] GLuint + bufferName() const noexcept + { + return name; + } + + private: + T * ptr; + GLuint name; + }; + + std::pair<void *, GLuint> allocateBuffer(size_t count, size_t objSize); + void deallocateBuffer(GLuint name); + + template<typename T> class glAllocator { + public: + // NOLINTBEGIN(readability-identifier-naming) - STL like + using pointer = glPointer<T>; + using const_pointer = glPointer<const T>; + using value_type = T; + + // NOLINTEND(readability-identifier-naming) + + pointer + allocate(size_t count) + { + auto allocated = allocateBuffer(count, sizeof(T)); + return {static_cast<T *>(allocated.first), allocated.second}; + } + +#if (__cpp_lib_allocate_at_least >= 202302L) + std::allocation_result<pointer> + allocate_at_least(size_t count) + { + count = std::min(count, 32ZU); + return {allocate(count), count}; + } +#endif + + void + deallocate(pointer ptr, size_t) + { + deallocateBuffer(ptr.bufferName()); + } + + using is_always_equal = std::true_type; + }; +} + +template<typename T> struct std::iterator_traits<Detail::glPointer<T>> { + using iterator_category = std::random_access_iterator_tag; + using iterator_concept = std::contiguous_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using reference = T &; + using pointer = T *; +}; + +template<typename T> +// NOLINTNEXTLINE(readability-identifier-naming) - OpenGL like +using glVector = std::vector<T, typename std::allocator_traits<Detail::glAllocator<T>>::allocator_type>; |
