From d1b3611276f097f02c8379722319fcdc44ff02a4 Mon Sep 17 00:00:00 2001 From: James Benton Date: Thu, 9 Aug 2012 15:44:17 +0100 Subject: [PATCH] Add GL_ARB_debug_output support. --- retrace/glretrace_main.cpp | 82 ++++++++++++++++++++++++++++++++++++++ retrace/retrace.hpp | 1 + retrace/retrace_main.cpp | 2 + 3 files changed, 85 insertions(+) diff --git a/retrace/glretrace_main.cpp b/retrace/glretrace_main.cpp index 9d551af..f9d61e0 100644 --- a/retrace/glretrace_main.cpp +++ b/retrace/glretrace_main.cpp @@ -32,6 +32,11 @@ #include "glretrace.hpp" #include "os_time.hpp" +/* Synchronous debug output may reduce performance however, + * without it the callNo in the callback may be inaccurate + * as the callback may be called at any time. + */ +#define DEBUG_OUTPUT_SYNCHRONOUS 0 namespace glretrace { @@ -55,6 +60,8 @@ static bool supportsOcclusion = true; static bool firstFrame = true; static std::list callQueries; +static void +debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); void checkGlError(trace::Call &call) { @@ -238,6 +245,18 @@ initContext() { std::cout << "Error: Cannot run profile, GL_ARB_occlusion_query extension is not supported." << std::endl; exit(-1); } + + if (retrace::debug) { + bool supportsDebugOutput = glws::checkExtension("GL_ARB_debug_output", extensions); + + if (supportsDebugOutput) { + glDebugMessageCallbackARB(&debugOutputCallback, currentContext); + + if (DEBUG_OUTPUT_SYNCHRONOUS) { + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + } + } + } } void @@ -273,6 +292,69 @@ frame_complete(trace::Call &call) { } } +static const char* +getDebugOutputSource(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: + default: + return ""; + } +} + +static const char* +getDebugOutputType(GLenum type) { + switch(type) { + case GL_DEBUG_TYPE_ERROR_ARB: + return "error"; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: + return "deprecated behaviour"; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: + return "undefined behaviour"; + case GL_DEBUG_TYPE_PORTABILITY_ARB: + return "portability issue"; + case GL_DEBUG_TYPE_PERFORMANCE_ARB: + return "performance issue"; + case GL_DEBUG_TYPE_OTHER_ARB: + default: + return "unknown issue"; + } +} + +static const char* +getDebugOutputSeverity(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 "usnknown"; + } +} + +static void +debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam) { + std::cerr << retrace::callNo << ": "; + std::cerr << "glDebugOutputCallback: "; + std::cerr << getDebugOutputSeverity(severity) << " severity "; + std::cerr << getDebugOutputSource(source) << " " << getDebugOutputType(type); + std::cerr << " " << id; + std::cerr << ", " << message; + std::cerr << std::endl; +} + } /* namespace glretrace */ diff --git a/retrace/retrace.hpp b/retrace/retrace.hpp index 01d2609..56cebc6 100644 --- a/retrace/retrace.hpp +++ b/retrace/retrace.hpp @@ -162,6 +162,7 @@ extern bool doubleBuffer; extern bool coreProfile; extern unsigned frameNo; +extern unsigned callNo; std::ostream &warning(trace::Call &call); diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp index 5f5e095..9386a61 100644 --- a/retrace/retrace_main.cpp +++ b/retrace/retrace_main.cpp @@ -65,6 +65,7 @@ bool profilingCpuTimes = false; bool profilingPixelsDrawn = false; unsigned frameNo = 0; +unsigned callNo = 0; void @@ -152,6 +153,7 @@ mainLoop() { } } + callNo = call->no; retracer.retrace(*call); if (doSnapshot && !swapRenderTarget) { -- 2.43.0