(Define a macro to) facilitate OpenGL command debu

2020-06-04 04:34发布

问题:

Sometimes it takes a long time of inserting conditional prints and checks to glGetError() to narrow down using a form of binary search where the first function call is that an error is first reported by OpenGL.

I think it would be cool if there is a way to build a macro which I can wrap around all GL calls which may fail which will conditionally call glGetError immediately after. When compiling for a special target I can have it check glGetError with a very high granularity, while compiling for typical release or debug this wouldn't get enabled (I'd check it only once a frame).

Does this make sense to do? Searching for this a bit I find a few people recommending calling glGetError after every non-draw gl-call which is basically the same thing I'm describing.

So in this case is there anything clever that I can do (context: I am using GLEW) to simplify the process of instrumenting my gl calls this way? It would be a significant amount of work at this point to convert my code to wrap a macro around each OpenGL function call. What would be great is if I can do something clever and get all of this going without manually determining which are the sections of code to instrument (though that also has potential advantages... but not really. I really don't care about performance by the time I'm debugging the source of an error).

回答1:

Try this:

void CheckOpenGLError(const char* stmt, const char* fname, int line)
{
    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
    {
        printf("OpenGL error %08x, at %s:%i - for %s\n", err, fname, line, stmt);
        abort();
    }
}

#ifdef _DEBUG
    #define GL_CHECK(stmt) do { \
            stmt; \
            CheckOpenGLError(#stmt, __FILE__, __LINE__); \
        } while (0)
#else
    #define GL_CHECK(stmt) stmt
#endif

Use it like this:

GL_CHECK( glBindTexture2D(GL_TEXTURE_2D, id) );

If OpenGL function returns variable, then remember to declare it outside of GL_CHECK:

const char* vendor;
GL_CHECK( vendor = glGetString(GL_VENDOR) );

This way you'll have debug checking if _DEBUG preprocessor symbol is defined, but in "Release" build you'll have just the raw OpenGL calls.



回答2:

BuGLe sounds like it will do what you want:

  • Dump a textual log of all GL calls made.
  • Take a screenshot or capture a video.
  • Call glGetError after each call to check for errors, and wrap glGetError so that this checking is transparent to your program.
  • Capture and display statistics (such as frame rate)
  • Force a wireframe mode
  • Recover a backtrace from segmentation faults inside the driver, even if the driver is compiled without symbols.