KHR_debug
This is an OpenGL extension that adds some very useful debugging tools
- This extension is core in OpenGL 4.3+.
- View this extentions in the Khronos Registry.
If you're using a version of OpenGL older than 4.3. You should check against your function loading api for extension support.
If using glad
just include the extension when generating the loader and after loading your functions check against GLAD_GL_KHR_debug
.
Debug Messaging
With debug messaging we can recieve meaningful message on the state of OpenGL through a callback function.
This effectively replaces glGetError
.
You may need a debug context for this to work. If you're using GLFW
this can be achieved with a window flag.
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE)
To set this up you just need two api calls.
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(&message_callback, nullptr);
The callback function must match this signature.
void callback(GLenum src, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* msg, void const* user_param)
If you want useful stacktraces within the call back you'll want to enable GL_DEBUG_OUTPUT_SYNCHRONOUS
. Do note this will have a performance impact and should only be done for debug.
Example
static void message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param) {
std::cout << message << '\n';
}
void main() {
// ...
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(...);
// ...
glfwMakeContextCurrent(window);
gladLoadGL(&glfwGetProcAddress);
// ...
if (GLAD_GL_KHR_debug) {
glEnable(GL_DEBUG_OUTPUT);
#ifdef _DEBUG
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
#endif
glDebugMessageCallback(&message_callback, nullptr);
}
// Do something bad to trigger the message callback
GLuint program = glCreateProgram();
glDeleteProgram(program);
glDeleteProgram(program); // Double free
}
Debug Groups
KHR_debug also introduces debug groups. This is most helpful when debugging with RenderDoc. This lets up group api calls together.
Pushing and Popping Groups
constexpr GLuint myId = 0; // Can be whatever you want
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, myId, -1, "Shadow Pass");
// All following OpenGL api calls will be under the `Shadow Pass` Group.
glPopDebugGroup();
Within RenderDoc you can see the debug groups in action.