14#ifndef CSCI441_SHADER_UTILS_HPP
15#define CSCI441_SHADER_UTILS_HPP
17#ifdef CSCI441_USE_GLEW
30namespace CSCI441_INTERNAL::ShaderUtils {
31 static bool sDEBUG =
true;
34 [[maybe_unused]]
void enableDebugMessages();
37 [[maybe_unused]]
void disableDebugMessages();
42 const char* GLSL_type_to_string( GLenum type );
47 const char* GL_shader_type_to_string( GLenum type );
52 const char* GL_primitive_type_to_string( GLenum type );
58 bool readTextFromFile(
const char* filename, GLchar* &output );
64 GLuint compileShader(
const char *filename, GLenum shaderType );
67 void printShaderLog( GLuint shaderHandle );
70 void printProgramLog( GLuint programHandle );
73 void printProgramPipelineLog( GLuint pipelineHandle );
79 GLboolean printSubroutineInfo(GLuint programHandle, GLenum shaderStage, GLboolean printHeader );
90 void printShaderProgramInfo( GLuint programHandle,
91 GLboolean hasVertexShader,
92 GLboolean hasTessControlShader, GLboolean hasTessEvalShader,
93 GLboolean hasGeometryShader,
94 GLboolean hasFragmentShader,
95 GLboolean hasComputeShader,
96 GLboolean useLastNewLine );
102inline void CSCI441_INTERNAL::ShaderUtils::enableDebugMessages() {
107inline void CSCI441_INTERNAL::ShaderUtils::disableDebugMessages() {
113inline bool CSCI441_INTERNAL::ShaderUtils::readTextFromFile(
114 const char *filename,
117 std::string buf = std::string(
"");
120 std::ifstream in(filename);
121 if( !in.is_open() ) {
122 fprintf( stderr,
"[ERROR]: Could not open file %s\n", filename );
125 while( std::getline(in, line) ) {
129 output =
new GLchar[buf.length()+1];
130 strncpy(output, buf.c_str(), buf.length());
131 output[buf.length()] =
'\0';
138inline const char* CSCI441_INTERNAL::ShaderUtils::GLSL_type_to_string(
142 case GL_FLOAT:
return "float";
143 case GL_FLOAT_VEC2:
return "vec2";
144 case GL_FLOAT_VEC3:
return "vec3";
145 case GL_FLOAT_VEC4:
return "vec4";
146 case GL_DOUBLE:
return "double";
147 case GL_DOUBLE_VEC2:
return "dvec2";
148 case GL_DOUBLE_VEC3:
return "dvec3";
149 case GL_DOUBLE_VEC4:
return "dvec4";
150 case GL_INT:
return "int";
151 case GL_INT_VEC2:
return "ivec2";
152 case GL_INT_VEC3:
return "ivec3";
153 case GL_INT_VEC4:
return "ivec4";
154 case GL_UNSIGNED_INT:
return "unsigned int";
155 case GL_UNSIGNED_INT_VEC2:
return "uvec2";
156 case GL_UNSIGNED_INT_VEC3:
return "uvec3";
157 case GL_UNSIGNED_INT_VEC4:
return "uvec4";
158 case GL_BOOL:
return "bool";
159 case GL_BOOL_VEC2:
return "bvec2";
160 case GL_BOOL_VEC3:
return "bvec3";
161 case GL_BOOL_VEC4:
return "bvec4";
162 case GL_FLOAT_MAT2:
return "mat2";
163 case GL_FLOAT_MAT3:
return "mat3";
164 case GL_FLOAT_MAT4:
return "mat4";
165 case GL_FLOAT_MAT2x3:
return "mat2x3";
166 case GL_FLOAT_MAT2x4:
return "mat2x4";
167 case GL_FLOAT_MAT3x2:
return "mat3x2";
168 case GL_FLOAT_MAT3x4:
return "mat3x4";
169 case GL_FLOAT_MAT4x2:
return "mat4x2";
170 case GL_FLOAT_MAT4x3:
return "mat4x3";
171 case GL_DOUBLE_MAT2:
return "dmat2";
172 case GL_DOUBLE_MAT3:
return "dmat3";
173 case GL_DOUBLE_MAT4:
return "dmat4";
174 case GL_DOUBLE_MAT2x3:
return "dmat2x3";
175 case GL_DOUBLE_MAT2x4:
return "dmat2x4";
176 case GL_DOUBLE_MAT3x2:
return "dmat3x2";
177 case GL_DOUBLE_MAT3x4:
return "dmat3x4";
178 case GL_DOUBLE_MAT4x2:
return "dmat4x2";
179 case GL_DOUBLE_MAT4x3:
return "dmat4x3";
180 case GL_SAMPLER_1D:
return "sampler1D";
181 case GL_SAMPLER_2D:
return "sampler2D";
182 case GL_SAMPLER_3D:
return "sampler3D";
183 case GL_SAMPLER_CUBE:
return "samplerCube";
184 case GL_SAMPLER_1D_SHADOW:
return "sampler1DShadow";
185 case GL_SAMPLER_2D_SHADOW:
return "sampler2DShadow";
186 case GL_SAMPLER_1D_ARRAY:
return "sampler1DArray";
187 case GL_SAMPLER_2D_ARRAY:
return "sampler2DArray";
188 case GL_SAMPLER_2D_MULTISAMPLE:
return "sampler2DMS";
189 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
return "sampler2DMSArray";
190 case GL_SAMPLER_CUBE_SHADOW:
return "samplerCubeShadow";
191 case GL_SAMPLER_BUFFER:
return "samplerBuffer";
192 case GL_SAMPLER_2D_RECT:
return "sampler2DRect";
193 case GL_SAMPLER_2D_RECT_SHADOW:
return "sampler2DRectShadow";
194 case GL_INT_SAMPLER_1D:
return "isampler1D";
195 case GL_INT_SAMPLER_2D:
return "isampler2D";
196 case GL_INT_SAMPLER_3D:
return "isampler3D";
197 case GL_INT_SAMPLER_CUBE:
return "isamplerCube";
198 case GL_INT_SAMPLER_1D_ARRAY:
return "isampler1DArray";
199 case GL_INT_SAMPLER_2D_ARRAY:
return "isampler2DArray";
200 case GL_INT_SAMPLER_2D_MULTISAMPLE:
return "isampler2DMS";
201 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
return "isampler2DMSArray";
202 case GL_INT_SAMPLER_BUFFER:
return "isamplerBuffer";
203 case GL_INT_SAMPLER_2D_RECT:
return "isampler2DRect";
204 case GL_UNSIGNED_INT_SAMPLER_1D:
return "usampler1D";
205 case GL_UNSIGNED_INT_SAMPLER_2D:
return "usampler2D";
206 case GL_UNSIGNED_INT_SAMPLER_3D:
return "usampler3D";
207 case GL_UNSIGNED_INT_SAMPLER_CUBE:
return "usamplerCube";
208 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
return "usampler1DArray";
209 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
return "usampler2DArray";
210 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
return "usampler2DMS";
211 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
return "usampler2DMSArray";
212 case GL_UNSIGNED_INT_SAMPLER_BUFFER:
return "usamplerBuffer";
213 case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
return "usampler2DRect";
214 case GL_IMAGE_1D:
return "image1D";
215 case GL_IMAGE_2D:
return "image2D";
216 case GL_IMAGE_3D:
return "image3D";
217 case GL_IMAGE_2D_RECT:
return "image2DRect";
218 case GL_IMAGE_CUBE:
return "imageCube";
219 case GL_IMAGE_BUFFER:
return "imageBuffer";
220 case GL_IMAGE_1D_ARRAY:
return "image1DArray";
221 case GL_IMAGE_2D_ARRAY:
return "image2DArray";
222 case GL_IMAGE_2D_MULTISAMPLE:
return "image2DMS";
223 case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
return "image2DMSArray";
224 case GL_INT_IMAGE_1D:
return "iimage1D";
225 case GL_INT_IMAGE_2D:
return "iimage2D";
226 case GL_INT_IMAGE_3D:
return "iimage3D";
227 case GL_INT_IMAGE_2D_RECT:
return "iimage2DRect";
228 case GL_INT_IMAGE_CUBE:
return "iimageCube";
229 case GL_INT_IMAGE_BUFFER:
return "iimageBuffer";
230 case GL_INT_IMAGE_1D_ARRAY:
return "iimage1DArray";
231 case GL_INT_IMAGE_2D_ARRAY:
return "iimage2DArray";
232 case GL_INT_IMAGE_2D_MULTISAMPLE:
return "iimage2DMS";
233 case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
return "iimage2DMSArray";
234 case GL_UNSIGNED_INT_IMAGE_1D:
return "uimage1D";
235 case GL_UNSIGNED_INT_IMAGE_2D:
return "uimage2D";
236 case GL_UNSIGNED_INT_IMAGE_3D:
return "uimage3D";
237 case GL_UNSIGNED_INT_IMAGE_2D_RECT:
return "uimage2DRect";
238 case GL_UNSIGNED_INT_IMAGE_CUBE:
return "uimageCube";
239 case GL_UNSIGNED_INT_IMAGE_BUFFER:
return "uimageBuffer";
240 case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
return "uimage1DArray";
241 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
return "uimage2DArray";
242 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
return "uimage2DMS";
243 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
return "uimage2DMSArray";
244 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return "atomic_uint";
247 return "other data type";
250inline const char* CSCI441_INTERNAL::ShaderUtils::GL_shader_type_to_string(
254 case GL_VERTEX_SHADER:
return "Vertex Shader";
255 case GL_TESS_CONTROL_SHADER:
return "Tess Ctrl Shader";
256 case GL_TESS_EVALUATION_SHADER:
return "Tess Eval Shader";
257 case GL_GEOMETRY_SHADER:
return "Geometry Shader";
258 case GL_FRAGMENT_SHADER:
return "Fragment Shader";
259 case GL_COMPUTE_SHADER:
return "Compute Shader";
262 return "other shader type";
265inline const char* CSCI441_INTERNAL::ShaderUtils::GL_primitive_type_to_string(
269 case GL_POINTS:
return "Points";
270 case GL_LINES:
return "Lines";
271 case GL_LINE_STRIP:
return "Line Strip";
272 case GL_LINE_LOOP:
return "Line Loop";
273 case GL_LINES_ADJACENCY:
return "Line Adjacency";
274 case GL_TRIANGLES:
return "Triangles";
275 case GL_TRIANGLE_STRIP:
return "Triangle Strip";
276 case GL_TRIANGLES_ADJACENCY:
return "Triangle Adjacency";
277 case GL_PATCHES:
return "Patches";
280 return "other primitive type";
283inline void CSCI441_INTERNAL::ShaderUtils::printShaderLog(
284 const GLuint shaderHandle
287 if( glIsShader( shaderHandle ) ) {
288 GLint maxLength = 0, status = 0, infoLogLength = 0;
289 glGetShaderiv( shaderHandle, GL_INFO_LOG_LENGTH, &maxLength );
292 const auto infoLog =
new GLchar[maxLength];
294 glGetShaderiv( shaderHandle, GL_COMPILE_STATUS, &status );
295 if( sDEBUG ) printf(
"[INFO]: | Shader Handle %2d: Compile%-26s |\n", shaderHandle, (status == 1 ?
"d Successfully" :
"r Error") );
298 glGetShaderInfoLog(shaderHandle, maxLength, &infoLogLength, infoLog );
300 if(infoLogLength > 0 ) {
302 if( sDEBUG ) printf(
"[INFO]: | Shader Handle %d: %s\n", shaderHandle, infoLog );
307 if( sDEBUG ) fprintf( stderr,
"[WARN]: | Handle %-3d is not for a Shader |\n", shaderHandle );
311inline void CSCI441_INTERNAL::ShaderUtils::printProgramLog(
312 const GLuint programHandle
315 if( glIsProgram( programHandle ) ) {
316 GLint maxLength = 0, status = 0, infoLogLength = 0;
317 glGetProgramiv( programHandle, GL_INFO_LOG_LENGTH, &maxLength );
320 const auto infoLog =
new GLchar[maxLength];
322 glGetProgramiv( programHandle, GL_LINK_STATUS, &status );
323 if( sDEBUG ) printf(
"[INFO]: | Program Handle %2d: Linke%-28s |\n", programHandle, (status == 1 ?
"d Successfully" :
"r Error") );
326 glGetProgramInfoLog(programHandle, maxLength, &infoLogLength, infoLog );
328 if(infoLogLength > 0 ) {
330 if( sDEBUG ) printf(
"[INFO]: | Program Handle %d: %s\n", programHandle, infoLog );
335 if( sDEBUG ) fprintf( stderr,
"[WARN]: | Handle %-3d is not for a Shader Program |\n", programHandle );
339inline void CSCI441_INTERNAL::ShaderUtils::printProgramPipelineLog(
340 const GLuint pipelineHandle
343 if( glIsProgramPipeline( pipelineHandle ) ) {
344 GLint maxLength = 0, infoLogLength = 0;
346 glGetProgramPipelineiv( pipelineHandle, GL_INFO_LOG_LENGTH, &maxLength );
349 const auto infoLog =
new GLchar[maxLength];
352 glGetProgramPipelineInfoLog(pipelineHandle, maxLength, &infoLogLength, infoLog );
354 if( infoLogLength > 0 ) {
356 if( sDEBUG ) printf(
"[INFO]: | Pipeline Handle %d: %s\n", pipelineHandle, infoLog );
361 if( sDEBUG ) fprintf( stderr,
"[WARN]: | Handle %-3d is not for a Shader Program Pipeline |\n", pipelineHandle );
365inline GLboolean CSCI441_INTERNAL::ShaderUtils::printSubroutineInfo(
366 const GLuint programHandle,
367 const GLenum shaderStage,
368 const GLboolean printHeader
370 GLint numSubroutineUniforms = 0;
371 glGetProgramStageiv(programHandle, shaderStage, GL_ACTIVE_SUBROUTINE_UNIFORMS, &numSubroutineUniforms);
372 bool headerPrinted =
false;
373 if( numSubroutineUniforms > 0 ) {
375 printf(
"[INFO]: >--------------------------------------------------------<\n");
376 headerPrinted =
true;
378 printf(
"[INFO]: | GL_ACTIVE_SUBROUTINE_UNIFORMS (%-15s): %5i |\n", CSCI441_INTERNAL::ShaderUtils::GL_shader_type_to_string(shaderStage), numSubroutineUniforms);
379 for(
int i = 0; i < numSubroutineUniforms; i++ ) {
380 GLchar subroutineName[256];
381 GLint max_length = 256, actual_length = 0;
382 GLint numCompatibleSubroutines = 0;
384 glGetActiveSubroutineUniformName(programHandle, shaderStage, i, max_length, &actual_length, subroutineName );
385 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_NUM_COMPATIBLE_SUBROUTINES, &numCompatibleSubroutines );
387 const auto compatibleSubroutines =
new GLint[numCompatibleSubroutines];
388 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_COMPATIBLE_SUBROUTINES, compatibleSubroutines );
390 GLint loc = glGetSubroutineUniformLocation(programHandle, shaderStage, subroutineName );
392 printf(
"[INFO]: | %i) name: %-15s #subRoutines: %-5i loc: %2i |\n", i, subroutineName, numCompatibleSubroutines, loc );
394 for(
int j = 0; j < numCompatibleSubroutines; j++ ) {
395 GLint idx = compatibleSubroutines[j];
397 GLchar subroutineImplName[64];
398 GLint max_length2 = 64, actual_length2 = 0;
399 glGetActiveSubroutineName(programHandle, shaderStage, idx, max_length2, &actual_length2, subroutineImplName );
401 printf(
"[INFO]: | %i) subroutine: %-25s index: %2i |\n", j, subroutineImplName, idx );
404 delete[] compatibleSubroutines;
407 return !headerPrinted;
410inline void CSCI441_INTERNAL::ShaderUtils::printShaderProgramInfo(
411 const GLuint programHandle,
412 const GLboolean hasVertexShader,
413 const GLboolean hasTessControlShader,
414 const GLboolean hasTessEvalShader,
415 const GLboolean hasGeometryShader,
416 const GLboolean hasFragmentShader,
417 const GLboolean hasComputeShader,
418 const GLboolean useLastNewLine =
true
420 GLint major = 0, minor = 0;
421 glGetIntegerv(GL_MAJOR_VERSION, &major);
422 glGetIntegerv(GL_MINOR_VERSION, &minor);
424 GLuint shaders[6] = {0};
426 GLint actual_count = 0;
428 GLint max_attr_name_size = 0;
429 GLint max_uniform_name_size = 0;
433 glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_size);
434 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_size);
436 glGetAttachedShaders(programHandle, max_count, &actual_count, shaders );
437 if(actual_count > 0) {
438 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n");
439 if( sDEBUG ) printf(
"[INFO]: | GL_ATTACHED_SHADERS: %33i |\n", actual_count);
440 for(
int i = 0; i < actual_count; i++ ) {
442 glGetShaderiv( shaders[i], GL_SHADER_TYPE, &shaderType );
443 if( sDEBUG ) printf(
"[INFO]: | %i) %-38s Handle: %2i |\n", i, GL_shader_type_to_string(shaderType), shaders[i]);
448 if(hasGeometryShader) {
449 if( major > 3 || (major >= 3 && minor >= 2) ) {
450 GLint verticesOut = 0, inputType = 0, outputType = 0;
451 glGetProgramiv(programHandle, GL_GEOMETRY_VERTICES_OUT, &verticesOut);
452 glGetProgramiv(programHandle, GL_GEOMETRY_INPUT_TYPE, &inputType);
453 glGetProgramiv(programHandle, GL_GEOMETRY_OUTPUT_TYPE, &outputType);
455 printf(
"[INFO]: >--------------------------------------------------------<\n");
456 printf(
"[INFO]: | GEOMETRY SHADER PRIMITIVE I/O |\n");
457 printf(
"[INFO]: | Input Type: %40s |\n", GL_primitive_type_to_string(inputType) );
458 printf(
"[INFO]: | Output Type: %39s |\n", GL_primitive_type_to_string(outputType) );
459 printf(
"[INFO]: | Max Vertices Out: %34d |\n", verticesOut );
464 if(hasVertexShader) {
465 GLint numActiveAttributes = 0;
466 glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTES, &numActiveAttributes );
467 if( numActiveAttributes > 0 ) {
468 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n");
469 if( sDEBUG ) printf(
"[INFO]: | GL_ACTIVE_ATTRIBUTES: %32i |\n", numActiveAttributes );
470 for(
int i = 0; i < numActiveAttributes; i++ ) {
471 const auto name =
new GLchar[max_attr_name_size];
472 GLint actual_length = 0, size = 0;
473 GLenum type = GL_NONE;
474 glGetActiveAttrib(programHandle, i, max_attr_name_size, &actual_length, &size, &type, name );
476 for(
int j = 0; j < size; j++ ) {
479 int max_array_size = actual_length + 4 + 2 + 1;
480 const auto array_name =
new GLchar[max_array_size];
482 snprintf( array_name, max_array_size,
"%s[%i]", name, j );
483 GLint location = glGetAttribLocation(programHandle, array_name);
484 if( sDEBUG ) printf(
"[INFO]: | %i) type: %-15s name: %-13s loc: %2i |\n", i, GLSL_type_to_string( type ), array_name, location );
488 GLint location = glGetAttribLocation(programHandle, name );
489 if( sDEBUG ) printf(
"[INFO]: | %i) type: %-15s name: %-13s loc: %2i |\n",i, GLSL_type_to_string( type ), name, location );
497 GLint numActiveUniforms = 0;
498 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORMS, &numActiveUniforms);
499 if( numActiveUniforms > 0 ) {
500 constexpr int NUM_PROPS = 6;
501 GLenum props[NUM_PROPS] = {GL_REFERENCED_BY_VERTEX_SHADER,
502 GL_REFERENCED_BY_TESS_CONTROL_SHADER,
503 GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
504 GL_REFERENCED_BY_GEOMETRY_SHADER,
505 GL_REFERENCED_BY_FRAGMENT_SHADER,
508 if((major == 4 && minor >= 3) || major > 4) {
509 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
511 GLint results[NUM_PROPS] = {0};
513 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n" );
514 if( sDEBUG ) printf(
"[INFO]: | GL_ACTIVE_UNIFORMS: %34i |\n", numActiveUniforms);
515 for(
int uIdx = 0; uIdx < numActiveUniforms; uIdx++) {
516 const auto name =
new GLchar[max_uniform_name_size];
517 GLint actual_length = 0, size = 0, location = -1;
518 GLenum type = GL_NONE;
519 glGetActiveUniform(programHandle, uIdx, max_uniform_name_size, &actual_length, &size, &type, name );
521 for(
int j = 0; j < size; j++) {
522 int max_array_size = actual_length + 4 + 2 + 1;
523 const auto array_name =
new GLchar[max_array_size];
524 snprintf(array_name, max_array_size,
"%s[%i]", name, j);
525 location = glGetUniformLocation(programHandle, array_name);
527 if (sDEBUG) printf(
"[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), array_name, location);
532 location = glGetUniformLocation(programHandle, name);
534 if (sDEBUG) printf(
"[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), name, location);
538 if(((major == 4 && minor >= 3) || major > 4) && location != -1) {
539 glGetProgramResourceiv(programHandle, GL_UNIFORM, uIdx, NUM_PROPS, props, NUM_PROPS,
nullptr, results);
540 if( sDEBUG ) printf(
"[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" :
""));
547 GLint numActiveUniformBlocks = 0;
548 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks);
549 if( numActiveUniformBlocks > 0 ) {
550 int vsCount, tcsCount, tesCount, gsCount, fsCount, csCount;
551 vsCount = tcsCount = tesCount = gsCount = fsCount = csCount = 0;
553 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n");
554 if( sDEBUG ) printf(
"[INFO]: | GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: %20d |\n", numActiveUniformBlocks);
555 for(
int i = 0; i < numActiveUniformBlocks; i++ ) {
556 GLint numActiveUniformsInBlock = 0, bindingPoint = 0;
557 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numActiveUniformsInBlock );
558 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_BINDING, &bindingPoint);
561 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &actualLen);
562 const auto name =
new GLchar[actualLen];
563 glGetActiveUniformBlockName(programHandle, i, actualLen,
nullptr, name);
565 const auto indices =
new GLint[numActiveUniformsInBlock];
566 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices);
568 const auto offsets =
new GLint[numActiveUniformsInBlock];
569 glGetActiveUniformsiv(programHandle, numActiveUniformsInBlock, (GLuint*)indices, GL_UNIFORM_OFFSET, offsets);
571 if( sDEBUG ) printf(
"[INFO]: | %d) %-19s binding: %3d |\n", i, name, bindingPoint);
573 GLint vs, tcs, tes, gs, fs, cs;
574 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &vs);
if( vs ) vsCount++;
575 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER, &tcs);
if( tcs) tcsCount++;
576 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER, &tes);
if( tes) tesCount++;
577 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, &gs);
if( gs ) gsCount++;
578 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &fs);
if( fs ) fsCount++;
579 if((major == 4 && minor >= 3) || major > 4) {
580 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER, &cs);
if( cs ) csCount++;
582 if( sDEBUG ) printf(
"[INFO]: | Used in: %-4s %-4s %-4s %-3s %-4s %-4s Shader(s) |\n", (vs ?
"Vert" :
""), (tcs ?
"Ctrl" :
""), (tes ?
"Eval" :
""), (gs ?
"Geo" :
""), (fs ?
"Frag" :
""), (cs ?
"Comp" :
""));
584 const auto name2 =
new char[max_uniform_name_size];
585 for(
int j = 0; j < numActiveUniformsInBlock; j++) {
588 glGetActiveUniform(programHandle, indices[j], max_uniform_name_size, &actualLen, &uniSize, &type, name2);
590 constexpr GLsizei NUM_ATOMIC_PROPERTIES = 1;
591 GLint atomicIndex[NUM_ATOMIC_PROPERTIES] = {-1};
592 if((major == 4 && minor >= 3) || major > 4) {
593 GLenum atomicProps[NUM_ATOMIC_PROPERTIES] = {GL_ATOMIC_COUNTER_BUFFER_INDEX};
594 glGetProgramResourceiv(programHandle, GL_UNIFORM, indices[j], NUM_ATOMIC_PROPERTIES, atomicProps, NUM_ATOMIC_PROPERTIES,
nullptr, atomicIndex);
597 if( atomicIndex[0] == -1 && sDEBUG ) {
598 printf(
"[INFO]: | %2d) type: %-15s name: %-21s |\n", j, GLSL_type_to_string(type), name2);
599 printf(
"[INFO]: | uniform index: %3d offset: %4d |\n", indices[j], offsets[j]);
609 if( vsCount + tcsCount + tesCount + gsCount + fsCount + csCount > 0 ) {
610 GLint maxUniBlocks = 0;
611 glGetIntegerv( GL_MAX_COMBINED_UNIFORM_BLOCKS, &maxUniBlocks );
612 if( sDEBUG ) printf(
"[INFO]: | Shader Uniform Block Counts %2d/%2d |\n", numActiveUniformBlocks, maxUniBlocks);
613 if( hasVertexShader ) {
614 GLint maxVertexUniformBlocks = 0;
615 glGetIntegerv( GL_MAX_VERTEX_UNIFORM_BLOCKS, &maxVertexUniformBlocks );
617 if( sDEBUG ) printf(
"[INFO]: | Vertex Shader Uniform Blocks: %18d/%2d |\n", vsCount, maxVertexUniformBlocks );
619 if( hasTessControlShader ) {
620 GLint maxTessControlUniformBlocks = 0;
621 glGetIntegerv( GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, &maxTessControlUniformBlocks );
623 if( sDEBUG ) printf(
"[INFO]: | Tess Ctrl Shader Uniform Blocks: %15d/%2d |\n", tcsCount, maxTessControlUniformBlocks );
625 if( hasTessEvalShader ) {
626 GLint maxTessEvalUniformBlocks = 0;
627 glGetIntegerv( GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, &maxTessEvalUniformBlocks );
629 if( sDEBUG ) printf(
"[INFO]: | Tess Eval Shader Uniform Blocks: %15d/%2d |\n", tesCount, maxTessEvalUniformBlocks );
631 if( hasGeometryShader ) {
632 GLint maxGeometryUniformBlocks = 0;
633 glGetIntegerv( GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &maxGeometryUniformBlocks );
635 if( sDEBUG ) printf(
"[INFO]: | Geometry Shader Uniform Blocks: %16d/%2d |\n", gsCount, maxGeometryUniformBlocks );
637 if( hasFragmentShader ) {
638 GLint maxFragmentUniformBlocks = 0;
639 glGetIntegerv( GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &maxFragmentUniformBlocks );
641 if( sDEBUG ) printf(
"[INFO]: | Fragment Shader Uniform Blocks: %16d/%2d |\n", fsCount, maxFragmentUniformBlocks );
643 if( hasComputeShader ) {
644 GLint maxComputeUniformBlocks = 0;
645 glGetIntegerv( GL_MAX_COMPUTE_UNIFORM_BLOCKS, &maxComputeUniformBlocks );
647 if( sDEBUG ) printf(
"[INFO]: | Compute Shader Uniform Blocks: %17d/%2d |\n", csCount, maxComputeUniformBlocks );
653 if((major == 4 && minor >= 3) || major > 4) {
655 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numSSBO);
658 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &maxLen);
659 const auto ssboName =
new GLchar[maxLen];
660 GLsizei ssboNameLen = 0;
662 constexpr int NUM_PROPS = 7;
663 GLenum props[NUM_PROPS] = {GL_BUFFER_BINDING,
664 GL_REFERENCED_BY_VERTEX_SHADER,
665 GL_REFERENCED_BY_TESS_CONTROL_SHADER, GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
666 GL_REFERENCED_BY_GEOMETRY_SHADER,
667 GL_REFERENCED_BY_FRAGMENT_SHADER,
668 GL_REFERENCED_BY_COMPUTE_SHADER};
669 GLsizei numWritten = 0;
670 GLint results[NUM_PROPS] = {0};
672 int vSSB, teSSB, tcSSB, gSSB, fSSB, cSSB;
673 vSSB = teSSB = tcSSB = gSSB = fSSB = cSSB = 0;
675 printf(
"[INFO]: >--------------------------------------------------------<\n");
676 printf(
"[INFO]: | GL_SHADER_STORAGE_BLOCK: %29d |\n", numSSBO );
677 for(
int i = 0; i < numSSBO; i++) {
678 glGetProgramResourceName(programHandle, GL_SHADER_STORAGE_BLOCK, i, maxLen, &ssboNameLen, ssboName);
679 GLuint ssboIndex = glGetProgramResourceIndex(programHandle, GL_SHADER_STORAGE_BLOCK, ssboName);
680 glGetProgramResourceiv(programHandle, GL_SHADER_STORAGE_BLOCK, i, NUM_PROPS, props, NUM_PROPS, &numWritten, results);
682 printf(
"[INFO]: | %3d) name: %-19s index: %3d binding: %3d |\n", i, ssboName, ssboIndex, results[0] );
683 printf(
"[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" :
""));
685 if(results[1]) vSSB++;
686 if(results[2]) teSSB++;
687 if(results[3]) tcSSB++;
688 if(results[4]) gSSB++;
689 if(results[5]) fSSB++;
690 if(results[6]) cSSB++;
693 GLint maxSSBCounters = 0;
694 glGetIntegerv( GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxSSBCounters );
695 printf(
"[INFO]: | Shader Storage Block Counts: %2d/%2d |\n", numSSBO, maxSSBCounters );
696 if(hasVertexShader) {
697 GLint maxVertSSB = 0;
698 glGetIntegerv( GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertSSB );
699 printf(
"[INFO]: | Vertex Shader Storage Blocks: %2d/%2d |\n", vSSB, maxVertSSB );
701 if(hasTessControlShader) {
703 glGetIntegerv( GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &maxTESSB );
704 printf(
"[INFO]: | Tess Ctrl Shader Storage Blocks: %2d/%2d |\n", teSSB, maxTESSB );
706 if(hasTessEvalShader) {
708 glGetIntegerv( GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &maxTCSSB );
709 printf(
"[INFO]: | Tess Eval Shader Storage Blocks: %2d/%2d |\n", tcSSB, maxTCSSB );
711 if(hasGeometryShader) {
713 glGetIntegerv( GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &maxGeoSSB );
714 printf(
"[INFO]: | Geometry Shader Storage Blocks: %2d/%2d |\n", gSSB, maxGeoSSB );
716 if(hasFragmentShader) {
717 GLint maxFragSSB = 0;
718 glGetIntegerv( GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragSSB );
719 printf(
"[INFO]: | Fragment Shader Storage Blocks: %2d/%2d |\n", fSSB, maxFragSSB );
721 if(hasComputeShader) {
722 GLint maxComputeSSB = 0;
723 glGetIntegerv( GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeSSB );
724 printf(
"[INFO]: | Compute Shader Storage Blocks: %2d/%2d |\n", cSSB, maxComputeSSB );
731 if((major == 4 && minor >= 2) || major > 4) {
732 GLint numAtomicCounters = 0;
733 glGetProgramInterfaceiv(programHandle, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numAtomicCounters);
735 if(numAtomicCounters > 0) {
736 constexpr int NUM_PROPS = 6;
737 GLenum props[NUM_PROPS] = {GL_REFERENCED_BY_VERTEX_SHADER,
738 GL_REFERENCED_BY_TESS_CONTROL_SHADER,
739 GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
740 GL_REFERENCED_BY_GEOMETRY_SHADER,
741 GL_REFERENCED_BY_FRAGMENT_SHADER,
744 if((major == 4 && minor >= 3) || major > 4) {
745 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
748 GLsizei numWritten = 0;
749 GLint results[NUM_PROPS] = {0};
751 printf(
"[INFO]: >--------------------------------------------------------<\n");
752 printf(
"[INFO]: | GL_ATOMIC_COUNTER_BUFFER: %28d |\n", numAtomicCounters );
754 int vAC, teAC, tcAC, gAC, fAC, cAC;
755 vAC = teAC = tcAC = gAC = fAC = cAC = 0;
757 for(GLint acIdx = 0; acIdx < numAtomicCounters; acIdx++) {
758 GLint binding = -1, bufferSize = 0, nac = 0;
760 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_BINDING, &binding);
761 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE, &bufferSize);
762 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS, &nac);
764 const auto uniformIndices =
new GLint[nac];
765 const auto atomicOffsets =
new GLint[nac];
766 const auto atomicName =
new GLchar[max_uniform_name_size];
768 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES, uniformIndices);
769 glGetActiveUniformsiv(programHandle, nac, (GLuint*)uniformIndices, GL_UNIFORM_OFFSET, atomicOffsets);
770 glGetProgramResourceiv(programHandle, GL_ATOMIC_COUNTER_BUFFER, acIdx, NUM_PROPS, props, NUM_PROPS, &numWritten, results);
773 if(results[0]) vAC++;
774 if(results[1]) teAC++;
775 if(results[2]) tcAC++;
776 if(results[3]) gAC++;
777 if(results[4]) fAC++;
778 if(results[5]) cAC++;
780 printf(
"[INFO]: | %d) binding: %11d buffer size: %4d |\n", acIdx, binding, bufferSize );
781 printf(
"[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" :
""));
783 GLint acCtr = 0, actualLen = 0, uniSize = 0;
784 GLenum type = GL_NONE;
785 for(GLint uniIdx = 0; uniIdx < nac; uniIdx++) {
786 glGetActiveUniform(programHandle, uniformIndices[uniIdx], max_uniform_name_size, &actualLen, &uniSize, &type, atomicName);
788 constexpr GLsizei NUM_ATOMIC_PROPERTIES = 1;
789 GLenum atomicProps[NUM_ATOMIC_PROPERTIES] = {GL_ATOMIC_COUNTER_BUFFER_INDEX};
790 GLint atomicIndex [NUM_ATOMIC_PROPERTIES] = {-1};
791 glGetProgramResourceiv(programHandle, GL_UNIFORM, uniformIndices[uniIdx], NUM_ATOMIC_PROPERTIES, atomicProps, NUM_ATOMIC_PROPERTIES,
nullptr, atomicIndex);
793 if(atomicIndex[0] == acIdx) {
794 printf(
"[INFO]: | %3d) type: %-15s name: %-21s |\n", acCtr++, GLSL_type_to_string(type), atomicName );
795 printf(
"[INFO]: | uniform index: %3d offset: %7d |\n", uniformIndices[uniIdx], atomicOffsets[uniIdx] );
799 delete[] uniformIndices;
800 delete[] atomicOffsets;
804 GLint maxAtomicCounters = 0;
805 glGetIntegerv( GL_MAX_COMBINED_ATOMIC_COUNTERS, &maxAtomicCounters );
806 printf(
"[INFO]: | Atomic Counter Counts: %4d/%4d |\n", numAtomicCounters, maxAtomicCounters );
807 if(hasVertexShader) {
808 GLint maxVertAtomicCounters = 0;
809 glGetIntegerv( GL_MAX_VERTEX_ATOMIC_COUNTERS, &maxVertAtomicCounters );
810 printf(
"[INFO]: | Vertex Atomic Counters: %4d/%4d |\n", vAC, maxVertAtomicCounters );
812 if(hasTessControlShader) {
813 GLint maxTCAtomicCounters = 0;
814 glGetIntegerv( GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, &maxTCAtomicCounters );
815 printf(
"[INFO]: | Tess Ctrl Atomic Counters: %4d/%4d |\n", teAC, maxTCAtomicCounters );
817 if(hasTessEvalShader) {
818 GLint maxTEAtomicCounters = 0;
819 glGetIntegerv( GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, &maxTEAtomicCounters );
820 printf(
"[INFO]: | Tess Eval Atomic Counters: %4d/%4d |\n", tcAC, maxTEAtomicCounters );
822 if(hasGeometryShader) {
823 GLint maxGeoAtomicCounters = 0;
824 glGetIntegerv( GL_MAX_GEOMETRY_ATOMIC_COUNTERS, &maxGeoAtomicCounters );
825 printf(
"[INFO]: | Geometry Atomic Counters: %4d/%4d |\n", gAC, maxGeoAtomicCounters );
827 if(hasFragmentShader) {
828 GLint maxFragAtomicCounters = 0;
829 glGetIntegerv( GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &maxFragAtomicCounters );
830 printf(
"[INFO]: | Fragment Atomic Counters: %4d/%4d |\n", fAC, maxFragAtomicCounters );
832 if(hasComputeShader) {
833 GLint maxComputeAtomicCounters = 0;
834 glGetIntegerv( GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxComputeAtomicCounters );
835 printf(
"[INFO]: | Compute Atomic Counters: %4d/%4d |\n", cAC, maxComputeAtomicCounters );
841 GLboolean printHeader = GL_TRUE;
842 if( hasVertexShader ) printHeader = printSubroutineInfo(programHandle, GL_VERTEX_SHADER, printHeader );
843 if( hasTessControlShader) printHeader = printSubroutineInfo(programHandle, GL_TESS_CONTROL_SHADER, printHeader );
844 if( hasTessEvalShader) printHeader = printSubroutineInfo(programHandle, GL_TESS_EVALUATION_SHADER, printHeader );
845 if( hasGeometryShader ) printHeader = printSubroutineInfo(programHandle, GL_GEOMETRY_SHADER, printHeader );
846 if( hasFragmentShader ) printHeader = printSubroutineInfo(programHandle, GL_FRAGMENT_SHADER, printHeader );
847 if( hasComputeShader ) printSubroutineInfo(programHandle, GL_COMPUTE_SHADER, printHeader );
851 if(useLastNewLine && sDEBUG) printf(
"[INFO]: \\--------------------------------------------------------/\n\n");
854inline GLuint CSCI441_INTERNAL::ShaderUtils::compileShader(
855 const char *filename,
856 const GLenum shaderType
859 GLchar *shaderString;
862 if( readTextFromFile( filename, shaderString ) ) {
864 GLuint shaderHandle = glCreateShader( shaderType );
867 glShaderSource( shaderHandle, 1, (
const char**)&shaderString,
nullptr );
870 delete [] shaderString;
873 glCompileShader( shaderHandle );
876 printShaderLog( shaderHandle );