OpenGL Errors
Prior to OpenGL version 4.3, detecting OpenGL errors has been a common problem, since OpenGL would not give you error messages unless you specifically asked for them. Even if you don't have any visual problems in your code, resolving OpenGL errors is still important, because the errors may negatively impact the performance of your program.
Detecting OpenGL errors became easier after OpenGL version 4.3 with the introduction of a debug callback. Still, one needs to register a debug callback function and then interpret the data sent to this function.
This solution provides simple ways to retrieve OpenGL errors using either the modern OpenGL Debug Callback or the old-style explicit OpenGL Error Checking.
OpenGL Debug Callback
In version 4.3 OpenGL introduced the OpenGL debug callback, as a part of the GL_KHR_debug
extension.
Even if your OpenGL context uses an earlier version of OpenGL, if you have the GL_KHR_debug
extension,
you can use the debug callbacks. If your OpenGL context does not support this extention, however,
you are left the with old-style OpenGL Error Checking.
The OpenGL debug callback is quite convenient. It provides detailed information about both errors and other non-error messages. Perhaps more importantly, it does so without the need for cluttering your code with the old-style explicit error checking calls.
For using the debug callback, the OpenGL context should be created in debug mode. How you accomplish this depends on the way you generate your OpenGL context. The good news is that I have seen the OpenGL debug callback working even without explicitly specifying debug mode, so you might get lucky. If you are using FreeGLUT, you can turn of the debug bit before creating the window using the following call.
glutInitContextFlags(GLUT_DEBUG);
If you can using GLFW, you can use the following initialization.
glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, false);
Similarly, in Qt the debug mode can be enabled using something like the following lines.
QOpenGLWidget *glWidget = new QOpenGLWidget; QSurfaceFormat glFormat; glFormat.setOption( QSurfaceFormat::DebugContext ); glWidget->setFormat(glFormat);
After you set the debug mode and create the OpenGL context/window, you can register the debug callback. Using the cyGL code release this is extremely simple. You can simply use the following macro.
CY_GL_REGISTER_DEBUG_CALLBACK;
This macro registers the callback using the default parameters.
If you'd like to customize the parameters, you can create an object of the
cyGLDebugCallback
class
and register the callback.
{ cyGLDebugCallback callback; callback.Register(); callback.IgnoreNotifications(); }
Note that this class is merely used for initializing the callback and it does not store any data itself. Therefore, it is safe to delete the object after registering the callback. The callback is still remains effective.
Using the default settings, whenever there is an OpenGL callback, the OpenGL message is printed to the standard output stream. If you'd like to print the error message somewhere else, you can either change the standard output stream or specify a different output stream while registering.
The callback, however, does not tell you which function in your program triggers the printed debug message.
For receiving this information, you can simply place a break point at the end of the cyGLDebugCallback::Callback
function. This way, when the break point it triggered, the debug message is printed and the
call stack shows you which OpenGL function call in your code triggered the callback.
OpenGL Error Checking
If your OpenGL context does not support debug callback messages, you can use the old-style explicit error checking. The disadvantage is that this process involves cluttering your code with some OpenGL error checking code.
OpenGL errors can be retrieved using glGetError
function, which
returns a GLenum
value that can be converted to a string
using gluErrorString
function as follows:
GLenum error = glGetError(); cout << gluErrorString( error );
For keeping things simple you can use the CY_GL_ERROR
macro
defined in the cyGL code release.
This macro prints all OpenGL errors encountered up to that point.
To find out the OpenGL call that trigerred the error, you should
use this macro before and after each call.
CY_GL_ERROR; // some OpenGL call CY_GL_ERROR; // another OpenGL call CY_GL_ERROR;
The CY_GL_ERROR
macro prints the source file name and the
line number, so that you can find the source of the error.
This can be simplified using the CY_GL_ERR
macro that
takes your OpenGL call as an argument.
CY_GL_ERR(glBegin(GL_POINT)); // This will trigger an error
An added benefit of the CY_GL_ERR
macro is that it prints
the OpenGL function call that cause the error as well, so that you can immediately tell
what has triggered the error.
One might want to disable the error checking in the release version
of the code, since error checking introduces some minor overhead.
This can be done easily using the CY_GL_ERROR_D
and CY_GL_ERR_D
macros instead, which only work
when _DEBUG
is defined.
One way to use these macros is to put them in only one place in your code,
where it will be repeatedly called.
As long as you don't receive any error messages, you can rest assured that
your code does not generate any OpenGL errors.
Once you receive an error message, however, you will need to place
multiple CY_GL_ERROR
calls to pin point which call generated the error.