wGL: Allow OpenGL debugging

This introduces a new command line parameter "--debug-opengl", which
will create special debug OpenGL contexts and attach a callback that the
driver will invoke when it detects a problem. The callback will then
write the error message to the logfile, and break into the debugger if
one is attached.
Currently only works on Windows.
issue1247
Nicolas Hake 2015-02-16 17:42:23 +01:00
parent 00a24846cc
commit cac94659d0
4 changed files with 82 additions and 1 deletions

View File

@ -116,6 +116,7 @@ public:
int32_t NoOffscreenBlits; // if set, all blits to non-primary-surfaces are emulated
int32_t MultiSampling; // multisampling samples
int32_t AutoFrameSkip; // if true, gfx frames are skipped when they would slow down the game
int32_t DebugOpenGL; // if true, enables OpenGL debugging
void CompileFunc(StdCompiler *pComp);
};

View File

@ -259,6 +259,8 @@ void C4Application::ParseCommandLine(int argc, char * argv[])
{"record", no_argument, 0, 'r'},
{"lobby", required_argument, 0, 'l'},
{"debug-opengl", no_argument, &Config.Graphics.DebugOpenGL, 1},
{0, 0, 0, 0}
};
int option_index = 0;

View File

@ -36,6 +36,61 @@
#include <stdio.h>
#include <math.h>
namespace
{
const char *MsgSourceToStr(GLenum source)
{
switch (source)
{
case GL_DEBUG_SOURCE_API_ARB: return "API";
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: return "window system";
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: return "shader compiler";
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: return "third party";
case GL_DEBUG_SOURCE_APPLICATION_ARB: return "application";
case GL_DEBUG_SOURCE_OTHER_ARB: return "other";
default: return "<unknown>";
}
}
const char *MsgTypeToStr(GLenum type)
{
switch (type)
{
case GL_DEBUG_TYPE_ERROR_ARB: return "error";
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: return "deprecation warning";
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: return "undefined behavior warning";
case GL_DEBUG_TYPE_PORTABILITY_ARB: return "portability warning";
case GL_DEBUG_TYPE_PERFORMANCE_ARB: return "performance warning";
case GL_DEBUG_TYPE_OTHER_ARB: return "other message";
default: return "unknown message";
}
}
const char *MsgSeverityToStr(GLenum severity)
{
switch (severity)
{
case GL_DEBUG_SEVERITY_HIGH_ARB: return "high";
case GL_DEBUG_SEVERITY_MEDIUM_ARB: return "medium";
case GL_DEBUG_SEVERITY_LOW_ARB: return "low";
default: return "<unknown>";
}
}
void APIENTRY OpenGLDebugProc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* userParam)
{
const char *msg_source = MsgSourceToStr(source);
const char *msg_type = MsgTypeToStr(type);
const char *msg_severity = MsgSeverityToStr(severity);
DebugLogF(" gl: %s severity %s %s: %s", msg_severity, msg_source, msg_type, message);
#ifdef USE_WIN32_WINDOWS
if (IsDebuggerPresent() && severity == GL_DEBUG_SEVERITY_HIGH_ARB)
BREAKPOINT_HERE;
#endif
}
}
CStdGL::CStdGL():
pMainCtx(0)
{
@ -153,6 +208,11 @@ CStdGLCtx *CStdGL::CreateContext(C4Window * pWindow, C4AbstractApp *pApp)
bool first_ctx = !pMainCtx;
if (first_ctx) pMainCtx = pCtx;
bool success = pCtx->Init(pWindow, pApp);
if (Config.Graphics.DebugOpenGL && glDebugMessageCallbackARB)
{
glDebugMessageCallbackARB(&OpenGLDebugProc, nullptr);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}
// First context: Log some information about hardware/drivers
// Must log after context creation to get valid results
if (first_ctx)
@ -186,6 +246,11 @@ CStdGLCtx *CStdGL::CreateContext(HWND hWindow, C4AbstractApp *pApp)
{
delete pCtx; Error(" gl: Error creating secondary context!"); return NULL;
}
if (Config.Graphics.DebugOpenGL && glDebugMessageCallbackARB)
{
glDebugMessageCallbackARB(&OpenGLDebugProc, nullptr);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}
if (!pMainCtx)
{
pMainCtx = pCtx;

View File

@ -306,7 +306,20 @@ bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *pApp, HWND hWindow)
else
{
// create context
hrc = wglCreateContext(hDC);
if (Config.Graphics.DebugOpenGL && wglCreateContextAttribsARB)
{
const int attribs[] = {
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
0
};
DebugLog(" gl: Creating debug context.");
hrc = wglCreateContextAttribsARB(hDC, 0, attribs);
}
else
{
hrc = wglCreateContext(hDC);
}
if(!hrc)
{
pGL->Error(" gl: Error creating gl context");