14#ifndef CSCI441_SHADER_UTILS_HPP
15#define CSCI441_SHADER_UTILS_HPP
18#include "LogUtils.hpp"
20#ifdef CSCI441_USE_GLEW
33namespace CSCI441_INTERNAL::ShaderUtils {
34 inline bool sDEBUG =
true;
37 [[maybe_unused]]
void enableDebugMessages();
40 [[maybe_unused]]
void disableDebugMessages();
45 const char* GLSL_type_to_string( GLenum type );
50 const char* GL_shader_type_to_string( GLenum type );
55 const char* GL_primitive_type_to_string( GLenum type );
61 bool readTextFromFile(
const char* filename, GLchar* &output );
67 GLuint compileShader(
const char *filename, GLenum shaderType );
70 void printShaderLog( GLuint shaderHandle );
73 void printProgramLog( GLuint programHandle );
76 void printProgramInfoLog( GLuint programHandle );
79 void printProgramPipelineLog( GLuint pipelineHandle );
85 GLboolean printSubroutineInfo(GLuint programHandle, GLenum shaderStage, GLboolean printHeader );
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 );
108inline void CSCI441_INTERNAL::ShaderUtils::enableDebugMessages() {
113inline void CSCI441_INTERNAL::ShaderUtils::disableDebugMessages() {
119inline bool CSCI441_INTERNAL::ShaderUtils::readTextFromFile(
120 const char *filename,
123 std::string buf = std::string(
"");
126 std::ifstream in(filename);
127 if( !in.is_open() ) {
131 while( std::getline(in, line) ) {
135 output =
new GLchar[buf.length()+1];
136 strncpy(output, buf.c_str(), buf.length());
137 output[buf.length()] =
'\0';
144inline const char* CSCI441_INTERNAL::ShaderUtils::GLSL_type_to_string(
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";
253 return "other data type";
256inline const char* CSCI441_INTERNAL::ShaderUtils::GL_shader_type_to_string(
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";
268 return "other shader type";
271inline const char* CSCI441_INTERNAL::ShaderUtils::GL_primitive_type_to_string(
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";
286 return "other primitive type";
289inline void CSCI441_INTERNAL::ShaderUtils::printShaderLog(
290 const GLuint shaderHandle
293 if( glIsShader( shaderHandle ) ) {
294 GLint maxLength = 0, status = 0, infoLogLength = 0;
295 glGetShaderiv( shaderHandle, GL_INFO_LOG_LENGTH, &maxLength );
298 const auto infoLog =
new GLchar[maxLength];
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") );
304 glGetShaderInfoLog(shaderHandle, maxLength, &infoLogLength, infoLog );
306 if(infoLogLength > 0 ) {
317inline void CSCI441_INTERNAL::ShaderUtils::printProgramLog(
318 const GLuint programHandle
321 if( glIsProgram( programHandle ) ) {
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") );
326 printProgramInfoLog(programHandle);
332inline void CSCI441_INTERNAL::ShaderUtils::printProgramInfoLog(
333 const GLuint programHandle
336 if( glIsProgram( programHandle ) ) {
337 GLint maxLength = 0, infoLogLength = 0;
338 glGetProgramiv( programHandle, GL_INFO_LOG_LENGTH, &maxLength );
341 const auto infoLog =
new GLchar[maxLength];
344 glGetProgramInfoLog(programHandle, maxLength, &infoLogLength, infoLog );
346 if(infoLogLength > 0 ) {
357inline void CSCI441_INTERNAL::ShaderUtils::printProgramPipelineLog(
358 const GLuint pipelineHandle
361 if( glIsProgramPipeline( pipelineHandle ) ) {
362 GLint maxLength = 0, infoLogLength = 0;
364 glGetProgramPipelineiv( pipelineHandle, GL_INFO_LOG_LENGTH, &maxLength );
367 const auto infoLog =
new GLchar[maxLength];
370 glGetProgramPipelineInfoLog(pipelineHandle, maxLength, &infoLogLength, infoLog );
372 if( infoLogLength > 0 ) {
383inline GLboolean CSCI441_INTERNAL::ShaderUtils::printSubroutineInfo(
384 const GLuint programHandle,
385 const GLenum shaderStage,
386 const GLboolean printHeader
388 GLint numSubroutineUniforms = 0;
389 glGetProgramStageiv(programHandle, shaderStage, GL_ACTIVE_SUBROUTINE_UNIFORMS, &numSubroutineUniforms);
390 bool headerPrinted =
false;
391 if( numSubroutineUniforms > 0 ) {
394 headerPrinted =
true;
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;
402 glGetActiveSubroutineUniformName(programHandle, shaderStage, i, max_length, &actual_length, subroutineName );
403 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_NUM_COMPATIBLE_SUBROUTINES, &numCompatibleSubroutines );
405 const auto compatibleSubroutines =
new GLint[numCompatibleSubroutines];
406 glGetActiveSubroutineUniformiv(programHandle, shaderStage, i, GL_COMPATIBLE_SUBROUTINES, compatibleSubroutines );
408 GLint loc = glGetSubroutineUniformLocation(programHandle, shaderStage, subroutineName );
410 CSCI441::LogUtils::log(
"[INFO]: | %i) name: %-15s #subRoutines: %-5i loc: %2i |\n", i, subroutineName, numCompatibleSubroutines, loc );
412 for(
int j = 0; j < numCompatibleSubroutines; j++ ) {
413 GLint idx = compatibleSubroutines[j];
415 GLchar subroutineImplName[64];
416 GLint max_length2 = 64, actual_length2 = 0;
417 glGetActiveSubroutineName(programHandle, shaderStage, idx, max_length2, &actual_length2, subroutineImplName );
422 delete[] compatibleSubroutines;
425 return !headerPrinted;
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
438 GLint major = 0, minor = 0;
439 glGetIntegerv(GL_MAJOR_VERSION, &major);
440 glGetIntegerv(GL_MINOR_VERSION, &minor);
442 GLuint shaders[6] = {0};
444 GLint actual_count = 0;
446 GLint maxAttributeNameLength = 0;
447 GLint maxUniformNameLength = 0;
451 glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeNameLength);
452 glGetProgramiv(programHandle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformNameLength);
454 glGetAttachedShaders(programHandle, max_count, &actual_count, shaders );
455 if(actual_count > 0) {
456 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: >--------------------------------------------------------<\n");
458 for(
int i = 0; i < actual_count; i++ ) {
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]);
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);
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");
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 );
494 for(
int j = 0; j < size; j++ ) {
497 int max_array_size = actual_length + 4 + 2 + 1;
498 const auto array_name =
new GLchar[max_array_size];
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 );
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 );
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,
526 if((major == 4 && minor >= 3) || major > 4) {
527 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
529 GLint results[NUM_PROPS] = {0};
531 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: >--------------------------------------------------------<\n" );
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 );
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);
550 if (sDEBUG)
CSCI441::LogUtils::log(
"[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), array_name, location);
557 location = glGetUniformLocation(programHandle, name);
559 if (sDEBUG)
CSCI441::LogUtils::log(
"[INFO]: | %2i) type: %-15s name: %-13s loc: %2i |\n", uIdx, GLSL_type_to_string(type), name, location);
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" :
""));
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;
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);
586 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &actualLen);
587 const auto name =
new GLchar[actualLen];
588 glGetActiveUniformBlockName(programHandle, i, actualLen,
nullptr, name);
590 const auto indices =
new GLint[numActiveUniformsInBlock];
591 glGetActiveUniformBlockiv(programHandle, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices);
593 const auto offsets =
new GLint[numActiveUniformsInBlock];
594 glGetActiveUniformsiv(programHandle, numActiveUniformsInBlock, (GLuint*)indices, GL_UNIFORM_OFFSET, offsets);
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++;
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" :
""));
610 const auto name2 =
new char[maxUniformNameLength];
611 for(
int j = 0; j < numActiveUniformsInBlock; j++) {
614 glGetActiveUniform(programHandle, indices[j], maxUniformNameLength, &actualLen, &uniSize, &type, name2);
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);
623 if( atomicIndex[0] == -1 && sDEBUG ) {
624 CSCI441::LogUtils::log(
"[INFO]: | %2d) type: %-15s name: %-21s |\n", j, GLSL_type_to_string(type), name2);
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 );
643 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: | Vertex Shader Uniform Blocks: %18d/%2d |\n", vsCount, maxVertexUniformBlocks );
645 if( hasTessControlShader ) {
646 GLint maxTessControlUniformBlocks = 0;
647 glGetIntegerv( GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, &maxTessControlUniformBlocks );
649 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: | Tess Ctrl Shader Uniform Blocks: %15d/%2d |\n", tcsCount, maxTessControlUniformBlocks );
651 if( hasTessEvalShader ) {
652 GLint maxTessEvalUniformBlocks = 0;
653 glGetIntegerv( GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, &maxTessEvalUniformBlocks );
655 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: | Tess Eval Shader Uniform Blocks: %15d/%2d |\n", tesCount, maxTessEvalUniformBlocks );
657 if( hasGeometryShader ) {
658 GLint maxGeometryUniformBlocks = 0;
659 glGetIntegerv( GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &maxGeometryUniformBlocks );
661 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: | Geometry Shader Uniform Blocks: %16d/%2d |\n", gsCount, maxGeometryUniformBlocks );
663 if( hasFragmentShader ) {
664 GLint maxFragmentUniformBlocks = 0;
665 glGetIntegerv( GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &maxFragmentUniformBlocks );
667 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: | Fragment Shader Uniform Blocks: %16d/%2d |\n", fsCount, maxFragmentUniformBlocks );
669 if( hasComputeShader ) {
670 GLint maxComputeUniformBlocks = 0;
671 glGetIntegerv( GL_MAX_COMPUTE_UNIFORM_BLOCKS, &maxComputeUniformBlocks );
673 if( sDEBUG )
CSCI441::LogUtils::log(
"[INFO]: | Compute Shader Uniform Blocks: %17d/%2d |\n", csCount, maxComputeUniformBlocks );
679 if ((major == 4 && minor >=3) || major > 4) {
680 GLint numFragOutputs;
681 glGetProgramInterfaceiv(programHandle, GL_PROGRAM_OUTPUT,GL_ACTIVE_RESOURCES, &numFragOutputs);
686 if(numFragOutputs > 0) {
688 glGetProgramInterfaceiv(programHandle, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, &maxLen);
690 const auto outputName =
new GLchar[maxLen];
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 );
707 if((major == 4 && minor >= 3) || major > 4) {
709 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numSSBO);
712 glGetProgramInterfaceiv(programHandle, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &maxLen);
713 const auto ssboName =
new GLchar[maxLen];
714 GLsizei ssboNameLen = 0;
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};
726 int vSSB, teSSB, tcSSB, gSSB, fSSB, cSSB;
727 vSSB = teSSB = tcSSB = gSSB = fSSB = cSSB = 0;
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);
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" :
""));
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++;
747 GLint maxSSBCounters = 0;
748 glGetIntegerv( GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxSSBCounters );
750 if(hasVertexShader) {
751 GLint maxVertSSB = 0;
752 glGetIntegerv( GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertSSB );
755 if(hasTessControlShader) {
757 glGetIntegerv( GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &maxTESSB );
760 if(hasTessEvalShader) {
762 glGetIntegerv( GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &maxTCSSB );
765 if(hasGeometryShader) {
767 glGetIntegerv( GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &maxGeoSSB );
770 if(hasFragmentShader) {
771 GLint maxFragSSB = 0;
772 glGetIntegerv( GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragSSB );
775 if(hasComputeShader) {
776 GLint maxComputeSSB = 0;
777 glGetIntegerv( GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeSSB );
785 if((major == 4 && minor >= 2) || major > 4) {
786 GLint numAtomicCounters = 0;
787 glGetProgramInterfaceiv(programHandle, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numAtomicCounters);
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,
798 if((major == 4 && minor >= 3) || major > 4) {
799 props[5] = GL_REFERENCED_BY_COMPUTE_SHADER;
802 GLsizei numWritten = 0;
803 GLint results[NUM_PROPS] = {0};
808 int vAC, teAC, tcAC, gAC, fAC, cAC;
809 vAC = teAC = tcAC = gAC = fAC = cAC = 0;
811 for(GLint acIdx = 0; acIdx < numAtomicCounters; acIdx++) {
812 GLint binding = -1, bufferSize = 0, nac = 0;
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);
818 const auto uniformIndices =
new GLint[nac];
819 const auto atomicOffsets =
new GLint[nac];
820 const auto atomicName =
new GLchar[maxUniformNameLength];
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);
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++;
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" :
""));
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);
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);
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] );
853 delete[] uniformIndices;
854 delete[] atomicOffsets;
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 );
866 if(hasTessControlShader) {
867 GLint maxTCAtomicCounters = 0;
868 glGetIntegerv( GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, &maxTCAtomicCounters );
871 if(hasTessEvalShader) {
872 GLint maxTEAtomicCounters = 0;
873 glGetIntegerv( GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, &maxTEAtomicCounters );
876 if(hasGeometryShader) {
877 GLint maxGeoAtomicCounters = 0;
878 glGetIntegerv( GL_MAX_GEOMETRY_ATOMIC_COUNTERS, &maxGeoAtomicCounters );
881 if(hasFragmentShader) {
882 GLint maxFragAtomicCounters = 0;
883 glGetIntegerv( GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &maxFragAtomicCounters );
886 if(hasComputeShader) {
887 GLint maxComputeAtomicCounters = 0;
888 glGetIntegerv( GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxComputeAtomicCounters );
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 );
905 if(useLastNewLine && sDEBUG)
CSCI441::LogUtils::log(
"[INFO]: \\--------------------------------------------------------/\n\n");
908inline GLuint CSCI441_INTERNAL::ShaderUtils::compileShader(
909 const char *filename,
910 const GLenum shaderType
913 GLchar *shaderString;
916 if( readTextFromFile( filename, shaderString ) ) {
918 GLuint shaderHandle = glCreateShader( shaderType );
921 glShaderSource( shaderHandle, 1, (
const char**)&shaderString,
nullptr );
924 delete [] shaderString;
927 glCompileShader( shaderHandle );
930 printShaderLog( shaderHandle );
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