14#ifndef CSCI441_SHADER_UTILS_HPP
15#define CSCI441_SHADER_UTILS_HPP
19#ifdef CSCI441_USE_GLEW
32namespace CSCI441_INTERNAL::ShaderUtils {
33 static bool sDEBUG =
true;
36 [[maybe_unused]]
void enableDebugMessages();
39 [[maybe_unused]]
void disableDebugMessages();
44 const char* GLSL_type_to_string( GLenum type );
49 const char* GL_shader_type_to_string( GLenum type );
54 const char* GL_primitive_type_to_string( GLenum type );
60 bool readTextFromFile(
const char* filename, GLchar* &output );
66 GLuint compileShader(
const char *filename, GLenum shaderType );
69 void printShaderLog( GLuint shaderHandle );
72 void printProgramLog( GLuint programHandle );
75 void printProgramInfoLog( GLuint programHandle );
78 void printProgramPipelineLog( GLuint pipelineHandle );
84 GLboolean printSubroutineInfo(GLuint programHandle, GLenum shaderStage, GLboolean printHeader );
95 void printShaderProgramInfo( GLuint programHandle,
96 GLboolean hasVertexShader,
97 GLboolean hasTessControlShader, GLboolean hasTessEvalShader,
98 GLboolean hasGeometryShader,
99 GLboolean hasFragmentShader,
100 GLboolean hasComputeShader,
101 GLboolean useLastNewLine );
107inline void CSCI441_INTERNAL::ShaderUtils::enableDebugMessages() {
112inline void CSCI441_INTERNAL::ShaderUtils::disableDebugMessages() {
118inline bool CSCI441_INTERNAL::ShaderUtils::readTextFromFile(
119 const char *filename,
122 std::string buf = std::string(
"");
125 std::ifstream in(filename);
126 if( !in.is_open() ) {
127 fprintf( stderr,
"[ERROR]: Could not open file %s\n", filename );
130 while( std::getline(in, line) ) {
134 output =
new GLchar[buf.length()+1];
135 strncpy(output, buf.c_str(), buf.length());
136 output[buf.length()] =
'\0';
143inline const char* CSCI441_INTERNAL::ShaderUtils::GLSL_type_to_string(
147 case GL_FLOAT:
return "float";
148 case GL_FLOAT_VEC2:
return "vec2";
149 case GL_FLOAT_VEC3:
return "vec3";
150 case GL_FLOAT_VEC4:
return "vec4";
151 case GL_DOUBLE:
return "double";
152 case GL_DOUBLE_VEC2:
return "dvec2";
153 case GL_DOUBLE_VEC3:
return "dvec3";
154 case GL_DOUBLE_VEC4:
return "dvec4";
155 case GL_INT:
return "int";
156 case GL_INT_VEC2:
return "ivec2";
157 case GL_INT_VEC3:
return "ivec3";
158 case GL_INT_VEC4:
return "ivec4";
159 case GL_UNSIGNED_INT:
return "unsigned int";
160 case GL_UNSIGNED_INT_VEC2:
return "uvec2";
161 case GL_UNSIGNED_INT_VEC3:
return "uvec3";
162 case GL_UNSIGNED_INT_VEC4:
return "uvec4";
163 case GL_BOOL:
return "bool";
164 case GL_BOOL_VEC2:
return "bvec2";
165 case GL_BOOL_VEC3:
return "bvec3";
166 case GL_BOOL_VEC4:
return "bvec4";
167 case GL_FLOAT_MAT2:
return "mat2";
168 case GL_FLOAT_MAT3:
return "mat3";
169 case GL_FLOAT_MAT4:
return "mat4";
170 case GL_FLOAT_MAT2x3:
return "mat2x3";
171 case GL_FLOAT_MAT2x4:
return "mat2x4";
172 case GL_FLOAT_MAT3x2:
return "mat3x2";
173 case GL_FLOAT_MAT3x4:
return "mat3x4";
174 case GL_FLOAT_MAT4x2:
return "mat4x2";
175 case GL_FLOAT_MAT4x3:
return "mat4x3";
176 case GL_DOUBLE_MAT2:
return "dmat2";
177 case GL_DOUBLE_MAT3:
return "dmat3";
178 case GL_DOUBLE_MAT4:
return "dmat4";
179 case GL_DOUBLE_MAT2x3:
return "dmat2x3";
180 case GL_DOUBLE_MAT2x4:
return "dmat2x4";
181 case GL_DOUBLE_MAT3x2:
return "dmat3x2";
182 case GL_DOUBLE_MAT3x4:
return "dmat3x4";
183 case GL_DOUBLE_MAT4x2:
return "dmat4x2";
184 case GL_DOUBLE_MAT4x3:
return "dmat4x3";
185 case GL_SAMPLER_1D:
return "sampler1D";
186 case GL_SAMPLER_2D:
return "sampler2D";
187 case GL_SAMPLER_3D:
return "sampler3D";
188 case GL_SAMPLER_CUBE:
return "samplerCube";
189 case GL_SAMPLER_1D_SHADOW:
return "sampler1DShadow";
190 case GL_SAMPLER_2D_SHADOW:
return "sampler2DShadow";
191 case GL_SAMPLER_1D_ARRAY:
return "sampler1DArray";
192 case GL_SAMPLER_2D_ARRAY:
return "sampler2DArray";
193 case GL_SAMPLER_2D_MULTISAMPLE:
return "sampler2DMS";
194 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
return "sampler2DMSArray";
195 case GL_SAMPLER_CUBE_SHADOW:
return "samplerCubeShadow";
196 case GL_SAMPLER_BUFFER:
return "samplerBuffer";
197 case GL_SAMPLER_2D_RECT:
return "sampler2DRect";
198 case GL_SAMPLER_2D_RECT_SHADOW:
return "sampler2DRectShadow";
199 case GL_INT_SAMPLER_1D:
return "isampler1D";
200 case GL_INT_SAMPLER_2D:
return "isampler2D";
201 case GL_INT_SAMPLER_3D:
return "isampler3D";
202 case GL_INT_SAMPLER_CUBE:
return "isamplerCube";
203 case GL_INT_SAMPLER_1D_ARRAY:
return "isampler1DArray";
204 case GL_INT_SAMPLER_2D_ARRAY:
return "isampler2DArray";
205 case GL_INT_SAMPLER_2D_MULTISAMPLE:
return "isampler2DMS";
206 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
return "isampler2DMSArray";
207 case GL_INT_SAMPLER_BUFFER:
return "isamplerBuffer";
208 case GL_INT_SAMPLER_2D_RECT:
return "isampler2DRect";
209 case GL_UNSIGNED_INT_SAMPLER_1D:
return "usampler1D";
210 case GL_UNSIGNED_INT_SAMPLER_2D:
return "usampler2D";
211 case GL_UNSIGNED_INT_SAMPLER_3D:
return "usampler3D";
212 case GL_UNSIGNED_INT_SAMPLER_CUBE:
return "usamplerCube";
213 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
return "usampler1DArray";
214 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
return "usampler2DArray";
215 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
return "usampler2DMS";
216 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
return "usampler2DMSArray";
217 case GL_UNSIGNED_INT_SAMPLER_BUFFER:
return "usamplerBuffer";
218 case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
return "usampler2DRect";
219 case GL_IMAGE_1D:
return "image1D";
220 case GL_IMAGE_2D:
return "image2D";
221 case GL_IMAGE_3D:
return "image3D";
222 case GL_IMAGE_2D_RECT:
return "image2DRect";
223 case GL_IMAGE_CUBE:
return "imageCube";
224 case GL_IMAGE_BUFFER:
return "imageBuffer";
225 case GL_IMAGE_1D_ARRAY:
return "image1DArray";
226 case GL_IMAGE_2D_ARRAY:
return "image2DArray";
227 case GL_IMAGE_2D_MULTISAMPLE:
return "image2DMS";
228 case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
return "image2DMSArray";
229 case GL_INT_IMAGE_1D:
return "iimage1D";
230 case GL_INT_IMAGE_2D:
return "iimage2D";
231 case GL_INT_IMAGE_3D:
return "iimage3D";
232 case GL_INT_IMAGE_2D_RECT:
return "iimage2DRect";
233 case GL_INT_IMAGE_CUBE:
return "iimageCube";
234 case GL_INT_IMAGE_BUFFER:
return "iimageBuffer";
235 case GL_INT_IMAGE_1D_ARRAY:
return "iimage1DArray";
236 case GL_INT_IMAGE_2D_ARRAY:
return "iimage2DArray";
237 case GL_INT_IMAGE_2D_MULTISAMPLE:
return "iimage2DMS";
238 case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
return "iimage2DMSArray";
239 case GL_UNSIGNED_INT_IMAGE_1D:
return "uimage1D";
240 case GL_UNSIGNED_INT_IMAGE_2D:
return "uimage2D";
241 case GL_UNSIGNED_INT_IMAGE_3D:
return "uimage3D";
242 case GL_UNSIGNED_INT_IMAGE_2D_RECT:
return "uimage2DRect";
243 case GL_UNSIGNED_INT_IMAGE_CUBE:
return "uimageCube";
244 case GL_UNSIGNED_INT_IMAGE_BUFFER:
return "uimageBuffer";
245 case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
return "uimage1DArray";
246 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
return "uimage2DArray";
247 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
return "uimage2DMS";
248 case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
return "uimage2DMSArray";
249 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return "atomic_uint";
252 return "other data type";
255inline const char* CSCI441_INTERNAL::ShaderUtils::GL_shader_type_to_string(
259 case GL_VERTEX_SHADER:
return "Vertex Shader";
260 case GL_TESS_CONTROL_SHADER:
return "Tess Ctrl Shader";
261 case GL_TESS_EVALUATION_SHADER:
return "Tess Eval Shader";
262 case GL_GEOMETRY_SHADER:
return "Geometry Shader";
263 case GL_FRAGMENT_SHADER:
return "Fragment Shader";
264 case GL_COMPUTE_SHADER:
return "Compute Shader";
267 return "other shader type";
270inline const char* CSCI441_INTERNAL::ShaderUtils::GL_primitive_type_to_string(
274 case GL_POINTS:
return "Points";
275 case GL_LINES:
return "Lines";
276 case GL_LINE_STRIP:
return "Line Strip";
277 case GL_LINE_LOOP:
return "Line Loop";
278 case GL_LINES_ADJACENCY:
return "Line Adjacency";
279 case GL_TRIANGLES:
return "Triangles";
280 case GL_TRIANGLE_STRIP:
return "Triangle Strip";
281 case GL_TRIANGLES_ADJACENCY:
return "Triangle Adjacency";
282 case GL_PATCHES:
return "Patches";
285 return "other primitive type";
288inline void CSCI441_INTERNAL::ShaderUtils::printShaderLog(
289 const GLuint shaderHandle
292 if( glIsShader( shaderHandle ) ) {
293 GLint maxLength = 0, status = 0, infoLogLength = 0;
294 glGetShaderiv( shaderHandle, GL_INFO_LOG_LENGTH, &maxLength );
297 const auto infoLog =
new GLchar[maxLength];
299 glGetShaderiv( shaderHandle, GL_COMPILE_STATUS, &status );
300 if( sDEBUG ) printf(
"[INFO]: | Shader Handle %2d: Compile%-26s |\n", shaderHandle, (status == 1 ?
"d Successfully" :
"r Error") );
303 glGetShaderInfoLog(shaderHandle, maxLength, &infoLogLength, infoLog );
305 if(infoLogLength > 0 ) {
307 if( sDEBUG ) printf(
"[INFO]: | Shader Handle %d: %s\n", shaderHandle, infoLog );
312 if( sDEBUG ) fprintf( stderr,
"[WARN]: | Handle %-3d is not for a Shader |\n", shaderHandle );
316inline void CSCI441_INTERNAL::ShaderUtils::printProgramLog(
317 const GLuint programHandle
320 if( glIsProgram( programHandle ) ) {
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") );
325 printProgramInfoLog(programHandle);
327 if( sDEBUG ) fprintf( stderr,
"[WARN]: | Handle %-3d is not for a Shader Program |\n", programHandle );
331inline void CSCI441_INTERNAL::ShaderUtils::printProgramInfoLog(
332 const GLuint programHandle
335 if( glIsProgram( programHandle ) ) {
336 GLint maxLength = 0, infoLogLength = 0;
337 glGetProgramiv( programHandle, GL_INFO_LOG_LENGTH, &maxLength );
340 const auto infoLog =
new GLchar[maxLength];
343 glGetProgramInfoLog(programHandle, maxLength, &infoLogLength, infoLog );
345 if(infoLogLength > 0 ) {
347 if( sDEBUG ) printf(
"[INFO]: | Program Handle %d: %s\n", programHandle, infoLog );
352 if( sDEBUG ) fprintf( stderr,
"[WARN]: | Handle %-3d is not for a Shader Program |\n", programHandle );
356inline void CSCI441_INTERNAL::ShaderUtils::printProgramPipelineLog(
357 const GLuint pipelineHandle
360 if( glIsProgramPipeline( pipelineHandle ) ) {
361 GLint maxLength = 0, infoLogLength = 0;
363 glGetProgramPipelineiv( pipelineHandle, GL_INFO_LOG_LENGTH, &maxLength );
366 const auto infoLog =
new GLchar[maxLength];
369 glGetProgramPipelineInfoLog(pipelineHandle, maxLength, &infoLogLength, infoLog );
371 if( infoLogLength > 0 ) {
373 if( sDEBUG ) printf(
"[INFO]: | Pipeline Handle %d: %s\n", pipelineHandle, infoLog );
378 if( sDEBUG ) fprintf( stderr,
"[WARN]: | Handle %-3d is not for a Shader Program Pipeline |\n", pipelineHandle );
382inline GLboolean CSCI441_INTERNAL::ShaderUtils::printSubroutineInfo(
383 const GLuint programHandle,
384 const GLenum shaderStage,
385 const GLboolean printHeader
387 GLint numSubroutineUniforms = 0;
388 glGetProgramStageiv(programHandle, shaderStage, GL_ACTIVE_SUBROUTINE_UNIFORMS, &numSubroutineUniforms);
389 bool headerPrinted =
false;
390 if( numSubroutineUniforms > 0 ) {
392 printf(
"[INFO]: >--------------------------------------------------------<\n");
393 headerPrinted =
true;
395 printf(
"[INFO]: | GL_ACTIVE_SUBROUTINE_UNIFORMS (%-15s): %5i |\n", CSCI441_INTERNAL::ShaderUtils::GL_shader_type_to_string(shaderStage), numSubroutineUniforms);
396 for(
int i = 0; i < numSubroutineUniforms; i++ ) {
397 GLchar subroutineName[256];
398 GLint max_length = 256, actual_length = 0;
399 GLint numCompatibleSubroutines = 0;
401 glGetActiveSubroutineUniformName(programHandle, shaderStage, i, max_length, &actual_length, subroutineName );
402 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_NUM_COMPATIBLE_SUBROUTINES, &numCompatibleSubroutines );
404 const auto compatibleSubroutines =
new GLint[numCompatibleSubroutines];
405 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_COMPATIBLE_SUBROUTINES, compatibleSubroutines );
407 GLint loc = glGetSubroutineUniformLocation(programHandle, shaderStage, subroutineName );
409 printf(
"[INFO]: | %i) name: %-15s #subRoutines: %-5i loc: %2i |\n", i, subroutineName, numCompatibleSubroutines, loc );
411 for(
int j = 0; j < numCompatibleSubroutines; j++ ) {
412 GLint idx = compatibleSubroutines[j];
414 GLchar subroutineImplName[64];
415 GLint max_length2 = 64, actual_length2 = 0;
416 glGetActiveSubroutineName(programHandle, shaderStage, idx, max_length2, &actual_length2, subroutineImplName );
418 printf(
"[INFO]: | %i) subroutine: %-25s index: %2i |\n", j, subroutineImplName, idx );
421 delete[] compatibleSubroutines;
424 return !headerPrinted;
427inline void CSCI441_INTERNAL::ShaderUtils::printShaderProgramInfo(
428 const GLuint programHandle,
429 const GLboolean hasVertexShader,
430 const GLboolean hasTessControlShader,
431 const GLboolean hasTessEvalShader,
432 const GLboolean hasGeometryShader,
433 const GLboolean hasFragmentShader,
434 const GLboolean hasComputeShader,
435 const GLboolean useLastNewLine =
true
437 GLint major = 0, minor = 0;
438 glGetIntegerv(GL_MAJOR_VERSION, &major);
439 glGetIntegerv(GL_MINOR_VERSION, &minor);
441 GLuint shaders[6] = {0};
443 GLint actual_count = 0;
445 GLint maxAttributeNameLength = 0;
446 GLint maxUniformNameLength = 0;
450 glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeNameLength);
451 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformNameLength);
453 glGetAttachedShaders(programHandle, max_count, &actual_count, shaders );
454 if(actual_count > 0) {
455 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n");
456 if( sDEBUG ) printf(
"[INFO]: | GL_ATTACHED_SHADERS: %33i |\n", actual_count);
457 for(
int i = 0; i < actual_count; i++ ) {
459 glGetShaderiv( shaders[i], GL_SHADER_TYPE, &shaderType );
460 if( sDEBUG ) printf(
"[INFO]: | %i) %-38s Handle: %2i |\n", i, GL_shader_type_to_string(shaderType), shaders[i]);
465 if(hasGeometryShader) {
466 if( major > 3 || (major >= 3 && minor >= 2) ) {
467 GLint verticesOut = 0, inputType = 0, outputType = 0;
468 glGetProgramiv(programHandle, GL_GEOMETRY_VERTICES_OUT, &verticesOut);
469 glGetProgramiv(programHandle, GL_GEOMETRY_INPUT_TYPE, &inputType);
470 glGetProgramiv(programHandle, GL_GEOMETRY_OUTPUT_TYPE, &outputType);
472 printf(
"[INFO]: >--------------------------------------------------------<\n");
473 printf(
"[INFO]: | GEOMETRY SHADER PRIMITIVE I/O |\n");
474 printf(
"[INFO]: | Input Type: %40s |\n", GL_primitive_type_to_string(inputType) );
475 printf(
"[INFO]: | Output Type: %39s |\n", GL_primitive_type_to_string(outputType) );
476 printf(
"[INFO]: | Max Vertices Out: %34d |\n", verticesOut );
481 if(hasVertexShader) {
482 GLint numActiveAttributes = 0;
483 glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTES, &numActiveAttributes );
484 if( numActiveAttributes > 0 ) {
485 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n");
486 if( sDEBUG ) printf(
"[INFO]: | GL_ACTIVE_ATTRIBUTES: %32i |\n", numActiveAttributes );
487 for(
int i = 0; i < numActiveAttributes; i++ ) {
488 const auto name =
new GLchar[maxAttributeNameLength];
489 GLint actual_length = 0, size = 0;
490 GLenum type = GL_NONE;
491 glGetActiveAttrib(programHandle, i, maxAttributeNameLength, &actual_length, &size, &type, name );
493 for(
int j = 0; j < size; j++ ) {
496 int max_array_size = actual_length + 4 + 2 + 1;
497 const auto array_name =
new GLchar[max_array_size];
499 snprintf( array_name, max_array_size,
"%s[%i]", name, j );
500 GLint location = glGetAttribLocation(programHandle, array_name);
501 if( sDEBUG ) printf(
"[INFO]: | %i) type: %-15s name: %-13s loc: %2i |\n", i, GLSL_type_to_string( type ), array_name, location );
505 GLint location = glGetAttribLocation(programHandle, name );
506 if( sDEBUG ) printf(
"[INFO]: | %i) type: %-15s name: %-13s loc: %2i |\n",i, GLSL_type_to_string( type ), name, location );
514 GLint numActiveUniforms = 0;
515 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORMS, &numActiveUniforms);
516 if( numActiveUniforms > 0 ) {
517 constexpr int NUM_PROPS = 6;
518 GLenum props[NUM_PROPS] = {GL_REFERENCED_BY_VERTEX_SHADER,
519 GL_REFERENCED_BY_TESS_CONTROL_SHADER,
520 GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
521 GL_REFERENCED_BY_GEOMETRY_SHADER,
522 GL_REFERENCED_BY_FRAGMENT_SHADER,
525 if((major == 4 && minor >= 3) || major > 4) {
526 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
528 GLint results[NUM_PROPS] = {0};
530 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n" );
531 if( sDEBUG ) printf(
"[INFO]: | GL_ACTIVE_UNIFORMS: %34i |\n", numActiveUniforms);
532 for(
int uIdx = 0; uIdx < numActiveUniforms; uIdx++) {
533 const auto name =
new GLchar[maxUniformNameLength];
534 GLint actual_length = 0, size = 0, location = -1;
535 GLenum type = GL_NONE;
536 glGetActiveUniform(programHandle, uIdx, maxUniformNameLength, &actual_length, &size, &type, name );
538 for(
int j = 0; j < size; j++) {
539 int max_array_size = actual_length + 4 + 2 + 1;
540 const auto array_name =
new GLchar[max_array_size];
541 snprintf(array_name, max_array_size,
"%s[%i]", name, j);
542 location = glGetUniformLocation(programHandle, array_name);
544 if (sDEBUG) printf(
"[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), array_name, location);
549 location = glGetUniformLocation(programHandle, name);
551 if (sDEBUG) printf(
"[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), name, location);
555 if(((major == 4 && minor >= 3) || major > 4) && location != -1) {
556 glGetProgramResourceiv(programHandle, GL_UNIFORM, uIdx, NUM_PROPS, props, NUM_PROPS,
nullptr, results);
557 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" :
""));
564 GLint numActiveUniformBlocks = 0;
565 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveUniformBlocks);
566 if( numActiveUniformBlocks > 0 ) {
567 int vsCount, tcsCount, tesCount, gsCount, fsCount, csCount;
568 vsCount = tcsCount = tesCount = gsCount = fsCount = csCount = 0;
570 if( sDEBUG ) printf(
"[INFO]: >--------------------------------------------------------<\n");
571 if( sDEBUG ) printf(
"[INFO]: | GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: %20d |\n", numActiveUniformBlocks);
572 for(
int i = 0; i < numActiveUniformBlocks; i++ ) {
573 GLint numActiveUniformsInBlock = 0, bindingPoint = 0;
574 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numActiveUniformsInBlock );
575 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_BINDING, &bindingPoint);
578 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &actualLen);
579 const auto name =
new GLchar[actualLen];
580 glGetActiveUniformBlockName(programHandle, i, actualLen,
nullptr, name);
582 const auto indices =
new GLint[numActiveUniformsInBlock];
583 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices);
585 const auto offsets =
new GLint[numActiveUniformsInBlock];
586 glGetActiveUniformsiv(programHandle, numActiveUniformsInBlock, (GLuint*)indices, GL_UNIFORM_OFFSET, offsets);
588 if( sDEBUG ) printf(
"[INFO]: | %d) %-19s binding: %3d |\n", i, name, bindingPoint);
590 GLint vs, tcs, tes, gs, fs, cs;
591 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &vs);
if( vs ) vsCount++;
592 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER, &tcs);
if( tcs) tcsCount++;
593 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER, &tes);
if( tes) tesCount++;
594 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, &gs);
if( gs ) gsCount++;
595 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &fs);
if( fs ) fsCount++;
596 if((major == 4 && minor >= 3) || major > 4) {
597 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER, &cs);
if( cs ) csCount++;
599 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" :
""));
601 const auto name2 =
new char[maxUniformNameLength];
602 for(
int j = 0; j < numActiveUniformsInBlock; j++) {
605 glGetActiveUniform(programHandle, indices[j], maxUniformNameLength, &actualLen, &uniSize, &type, name2);
607 constexpr GLsizei NUM_ATOMIC_PROPERTIES = 1;
608 GLint atomicIndex[NUM_ATOMIC_PROPERTIES] = {-1};
609 if((major == 4 && minor >= 3) || major > 4) {
610 GLenum atomicProps[NUM_ATOMIC_PROPERTIES] = {GL_ATOMIC_COUNTER_BUFFER_INDEX};
611 glGetProgramResourceiv(programHandle, GL_UNIFORM, indices[j], NUM_ATOMIC_PROPERTIES, atomicProps, NUM_ATOMIC_PROPERTIES,
nullptr, atomicIndex);
614 if( atomicIndex[0] == -1 && sDEBUG ) {
615 printf(
"[INFO]: | %2d) type: %-15s name: %-21s |\n", j, GLSL_type_to_string(type), name2);
616 printf(
"[INFO]: | uniform index: %3d offset: %4d |\n", indices[j], offsets[j]);
626 if( vsCount + tcsCount + tesCount + gsCount + fsCount + csCount > 0 ) {
627 GLint maxUniBlocks = 0;
628 glGetIntegerv( GL_MAX_COMBINED_UNIFORM_BLOCKS, &maxUniBlocks );
629 if( sDEBUG ) printf(
"[INFO]: | Shader Uniform Block Counts %2d/%2d |\n", numActiveUniformBlocks, maxUniBlocks);
630 if( hasVertexShader ) {
631 GLint maxVertexUniformBlocks = 0;
632 glGetIntegerv( GL_MAX_VERTEX_UNIFORM_BLOCKS, &maxVertexUniformBlocks );
634 if( sDEBUG ) printf(
"[INFO]: | Vertex Shader Uniform Blocks: %18d/%2d |\n", vsCount, maxVertexUniformBlocks );
636 if( hasTessControlShader ) {
637 GLint maxTessControlUniformBlocks = 0;
638 glGetIntegerv( GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, &maxTessControlUniformBlocks );
640 if( sDEBUG ) printf(
"[INFO]: | Tess Ctrl Shader Uniform Blocks: %15d/%2d |\n", tcsCount, maxTessControlUniformBlocks );
642 if( hasTessEvalShader ) {
643 GLint maxTessEvalUniformBlocks = 0;
644 glGetIntegerv( GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, &maxTessEvalUniformBlocks );
646 if( sDEBUG ) printf(
"[INFO]: | Tess Eval Shader Uniform Blocks: %15d/%2d |\n", tesCount, maxTessEvalUniformBlocks );
648 if( hasGeometryShader ) {
649 GLint maxGeometryUniformBlocks = 0;
650 glGetIntegerv( GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &maxGeometryUniformBlocks );
652 if( sDEBUG ) printf(
"[INFO]: | Geometry Shader Uniform Blocks: %16d/%2d |\n", gsCount, maxGeometryUniformBlocks );
654 if( hasFragmentShader ) {
655 GLint maxFragmentUniformBlocks = 0;
656 glGetIntegerv( GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &maxFragmentUniformBlocks );
658 if( sDEBUG ) printf(
"[INFO]: | Fragment Shader Uniform Blocks: %16d/%2d |\n", fsCount, maxFragmentUniformBlocks );
660 if( hasComputeShader ) {
661 GLint maxComputeUniformBlocks = 0;
662 glGetIntegerv( GL_MAX_COMPUTE_UNIFORM_BLOCKS, &maxComputeUniformBlocks );
664 if( sDEBUG ) printf(
"[INFO]: | Compute Shader Uniform Blocks: %17d/%2d |\n", csCount, maxComputeUniformBlocks );
670 if ((major == 4 && minor >=3) || major > 4) {
671 GLint numFragOutputs;
672 glGetProgramInterfaceiv(programHandle, GL_PROGRAM_OUTPUT,GL_ACTIVE_RESOURCES, &numFragOutputs);
674 printf(
"[INFO]: >--------------------------------------------------------<\n");
675 printf(
"[INFO]: | GL_PROGRAM_OUTPUT: %35d |\n", numFragOutputs);
677 if(numFragOutputs > 0) {
679 glGetProgramInterfaceiv(programHandle, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, &maxLen);
681 const auto outputName =
new GLchar[maxLen];
684 for (GLint i = 0; i < numFragOutputs; i++) {
685 GLsizei actualLength = 0;
686 glGetProgramResourceName(programHandle, GL_PROGRAM_OUTPUT, i, maxLen, &actualLength, outputName);
687 GLint location = glGetFragDataLocation(programHandle, outputName);
688 GLint index = glGetFragDataIndex(programHandle, outputName);
689 printf(
"[INFO]: | %3d) name: %-18s location: %3d index: %3d |\n", i, outputName, location, index );
698 if((major == 4 && minor >= 3) || major > 4) {
700 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numSSBO);
703 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &maxLen);
704 const auto ssboName =
new GLchar[maxLen];
705 GLsizei ssboNameLen = 0;
707 constexpr int NUM_PROPS = 7;
708 GLenum props[NUM_PROPS] = {GL_BUFFER_BINDING,
709 GL_REFERENCED_BY_VERTEX_SHADER,
710 GL_REFERENCED_BY_TESS_CONTROL_SHADER, GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
711 GL_REFERENCED_BY_GEOMETRY_SHADER,
712 GL_REFERENCED_BY_FRAGMENT_SHADER,
713 GL_REFERENCED_BY_COMPUTE_SHADER};
714 GLsizei numWritten = 0;
715 GLint results[NUM_PROPS] = {0};
717 int vSSB, teSSB, tcSSB, gSSB, fSSB, cSSB;
718 vSSB = teSSB = tcSSB = gSSB = fSSB = cSSB = 0;
720 printf(
"[INFO]: >--------------------------------------------------------<\n");
721 printf(
"[INFO]: | GL_SHADER_STORAGE_BLOCK: %29d |\n", numSSBO );
722 for(
int i = 0; i < numSSBO; i++) {
723 glGetProgramResourceName(programHandle, GL_SHADER_STORAGE_BLOCK, i, maxLen, &ssboNameLen, ssboName);
724 GLuint ssboIndex = glGetProgramResourceIndex(programHandle, GL_SHADER_STORAGE_BLOCK, ssboName);
725 glGetProgramResourceiv(programHandle, GL_SHADER_STORAGE_BLOCK, i, NUM_PROPS, props, NUM_PROPS, &numWritten, results);
727 printf(
"[INFO]: | %3d) name: %-19s index: %3d binding: %3d |\n", i, ssboName, ssboIndex, results[0] );
728 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" :
""));
730 if(results[1]) vSSB++;
731 if(results[2]) teSSB++;
732 if(results[3]) tcSSB++;
733 if(results[4]) gSSB++;
734 if(results[5]) fSSB++;
735 if(results[6]) cSSB++;
738 GLint maxSSBCounters = 0;
739 glGetIntegerv( GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxSSBCounters );
740 printf(
"[INFO]: | Shader Storage Block Counts: %2d/%2d |\n", numSSBO, maxSSBCounters );
741 if(hasVertexShader) {
742 GLint maxVertSSB = 0;
743 glGetIntegerv( GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertSSB );
744 printf(
"[INFO]: | Vertex Shader Storage Blocks: %2d/%2d |\n", vSSB, maxVertSSB );
746 if(hasTessControlShader) {
748 glGetIntegerv( GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &maxTESSB );
749 printf(
"[INFO]: | Tess Ctrl Shader Storage Blocks: %2d/%2d |\n", teSSB, maxTESSB );
751 if(hasTessEvalShader) {
753 glGetIntegerv( GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &maxTCSSB );
754 printf(
"[INFO]: | Tess Eval Shader Storage Blocks: %2d/%2d |\n", tcSSB, maxTCSSB );
756 if(hasGeometryShader) {
758 glGetIntegerv( GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &maxGeoSSB );
759 printf(
"[INFO]: | Geometry Shader Storage Blocks: %2d/%2d |\n", gSSB, maxGeoSSB );
761 if(hasFragmentShader) {
762 GLint maxFragSSB = 0;
763 glGetIntegerv( GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragSSB );
764 printf(
"[INFO]: | Fragment Shader Storage Blocks: %2d/%2d |\n", fSSB, maxFragSSB );
766 if(hasComputeShader) {
767 GLint maxComputeSSB = 0;
768 glGetIntegerv( GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeSSB );
769 printf(
"[INFO]: | Compute Shader Storage Blocks: %2d/%2d |\n", cSSB, maxComputeSSB );
776 if((major == 4 && minor >= 2) || major > 4) {
777 GLint numAtomicCounters = 0;
778 glGetProgramInterfaceiv(programHandle, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numAtomicCounters);
780 if(numAtomicCounters > 0) {
781 constexpr int NUM_PROPS = 6;
782 GLenum props[NUM_PROPS] = {GL_REFERENCED_BY_VERTEX_SHADER,
783 GL_REFERENCED_BY_TESS_CONTROL_SHADER,
784 GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
785 GL_REFERENCED_BY_GEOMETRY_SHADER,
786 GL_REFERENCED_BY_FRAGMENT_SHADER,
789 if((major == 4 && minor >= 3) || major > 4) {
790 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
793 GLsizei numWritten = 0;
794 GLint results[NUM_PROPS] = {0};
796 printf(
"[INFO]: >--------------------------------------------------------<\n");
797 printf(
"[INFO]: | GL_ATOMIC_COUNTER_BUFFER: %28d |\n", numAtomicCounters );
799 int vAC, teAC, tcAC, gAC, fAC, cAC;
800 vAC = teAC = tcAC = gAC = fAC = cAC = 0;
802 for(GLint acIdx = 0; acIdx < numAtomicCounters; acIdx++) {
803 GLint binding = -1, bufferSize = 0, nac = 0;
805 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_BINDING, &binding);
806 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE, &bufferSize);
807 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS, &nac);
809 const auto uniformIndices =
new GLint[nac];
810 const auto atomicOffsets =
new GLint[nac];
811 const auto atomicName =
new GLchar[maxUniformNameLength];
813 glGetActiveAtomicCounterBufferiv(programHandle, acIdx, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES, uniformIndices);
814 glGetActiveUniformsiv(programHandle, nac, (GLuint*)uniformIndices, GL_UNIFORM_OFFSET, atomicOffsets);
815 glGetProgramResourceiv(programHandle, GL_ATOMIC_COUNTER_BUFFER, acIdx, NUM_PROPS, props, NUM_PROPS, &numWritten, results);
818 if(results[0]) vAC++;
819 if(results[1]) teAC++;
820 if(results[2]) tcAC++;
821 if(results[3]) gAC++;
822 if(results[4]) fAC++;
823 if(results[5]) cAC++;
825 printf(
"[INFO]: | %d) binding: %11d buffer size: %4d |\n", acIdx, binding, bufferSize );
826 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" :
""));
828 GLint acCtr = 0, actualLen = 0, uniSize = 0;
829 GLenum type = GL_NONE;
830 for(GLint uniIdx = 0; uniIdx < nac; uniIdx++) {
831 glGetActiveUniform(programHandle, uniformIndices[uniIdx], maxUniformNameLength, &actualLen, &uniSize, &type, atomicName);
833 constexpr GLsizei NUM_ATOMIC_PROPERTIES = 1;
834 GLenum atomicProps[NUM_ATOMIC_PROPERTIES] = {GL_ATOMIC_COUNTER_BUFFER_INDEX};
835 GLint atomicIndex [NUM_ATOMIC_PROPERTIES] = {-1};
836 glGetProgramResourceiv(programHandle, GL_UNIFORM, uniformIndices[uniIdx], NUM_ATOMIC_PROPERTIES, atomicProps, NUM_ATOMIC_PROPERTIES,
nullptr, atomicIndex);
838 if(atomicIndex[0] == acIdx) {
839 printf(
"[INFO]: | %3d) type: %-15s name: %-21s |\n", acCtr++, GLSL_type_to_string(type), atomicName );
840 printf(
"[INFO]: | uniform index: %3d offset: %7d |\n", uniformIndices[uniIdx], atomicOffsets[uniIdx] );
844 delete[] uniformIndices;
845 delete[] atomicOffsets;
849 GLint maxAtomicCounters = 0;
850 glGetIntegerv( GL_MAX_COMBINED_ATOMIC_COUNTERS, &maxAtomicCounters );
851 printf(
"[INFO]: | Atomic Counter Counts: %4d/%4d |\n", numAtomicCounters, maxAtomicCounters );
852 if(hasVertexShader) {
853 GLint maxVertAtomicCounters = 0;
854 glGetIntegerv( GL_MAX_VERTEX_ATOMIC_COUNTERS, &maxVertAtomicCounters );
855 printf(
"[INFO]: | Vertex Atomic Counters: %4d/%4d |\n", vAC, maxVertAtomicCounters );
857 if(hasTessControlShader) {
858 GLint maxTCAtomicCounters = 0;
859 glGetIntegerv( GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, &maxTCAtomicCounters );
860 printf(
"[INFO]: | Tess Ctrl Atomic Counters: %4d/%4d |\n", teAC, maxTCAtomicCounters );
862 if(hasTessEvalShader) {
863 GLint maxTEAtomicCounters = 0;
864 glGetIntegerv( GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, &maxTEAtomicCounters );
865 printf(
"[INFO]: | Tess Eval Atomic Counters: %4d/%4d |\n", tcAC, maxTEAtomicCounters );
867 if(hasGeometryShader) {
868 GLint maxGeoAtomicCounters = 0;
869 glGetIntegerv( GL_MAX_GEOMETRY_ATOMIC_COUNTERS, &maxGeoAtomicCounters );
870 printf(
"[INFO]: | Geometry Atomic Counters: %4d/%4d |\n", gAC, maxGeoAtomicCounters );
872 if(hasFragmentShader) {
873 GLint maxFragAtomicCounters = 0;
874 glGetIntegerv( GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &maxFragAtomicCounters );
875 printf(
"[INFO]: | Fragment Atomic Counters: %4d/%4d |\n", fAC, maxFragAtomicCounters );
877 if(hasComputeShader) {
878 GLint maxComputeAtomicCounters = 0;
879 glGetIntegerv( GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxComputeAtomicCounters );
880 printf(
"[INFO]: | Compute Atomic Counters: %4d/%4d |\n", cAC, maxComputeAtomicCounters );
886 GLboolean printHeader = GL_TRUE;
887 if( hasVertexShader ) printHeader = printSubroutineInfo(programHandle, GL_VERTEX_SHADER, printHeader );
888 if( hasTessControlShader) printHeader = printSubroutineInfo(programHandle, GL_TESS_CONTROL_SHADER, printHeader );
889 if( hasTessEvalShader) printHeader = printSubroutineInfo(programHandle, GL_TESS_EVALUATION_SHADER, printHeader );
890 if( hasGeometryShader ) printHeader = printSubroutineInfo(programHandle, GL_GEOMETRY_SHADER, printHeader );
891 if( hasFragmentShader ) printHeader = printSubroutineInfo(programHandle, GL_FRAGMENT_SHADER, printHeader );
892 if( hasComputeShader ) printSubroutineInfo(programHandle, GL_COMPUTE_SHADER, printHeader );
896 if(useLastNewLine && sDEBUG) printf(
"[INFO]: \\--------------------------------------------------------/\n\n");
899inline GLuint CSCI441_INTERNAL::ShaderUtils::compileShader(
900 const char *filename,
901 const GLenum shaderType
904 GLchar *shaderString;
907 if( readTextFromFile( filename, shaderString ) ) {
909 GLuint shaderHandle = glCreateShader( shaderType );
912 glShaderSource( shaderHandle, 1, (
const char**)&shaderString,
nullptr );
915 delete [] shaderString;
918 glCompileShader( shaderHandle );
921 printShaderLog( shaderHandle );