19#ifndef FENNEC_RENDERERS_OPENGL_LIB_BUFFER_H
20#define FENNEC_RENDERERS_OPENGL_LIB_BUFFER_H
23#include <fennec/renderers/opengl/lib/fwd.h>
24#include <fennec/renderers/opengl/lib/enum.h>
32template<GLbitfield FlagsV, GL
boolean ImmutableV>
using vertex_buffer = buffer<VERTEX, FlagsV, ImmutableV>;
33template<GLbitfield FlagsV, GL
boolean ImmutableV>
using element_buffer = buffer<ELEMENT, FlagsV, ImmutableV>;
34template<GLbitfield FlagsV, GL
boolean ImmutableV>
using uniform_buffer = buffer<UNIFORM, FlagsV, ImmutableV>;
35template<GLbitfield FlagsV, GL
boolean ImmutableV>
using shader_storage_buffer = buffer<SHADER_STORAGE, FlagsV, ImmutableV>;
36template<GLbitfield FlagsV, GL
boolean ImmutableV>
using query_buffer = buffer<QUERY, FlagsV, ImmutableV>;
37template<GLbitfield FlagsV, GL
boolean ImmutableV>
using texture_buffer = buffer<TEXTURE, FlagsV, ImmutableV>;
38template<GLbitfield FlagsV, GL
boolean ImmutableV>
using transform_feedback_buffer = buffer<TRANSFORM_FEEDBACK, FlagsV, ImmutableV>;
39template<GLbitfield FlagsV, GL
boolean ImmutableV>
using atomic_counter_buffer = buffer<ATOMIC_COUNTER, FlagsV, ImmutableV>;
40template<GLbitfield FlagsV, GL
boolean ImmutableV>
using parameter_buffer = buffer<PARAMETER, FlagsV, ImmutableV>;
41template<GLbitfield FlagsV, GL
boolean ImmutableV>
using indirect_draw_buffer = buffer<INDIRECT_DRAW, FlagsV, ImmutableV>;
42template<GLbitfield FlagsV, GL
boolean ImmutableV>
using indirect_dispatch_buffer = buffer<INDIRECT_DISPATCH, FlagsV, ImmutableV>;
43template<GLbitfield FlagsV, GL
boolean ImmutableV>
using copy_read_buffer = buffer<COPY_READ, FlagsV, ImmutableV>;
44template<GLbitfield FlagsV, GL
boolean ImmutableV>
using copy_write_buffer = buffer<COPY_WRITE, FlagsV, ImmutableV>;
45template<GLbitfield FlagsV, GL
boolean ImmutableV>
using pixel_pack_buffer = buffer<PIXEL_PACK, FlagsV, ImmutableV>;
46template<GLbitfield FlagsV, GL
boolean ImmutableV>
using pixel_unpack_buffer = buffer<PIXEL_UNPACK, FlagsV, ImmutableV>;
48template<GLenum TypeV, GLbitfield FlagsV, GL
boolean ImmutableV>
54 static constexpr GLenum get_mutable_traits() {
58 if constexpr (map_read) {
60 }
else if constexpr (map_write) {
67 if constexpr (client or coherent) {
69 }
else if constexpr (dynamic or persistent) {
82 static constexpr GLenum type = TypeV;
83 static constexpr GLboolean immutable = ImmutableV;
84 static constexpr GLbitfield flags = FlagsV;
85 static constexpr GLboolean indexed = type == ATOMIC_COUNTER or type == SHADER_STORAGE or type == TRANSFORM_FEEDBACK or type == UNIFORM;
86 static constexpr GLboolean map_read = flags & READ;
87 static constexpr GLboolean map_write = flags & WRITE;
88 static constexpr GLboolean mapped = map_read or map_write;
89 static constexpr GLboolean dynamic = flags & DYNAMIC;
90 static constexpr GLboolean persistent = flags & PERSISTENT;
91 static constexpr GLboolean coherent = flags & COHERENT;
92 static constexpr GLboolean client = flags & CLIENT;
93 static constexpr GLenum usage = get_mutable_traits();
95 static_assert(not persistent or persistent == mapped);
96 static_assert(not coherent or coherent == persistent);
101 constexpr buffer(
const void* data, GLsizeiptr size)
104 glGenBuffers(1, &_handle);
106 if constexpr(immutable) {
107 glBufferStorage(type, _size, data, flags);
109 glBufferData(type, _size, data, usage);
113 constexpr buffer(buffer&& buff) noexcept
116 , _mapping(
nullptr) {
119 constexpr buffer& operator=(buffer&& buff)
noexcept {
120 glDeleteBuffers(1, &_handle);
121 _handle = buff._handle;
126 constexpr buffer(
const buffer&) =
delete;
127 constexpr buffer& operator=(
const buffer&) =
delete;
132 constexpr void start()
const {
133 glBindBuffer(type, _handle);
136 constexpr void end()
const {
137 glBindBuffer(type, NULL);
140 constexpr void bind(GLuint i, GLsizeiptr size = -1, GLintptr offset = 0) {
141 offset =
max(offset, GLintptr(0));
142 size = size < 0 ? _size : size;
143 size =
min(size, _size - offset);
144 if (size <= 0)
return;
145 glBindBufferRange(type, i, _handle, offset, size);
151 constexpr void resize(GLsizei size)
requires not immutable {
153 glBufferData(type, _size = size,
nullptr, usage);
156 constexpr void* map(GLbitfield access, GLsizeiptr size, GLintptr offset = 0) {
160 offset =
max(offset, GLintptr(0));
161 size = size < 0 ? _size : size;
162 size =
min(size, _size - offset);
163 if (size <= 0)
return nullptr;
164 return _mapping = glMapBufferRange(type, offset, size, _mapflags = access);
167 constexpr void unmap() {
172 constexpr void clear(GLsizeiptr size = -1, GLintptr offset = 0,
const void* data =
nullptr, GLenum data_type = BYTE, GLenum format = R, GLenum internal = R8) {
173 offset =
max(offset, GLintptr(0));
174 size = size < 0 ? _size : size;
175 size =
min(size, _size - offset);
176 if (size <= 0)
return;
177 glClearBufferSubData(type, internal, offset, size, format, type, data);
180 template<GLenum OTypeV, GLbitfield OFlagsV, GL
boolean OImmutableV>
181 constexpr void copy(
const buffer<OTypeV, OFlagsV, OImmutableV>& cpy, GLsizeiptr size = -1, GLintptr write_offset = 0, GLintptr read_offset = 0) {
182 write_offset =
max(write_offset, GLintptr(0));
183 read_offset =
max(read_offset, GLintptr(0));
184 size = size < 0 ? _size : size;
187 if (size <= 0)
return;
188 glBindBuffer(COPY_READ, cpy._handle);
189 glBindBuffer(COPY_WRITE, _handle);
190 glCopyBufferSubData(COPY_READ, COPY_WRITE, read_offset, write_offset, size);
191 glBindBuffer(COPY_READ, NULL);
192 glBindBuffer(COPY_WRITE, NULL);
195 constexpr void read(
void* data, GLsizeiptr size, GLintptr offset = 0)
const {
196 static_assert(dynamic or persistent and not (client or coherent));
197 offset =
max(offset, GLintptr(0));
198 size = size < 0 ? _size : size;
199 size =
min(size, _size - offset);
200 if (size <= 0)
return;
201 glGetBufferSubData(type, offset, size, data);
204 constexpr void write(
const void* data, GLsizeiptr size, GLintptr offset = 0) {
205 static_assert(dynamic or persistent and not (client or coherent));
206 offset =
max(offset, GLintptr(0));
207 size = size < 0 ? _size : size;
208 size =
min(size, _size - offset);
209 if (size <= 0)
return;
210 glBufferSubData(type, offset, size, data);
213 constexpr void flush(GLsizeiptr size = -1, GLintptr offset = 0) {
214 if (not _mapping)
return;
215 if (not (_mapflags & EXPLICIT_FLUSH))
return;
216 offset =
max(offset, GLintptr(0));
217 size = size < 0 ? _size : size;
218 size =
min(size, _size - offset);
219 if (size <= 0)
return;
220 glFlushMappedBufferRange(type, offset, size);
223 constexpr void invalidate(GLsizeiptr size, GLintptr offset = 0) {
224 offset =
max(offset, GLintptr(0));
225 size = size < 0 ? _size : size;
226 size =
min(size, _size - offset);
227 if (size <= 0)
return;
228 glInvalidateBufferSubData(type, offset, size);
234 template<
typename TypeT>
235 constexpr TypeT* map(GLbitfield access, GLsizeiptr n, GLintptr offset = 0) {
236 return static_cast<TypeT*
>(map(access, n *
sizeof(TypeT), offset *
sizeof(TypeT)));
243 GLbitfield _mapflags;
constexpr genType min(genType x, genType y)
Returns if otherwise it returns .
Definition common.h:688
constexpr genType max(genType x, genType y)
Returns if , otherwise it returns .
Definition common.h:705
constexpr const remove_reference_t< T > & copy(T &&x) noexcept
produces an r-value type to indicate x may be "copied"
Definition utility.h:104