What is the best way to debug OpenGL?
Excluding additional and external tools (what other answers are already there).
Then the general way is to urgently call glGetError() . However, a better alternative is to use Debug output ( KHR_debug , ARB_debug_output ). This gives you the ability to set up callbacks for messages of varying severity.
To use debug output, a context must be created using the WGL/GLX_DEBUG_CONTEXT_BIT . With GLFW, this can be set using the GLFW_OPENGL_DEBUG_CONTEXT prompt .
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
Please note that if the context is not a debugging context, then receiving all or even any messages is not guaranteed.
If you have a debugging context or not, you can find out by checking GL_CONTEXT_FLAGS :
GLint flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags); if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
Then you go and specify the callback:
void debugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) {
Each possible value for the listings can be seen here . Especially remember to check the severity, as some messages may be just notifications, not errors.
Now you can complete and register a callback.
glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glDebugMessageCallback(debugMessage, NULL); glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
You can even enter your own messages using glDebugMessageInsert() .
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Vary dangerous error");
When it comes to shaders and programs, you always want to check GL_COMPILE_STATUS , GL_LINK_STATUS and GL_VALIDATE_STATUS . If any of them reflects that something is wrong, then additionally check glGetShaderInfoLog() / glGetProgramInfoLog() .
GLint linkStatus; glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); if (!linkStatus) { GLchar *infoLog = new GLchar[infoLogLength + 1]; glGetProgramInfoLog(program, infoLogLength * sizeof(GLchar), NULL, infoLog); ... delete[] infoLog; }
The string returned by glGetProgramInfoLog() will be null terminated.
You can also go a little more extreme and use some debugging macros in the debug assembly. Thus, using the glIs*() functions to check if the expected type is also actual.
assert(glIsProgram(program) == GL_TRUE); glUseProgram(program);
If debugging output is not available and you just want to use glGetError() , then you can of course do it.
GLenum err; while ((err = glGetError()) != GL_NO_ERROR) printf("OpenGL Error: %u\n", err);
Since the numerical error code is not so useful, we could make it more understandable for humans by comparing the numerical error codes with the message.
const char* glGetErrorString(GLenum error) { switch (error) { case GL_NO_ERROR: return "No Error"; case GL_INVALID_ENUM: return "Invalid Enum"; case GL_INVALID_VALUE: return "Invalid Value"; case GL_INVALID_OPERATION: return "Invalid Operation"; case GL_INVALID_FRAMEBUFFER_OPERATION: return "Invalid Framebuffer Operation"; case GL_OUT_OF_MEMORY: return "Out of Memory"; case GL_STACK_UNDERFLOW: return "Stack Underflow"; case GL_STACK_OVERFLOW: return "Stack Overflow"; case GL_CONTEXT_LOST: return "Context Lost"; default: return "Unknown Error"; } }
Then check it as follows:
printf("OpenGL Error: [%u] %s\n", err, glGetErrorString(err));
It is still not very useful or better said intuitively, as if you had sprinkled a few glGetError() here and there. Then finding someone who registered the error can be unpleasant.
Again, macros come to the rescue.
void _glCheckError(const char *filename, int line) { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) printf("OpenGL Error: %s (%d) [%u] %s\n", filename, line, err, glGetErrorString(err)); }
Now simply define the macro as follows:
#define glCheckError() _glCheckError(__FILE__, __LINE__)
and voila you can now call glCheckError() after whatever you want, and in case of errors it will tell you the exact file and the line in which it was found.