What is the best way to debug OpenGL?

GLIntercept is your best bet. From their web page:

  • Save all OpenGL function calls to text or XML format with the option to log individual frames.
  • Free camera. Fly around the geometry sent to the graphics card and enable/disable wireframe/backface-culling/view frustum render
  • Save and track display lists. Saving of the OpenGL frame buffer (color/depth/stencil) pre and post render calls. The ability to save the "diff" of pre and post images is also available.

Apitrace is a relatively new tool from some folks at Valve, but It works great! Give it a try: https://github.com/apitrace/apitrace


There is no straight answer. It all depends on what you are trying to understand. Since OpenGL is a state machine, sometimes it does not do what you expect as the required state is not set or things like that.

In general, use tools like glTrace / glIntercept (to look at the OpenGL call trace), gDebugger (to visualize textures, shaders, OGL state etc.) and paper/pencil :). Sometimes it helps to understand how you have setup the camera and where it is looking, what is being clipped etc. I have personally relied more to the last than the previous two approaches. But when I can argue that the depth is wrong then it helps to look at the trace. gDebugger is also the only tool that can be used effectively for profiling and optimization of your OpenGL app.

Apart from this tool, most of the time it is the math that people get wrong and it can't be understood using any tool. Post on the OpenGL.org newsgroup for code specific comments, you will be never disappointed.


What is the best way to debug OpenGL?

Without considering additional and external tools (which other answers already do).

Then the general way is to extensively call glGetError(). However a better alternative is to use Debug Output (KHR_debug, ARB_debug_output). This provides you with the functionality of setting a callback for messages of varying severity level.

In order to use debug output, the context must be created with the WGL/GLX_DEBUG_CONTEXT_BIT flag. With GLFW this can be set with the GLFW_OPENGL_DEBUG_CONTEXT window hint.

glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

Note that if the context isn't a debug context, then receiving all or even any messages aren't guaranteed.

Whether you have a debug context or not can be detected by checking GL_CONTEXT_FLAGS:

GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);

if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
    // It's a debug context

You would then go ahead and specify a callback:

void debugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
                  const GLchar *message, const void *userParam)
{
    // Print, log, whatever based on the enums and message
}

Each possible value for the enums can be seen on here. Especially remember to check the severity, as some messages might just be notifications and not errors.

You can now do ahead and register the 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 inject 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 be checking GL_COMPILE_STATUS, GL_LINK_STATUS and GL_VALIDATE_STATUS. If any of them reflects that something is wrong, then additionally always 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 bit more extreme and utilize a few debug macros in a debug build. Thus using glIs*() functions to check if the expected type is the actual type as well.

assert(glIsProgram(program) == GL_TRUE);
glUseProgram(program);

If debug output isn't available and you just want to use glGetError(), then you're of course free to do so.

GLenum err;
while ((err = glGetError()) != GL_NO_ERROR)
    printf("OpenGL Error: %u\n", err);

Since a numeric error code isn't that helpful, we could make it a bit more human readable by mapping the numeric error codes to a 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 checking it like this:

printf("OpenGL Error: [%u] %s\n", err, glGetErrorString(err));

That still isn't very helpful or better said intuitive, as if you have sprinkled a few glGetError() here and there. Then locating which one logged an error can be troublesome.

Again macros come to the rescue.

void _glCheckErrors(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 a macro like this:

#define glCheckErrors() _glCheckErrors(__FILE__, __LINE__)

and voila now you can call glCheckErrors() after everything you want, and in case of errors it will tell you the exact file and line it was detected at.