Gamp v0.0.8
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
gamp_gl.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11
12#include <jau/float_types.hpp>
18
19using namespace gamp::render::gl;
20using namespace gamp::render::gl::glsl;
21
22std::atomic<size_t> ShaderCode::m_nextID = 1;
23std::atomic<size_t> ShaderProgram::m_nextID = 1;
24
25bool GLProfile::isValidArrayDataType(GLenum index, GLsizei comps, GLenum type,
26 bool isVertexAttribPointer, bool throwException) const
27{
28 if( isGLES1() ) {
29 if(isVertexAttribPointer) {
30 if(throwException) {
31 throw RenderException("Illegal array type for "+std::string(getGLArrayName(index))+" on profile GLES1: VertexAttribPointer", E_FILE_LINE);
32 }
33 return false;
34 }
35 switch(index) {
36 case GL_VERTEX_ARRAY:
37 case GL_TEXTURE_COORD_ARRAY:
38 switch(type) {
39 case GL_BYTE:
40 case GL_SHORT:
41 case GL_FIXED:
42 case GL_FLOAT:
43 break;
44 default:
45 if(throwException) {
46 throw RenderException("Illegal data type for "+std::string(getGLArrayName(index))+" on profile GLES1: "+jau::toHexString(type), E_FILE_LINE);
47 }
48 return false;
49 }
50 switch(comps) {
51 case 0:
52 case 2:
53 case 3:
54 case 4:
55 break;
56 default:
57 if(throwException) {
58 throw RenderException("Illegal component number for "+std::string(getGLArrayName(index))+" on profile GLES1: "+std::to_string(comps), E_FILE_LINE);
59 }
60 return false;
61 }
62 break;
63 case GL_NORMAL_ARRAY:
64 switch(type) {
65 case GL_BYTE:
66 case GL_SHORT:
67 case GL_FIXED:
68 case GL_FLOAT:
69 break;
70 default:
71 if(throwException) {
72 throw RenderException("Illegal data type for "+std::string(getGLArrayName(index))+" on profile GLES1: "+jau::toHexString(type), E_FILE_LINE);
73 }
74 return false;
75 }
76 switch(comps) {
77 case 0:
78 case 3:
79 break;
80 default:
81 if(throwException) {
82 throw RenderException("Illegal component number for "+std::string(getGLArrayName(index))+" on profile GLES1: "+std::to_string(comps), E_FILE_LINE);
83 }
84 return false;
85 }
86 break;
87 case GL_COLOR_ARRAY:
88 switch(type) {
89 case GL_UNSIGNED_BYTE:
90 case GL_FIXED:
91 case GL_FLOAT:
92 break;
93 default:
94 if(throwException) {
95 throw RenderException("Illegal data type for "+std::string(getGLArrayName(index))+" on profile GLES1: "+jau::toHexString(type), E_FILE_LINE);
96 }
97 return false;
98 }
99 switch(comps) {
100 case 0:
101 case 4:
102 break;
103 default:
104 if(throwException) {
105 throw RenderException("Illegal component number for "+std::string(getGLArrayName(index))+" on profile GLES1: "+std::to_string(comps), E_FILE_LINE);
106 }
107 return false;
108 }
109 break;
110 default: break;
111 }
112 } else if( isGLES3() ) {
113 // simply ignore !isVertexAttribPointer case, since it is simulated anyway ..
114 switch(type) {
115 case GL_UNSIGNED_BYTE:
116 case GL_BYTE:
117 case GL_UNSIGNED_SHORT:
118 case GL_SHORT:
119 case GL_INT: // GL2ES2
120 case GL_UNSIGNED_INT:
121 case GL_HALF_FLOAT:
122 case GL_FLOAT:
123 case GL_FIXED:
124 case GL_INT_2_10_10_10_REV: // GL3ES3
125 case GL_UNSIGNED_INT_2_10_10_10_REV: // GL3ES2
126 case GL_UNSIGNED_INT_10F_11F_11F_REV:
127 break;
128 default:
129 if(throwException) {
130 throw RenderException("Illegal data type on profile GLES3: "+jau::toHexString(type), E_FILE_LINE);
131 }
132 return false;
133 }
134 /** unable to validate .. could be any valid type/component combination
135 switch(comps) {
136 case 0:
137 case 1:
138 case 2:
139 case 3:
140 case 4:
141 break;
142 default:
143 if(throwException) {
144 throw GLException("Illegal component number on profile GLES3: "+std::to_string(comps));
145 }
146 return false;
147 } */
148 } else if( isGLES2() ) {
149 // simply ignore !isVertexAttribPointer case, since it is simulated anyway ..
150 switch(type) {
151 case GL_UNSIGNED_BYTE:
152 case GL_BYTE:
153 case GL_UNSIGNED_SHORT:
154 case GL_SHORT:
155 case GL_FLOAT:
156 case GL_FIXED:
157 break;
158 default:
159 if(throwException) {
160 throw RenderException("Illegal data type on profile GLES2: "+jau::toHexString(type), E_FILE_LINE);
161 }
162 return false;
163 }
164 /** unable to validate .. could be any valid type/component combination
165 switch(comps) {
166 case 0:
167 case 1:
168 case 2:
169 case 3:
170 case 4:
171 break;
172 default:
173 if(throwException) {
174 throw GLException("Illegal component number on profile GLES2: "+std::to_string(comps), E_FILE_LINE);
175 }
176 return false;
177 } */
178 } else if( isGL2ES2() ) {
179 if(isVertexAttribPointer) {
180 switch(type) {
181 case GL_UNSIGNED_BYTE:
182 case GL_BYTE:
183 case GL_UNSIGNED_SHORT:
184 case GL_SHORT:
185 case GL_INT: // GL3ES2
186 case GL_UNSIGNED_INT:
187 case GL_HALF_FLOAT:
188 case GL_FLOAT:
189 case GL_FIXED:
190 case GL_INT_2_10_10_10_REV: // GL3ES3
191 case GL_UNSIGNED_INT_2_10_10_10_REV: // GL3ES2
192 case GL_DOUBLE: // GL2GL3
193 case GL_UNSIGNED_INT_10F_11F_11F_REV:
194 break;
195 default:
196 if(throwException) {
197 throw RenderException("Illegal data type on profile GL2: "+jau::toHexString(type), E_FILE_LINE);
198 }
199 return false;
200 }
201 switch(comps) {
202 case 0:
203 case 1:
204 case 2:
205 case 3:
206 case 4:
207 break;
208 default:
209 if(throwException) {
210 throw RenderException("Illegal component number on profile GL2: "+std::to_string(comps), E_FILE_LINE);
211 }
212 return false;
213 }
214 } else {
215 switch(index) {
216 case GL_VERTEX_ARRAY:
217 switch(type) {
218 case GL_SHORT:
219 case GL_FLOAT:
220 case GL_INT: // GL2ES2
221 case GL_DOUBLE: // GL2GL3
222 break;
223 default:
224 if(throwException) {
225 throw RenderException("Illegal data type for "+std::string(getGLArrayName(index))+" on profile GL2: "+jau::toHexString(type), E_FILE_LINE);
226 }
227 return false;
228 }
229 switch(comps) {
230 case 0:
231 case 2:
232 case 3:
233 case 4:
234 break;
235 default:
236 if(throwException) {
237 throw RenderException("Illegal component number for "+std::string(getGLArrayName(index))+" on profile GL2: "+std::to_string(comps), E_FILE_LINE);
238 }
239 return false;
240 }
241 break;
242 case GL_NORMAL_ARRAY:
243 switch(type) {
244 case GL_BYTE:
245 case GL_SHORT:
246 case GL_FLOAT:
247 case GL_INT: // GL2ES2
248 case GL_DOUBLE: // GL2GL3
249 break;
250 default:
251 if(throwException) {
252 throw RenderException("Illegal data type for "+std::string(getGLArrayName(index))+" on profile GL2: "+jau::toHexString(type), E_FILE_LINE);
253 }
254 return false;
255 }
256 switch(comps) {
257 case 0:
258 case 3:
259 break;
260 default:
261 if(throwException) {
262 throw RenderException("Illegal component number for "+std::string(getGLArrayName(index))+" on profile GLES1: "+std::to_string(comps), E_FILE_LINE);
263 }
264 return false;
265 }
266 break;
267 case GL_COLOR_ARRAY:
268 switch(type) {
269 case GL_UNSIGNED_BYTE:
270 case GL_BYTE:
271 case GL_UNSIGNED_SHORT:
272 case GL_SHORT:
273 case GL_FLOAT:
274 case GL_INT: // GL2ES2
275 case GL_UNSIGNED_INT:
276 case GL_DOUBLE: // GL2GL3
277 break;
278 default:
279 if(throwException) {
280 throw RenderException("Illegal data type for "+std::string(getGLArrayName(index))+" on profile GL2: "+jau::toHexString(type), E_FILE_LINE);
281 }
282 return false;
283 }
284 switch(comps) {
285 case 0:
286 case 3:
287 case 4:
288 break;
289 default:
290 if(throwException) {
291 throw RenderException("Illegal component number for "+std::string(getGLArrayName(index))+" on profile GL2: "+std::to_string(comps), E_FILE_LINE);
292 }
293 return false;
294 }
295 break;
296 case GL_TEXTURE_COORD_ARRAY:
297 switch(type) {
298 case GL_SHORT:
299 case GL_FLOAT:
300 case GL_INT: // GL2ES2
301 case GL_DOUBLE: // GL2GL3
302 break;
303 default:
304 if(throwException) {
305 throw RenderException("Illegal data type for "+std::string(getGLArrayName(index))+" on profile GL2: "+jau::toHexString(type), E_FILE_LINE);
306 }
307 return false;
308 }
309 switch(comps) {
310 case 0:
311 case 1:
312 case 2:
313 case 3:
314 case 4:
315 break;
316 default:
317 if(throwException) {
318 throw RenderException("Illegal component number for "+std::string(getGLArrayName(index))+" on profile GL2: "+std::to_string(comps), E_FILE_LINE);
319 }
320 return false;
321 }
322 break;
323 default: break;
324 }
325 }
326 }
327 return true;
328}
329
330bool gamp::render::gl::data::GLUniformData::resolveLocation(const GL&, GLuint program) noexcept {
331 if( isBuffer() ) {
332 m_bufferIndex = ::glGetUniformBlockIndex(program, string_t(m_name).c_str());
333 if (m_bufferIndex == GL_INVALID_INDEX) {
334 return false;
335 }
336 if( 0 == m_bufferName ) {
337 // buffer init once
338 ::glGenBuffers(1, &m_bufferName);
339 if( 0 == bufferName() ) {
340 return false;
341 }
342 ::glBindBuffer(GL_UNIFORM_BUFFER, bufferName());
343 ::glBufferData(GL_UNIFORM_BUFFER, bufferSize(), nullptr, GL_STREAM_DRAW);
344 ::glBindBuffer(GL_UNIFORM_BUFFER, 0);
345
346 ::glUniformBlockBinding(program, m_bufferIndex, m_bufferGlobalBinding); // per program/index
347
348 // only once
349 ::glBindBufferBase(GL_UNIFORM_BLOCK_BINDING, m_bufferGlobalBinding, bufferName());
350 } else {
351 ::glUniformBlockBinding(program, m_bufferIndex, m_bufferGlobalBinding); // per program/index
352 }
353 return true;
354 } else {
355 m_location = ::glGetUniformLocation(program, string_t(m_name).c_str());
356 return m_location >= 0;
357 }
358}
359bool gamp::render::gl::data::GLUniformData::sendSub(const GL&, GLintptr offset, GLsizeiptr size) noexcept {
360 if( !hasLocation() || !isBuffer() || 0 == bufferName() || offset+size > bufferSize()) {
361 return false;
362 }
363 ::glBindBuffer(GL_UNIFORM_BUFFER, bufferName());
364 ::glBufferSubData(GL_UNIFORM_BUFFER, offset, size, reinterpret_cast<const uint8_t*>(data())+offset);
365 ::glBindBuffer(GL_UNIFORM_BUFFER, 0);
366 return true;
367}
368
370 if( !hasLocation() ) { return false; }
371 if( isBuffer() ) {
372 if( 0 == bufferName() || 0 == bufferSize() ) {
373 return false;
374 }
375 ::glBindBuffer(GL_UNIFORM_BUFFER, bufferName());
376 ::glBufferSubData(GL_UNIFORM_BUFFER, 0, bufferSize(), data());
377 ::glBindBuffer(GL_UNIFORM_BUFFER, 0);
378 } else if( columns() > 1 ) {
379 if( rows() > 1 ) {
381 return false;
382 }
383 switch( columns() ) {
384 case 2: ::glUniformMatrix2fv(location(), count(), false, reinterpret_cast<const GLfloat*>(data())); break;
385 case 3: ::glUniformMatrix3fv(location(), count(), false, reinterpret_cast<const GLfloat*>(data())); break;
386 case 4: ::glUniformMatrix4fv(location(), count(), false, reinterpret_cast<const GLfloat*>(data())); break;
387 default: return false;
388 }
389 } else {
391 switch( components() ) {
392 case 1: ::glUniform1fv(location(), count(), reinterpret_cast<const GLfloat*>(data())); break;
393 case 2: ::glUniform2fv(location(), count(), reinterpret_cast<const GLfloat*>(data())); break;
394 case 3: ::glUniform3fv(location(), count(), reinterpret_cast<const GLfloat*>(data())); break;
395 case 4: ::glUniform4fv(location(), count(), reinterpret_cast<const GLfloat*>(data())); break;
396 default: return false;
397 }
398 } else if( compSignature() == jau::int_ctti::i32() ) {
399 switch( components() ) {
400 case 1: ::glUniform1iv(location(), count(), reinterpret_cast<const GLint*>(data())); break;
401 case 2: ::glUniform2iv(location(), count(), reinterpret_cast<const GLint*>(data())); break;
402 case 3: ::glUniform3iv(location(), count(), reinterpret_cast<const GLint*>(data())); break;
403 case 4: ::glUniform4iv(location(), count(), reinterpret_cast<const GLint*>(data())); break;
404 default: return false;
405 }
406 } else {
407 return false;
408 }
409 }
410 } else {
411 if( compSignature() == jau::int_ctti::i32() ) {
412 ::glUniform1i(location(), *reinterpret_cast<const GLint*>(data()));
413 } else if( compSignature() == jau::float_ctti::f32() ) {
414 ::glUniform1f(location(), *reinterpret_cast<const GLfloat*>(data()));
415 } else {
416 return false;
417 }
418 }
419 return true;
420}
constexpr bool isGLES1() const noexcept
Indicates whether this profile is capable of GLES1.
bool isValidArrayDataType(GLenum index, GLsizei comps, GLenum type, bool isVertexAttribPointer, bool throwException) const
General validation if index, comps and type are valid for the current profile.
Definition gamp_gl.cpp:25
constexpr bool isGLES2() const noexcept
Indicates whether this profile is capable of GLES2.
constexpr bool isGLES3() const noexcept
Indicates whether this profile is capable of GLES3.
constexpr bool isGL2ES2() const noexcept
Indicates whether this profile is capable of GL2ES2.
constexpr GLint location() const noexcept
Returns the uniform's location, -1 if no location has been retrieved or set or if isBuffer()
constexpr GLsizeiptr bufferSize() const noexcept
virtual const void * data() const noexcept=0
Return the underlying data buffer pointer.
constexpr GLsizei columns() const noexcept
Returns column count, i.e.
constexpr GLsizei count() const noexcept
Returns element count.
bool hasLocation() const noexcept
Returns true if buffer index or location is valid, otherwise false.
constexpr GLsizei components() const noexcept
Returns component count per element, i.e.
bool sendSub(const GL &gl, GLintptr offset, GLsizeiptr size) noexcept
Sends a subset of the uniform buffer to the GPU, specialization must have passed bufferSignature() fo...
Definition gamp_gl.cpp:359
constexpr GLsizei rows() const noexcept
Returns row count, i.e.
constexpr bool isBuffer() const noexcept
Returns true if instance refers to a uniform buffer object.
const jau::type_info & compSignature() const noexcept
Returns type signature of implementing class's stored component value type.
constexpr GLuint bufferName() const noexcept
bool resolveLocation(const GL &, GLuint program) noexcept
Retrieves the location or buffer-index of the shader uniform (buffer) with getName() from the linked ...
Definition gamp_gl.cpp:330
bool send(const GL &gl) noexcept
Sends the uniform data to the GPU, i.e.
Definition gamp_gl.cpp:369
static const jau::type_info & f32()
jau::float_32_t or just float
static const jau::type_info & i32()
int32_t
#define E_FILE_LINE
constexpr std::string_view getGLArrayName(GLenum array) noexcept
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.