NDEVR
API Documentation
GLBuffer.h
1#pragma once
2#include "../Headers/GLESGraphicsDevice.h"
3#include <NDEVR/GraphicsBuffer.h>
4#include <NDEVR/GraphicsException.h>
5#include <NDEVR/Translator.h>
6#include <QOpenGLFunctions>
7namespace NDEVR
8{
15 {
16 public:
22 , m_context(device)
23 {
24 //m_context->glGenBuffers(1, &m_buffer);
25 }
26
29 OpenGLBuffer(const TableColumn& reference_data, const DynamicPointer<GLESGraphicsDevice>& device)
30 : GraphicsBuffer(reference_data.label())
31 , m_context(device)
32 {
33 copyData(reference_data, true);
34 }
35
37 OpenGLBuffer(OpenGLBuffer&& other) noexcept
38 : GraphicsBuffer(std::move(other))
39 , m_buffer(other.m_buffer)
40 , m_context(other.m_context)
41 {
42 other.m_buffer = Constant<uint04>::Invalid;
43 }
44
46 {
47 cleanup();
48 }
49
51 virtual void setDefaultValueFrom(const TableColumn&) override {}
56 void* mapMemory(size_t offset, size_t size) const final override
57 {
58 lib_assert(size > 0, "Bad size map");
59 UNUSED(size);
60 if (!m_is_accessable)
61 throw GraphicsException(_t("OpenGL Buffer Error"), _td("opengl_buffer_memory_cannot_map", "Memory [label] Could not be mapped.").replace("label", m_label));
62
63 lib_assert(offset + size <= m_size * type().total_size, "Bad size update");
64 return m_temp_buffer.begin(cast<uint04>(offset));
65 }
66
67 void unmapMemory(size_t, size_t) const final override
68 {
69 //m_context->glBindBuffer(bindLocation(), bufferID());
70 //m_context->glFlushMappedBufferRange(bindLocation(), m_mapped_start, m_mapped_size);
71 //m_context->glUnmapBuffer(bindLocation());
72 }
73
74 void cleanup() final override
75 {
76 if (m_is_memory_owner && IsValid(m_buffer))
77 {
78 m_context->glDeleteBuffers(1, &m_buffer);
79 m_buffer = Constant<uint04>::Invalid;
80 }
82 m_size = 0;
83 }
84
85 void getFromVideoCard(bool) final override
86 {
87 if (!m_is_accessable)
88 {
89 m_is_accessable = true;
90 m_temp_buffer.setSize(cast<uint04>(m_allocated_size * type().total_size));
91 }
92 };
93
94 void sendToVideoCard(bool) final override
95 {
97 {
98 if(IsInvalid(m_buffer))
99 createBuffer(GL_STATIC_DRAW, m_temp_buffer.begin());
100 else
101 setBuffer(GL_STATIC_DRAW, m_temp_buffer.begin());
102 m_temp_buffer.clear();
103 if (m_internal_type != INSTANCE)//keep the instance around as it changes regularly
104 m_temp_buffer.ensureCapacity(0, true, true);
105 m_is_accessable = false;
106 }
107 };
108
110 GLuint getFormat(uint01) const
111 {
112 if (type().is_number)
113 {
114 switch (type().byte_size)
115 {
116 case 1:
117 if (type().is_unsigned) return GL_UNSIGNED_BYTE;
118 else return GL_BYTE;
119 case 2:
120 if (type().is_float) return GL_SHORT;
121 if (type().is_unsigned) return GL_UNSIGNED_SHORT;
122 else return GL_SHORT;
123 case 4:
124 if (type().is_float) return GL_FLOAT;
125 if (type().is_unsigned) return GL_UNSIGNED_INT;
126 else return GL_INT;
127 #ifdef GL_DOUBLE
128 case 8:
129 if (type().is_float) return GL_DOUBLE;
130 break;
131 #endif
132 case 16:
133 if (type().is_float) return GL_FLOAT;
134 break;
135 default:
136 break;
137 }
138 }
139 else if (type().is_color)
140 {
141 return GL_UNSIGNED_BYTE;
142 }
143 lib_assert(false, "unknown vulkanbuffer format");
144 return GL_INT;
145 };
146
149 {
150 //if (type().is_color)
151 //return 4;
152 switch (type().byte_size)
153 {
154 case 1: return 1;
155 case 2: return 2;
156 case 4: return 4;
157 case 8: return 8;
158 case 16: return 4;
159 default:
160 lib_assert(false, "unknown vulkanbuffer format");
161 break;
162 }
163 return 1;
164 };
165
167 GLint vectorSize() const
168 {
169 if (type().byte_size == 16)
170 return 4;//we are a 4x4 matrix
171 return cast<GLint>(getMax<uint02>(1U, type().vector_size));
172 };
173
175 GLuint getFormat() const
176 {
177 return getFormat(0);
178 }
179
180 void insertRows(uint04, uint04) final override
181 {
182 lib_assert(false, "Not yet implemented");
183 };
184
186 void setSize(uint04 buffer_size) final override
187 {
188 if (m_size == buffer_size)
189 return;
190 lib_assert(m_is_accessable, "Should only be called when accessable");
191 m_temp_buffer.setSize(buffer_size * type().total_size);
192 m_size = buffer_size;
193 m_allocated_size = buffer_size;
194 }
195
199 void updateRegion(const TableColumn& reference_data, uint04 offset, uint04 size) final override
200 {
201 if (m_is_accessable)
202 {
203 void* data = mapMemory(cast<size_t>(offset) * type().total_size, size * type().total_size);
204 if (reference_data.type() == type())
205 {
206 memcpy((uint01*)data, (uint01*)reference_data.begin() + (cast<size_t>(offset) * type().total_size), size * type().total_size);
207 }
208 else
209 {
210 lib_assert(false, "Not yet implimented");
211 }
212 }
213 else
214 {
215 setSubBuffer(offset, size, (uint01*)reference_data.begin() + (cast<size_t>(offset) * type().total_size));
216 }
217 }
218
221 void copyData(const TableColumn& reference_data, bool set_type) final override
222 {
223
224 if (set_type && m_type != reference_data.type())
225 {
226 cleanup();
227 setType(reference_data.type());
228 }
229 setSize(reference_data.size());
230 updateRegion(reference_data, 0, reference_data.size());
231 m_modified_time = reference_data.getModifiedTime();
232 }
233
235 GLuint bufferID() const
236 {
237 lib_assert(IsValid(m_buffer), "Bad buffer");
238 return m_buffer;
239 }
240
241 void bind()
242 {
243 m_context->glBindBuffer(bindLocation(), bufferID());
244 }
245
248 void bind(uint04 offset, uint04 size)
249 {
250 lib_assert(offset + size <= this->size(), "invalid bind location");
251 m_context->glBindBufferRange(bindLocation(), 0, bufferID(), type().total_size * offset, type().total_size * size);
252 }
253
259 void setAttributeRange(GLint attribute, uint04 buffer_start, uint04 buffer_size, uint04 offset = 0, uint04 stride = Constant<uint04>::Invalid)
260 {
261 if (IsInvalid(stride))
262 stride = vectorSize();
263 size_t loc = offset * typeStride();
264 GLsizei gl_stride = cast<GLsizei>(stride * typeStride());
265 bind(buffer_start, buffer_size);
266 setRawAttribute(attribute, vectorSize(), getFormat(), gl_stride, loc);
267 }
268
272 void setAttribute(GLint attribute, uint04 offset = 0, uint04 stride = Constant<uint04>::Invalid)
273 {
274 if (IsInvalid(stride))
275 stride = vectorSize();
276 size_t loc = offset * typeStride();
277 GLsizei gl_stride = cast<GLsizei>(stride * typeStride());
278 bind();
279 setRawAttribute(attribute, vectorSize(), getFormat(), gl_stride, loc);
280 }
281
287 void setRawAttribute(GLint attribute, uint04 vector_size, GLuint format, GLsizei stride, size_t offset)
288 {
289 lib_assert(!m_is_accessable, "Buffer not setup");
290 m_context->glEnableVertexAttribArray(attribute);
291 switch (format)
292 {
293 case GL_FLOAT:
294#ifdef GL_DOUBLE
295 case GL_DOUBLE:
296#endif
297 m_context->glVertexAttribPointer(attribute, vector_size, format, GL_FALSE, stride, (void*)offset);
298 break;
299 default:
300 {
301 /*
302 #define GL_UNSIGNED_BYTE 5121
303 #define GL_SHORT 5122
304 #define GL_UNSIGNED_SHORT 5123
305 #define GL_INT 5124
306 #define GL_UINT 5125
307 */
308 if (type().is_color)
309 m_context->glVertexAttribPointer(attribute, vector_size, format, GL_TRUE, stride, (void*)offset);
310 else if(m_internal_type == Type::VERTEX && type().byte_size < 4)
311 m_context->glVertexAttribPointer(attribute, vector_size, format, GL_FALSE, stride, (void*)offset);
312 else
313 m_context->glVertexAttribIPointer(attribute, vector_size, format, stride, (void*)offset);
314 } break;
315 }
317 m_context->glVertexAttribDivisor(attribute, 1);
318 release();
319 }
322 GLuint bindLocation() const
323 {
324 switch (m_internal_type)
325 {
326 case Type::INDEX: return GL_ELEMENT_ARRAY_BUFFER; break;
327 case Type::INSTANCE: return GL_ARRAY_BUFFER; break;
328 case Type::VERTEX: return GL_ARRAY_BUFFER; break;
329 #ifdef GL_UNIFORM_BUFFER
330 case Type::UNIFORM: return GL_UNIFORM_BUFFER; break;
331 #endif
332 default: lib_assert(false, "unknown type"); break;
333 }
334 return GL_ARRAY_BUFFER;
335 }
336
337 void release()
338 {
339 m_context->glBindBuffer(bindLocation(), 0);
340 }
341 private:
345 void createBuffer(GLuint usage, const void* data)
346 {
347 lib_assert(size() > 0, "Bad buffer size");
348 lib_assert(IsInvalid(m_buffer), "Bad buffer generation");
349 m_buffer = 0;
350 m_context->glGenBuffers(1, &m_buffer);
351 setBuffer(usage, data);
352 }
356 void setBuffer(GLuint usage, const void* data)
357 {
358 lib_assert(m_buffer != 0, "Bad buffer allocation");
359 m_context->glBindBuffer(bindLocation(), m_buffer);
360 m_context->glBufferData(bindLocation(), size() * type().total_size, data, usage);
361 }
366 void setSubBuffer(uint04 offset, uint04 size, const void* data)
367 {
368 lib_assert(m_buffer != 0, "Bad buffer allocation");
369 m_context->glBindBuffer(bindLocation(), m_buffer);
370 m_context->glBufferSubData(bindLocation(), offset * type().total_size, size * type().total_size, data);
371 }
372 GLuint m_buffer = Constant<uint04>::Invalid;
373 DynamicPointer<GLESGraphicsDevice> m_context;
374 Buffer<uint01> m_temp_buffer;
375 };
376}
Provides a modifiable pointer that has shared ownership of a dynamically allocated object.
Definition Pointer.hpp:356
uint08 m_size
Current number of elements in the buffer.
GraphicsBuffer(const StringView &label)
Constructs a graphics buffer with the given label.
uint08 m_allocated_size
Allocated capacity in elements.
Type m_internal_type
Video card usage type.
bool m_is_memory_owner
Whether this buffer owns the underlying memory.
virtual TypeInfo type() const override
Returns the type information for this buffer.
bool m_is_accessable
Whether the buffer is CPU-accessible.
uint04 size() const final override
Returns the number of rows in this column.
@ INDEX
Index data for indexed drawing.
@ VERTEX
Vertex attribute data.
@ INSTANCE
Per-instance attribute data.
@ UNIFORM
Uniform (constant) data.
void setType(const TypeInfo &type)
Sets the element type for this buffer.
TypeInfo m_type
Element type information.
A common exeption thrown when an issue occurs within the NDEVR Graphics Engine.
void setAttribute(GLint attribute, uint04 offset=0, uint04 stride=Constant< uint04 >::Invalid)
Sets a vertex attribute pointer for the entire buffer.
Definition GLBuffer.h:272
void bind()
Binds the entire buffer to its target binding point.
Definition GLBuffer.h:241
void * mapMemory(size_t offset, size_t size) const final override
Maps a region of the buffer into CPU-accessible memory.
Definition GLBuffer.h:56
void insertRows(uint04, uint04) final override
Inserts rows into the buffer.
Definition GLBuffer.h:180
~OpenGLBuffer()
Destructor.
Definition GLBuffer.h:45
virtual void setDefaultValueFrom(const TableColumn &) override
No-op for OpenGL buffers.
Definition GLBuffer.h:51
GLint vectorSize() const
Returns the number of components per vertex attribute.
Definition GLBuffer.h:167
void getFromVideoCard(bool) final override
Prepares the buffer for CPU read-back by allocating a temp buffer.
Definition GLBuffer.h:85
void setAttributeRange(GLint attribute, uint04 buffer_start, uint04 buffer_size, uint04 offset=0, uint04 stride=Constant< uint04 >::Invalid)
Sets a vertex attribute pointer for a sub-range of the buffer.
Definition GLBuffer.h:259
GLuint getFormat() const
Returns the OpenGL data type enum for the buffer.
Definition GLBuffer.h:175
void setRawAttribute(GLint attribute, uint04 vector_size, GLuint format, GLsizei stride, size_t offset)
Sets a raw vertex attribute pointer with explicit format parameters.
Definition GLBuffer.h:287
void sendToVideoCard(bool) final override
Uploads the temp buffer data to the GPU.
Definition GLBuffer.h:94
OpenGLBuffer(const TableColumn &reference_data, const DynamicPointer< GLESGraphicsDevice > &device)
Constructs an OpenGLBuffer and copies data from a TableColumn.
Definition GLBuffer.h:29
GLuint bufferID() const
Returns the OpenGL buffer object ID.
Definition GLBuffer.h:235
OpenGLBuffer(OpenGLBuffer &&other) noexcept
Move constructor.
Definition GLBuffer.h:37
uint04 typeStride() const
Returns the byte stride per element component.
Definition GLBuffer.h:148
void release()
Unbinds this buffer from its target binding point.
Definition GLBuffer.h:332
void cleanup() final override
Deletes the GPU buffer and resets internal state.
Definition GLBuffer.h:74
OpenGLBuffer(const StringView &label, const DynamicPointer< GLESGraphicsDevice > &device)
Constructs an empty OpenGLBuffer with the given label.
Definition GLBuffer.h:20
GLuint bindLocation() const
Returns the OpenGL binding target for this buffer type.
Definition GLBuffer.h:317
void setSize(uint04 buffer_size) final override
Resizes the buffer to hold the specified number of elements.
Definition GLBuffer.h:186
void copyData(const TableColumn &reference_data, bool set_type) final override
Copies all data from a TableColumn into this buffer.
Definition GLBuffer.h:221
GLuint getFormat(uint01) const
Returns the OpenGL data type enum for the buffer's element type.
Definition GLBuffer.h:110
void bind(uint04 offset, uint04 size)
Binds a sub-range of the buffer to its target binding point.
Definition GLBuffer.h:248
void unmapMemory(size_t, size_t) const final override
Unmaps previously mapped buffer memory.
Definition GLBuffer.h:67
void updateRegion(const TableColumn &reference_data, uint04 offset, uint04 size) final override
Updates a sub-region of the buffer from a TableColumn.
Definition GLBuffer.h:199
The core String View class for the NDEVR API.
Definition StringView.h:58
A virtual storage type that is used with Table class to store data where the actual mechanism for sto...
Definition TableColumn.h:86
virtual uint04 size() const =0
Returns the number of rows in this column.
String m_label
The display name or identifier for this column.
const String & label() const
Returns the label (name) of this column.
Time m_modified_time
The timestamp of the most recent modification to this column.
The primary namespace for the NDEVR SDK.
constexpr t_type getMax(const t_type &left, const t_type &right)
Finds the max of the given arguments using the > operator The only requirement is that t_type have > ...
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
static constexpr bool IsInvalid(const Angle< t_type > &value)
Checks whether the given Angle holds an invalid value.
Definition Angle.h:388
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408