CSCI441 OpenGL Library 6.1.0.0
CS@Mines CSCI441 Computer Graphics Course Library
Loading...
Searching...
No Matches
ShaderUtils.hpp
Go to the documentation of this file.
1
14#ifndef CSCI441_SHADER_UTILS_HPP
15#define CSCI441_SHADER_UTILS_HPP
16
17#include "constants.h"
18#include "LogUtils.hpp"
19
20#ifdef CSCI441_USE_GLEW
21 #include <GL/glew.h>
22#else
23 #include <glad/gl.h>
24#endif
25
26#include <cstdio>
27#include <cstring>
28#include <fstream>
29#include <string>
30
31//********************************************************************************************************************
32
33namespace CSCI441_INTERNAL::ShaderUtils {
34 inline bool sDEBUG = true;
35
36 // Enables console output
37 [[maybe_unused]] void enableDebugMessages();
38
39 // Disables console output
40 [[maybe_unused]] void disableDebugMessages();
41
42 // Converts a GLenum data type variable to the string name of the associated value
43 // GLenum data type
44 // const char* name of data type
45 const char* GLSL_type_to_string( GLenum type );
46
47 // Converts a GLenum shader type variable to the string name of the associated value
48 // GLenum shader type
49 // const char* name of shader type
50 const char* GL_shader_type_to_string( GLenum type );
51
52 // Converts a GLenum primitive type variable to the string name of the associated value
53 // GLenum primitive type
54 // const char* name of primitive type
55 const char* GL_primitive_type_to_string( GLenum type );
56
57 // Reads the contents of a text file to a character array
58 // const char* filename of shader file to read in
59 // char*& character array to store the contents of the file. Will allocate memory and populate within the function
60 // bool true if file was successfully opened and read. false otherwise
61 bool readTextFromFile( const char* filename, GLchar* &output );
62
63 // Reads the contents of a text file and compiles the associated shader type
64 // const char* filename of shader file to read in
65 // GLenum type of shader file corresponds to
66 // GLuint shader handle if compilation successful. -1 otherwise
67 GLuint compileShader( const char *filename, GLenum shaderType );
68
69 // Prints the shader log for the associated Shader handle
70 void printShaderLog( GLuint shaderHandle );
71
72 // Prints the shader log for the associated Shader Program handle after linking
73 void printProgramLog( GLuint programHandle );
74
75 // Prints the shader log for the associated Shader Program handle
76 void printProgramInfoLog( GLuint programHandle );
77
78 // Prints the shader log for the associated Program Pipeline handle
79 void printProgramPipelineLog( GLuint pipelineHandle );
80
81 // Prints subroutine information from a Shader program
82 // GLuint Shader Program handle to inspect
83 // GLenum Shader Stage to inspect
84 // GLboolean if opening output line should be printed to console
85 GLboolean printSubroutineInfo(GLuint programHandle, GLenum shaderStage, GLboolean printHeader );
86
87 // Uses Shader Program introspection to print contents of Shader Program
88 // GLuint Shader Program handle to inspect
89 // GLboolean if Shader Program contains a vertex shader
90 // GLboolean if Shader Program contains a tessellation control shader
91 // GLboolean if Shader Program contains a tessellation evaluation shader
92 // GLboolean if Shader Program contains a geometry shader
93 // GLboolean if Shader Program contains a fragment shader
94 // GLboolean if Shader Program contains a compute shader
95 // GLboolean if closing output line should be printed to console (defaults to true)
96 void printShaderProgramInfo( GLuint programHandle,
97 GLboolean hasVertexShader,
98 GLboolean hasTessControlShader, GLboolean hasTessEvalShader,
99 GLboolean hasGeometryShader,
100 GLboolean hasFragmentShader,
101 GLboolean hasComputeShader,
102 GLboolean useLastNewLine );
103}
104
105//********************************************************************************************************************
106
107[[maybe_unused]]
108inline void CSCI441_INTERNAL::ShaderUtils::enableDebugMessages() {
109 sDEBUG = true;
110}
111
112[[maybe_unused]]
113inline void CSCI441_INTERNAL::ShaderUtils::disableDebugMessages() {
114 sDEBUG = false;
115}
116
117//********************************************************************************************************************
118
119inline bool CSCI441_INTERNAL::ShaderUtils::readTextFromFile(
120 const char *filename,
121 GLchar* &output
122){
123 std::string buf = std::string("");
124 std::string line;
125
126 std::ifstream in(filename);
127 if( !in.is_open() ) {
128 CSCI441::LogUtils::logError("[ERROR]: Could not open file %s\n", filename );
129 return false;
130 }
131 while( std::getline(in, line) ) {
132 buf += line + "\n";
133 }
134
135 output = new GLchar[buf.length()+1];
136 strncpy(output, buf.c_str(), buf.length());
137 output[buf.length()] = '\0';
138
139 in.close();
140
141 return true;
142}
143
144inline const char* CSCI441_INTERNAL::ShaderUtils::GLSL_type_to_string(
145 const GLenum type
146) {
147 switch(type) {
148 case GL_FLOAT: return "float";
149 case GL_FLOAT_VEC2: return "vec2";
150 case GL_FLOAT_VEC3: return "vec3";
151 case GL_FLOAT_VEC4: return "vec4";
152 case GL_DOUBLE: return "double";
153 case GL_DOUBLE_VEC2: return "dvec2";
154 case GL_DOUBLE_VEC3: return "dvec3";
155 case GL_DOUBLE_VEC4: return "dvec4";
156 case GL_INT: return "int";
157 case GL_INT_VEC2: return "ivec2";
158 case GL_INT_VEC3: return "ivec3";
159 case GL_INT_VEC4: return "ivec4";
160 case GL_UNSIGNED_INT: return "unsigned int";
161 case GL_UNSIGNED_INT_VEC2: return "uvec2";
162 case GL_UNSIGNED_INT_VEC3: return "uvec3";
163 case GL_UNSIGNED_INT_VEC4: return "uvec4";
164 case GL_BOOL: return "bool";
165 case GL_BOOL_VEC2: return "bvec2";
166 case GL_BOOL_VEC3: return "bvec3";
167 case GL_BOOL_VEC4: return "bvec4";
168 case GL_FLOAT_MAT2: return "mat2";
169 case GL_FLOAT_MAT3: return "mat3";
170 case GL_FLOAT_MAT4: return "mat4";
171 case GL_FLOAT_MAT2x3: return "mat2x3";
172 case GL_FLOAT_MAT2x4: return "mat2x4";
173 case GL_FLOAT_MAT3x2: return "mat3x2";
174 case GL_FLOAT_MAT3x4: return "mat3x4";
175 case GL_FLOAT_MAT4x2: return "mat4x2";
176 case GL_FLOAT_MAT4x3: return "mat4x3";
177 case GL_DOUBLE_MAT2: return "dmat2";
178 case GL_DOUBLE_MAT3: return "dmat3";
179 case GL_DOUBLE_MAT4: return "dmat4";
180 case GL_DOUBLE_MAT2x3: return "dmat2x3";
181 case GL_DOUBLE_MAT2x4: return "dmat2x4";
182 case GL_DOUBLE_MAT3x2: return "dmat3x2";
183 case GL_DOUBLE_MAT3x4: return "dmat3x4";
184 case GL_DOUBLE_MAT4x2: return "dmat4x2";
185 case GL_DOUBLE_MAT4x3: return "dmat4x3";
186 case GL_SAMPLER_1D: return "sampler1D";
187 case GL_SAMPLER_2D: return "sampler2D";
188 case GL_SAMPLER_3D: return "sampler3D";
189 case GL_SAMPLER_CUBE: return "samplerCube";
190 case GL_SAMPLER_1D_SHADOW: return "sampler1DShadow";
191 case GL_SAMPLER_2D_SHADOW: return "sampler2DShadow";
192 case GL_SAMPLER_1D_ARRAY: return "sampler1DArray";
193 case GL_SAMPLER_2D_ARRAY: return "sampler2DArray";
194 case GL_SAMPLER_2D_MULTISAMPLE: return "sampler2DMS";
195 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return "sampler2DMSArray";
196 case GL_SAMPLER_CUBE_SHADOW: return "samplerCubeShadow";
197 case GL_SAMPLER_BUFFER: return "samplerBuffer";
198 case GL_SAMPLER_2D_RECT: return "sampler2DRect";
199 case GL_SAMPLER_2D_RECT_SHADOW: return "sampler2DRectShadow";
200 case GL_INT_SAMPLER_1D: return "isampler1D";
201 case GL_INT_SAMPLER_2D: return "isampler2D";
202 case GL_INT_SAMPLER_3D: return "isampler3D";
203 case GL_INT_SAMPLER_CUBE: return "isamplerCube";
204 case GL_INT_SAMPLER_1D_ARRAY: return "isampler1DArray";
205 case GL_INT_SAMPLER_2D_ARRAY: return "isampler2DArray";
206 case GL_INT_SAMPLER_2D_MULTISAMPLE: return "isampler2DMS";
207 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return "isampler2DMSArray";
208 case GL_INT_SAMPLER_BUFFER: return "isamplerBuffer";
209 case GL_INT_SAMPLER_2D_RECT: return "isampler2DRect";
210 case GL_UNSIGNED_INT_SAMPLER_1D: return "usampler1D";
211 case GL_UNSIGNED_INT_SAMPLER_2D: return "usampler2D";
212 case GL_UNSIGNED_INT_SAMPLER_3D: return "usampler3D";
213 case GL_UNSIGNED_INT_SAMPLER_CUBE: return "usamplerCube";
214 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return "usampler1DArray";
215 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return "usampler2DArray";
216 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return "usampler2DMS";
217 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return "usampler2DMSArray";
218 case GL_UNSIGNED_INT_SAMPLER_BUFFER: return "usamplerBuffer";
219 case GL_UNSIGNED_INT_SAMPLER_2D_RECT: return "usampler2DRect";
220 case GL_IMAGE_1D: return "image1D";
221 case GL_IMAGE_2D: return "image2D";
222 case GL_IMAGE_3D: return "image3D";
223 case GL_IMAGE_2D_RECT: return "image2DRect";
224 case GL_IMAGE_CUBE: return "imageCube";
225 case GL_IMAGE_BUFFER: return "imageBuffer";
226 case GL_IMAGE_1D_ARRAY: return "image1DArray";
227 case GL_IMAGE_2D_ARRAY: return "image2DArray";
228 case GL_IMAGE_2D_MULTISAMPLE: return "image2DMS";
229 case GL_IMAGE_2D_MULTISAMPLE_ARRAY: return "image2DMSArray";
230 case GL_INT_IMAGE_1D: return "iimage1D";
231 case GL_INT_IMAGE_2D: return "iimage2D";
232 case GL_INT_IMAGE_3D: return "iimage3D";
233 case GL_INT_IMAGE_2D_RECT: return "iimage2DRect";
234 case GL_INT_IMAGE_CUBE: return "iimageCube";
235 case GL_INT_IMAGE_BUFFER: return "iimageBuffer";
236 case GL_INT_IMAGE_1D_ARRAY: return "iimage1DArray";
237 case GL_INT_IMAGE_2D_ARRAY: return "iimage2DArray";
238 case GL_INT_IMAGE_2D_MULTISAMPLE: return "iimage2DMS";
239 case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY: return "iimage2DMSArray";
240 case GL_UNSIGNED_INT_IMAGE_1D: return "uimage1D";
241 case GL_UNSIGNED_INT_IMAGE_2D: return "uimage2D";
242 case GL_UNSIGNED_INT_IMAGE_3D: return "uimage3D";
243 case GL_UNSIGNED_INT_IMAGE_2D_RECT: return "uimage2DRect";
244 case GL_UNSIGNED_INT_IMAGE_CUBE: return "uimageCube";
245 case GL_UNSIGNED_INT_IMAGE_BUFFER: return "uimageBuffer";
246 case GL_UNSIGNED_INT_IMAGE_1D_ARRAY: return "uimage1DArray";
247 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: return "uimage2DArray";
248 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE: return "uimage2DMS";
249 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY: return "uimage2DMSArray";
250 case GL_UNSIGNED_INT_ATOMIC_COUNTER: return "atomic_uint";
251 default: break;
252 }
253 return "other data type";
254}
255
256inline const char* CSCI441_INTERNAL::ShaderUtils::GL_shader_type_to_string(
257 const GLenum type
258) {
259 switch(type) {
260 case GL_VERTEX_SHADER: return "Vertex Shader";
261 case GL_TESS_CONTROL_SHADER: return "Tess Ctrl Shader";
262 case GL_TESS_EVALUATION_SHADER: return "Tess Eval Shader";
263 case GL_GEOMETRY_SHADER: return "Geometry Shader";
264 case GL_FRAGMENT_SHADER: return "Fragment Shader";
265 case GL_COMPUTE_SHADER: return "Compute Shader";
266 default: break;
267 }
268 return "other shader type";
269}
270
271inline const char* CSCI441_INTERNAL::ShaderUtils::GL_primitive_type_to_string(
272 const GLenum type
273) {
274 switch(type) {
275 case GL_POINTS: return "Points";
276 case GL_LINES: return "Lines";
277 case GL_LINE_STRIP: return "Line Strip";
278 case GL_LINE_LOOP: return "Line Loop";
279 case GL_LINES_ADJACENCY: return "Line Adjacency";
280 case GL_TRIANGLES: return "Triangles";
281 case GL_TRIANGLE_STRIP: return "Triangle Strip";
282 case GL_TRIANGLES_ADJACENCY: return "Triangle Adjacency";
283 case GL_PATCHES: return "Patches";
284 default: break;
285 }
286 return "other primitive type";
287}
288
289inline void CSCI441_INTERNAL::ShaderUtils::printShaderLog(
290 const GLuint shaderHandle
291) {
292 // check if the handle is to a vertex/fragment shader
293 if( glIsShader( shaderHandle ) ) {
294 GLint maxLength = 0, status = 0, infoLogLength = 0;
295 glGetShaderiv( shaderHandle, GL_INFO_LOG_LENGTH, &maxLength );
296
297 // create a buffer of designated length
298 const auto infoLog = new GLchar[maxLength];
299
300 glGetShaderiv( shaderHandle, GL_COMPILE_STATUS, &status );
301 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Shader Handle %2d: Compile%-26s |\n", shaderHandle, (status == 1 ? "d Successfully" : "r Error") );
302
303 // get the info log for the vertex/tesselation/geometry/fragment/compute shader
304 glGetShaderInfoLog(shaderHandle, maxLength, &infoLogLength, infoLog );
305
306 if(infoLogLength > 0 ) {
307 // print info to terminal
308 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Shader Handle %d: %s\n", shaderHandle, infoLog );
309 }
310
311 delete[] infoLog;
312 } else {
313 if( sDEBUG ) CSCI441::LogUtils::logError("[WARN]: | Handle %-3d is not for a Shader |\n", shaderHandle );
314 }
315}
316
317inline void CSCI441_INTERNAL::ShaderUtils::printProgramLog(
318 const GLuint programHandle
319) {
320 // check if the handle is to a vertex/fragment shader
321 if( glIsProgram( programHandle ) ) {
322 GLint status = 0;
323 glGetProgramiv( programHandle, GL_LINK_STATUS, &status );
324 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Program Handle %2d: Linke%-28s |\n", programHandle, (status == 1 ? "d Successfully" : "r Error") );
325
326 printProgramInfoLog(programHandle);
327 } else {
328 if( sDEBUG ) CSCI441::LogUtils::logError("[WARN]: | Handle %-3d is not for a Shader Program |\n", programHandle );
329 }
330}
331
332inline void CSCI441_INTERNAL::ShaderUtils::printProgramInfoLog(
333 const GLuint programHandle
334) {
335 // check if the handle is to a vertex/fragment shader
336 if( glIsProgram( programHandle ) ) {
337 GLint maxLength = 0, infoLogLength = 0;
338 glGetProgramiv( programHandle, GL_INFO_LOG_LENGTH, &maxLength );
339
340 // create a buffer of designated length
341 const auto infoLog = new GLchar[maxLength];
342
343 // get the info log for the vertex/tesselation/geometry/fragment/compute shader
344 glGetProgramInfoLog(programHandle, maxLength, &infoLogLength, infoLog );
345
346 if(infoLogLength > 0 ) {
347 // print info to terminal
348 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Program Handle %d: %s\n", programHandle, infoLog );
349 }
350
351 delete[] infoLog;
352 } else {
353 if( sDEBUG ) CSCI441::LogUtils::logError("[WARN]: | Handle %-3d is not for a Shader Program |\n", programHandle );
354 }
355}
356
357inline void CSCI441_INTERNAL::ShaderUtils::printProgramPipelineLog(
358 const GLuint pipelineHandle
359) {
360 // check if the handle is to a shader program pipeline
361 if( glIsProgramPipeline( pipelineHandle ) ) {
362 GLint maxLength = 0, infoLogLength = 0;
363
364 glGetProgramPipelineiv( pipelineHandle, GL_INFO_LOG_LENGTH, &maxLength );
365
366 // create a buffer of designated length
367 const auto infoLog = new GLchar[maxLength];
368
369 // get the info log for the shader program pipeline
370 glGetProgramPipelineInfoLog(pipelineHandle, maxLength, &infoLogLength, infoLog );
371
372 if( infoLogLength > 0 ) {
373 // print info to terminal
374 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Pipeline Handle %d: %s\n", pipelineHandle, infoLog );
375 }
376
377 delete[] infoLog;
378 } else {
379 if( sDEBUG ) CSCI441::LogUtils::logError("[WARN]: | Handle %-3d is not for a Shader Program Pipeline |\n", pipelineHandle );
380 }
381}
382
383inline GLboolean CSCI441_INTERNAL::ShaderUtils::printSubroutineInfo(
384 const GLuint programHandle,
385 const GLenum shaderStage,
386 const GLboolean printHeader
387) {
388 GLint numSubroutineUniforms = 0;
389 glGetProgramStageiv(programHandle, shaderStage, GL_ACTIVE_SUBROUTINE_UNIFORMS, &numSubroutineUniforms);
390 bool headerPrinted = false;
391 if( numSubroutineUniforms > 0 ) {
392 if( printHeader ) {
393 CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
394 headerPrinted = true;
395 }
396 CSCI441::LogUtils::log("[INFO]: | GL_ACTIVE_SUBROUTINE_UNIFORMS (%-15s): %5i |\n", CSCI441_INTERNAL::ShaderUtils::GL_shader_type_to_string(shaderStage), numSubroutineUniforms);
397 for(int i = 0; i < numSubroutineUniforms; i++ ) {
398 GLchar subroutineName[256];
399 GLint max_length = 256, actual_length = 0;
400 GLint numCompatibleSubroutines = 0;
401
402 glGetActiveSubroutineUniformName(programHandle, shaderStage, i, max_length, &actual_length, subroutineName );
403 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_NUM_COMPATIBLE_SUBROUTINES, &numCompatibleSubroutines );
404
405 const auto compatibleSubroutines = new GLint[numCompatibleSubroutines];
406 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_COMPATIBLE_SUBROUTINES, compatibleSubroutines );
407
408 GLint loc = glGetSubroutineUniformLocation(programHandle, shaderStage, subroutineName );
409
410 CSCI441::LogUtils::log("[INFO]: | %i) name: %-15s #subRoutines: %-5i loc: %2i |\n", i, subroutineName, numCompatibleSubroutines, loc );
411
412 for(int j = 0; j < numCompatibleSubroutines; j++ ) {
413 GLint idx = compatibleSubroutines[j];
414
415 GLchar subroutineImplName[64];
416 GLint max_length2 = 64, actual_length2 = 0;
417 glGetActiveSubroutineName(programHandle, shaderStage, idx, max_length2, &actual_length2, subroutineImplName );
418
419 CSCI441::LogUtils::log("[INFO]: | %i) subroutine: %-25s index: %2i |\n", j, subroutineImplName, idx );
420 }
421
422 delete[] compatibleSubroutines;
423 }
424 }
425 return !headerPrinted;
426}
427
428inline void CSCI441_INTERNAL::ShaderUtils::printShaderProgramInfo(
429 const GLuint programHandle,
430 const GLboolean hasVertexShader,
431 const GLboolean hasTessControlShader,
432 const GLboolean hasTessEvalShader,
433 const GLboolean hasGeometryShader,
434 const GLboolean hasFragmentShader,
435 const GLboolean hasComputeShader,
436 const GLboolean useLastNewLine = true
437) {
438 GLint major = 0, minor = 0;
439 glGetIntegerv(GL_MAJOR_VERSION, &major);
440 glGetIntegerv(GL_MINOR_VERSION, &minor);
441
442 GLuint shaders[6] = {0};
443 GLint max_count = 6;
444 GLint actual_count = 0;
445
446 GLint maxAttributeNameLength = 0;
447 GLint maxUniformNameLength = 0;
448
449 // get max var name from program
450 // https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGetActiveAttrib.xhtml
451 glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeNameLength);
452 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformNameLength);
453
454 glGetAttachedShaders(programHandle, max_count, &actual_count, shaders );
455 if(actual_count > 0) {
456 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
457 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | GL_ATTACHED_SHADERS: %33i |\n", actual_count);
458 for(int i = 0; i < actual_count; i++ ) {
459 GLint shaderType;
460 glGetShaderiv( shaders[i], GL_SHADER_TYPE, &shaderType );
461 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | %i) %-38s Handle: %2i |\n", i, GL_shader_type_to_string(shaderType), shaders[i]);
462 }
463 }
464
465 if(sDEBUG) {
466 if(hasGeometryShader) {
467 if( major > 3 || (major >= 3 && minor >= 2) ) {
468 GLint verticesOut = 0, inputType = 0, outputType = 0;
469 glGetProgramiv(programHandle, GL_GEOMETRY_VERTICES_OUT, &verticesOut);
470 glGetProgramiv(programHandle, GL_GEOMETRY_INPUT_TYPE, &inputType);
471 glGetProgramiv(programHandle, GL_GEOMETRY_OUTPUT_TYPE, &outputType);
472
473 CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
474 CSCI441::LogUtils::log("[INFO]: | GEOMETRY SHADER PRIMITIVE I/O |\n");
475 CSCI441::LogUtils::log("[INFO]: | Input Type: %40s |\n", GL_primitive_type_to_string(inputType) );
476 CSCI441::LogUtils::log("[INFO]: | Output Type: %39s |\n", GL_primitive_type_to_string(outputType) );
477 CSCI441::LogUtils::log("[INFO]: | Max Vertices Out: %34d |\n", verticesOut );
478 }
479 }
480 }
481
482 if(hasVertexShader) {
483 GLint numActiveAttributes = 0;
484 glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTES, &numActiveAttributes );
485 if( numActiveAttributes > 0 ) {
486 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
487 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | GL_ACTIVE_ATTRIBUTES: %32i |\n", numActiveAttributes );
488 for( int i = 0; i < numActiveAttributes; i++ ) {
489 const auto name = new GLchar[maxAttributeNameLength];
490 GLint actual_length = 0, size = 0;
491 GLenum type = GL_NONE;
492 glGetActiveAttrib(programHandle, i, maxAttributeNameLength, &actual_length, &size, &type, name );
493 if( size > 1 ) {
494 for( int j = 0; j < size; j++ ) {
495 // length of string + max array value size (technically it depends on the size of GL type, but I'm not aware a way to get the size)
496 // + array accessors + null
497 int max_array_size = actual_length + 4 + 2 + 1;
498 const auto array_name = new GLchar[max_array_size];
499
500 snprintf( array_name, max_array_size, "%s[%i]", name, j );
501 GLint location = glGetAttribLocation(programHandle, array_name);
502 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | %i) type: %-15s name: %-13s loc: %2i |\n", i, GLSL_type_to_string( type ), array_name, location );
503 delete[] array_name;
504 }
505 } else {
506 GLint location = glGetAttribLocation(programHandle, name );
507 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | %i) type: %-15s name: %-13s loc: %2i |\n",i, GLSL_type_to_string( type ), name, location );
508 }
509
510 delete[] name;
511 }
512 }
513 }
514
515 GLint numActiveUniforms = 0;
516 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORMS, &numActiveUniforms);
517 if( numActiveUniforms > 0 ) {
518 constexpr int NUM_PROPS = 6;
519 GLenum props[NUM_PROPS] = {GL_REFERENCED_BY_VERTEX_SHADER,
520 GL_REFERENCED_BY_TESS_CONTROL_SHADER,
521 GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
522 GL_REFERENCED_BY_GEOMETRY_SHADER,
523 GL_REFERENCED_BY_FRAGMENT_SHADER,
524 GL_NONE};
525
526 if((major == 4 && minor >= 3) || major > 4) {
527 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
528 }
529 GLint results[NUM_PROPS] = {0};
530
531 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n" );
532 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | GL_ACTIVE_UNIFORMS: %34i |\n", numActiveUniforms);
533 for(int uIdx = 0; uIdx < numActiveUniforms; uIdx++) {
534 const auto name = new GLchar[maxUniformNameLength];
535 GLint actual_length = 0, size = 0, location = -1;
536 GLenum type = GL_NONE;
537 glGetActiveUniform(programHandle, uIdx, maxUniformNameLength, &actual_length, &size, &type, name );
538 // if a uniform array
539 if(size > 1) {
540 const char* arrayIndexPos = strstr(name, "[");
541 for(int j = 0; j < size; j++) {
542 int max_array_size = actual_length + 4 + 2 + 1;
543 const auto array_name = new GLchar[max_array_size];
544 strncpy(array_name, name, arrayIndexPos - name + 1);
545 array_name[ strlen(name) ] = '\0';
546 strncat(array_name, std::to_string(j).c_str(), std::to_string(j).length());
547 strncat(array_name, "]", 1);
548 location = glGetUniformLocation(programHandle, array_name);
549 if(location != -1) {
550 if (sDEBUG) CSCI441::LogUtils::log("[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), array_name, location);
551 }
552 delete[] array_name;
553 }
554 }
555 // if uniform singleton
556 else {
557 location = glGetUniformLocation(programHandle, name);
558 if(location != -1) {
559 if (sDEBUG) CSCI441::LogUtils::log("[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), name, location);
560 }
561 }
562
563 if(((major == 4 && minor >= 3) || major > 4) && location != -1) {
564 glGetProgramResourceiv(programHandle, GL_UNIFORM, uIdx, NUM_PROPS, props, NUM_PROPS, nullptr, results);
565 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Used in: %-4s %-4s %-4s %-3s %-4s %-4s Shader(s) |\n", (results[0] ? "Vert" : ""), (results[1] ? "Ctrl" : ""), (results[2] ? "Eval" : ""), (results[3] ? "Geo" : ""), (results[4] ? "Frag" : ""), (results[5] ? "Comp" : ""));
566 }
567
568 delete[] name;
569 }
570 }
571
572 GLint numActiveUniformBlocks = 0;
573 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks);
574 if( numActiveUniformBlocks > 0 ) {
575 int vsCount, tcsCount, tesCount, gsCount, fsCount, csCount;
576 vsCount = tcsCount = tesCount = gsCount = fsCount = csCount = 0;
577
578 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
579 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: %20d |\n", numActiveUniformBlocks);
580 for(int i = 0; i < numActiveUniformBlocks; i++ ) {
581 GLint numActiveUniformsInBlock = 0, bindingPoint = 0;
582 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numActiveUniformsInBlock );
583 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_BINDING, &bindingPoint);
584
585 GLint actualLen;
586 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &actualLen);
587 const auto name = new GLchar[actualLen];
588 glGetActiveUniformBlockName(programHandle, i, actualLen, nullptr, name);
589
590 const auto indices = new GLint[numActiveUniformsInBlock];
591 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices);
592
593 const auto offsets = new GLint[numActiveUniformsInBlock];
594 glGetActiveUniformsiv(programHandle, numActiveUniformsInBlock, (GLuint*)indices, GL_UNIFORM_OFFSET, offsets);
595
596 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | %d) %-19s binding: %3d |\n", i, name, bindingPoint);
597
598 GLint vs, tcs, tes, gs, fs, cs;
599 vs = tcs = tes = gs = fs = cs = 0;
600 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &vs); if( vs ) vsCount++;
601 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER, &tcs); if( tcs) tcsCount++;
602 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER, &tes); if( tes) tesCount++;
603 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, &gs); if( gs ) gsCount++;
604 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &fs); if( fs ) fsCount++;
605 if((major == 4 && minor >= 3) || major > 4) {
606 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER, &cs); if( cs ) csCount++;
607 }
608 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Used in: %-4s %-4s %-4s %-3s %-4s %-4s Shader(s) |\n", (vs ? "Vert" : ""), (tcs ? "Ctrl" : ""), (tes ? "Eval" : ""), (gs ? "Geo" : ""), (fs ? "Frag" : ""), (cs ? "Comp" : ""));
609
610 const auto name2 = new char[maxUniformNameLength];
611 for(int j = 0; j < numActiveUniformsInBlock; j++) {
612 GLenum type;
613 int uniSize;
614 glGetActiveUniform(programHandle, indices[j], maxUniformNameLength, &actualLen, &uniSize, &type, name2);
615
616 constexpr GLsizei NUM_ATOMIC_PROPERTIES = 1;
617 GLint atomicIndex[NUM_ATOMIC_PROPERTIES] = {-1};
618 if((major == 4 && minor >= 3) || major > 4) {
619 GLenum atomicProps[NUM_ATOMIC_PROPERTIES] = {GL_ATOMIC_COUNTER_BUFFER_INDEX};
620 glGetProgramResourceiv(programHandle, GL_UNIFORM, indices[j], NUM_ATOMIC_PROPERTIES, atomicProps, NUM_ATOMIC_PROPERTIES, nullptr, atomicIndex);
621 }
622
623 if( atomicIndex[0] == -1 && sDEBUG ) {
624 CSCI441::LogUtils::log("[INFO]: | %2d) type: %-15s name: %-21s |\n", j, GLSL_type_to_string(type), name2);
625 CSCI441::LogUtils::log("[INFO]: | uniform index: %3d offset: %4d |\n", indices[j], offsets[j]);
626 }
627 }
628
629 delete[] name;
630 delete[] indices;
631 delete[] offsets;
632 delete[] name2;
633 }
634
635 if( vsCount + tcsCount + tesCount + gsCount + fsCount + csCount > 0 ) {
636 GLint maxUniBlocks = 0;
637 glGetIntegerv( GL_MAX_COMBINED_UNIFORM_BLOCKS, &maxUniBlocks );
638 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Shader Uniform Block Counts %2d/%2d |\n", numActiveUniformBlocks, maxUniBlocks);
639 if( hasVertexShader ) {
640 GLint maxVertexUniformBlocks = 0;
641 glGetIntegerv( GL_MAX_VERTEX_UNIFORM_BLOCKS, &maxVertexUniformBlocks );
642
643 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Vertex Shader Uniform Blocks: %18d/%2d |\n", vsCount, maxVertexUniformBlocks );
644 }
645 if( hasTessControlShader ) {
646 GLint maxTessControlUniformBlocks = 0;
647 glGetIntegerv( GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, &maxTessControlUniformBlocks );
648
649 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Tess Ctrl Shader Uniform Blocks: %15d/%2d |\n", tcsCount, maxTessControlUniformBlocks );
650 }
651 if( hasTessEvalShader ) {
652 GLint maxTessEvalUniformBlocks = 0;
653 glGetIntegerv( GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, &maxTessEvalUniformBlocks );
654
655 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Tess Eval Shader Uniform Blocks: %15d/%2d |\n", tesCount, maxTessEvalUniformBlocks );
656 }
657 if( hasGeometryShader ) {
658 GLint maxGeometryUniformBlocks = 0;
659 glGetIntegerv( GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &maxGeometryUniformBlocks );
660
661 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Geometry Shader Uniform Blocks: %16d/%2d |\n", gsCount, maxGeometryUniformBlocks );
662 }
663 if( hasFragmentShader ) {
664 GLint maxFragmentUniformBlocks = 0;
665 glGetIntegerv( GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &maxFragmentUniformBlocks );
666
667 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Fragment Shader Uniform Blocks: %16d/%2d |\n", fsCount, maxFragmentUniformBlocks );
668 }
669 if( hasComputeShader ) {
670 GLint maxComputeUniformBlocks = 0;
671 glGetIntegerv( GL_MAX_COMPUTE_UNIFORM_BLOCKS, &maxComputeUniformBlocks );
672
673 if( sDEBUG ) CSCI441::LogUtils::log("[INFO]: | Compute Shader Uniform Blocks: %17d/%2d |\n", csCount, maxComputeUniformBlocks );
674 }
675 }
676 }
677
678 if (sDEBUG) {
679 if ((major == 4 && minor >=3) || major > 4) {
680 GLint numFragOutputs; //Where GL will write the number of outputs
681 glGetProgramInterfaceiv(programHandle, GL_PROGRAM_OUTPUT,GL_ACTIVE_RESOURCES, &numFragOutputs);
682
683 CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
684 CSCI441::LogUtils::log("[INFO]: | GL_PROGRAM_OUTPUT: %35d |\n", numFragOutputs);
685
686 if(numFragOutputs > 0) {
687 GLint maxLen = 0;
688 glGetProgramInterfaceiv(programHandle, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, &maxLen);
689
690 const auto outputName = new GLchar[maxLen];
691
692 //Now you can query for the names and indices of the outputs
693 for (GLint i = 0; i < numFragOutputs; i++) {
694 GLsizei actualLength = 0;
695 glGetProgramResourceName(programHandle, GL_PROGRAM_OUTPUT, i, maxLen, &actualLength, outputName);
696 GLint location = glGetFragDataLocation(programHandle, outputName);
697 GLint index = glGetFragDataIndex(programHandle, outputName);
698 CSCI441::LogUtils::log("[INFO]: | %3d) name: %-18s location: %3d index: %3d |\n", i, outputName, location, index );
699 }
700
701 delete[] outputName;
702 }
703 }
704 }
705
706 if( sDEBUG ) {
707 if((major == 4 && minor >= 3) || major > 4) {
708 GLint numSSBO = 0;
709 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numSSBO);
710 if(numSSBO > 0) {
711 GLint maxLen = 0;
712 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &maxLen);
713 const auto ssboName = new GLchar[maxLen];
714 GLsizei ssboNameLen = 0;
715
716 constexpr int NUM_PROPS = 7;
717 GLenum props[NUM_PROPS] = {GL_BUFFER_BINDING,
718 GL_REFERENCED_BY_VERTEX_SHADER,
719 GL_REFERENCED_BY_TESS_CONTROL_SHADER, GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
720 GL_REFERENCED_BY_GEOMETRY_SHADER,
721 GL_REFERENCED_BY_FRAGMENT_SHADER,
722 GL_REFERENCED_BY_COMPUTE_SHADER};
723 GLsizei numWritten = 0;
724 GLint results[NUM_PROPS] = {0};
725
726 int vSSB, teSSB, tcSSB, gSSB, fSSB, cSSB;
727 vSSB = teSSB = tcSSB = gSSB = fSSB = cSSB = 0;
728
729 CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
730 CSCI441::LogUtils::log("[INFO]: | GL_SHADER_STORAGE_BLOCK: %29d |\n", numSSBO );
731 for(int i = 0; i < numSSBO; i++) {
732 glGetProgramResourceName(programHandle, GL_SHADER_STORAGE_BLOCK, i, maxLen, &ssboNameLen, ssboName);
733 GLuint ssboIndex = glGetProgramResourceIndex(programHandle, GL_SHADER_STORAGE_BLOCK, ssboName);
734 glGetProgramResourceiv(programHandle, GL_SHADER_STORAGE_BLOCK, i, NUM_PROPS, props, NUM_PROPS, &numWritten, results);
735
736 CSCI441::LogUtils::log("[INFO]: | %3d) name: %-19s index: %3d binding: %3d |\n", i, ssboName, ssboIndex, results[0] );
737 CSCI441::LogUtils::log("[INFO]: | Used in: %-4s %-4s %-4s %-3s %-4s %-4s Shader(s) |\n", (results[1] ? "Vert" : ""), (results[2] ? "Ctrl" : ""), (results[3] ? "Eval" : ""), (results[4] ? "Geo" : ""), (results[5] ? "Frag" : ""), (results[6] ? "Comp" : ""));
738
739 if(results[1]) vSSB++;
740 if(results[2]) teSSB++;
741 if(results[3]) tcSSB++;
742 if(results[4]) gSSB++;
743 if(results[5]) fSSB++;
744 if(results[6]) cSSB++;
745 }
746
747 GLint maxSSBCounters = 0;
748 glGetIntegerv( GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxSSBCounters );
749 CSCI441::LogUtils::log("[INFO]: | Shader Storage Block Counts: %2d/%2d |\n", numSSBO, maxSSBCounters );
750 if(hasVertexShader) {
751 GLint maxVertSSB = 0;
752 glGetIntegerv( GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertSSB );
753 CSCI441::LogUtils::log("[INFO]: | Vertex Shader Storage Blocks: %2d/%2d |\n", vSSB, maxVertSSB );
754 }
755 if(hasTessControlShader) {
756 GLint maxTESSB = 0;
757 glGetIntegerv( GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &maxTESSB );
758 CSCI441::LogUtils::log("[INFO]: | Tess Ctrl Shader Storage Blocks: %2d/%2d |\n", teSSB, maxTESSB );
759 }
760 if(hasTessEvalShader) {
761 GLint maxTCSSB = 0;
762 glGetIntegerv( GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &maxTCSSB );
763 CSCI441::LogUtils::log("[INFO]: | Tess Eval Shader Storage Blocks: %2d/%2d |\n", tcSSB, maxTCSSB );
764 }
765 if(hasGeometryShader) {
766 GLint maxGeoSSB = 0;
767 glGetIntegerv( GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &maxGeoSSB );
768 CSCI441::LogUtils::log("[INFO]: | Geometry Shader Storage Blocks: %2d/%2d |\n", gSSB, maxGeoSSB );
769 }
770 if(hasFragmentShader) {
771 GLint maxFragSSB = 0;
772 glGetIntegerv( GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragSSB );
773 CSCI441::LogUtils::log("[INFO]: | Fragment Shader Storage Blocks: %2d/%2d |\n", fSSB, maxFragSSB );
774 }
775 if(hasComputeShader) {
776 GLint maxComputeSSB = 0;
777 glGetIntegerv( GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeSSB );
778 CSCI441::LogUtils::log("[INFO]: | Compute Shader Storage Blocks: %2d/%2d |\n", cSSB, maxComputeSSB );
779 }
780
781 delete[] ssboName;
782 }
783 }
784
785 if((major == 4 && minor >= 2) || major > 4) {
786 GLint numAtomicCounters = 0;
787 glGetProgramInterfaceiv(programHandle, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numAtomicCounters);
788
789 if(numAtomicCounters > 0) {
790 constexpr int NUM_PROPS = 6;
791 GLenum props[NUM_PROPS] = {GL_REFERENCED_BY_VERTEX_SHADER,
792 GL_REFERENCED_BY_TESS_CONTROL_SHADER,
793 GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
794 GL_REFERENCED_BY_GEOMETRY_SHADER,
795 GL_REFERENCED_BY_FRAGMENT_SHADER,
796 GL_NONE};
797
798 if((major == 4 && minor >= 3) || major > 4) {
799 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
800 }
801
802 GLsizei numWritten = 0;
803 GLint results[NUM_PROPS] = {0};
804
805 CSCI441::LogUtils::log("[INFO]: >--------------------------------------------------------<\n");
806 CSCI441::LogUtils::log("[INFO]: | GL_ATOMIC_COUNTER_BUFFER: %28d |\n", numAtomicCounters );
807
808 int vAC, teAC, tcAC, gAC, fAC, cAC;
809 vAC = teAC = tcAC = gAC = fAC = cAC = 0;
810
811 for(GLint acIdx = 0; acIdx < numAtomicCounters; acIdx++) {
812 GLint binding = -1, bufferSize = 0, nac = 0;
813
814 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_BINDING, &binding);
815 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE, &bufferSize);
816 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS, &nac);
817
818 const auto uniformIndices = new GLint[nac];
819 const auto atomicOffsets = new GLint[nac];
820 const auto atomicName = new GLchar[maxUniformNameLength];
821
822 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES, uniformIndices);
823 glGetActiveUniformsiv(programHandle, nac, (GLuint*)uniformIndices, GL_UNIFORM_OFFSET, atomicOffsets);
824 glGetProgramResourceiv(programHandle, GL_ATOMIC_COUNTER_BUFFER, acIdx, NUM_PROPS, props, NUM_PROPS, &numWritten, results);
825
826 // increment counts of which shaders have an atomic counter
827 if(results[0]) vAC++;
828 if(results[1]) teAC++;
829 if(results[2]) tcAC++;
830 if(results[3]) gAC++;
831 if(results[4]) fAC++;
832 if(results[5]) cAC++;
833
834 CSCI441::LogUtils::log("[INFO]: | %d) binding: %11d buffer size: %4d |\n", acIdx, binding, bufferSize );
835 CSCI441::LogUtils::log("[INFO]: | Used in: %-4s %-4s %-4s %-3s %-4s %-4s Shader(s) |\n", (results[0] ? "Vert" : ""), (results[1] ? "Ctrl" : ""), (results[2] ? "Eval" : ""), (results[3] ? "Geo" : ""), (results[4] ? "Frag" : ""), (results[5] ? "Comp" : ""));
836
837 GLint acCtr = 0, actualLen = 0, uniSize = 0;
838 GLenum type = GL_NONE;
839 for(GLint uniIdx = 0; uniIdx < nac; uniIdx++) {
840 glGetActiveUniform(programHandle, uniformIndices[uniIdx], maxUniformNameLength, &actualLen, &uniSize, &type, atomicName);
841
842 constexpr GLsizei NUM_ATOMIC_PROPERTIES = 1;
843 GLenum atomicProps[NUM_ATOMIC_PROPERTIES] = {GL_ATOMIC_COUNTER_BUFFER_INDEX};
844 GLint atomicIndex [NUM_ATOMIC_PROPERTIES] = {-1};
845 glGetProgramResourceiv(programHandle, GL_UNIFORM, uniformIndices[uniIdx], NUM_ATOMIC_PROPERTIES, atomicProps, NUM_ATOMIC_PROPERTIES, nullptr, atomicIndex);
846
847 if(atomicIndex[0] == acIdx) {
848 CSCI441::LogUtils::log("[INFO]: | %3d) type: %-15s name: %-21s |\n", acCtr++, GLSL_type_to_string(type), atomicName );
849 CSCI441::LogUtils::log("[INFO]: | uniform index: %3d offset: %7d |\n", uniformIndices[uniIdx], atomicOffsets[uniIdx] );
850 }
851 }
852
853 delete[] uniformIndices;
854 delete[] atomicOffsets;
855 delete[] atomicName;
856 }
857
858 GLint maxAtomicCounters = 0;
859 glGetIntegerv( GL_MAX_COMBINED_ATOMIC_COUNTERS, &maxAtomicCounters );
860 CSCI441::LogUtils::log("[INFO]: | Atomic Counter Counts: %4d/%4d |\n", numAtomicCounters, maxAtomicCounters );
861 if(hasVertexShader) {
862 GLint maxVertAtomicCounters = 0;
863 glGetIntegerv( GL_MAX_VERTEX_ATOMIC_COUNTERS, &maxVertAtomicCounters );
864 CSCI441::LogUtils::log("[INFO]: | Vertex Atomic Counters: %4d/%4d |\n", vAC, maxVertAtomicCounters );
865 }
866 if(hasTessControlShader) {
867 GLint maxTCAtomicCounters = 0;
868 glGetIntegerv( GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, &maxTCAtomicCounters );
869 CSCI441::LogUtils::log("[INFO]: | Tess Ctrl Atomic Counters: %4d/%4d |\n", teAC, maxTCAtomicCounters );
870 }
871 if(hasTessEvalShader) {
872 GLint maxTEAtomicCounters = 0;
873 glGetIntegerv( GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, &maxTEAtomicCounters );
874 CSCI441::LogUtils::log("[INFO]: | Tess Eval Atomic Counters: %4d/%4d |\n", tcAC, maxTEAtomicCounters );
875 }
876 if(hasGeometryShader) {
877 GLint maxGeoAtomicCounters = 0;
878 glGetIntegerv( GL_MAX_GEOMETRY_ATOMIC_COUNTERS, &maxGeoAtomicCounters );
879 CSCI441::LogUtils::log("[INFO]: | Geometry Atomic Counters: %4d/%4d |\n", gAC, maxGeoAtomicCounters );
880 }
881 if(hasFragmentShader) {
882 GLint maxFragAtomicCounters = 0;
883 glGetIntegerv( GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &maxFragAtomicCounters );
884 CSCI441::LogUtils::log("[INFO]: | Fragment Atomic Counters: %4d/%4d |\n", fAC, maxFragAtomicCounters );
885 }
886 if(hasComputeShader) {
887 GLint maxComputeAtomicCounters = 0;
888 glGetIntegerv( GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxComputeAtomicCounters );
889 CSCI441::LogUtils::log("[INFO]: | Compute Atomic Counters: %4d/%4d |\n", cAC, maxComputeAtomicCounters );
890 }
891 }
892 }
893
894 if( major >= 4 ) {
895 GLboolean printHeader = GL_TRUE;
896 if( hasVertexShader ) printHeader = printSubroutineInfo(programHandle, GL_VERTEX_SHADER, printHeader );
897 if( hasTessControlShader) printHeader = printSubroutineInfo(programHandle, GL_TESS_CONTROL_SHADER, printHeader );
898 if( hasTessEvalShader) printHeader = printSubroutineInfo(programHandle, GL_TESS_EVALUATION_SHADER, printHeader );
899 if( hasGeometryShader ) printHeader = printSubroutineInfo(programHandle, GL_GEOMETRY_SHADER, printHeader );
900 if( hasFragmentShader ) printHeader = printSubroutineInfo(programHandle, GL_FRAGMENT_SHADER, printHeader );
901 if( hasComputeShader ) printSubroutineInfo(programHandle, GL_COMPUTE_SHADER, printHeader );
902 }
903 }
904
905 if(useLastNewLine && sDEBUG) CSCI441::LogUtils::log("[INFO]: \\--------------------------------------------------------/\n\n");
906}
907
908inline GLuint CSCI441_INTERNAL::ShaderUtils::compileShader(
909 const char *filename,
910 const GLenum shaderType
911) {
912 // will hold contents of shader source code, loaded from file
913 GLchar *shaderString;
914
915 // read in each text file and store the contents in a string
916 if( readTextFromFile( filename, shaderString ) ) {
917 // generate a shader handle for the corresponding shader type
918 GLuint shaderHandle = glCreateShader( shaderType );
919
920 // send the contents of each program to the GPU
921 glShaderSource( shaderHandle, 1, (const char**)&shaderString, nullptr );
922
923 // we are good programmers so free up the memory used by each buffer
924 delete [] shaderString;
925
926 // compile each shader on the GPU
927 glCompileShader( shaderHandle );
928
929 // check the shader log
930 printShaderLog( shaderHandle );
931
932 // return the handle of our shader
933 return shaderHandle;
934 } else {
935 return 0;
936 }
937}
938
939#endif // CSCI441_SHADER_UTILS_HPP
void log(const char *MSG,...)
log a message to both the standard output stream and file
Definition: LogUtils.hpp:116
void logError(const char *MSG,...)
log a message to both the standard error stream and file
Definition: LogUtils.hpp:128