Posted by: Morten Nobel-Jørgensen | February 17, 2013

Debugging OpenGL part 2 – using glDebugMessageCallback()


OpenGL DebuggingThe traditional way to debug OpenGL is to insert glGetError() after each OpenGL function call as described in the previous blog post Debugging OpenGL part 1 – using glGetError(). Using glGetError is both cumbersome and time consuming. One of the new features in OpenGL 4.3 is the ability to get a callback whenever an OpenGL-related error occur. In this blog I’ll give a short introduction to how to use this new functionality using FreeGLUT and GLEW.

Prerequisites

First of all, you need a graphics card and a graphics card driver, which either supports OpenGL 4.3 fully or have support for glDebugMessageCallback.

To use the glDebugMessageCallback, you need to create a OpenGL context in debug mode. In FreeGlut you create a debug context by passing the GLUT_DEBUG enum to the glutInitContextFlags function. Usually you only want a debug context in a debug build. The parameter should therefor be wrapped with the following preprocessor directive.

	glutInitContextFlags(GLUT_FORWARD_COMPATIBLE
#if _DEBUG
		| GLUT_DEBUG
#endif
	);

The callback function

The following shows a simple example how the actual callback function could look like:

void APIENTRY openglCallbackFunction(GLenum source,
                                           GLenum type,
                                           GLuint id,
                                           GLenum severity,
                                           GLsizei length,
                                           const GLchar* message,
                                           const void* userParam){

	cout << "---------------------opengl-callback-start------------" << endl;
	cout << "message: "<< message << endl;
	cout << "type: ";
	switch (type) {
	case GL_DEBUG_TYPE_ERROR:
		cout << "ERROR";
		break;
	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
		cout << "DEPRECATED_BEHAVIOR";
		break;
	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
		cout << "UNDEFINED_BEHAVIOR";
		break;
	case GL_DEBUG_TYPE_PORTABILITY:
		cout << "PORTABILITY";
		break;
	case GL_DEBUG_TYPE_PERFORMANCE:
		cout << "PERFORMANCE";
		break;
	case GL_DEBUG_TYPE_OTHER:
		cout << "OTHER";
		break;
	}
	cout << endl;

	cout << "id: " << id << endl;
	cout << "severity: ";
	switch (severity){
	case GL_DEBUG_SEVERITY_LOW:
		cout << "LOW";
		break;
	case GL_DEBUG_SEVERITY_MEDIUM:
		cout << "MEDIUM";
		break;
	case GL_DEBUG_SEVERITY_HIGH:
		cout << "HIGH";
		break;
	}
	cout << endl;
	cout << "---------------------opengl-callback-end--------------" << endl;
}

An important thing to notice: The function must be a C method with the same calling convention as the GL API functions; here this is done using APIENTRY function prefix.

Subscribing for callbacks

The only missing piece is to configure OpenGL to use the callback function after the OpenGL Context has been created. This works like many other logging libraries, where you can subscribe for certain events. In our case we want to get all possible events and therefor use GL_DONT_CARE as filter. An important detail is to enable GL_DEBUG_OUTPUT_SYNCHRONOUS, which allows us to see the origin of each error, simply by setting a breakpoint inside the callback function.

#if _DEBUG
	if(glDebugMessageCallback){
		cout << "Register OpenGL debug callback " << endl;
		glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
		glDebugMessageCallback(openglCallbackFunction, nullptr);
		GLuint unusedIds = 0;
		glDebugMessageControl(GL_DONT_CARE,
 			GL_DONT_CARE,
 			GL_DONT_CARE,
 			0,
 			&unusedIds,
 			true);
	}
	else
		cout << "glDebugMessageCallback not available" << endl;
#endif

Source code

A full running example of this is available at GitHub: https://github.com/mortennobel/OpenGL_4.3_VS_2010_freeglut

API documentation:

Advertisements

Responses

  1. Hey, very helpful post. Just wanted to note two things.

    1. The last argument in openglCallbackFunction should be const void * userParam, not void * userParam.

    For some reason VS2012 is really picky about the difference between const void * and void *. When I used VS2010 I never had a problem with this.

    2. Small typo in the debug function, line 34. I guess it should be cout << "id: " << id << endl;
    cout << "severity: ";

  2. Thanks for the corrections and the kind words 🙂 I have updated the post 🙂

  3. […] if you’re lucky. Morten Nobel’s blog here shows the usage of glDebugMessageCallback which can do the same sorts of things, but without the […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: