Dealing with Errors in OpenGL - hls333555/OpenGL GitHub Wiki
There are mainly two ways to deal with errors in OpenGL:
-
glGetError()
: which is compatible with all OpenGL versions and works in a very simple way: whenever we call an OpenGL function, if an error were to occur, a flag gets set internally in OpenGL's memory, when we callglGetError()
, that gives our error flag.The typical workflow with
glGetError()
is, first of all, before each OpenGL function call, clear all pending errors via a while loop callingglGetError()
, then call the certain OpenGL function you want to debug, and then callglGetError()
again, this can retrieve any errors that generated in the previous function call.To allow for distributed implementations, there may be several error flags. If any single error flag has recorded an error, the value of that flag is returned and that flag is reset to
GL_NO_ERROR
whenglGetError
is called. If more than one flag has recorded an error,glGetError
returns and clears an arbitrary error flag value. Thus,glGetError
should always be called in a loop, until it returnsGL_NO_ERROR
, if all error flags are to be reset. -
glDebugMessageCallback()
: which is only available since OpenGL 4.3 and allows us to specify a function pointer to OpenGL and OpenGL will call that function when an error occurs. This is much better thanglGetError()
obviously.
Here, we use the first method to track our error:
// Note that we must put brackets around x!
#define ASSERT(x) if(!(x)) __debugbreak();
// You should ensure "DEBUG" exists in PreprocessorDefinations of Debug configuration
#ifdef DEBUG
#define GLCALL(x) GLClearError();\
x;\
ASSERT(GLLogCall(__FILE__, #x, __LINE__))
#else
#define GLCALL(x) x
#endif
static void GLClearError()
{
// Loop to clear all previous errors
while (glGetError() != GL_NO_ERROR);
}
static bool GLLogCall(const char* file, const char* function, int line)
{
while (unsigned int error = glGetError())
{
std::cout << "OpenGL error: " << error << " in " << file << ", " << function << ", " << line << std::endl;
return false;
}
return true;
}
To use this for an OpenGL function call, just wrap those functions with GLCALL()
like below:
GLCALL(glDrawElements(GL_TRIANGLES, 6, GL_INT, nullptr));
When pressing F5 in debug mode, you will see a breakpoint being triggered if an error occurs in that call.