// NOTE: get useful debug messages from opengl // https://www.khronos.org/opengl/wiki/Debug_Output #ifndef GL_DEBUG_H #define GL_DEBUG_H #include #include "shader.h" void dumpShader(GLuint prog_id); const char* glEnumToString(GLenum e); void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); #endif // GL_DEBUG_H #ifdef GL_DEBUG_IMPLEMENTATION const char* glEnumToString(GLenum e) { switch (e) { case GL_FLOAT_MAT4: return "GL_FLOAT_MAT4"; case GL_FLOAT_VEC3: return "GL_FLOAT_VEC3"; case GL_FLOAT_VEC4: return "GL_FLOAT_VEC4"; case GL_BYTE: return "GL_BYTE"; case GL_UNSIGNED_BYTE: return "GL_UNSIGNED_BYTE"; case GL_SHORT: return "GL_SHORT"; case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT"; case GL_INT: return "GL_INT"; case GL_UNSIGNED_INT: return "GL_UNSIGNED_INT"; case GL_FLOAT: return "GL_FLOAT"; case GL_DOUBLE: return "GL_DOUBLE"; case GL_ARRAY_BUFFER: return "GL_ARRAY_BUFFER"; case GL_ELEMENT_ARRAY_BUFFER: return "GL_ELEMENT_ARRAY_BUFFER"; case GL_UNIFORM_BUFFER: return "GL_UNIFORM_BUFFER"; case GL_TEXTURE_BUFFER: return "GL_TEXTURE_BUFFER"; case GL_DEBUG_TYPE_ERROR: return "GL_DEBUG_TYPE_ERROR"; case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"; case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"; case GL_DEBUG_TYPE_PORTABILITY: return "GL_DEBUG_TYPE_PORTABILITY"; case GL_DEBUG_TYPE_PERFORMANCE: return "GL_DEBUG_TYPE_PERFORMANCE"; case GL_DEBUG_TYPE_MARKER: return "GL_DEBUG_TYPE_MARKER"; case GL_DEBUG_TYPE_PUSH_GROUP: return "GL_DEBUG_TYPE_PUSH_GROUP"; case GL_DEBUG_TYPE_POP_GROUP: return "GL_DEBUG_TYPE_POP_GROUP"; case GL_DEBUG_TYPE_OTHER: return "GL_DEBUG_TYPE_OTHER"; case GL_DEBUG_SEVERITY_HIGH: return "GL_DEBUG_SEVERITY_HIGH"; case GL_DEBUG_SEVERITY_MEDIUM: return "GL_DEBUG_SEVERITY_MEDIUM"; case GL_DEBUG_SEVERITY_LOW: return "GL_DEBUG_SEVERITY_LOW"; case GL_DEBUG_SEVERITY_NOTIFICATION: return "GL_DEBUG_SEVERITY_NOTIFICATION"; case GL_NO_ERROR: return "GL_NO_ERROR"; case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION"; case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; default: return "???"; } } void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { // NOTE: filter out notification about using video memory for buffer object if (id == 131185) return; #ifdef TANGERINE_GL_DEBUG_QUIET if (type != GL_DEBUG_TYPE_ERROR) return; #endif std::cout << "message id: " << id << ", " << ((type == GL_DEBUG_TYPE_ERROR) ? "Error" : "Debug") << (type == GL_DEBUG_TYPE_ERROR ? "** GL Error **" : "") << ", type: " << glEnumToString(type) << ", severity: " << glEnumToString(severity) << ", message: " << message << "\n"; } void dumpShader(GLuint prog_id) { LOGF(Debug, "------------------------\n"); LOGF(Debug, "%s(), dumping shader info, program id: %d\n", __FUNCTION__, prog_id); GLint active_uniforms; GLint active_uniform_blocks; GLint active_attribs; // NOTE: unused uniforms/attributes get optimized away // https://www.khronos.org/opengl/wiki/Program_Introspection#Attributes glGetProgramiv(prog_id, GL_ACTIVE_UNIFORMS, &active_uniforms); glGetProgramiv(prog_id, GL_ACTIVE_UNIFORM_BLOCKS, &active_uniform_blocks); glGetProgramiv(prog_id, GL_ACTIVE_ATTRIBUTES, &active_attribs); LOGF(Debug, "active uniforms: %d\n", active_uniforms); LOGF(Debug, "active uniform blocks: %d\n", active_uniform_blocks); LOGF(Debug, "active attributes: %d\n", active_attribs); GLchar uni_name[256]; GLsizei length; GLint size; GLenum type; for (int i = 0; i < active_uniforms; i++) { glGetActiveUniform(prog_id, i, sizeof(uni_name), &length, &size, &type, uni_name); LOGF(Debug, "uniform idx: %d, type: %s, name: %s \n", i, glEnumToString(type), uni_name); } for (int i = 0; i < active_attribs; i++) { glGetActiveAttrib(prog_id, i, sizeof(uni_name), &length, &size, &type, uni_name); LOGF(Debug, "attribute idx: %d, type: %s, name: %s \n", i, glEnumToString(type), uni_name); } LOGF(Debug, "------------------------\n"); } #endif // ifdef GL_DEBUG_IMPLEMENTATION