diff --git a/src/igl/opengl/DeviceFeatureSet.cpp b/src/igl/opengl/DeviceFeatureSet.cpp index 78c2ddc11b..90c6ae09c5 100644 --- a/src/igl/opengl/DeviceFeatureSet.cpp +++ b/src/igl/opengl/DeviceFeatureSet.cpp @@ -383,13 +383,17 @@ bool DeviceFeatureSet::isInternalFeatureSupported(InternalFeatures feature) cons case InternalFeatures::ClearDepthf: return hasDesktopOrESVersion(*this, GLVersion::v4_1, GLVersion::v2_0_ES); - case InternalFeatures::Debug: + case InternalFeatures::DebugLabel: + return hasDesktopOrESVersion(*this, GLVersion::v4_3, GLVersion::v3_2_ES) || + hasExtension(Extensions::Debug) || hasExtension(Extensions::DebugLabel); + + case InternalFeatures::DebugMessage: return hasDesktopOrESVersion(*this, GLVersion::v4_3, GLVersion::v3_2_ES) || hasExtension(Extensions::Debug) || hasExtension(Extensions::DebugMarker); - case InternalFeatures::DebugLabel: + case InternalFeatures::DebugMessageCallback: return hasDesktopOrESVersion(*this, GLVersion::v4_3, GLVersion::v3_2_ES) || - hasExtension(Extensions::Debug) || hasExtension(Extensions::DebugLabel); + hasExtension(Extensions::Debug); case InternalFeatures::FramebufferBlit: // TODO: Add support for GL_ANGLE_framebuffer_blit @@ -883,7 +887,10 @@ bool DeviceFeatureSet::hasInternalRequirement(InternalRequirement requirement) c case InternalRequirement::ColorTexImageRgbApple422Unsized: return usesOpenGLES() && !hasESVersion(*this, GLVersion::v3_0_ES); - case InternalRequirement::DebugExtReq: + case InternalRequirement::DebugMessageExtReq: + return !hasDesktopOrESVersion(*this, GLVersion::v4_3, GLVersion::v3_2_ES); + + case InternalRequirement::DebugMessageCallbackExtReq: return !hasDesktopOrESVersion(*this, GLVersion::v4_3, GLVersion::v3_2_ES); case InternalRequirement::DebugLabelExtEnumsReq: diff --git a/src/igl/opengl/DeviceFeatureSet.h b/src/igl/opengl/DeviceFeatureSet.h index dc0b6ffadd..c14661a34c 100644 --- a/src/igl/opengl/DeviceFeatureSet.h +++ b/src/igl/opengl/DeviceFeatureSet.h @@ -63,8 +63,9 @@ enum class Extensions { // clang-format off enum class InternalFeatures { ClearDepthf, // glClearDepthf is supported - Debug, // Debug messages and group markers are supported DebugLabel, // Debug labels on objects are supported + DebugMessage, // Debug messages and group markers are supported + DebugMessageCallback, // Debug message callbacks are supported FramebufferBlit, // BlitFramebuffer is supported FramebufferObject, // Framebuffer objects are supported GetStringi, // GetStringi is supported @@ -155,7 +156,8 @@ enum class InternalRequirement { ColorTexImageRgb5A1Unsized, ColorTexImageRgba4Unsized, ColorTexImageRgbApple422Unsized, - DebugExtReq, + DebugMessageExtReq, + DebugMessageCallbackExtReq, DebugLabelExtEnumsReq, DebugLabelExtReq, Depth24Stencil8Unsized, diff --git a/src/igl/opengl/GLFunc.cpp b/src/igl/opengl/GLFunc.cpp index 4f61ac6ddf..8a649e59e8 100644 --- a/src/igl/opengl/GLFunc.cpp +++ b/src/igl/opengl/GLFunc.cpp @@ -161,11 +161,15 @@ IGL_EXTERN_BEGIN #define CAN_CALL_glGetStringi 0 #endif #if defined(GL_VERSION_4_3) || defined(GL_ES_VERSION_3_2) +#define CAN_CALL_glDebugMessageCallback CAN_CALL #define CAN_CALL_glDebugMessageInsert CAN_CALL +#define CAN_CALL_glObjectLabel CAN_CALL #define CAN_CALL_glPopDebugGroup CAN_CALL #define CAN_CALL_glPushDebugGroup CAN_CALL #else +#define CAN_CALL_glDebugMessageCallback 0 #define CAN_CALL_glDebugMessageInsert 0 +#define CAN_CALL_glObjectLabel 0 #define CAN_CALL_glPopDebugGroup 0 #define CAN_CALL_glPushDebugGroup 0 #endif @@ -174,11 +178,14 @@ IGL_EXTERN_BEGIN #else #define CAN_CALL_glVertexAttribDivisor 0 #endif -#if defined(GL_VERSION_4_3) || defined(GL_ES_VERSION_3_2) -#define CAN_CALL_glObjectLabel CAN_CALL -#else -#define CAN_CALL_glObjectLabel 0 -#endif + +void iglDebugMessageCallback(PFNIGLDEBUGPROC callback, const void* userParam) { + GLEXTENSION_METHOD_BODY(CAN_CALL_glDebugMessageCallback, + glDebugMessageCallback, + PFNIGLDEBUGMESSAGECALLBACKPROC, + callback, + userParam); +} void iglDebugMessageInsert(GLenum source, GLenum type, @@ -1515,11 +1522,13 @@ void iglRenderbufferStorageMultisampleIMG(GLenum target, /// MARK: - GL_KHR_debug #if defined(GL_KHR_debug) +#define CAN_CALL_glDebugMessageCallbackKHR CAN_CALL #define CAN_CALL_glDebugMessageInsertKHR CAN_CALL #define CAN_CALL_glObjectLabelKHR CAN_CALL #define CAN_CALL_glPopDebugGroupKHR CAN_CALL #define CAN_CALL_glPushDebugGroupKHR CAN_CALL #else +#define CAN_CALL_glDebugMessageCallbackKHR 0 #define CAN_CALL_glDebugMessageInsertKHR 0 #define CAN_CALL_glObjectLabelKHR 0 #define CAN_CALL_glPopDebugGroupKHR 0 @@ -1527,17 +1536,27 @@ void iglRenderbufferStorageMultisampleIMG(GLenum target, #endif #if IGL_OPENGL +#define DebugMessageCallbackKHR glDebugMessageCallback #define DebugMessageInsertKHR glDebugMessageInsert #define ObjectLabelKHR glObjectLabel #define PopDebugGroupKHR glPopDebugGroup #define PushDebugGroupKHR glPushDebugGroup #else +#define DebugMessageCallbackKHR glDebugMessageCallbackKHR #define DebugMessageInsertKHR glDebugMessageInsertKHR #define ObjectLabelKHR glObjectLabelKHR #define PopDebugGroupKHR glPopDebugGroupKHR #define PushDebugGroupKHR glPushDebugGroupKHR #endif +void iglDebugMessageCallbackKHR(PFNIGLDEBUGPROC callback, const void* userParam) { + GLEXTENSION_METHOD_BODY(CAN_CALL_glDebugMessageCallbackKHR, + DebugMessageCallbackKHR, + PFNIGLDEBUGMESSAGECALLBACKPROC, + callback, + userParam); +} + void iglDebugMessageInsertKHR(GLenum source, GLenum type, GLuint id, diff --git a/src/igl/opengl/GLFunc.h b/src/igl/opengl/GLFunc.h index 69ee00d4b2..3fec3a71a1 100644 --- a/src/igl/opengl/GLFunc.h +++ b/src/igl/opengl/GLFunc.h @@ -78,6 +78,14 @@ using PFNIGLCOMPRESSEDTEXSUBIMAGE3DPROC = void (*)(GLenum target, GLsizei imageSize, const GLvoid* data); using PFNIGLCREATEMEMORYOBJECTSPROC = void (*)(GLsizei n, GLuint* memoryObjects); +using PFNIGLDEBUGPROC = void (*)(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam); +using PFNIGLDEBUGMESSAGECALLBACKPROC = void (*)(PFNIGLDEBUGPROC callback, const void* userParam); using PFNIGLDEBUGMESSAGEINSERTPROC = void (*)(GLenum source, GLenum type, GLuint id, @@ -289,6 +297,7 @@ void iglCompressedTexSubImage3D(GLenum target, GLenum format, GLsizei imageSize, const GLvoid* data); +void iglDebugMessageCallback(PFNIGLDEBUGPROC callback, const void* userParam); void iglDebugMessageInsert(GLenum source, GLenum type, GLuint id, @@ -642,6 +651,7 @@ void iglRenderbufferStorageMultisampleIMG(GLenum target, ///-------------------------------------- /// MARK: - GL_KHR_debug +void iglDebugMessageCallbackKHR(PFNIGLDEBUGPROC callback, const void* userParam); void iglDebugMessageInsertKHR(GLenum source, GLenum type, GLuint id, diff --git a/src/igl/opengl/GLIncludes.h b/src/igl/opengl/GLIncludes.h index 347e6dd522..191a5b1c44 100644 --- a/src/igl/opengl/GLIncludes.h +++ b/src/igl/opengl/GLIncludes.h @@ -277,15 +277,60 @@ #ifndef GL_COPY_WRITE_BUFFER #define GL_COPY_WRITE_BUFFER 0x8f37 #endif +#ifndef GL_DEBUG_OUTPUT +#define GL_DEBUG_OUTPUT 0x92e0 +#endif +#ifndef GL_DEBUG_SEVERITY_HIGH +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#endif #ifndef GL_DEBUG_SEVERITY_LOW #define GL_DEBUG_SEVERITY_LOW 0x9148 #endif +#ifndef GL_DEBUG_SEVERITY_MEDIUM +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#endif +#ifndef GL_DEBUG_SEVERITY_NOTIFICATION +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#endif +#ifndef GL_DEBUG_SOURCE_API +#define GL_DEBUG_SOURCE_API 0x8246 +#endif #ifndef GL_DEBUG_SOURCE_APPLICATION #define GL_DEBUG_SOURCE_APPLICATION 0x824A #endif +#ifndef GL_DEBUG_SOURCE_OTHER +#define GL_DEBUG_SOURCE_OTHER 0x824B +#endif +#ifndef GL_DEBUG_SOURCE_SHADER_COMPILER +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#endif +#ifndef GL_DEBUG_SOURCE_THIRD_PARTY +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#endif +#ifndef GL_DEBUG_SOURCE_WINDOW_SYSTEM +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#endif +#ifndef GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#endif +#ifndef GL_DEBUG_TYPE_ERROR +#define GL_DEBUG_TYPE_ERROR 0x824C +#endif #ifndef GL_DEBUG_TYPE_MARKER #define GL_DEBUG_TYPE_MARKER 0x8268 #endif +#ifndef GL_DEBUG_TYPE_OTHER +#define GL_DEBUG_TYPE_OTHER 0x8251 +#endif +#ifndef GL_DEBUG_TYPE_PERFORMANCE +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#endif +#ifndef GL_DEBUG_TYPE_PORTABILITY +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#endif +#ifndef GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#endif #ifndef GL_DEPTH #define GL_DEPTH 0x1801 #endif diff --git a/src/igl/opengl/IContext.cpp b/src/igl/opengl/IContext.cpp index 555b7d557f..f92684a5be 100644 --- a/src/igl/opengl/IContext.cpp +++ b/src/igl/opengl/IContext.cpp @@ -238,9 +238,24 @@ std::string GLenumToString(GLenum code) { RESULT_CASE(GL_CW) RESULT_CASE(GL_CCW) RESULT_CASE(GL_CURRENT_VERTEX_ATTRIB) + RESULT_CASE(GL_DEBUG_OUTPUT) + RESULT_CASE(GL_DEBUG_SEVERITY_HIGH) RESULT_CASE(GL_DEBUG_SEVERITY_LOW) + RESULT_CASE(GL_DEBUG_SEVERITY_MEDIUM) + RESULT_CASE(GL_DEBUG_SEVERITY_NOTIFICATION) + RESULT_CASE(GL_DEBUG_SOURCE_API) RESULT_CASE(GL_DEBUG_SOURCE_APPLICATION) + RESULT_CASE(GL_DEBUG_SOURCE_OTHER) + RESULT_CASE(GL_DEBUG_SOURCE_SHADER_COMPILER) + RESULT_CASE(GL_DEBUG_SOURCE_THIRD_PARTY) + RESULT_CASE(GL_DEBUG_SOURCE_WINDOW_SYSTEM) + RESULT_CASE(GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR) + RESULT_CASE(GL_DEBUG_TYPE_ERROR) RESULT_CASE(GL_DEBUG_TYPE_MARKER) + RESULT_CASE(GL_DEBUG_TYPE_OTHER) + RESULT_CASE(GL_DEBUG_TYPE_PERFORMANCE) + RESULT_CASE(GL_DEBUG_TYPE_PORTABILITY) + RESULT_CASE(GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR) RESULT_CASE(GL_DECR) RESULT_CASE(GL_DECR_WRAP) RESULT_CASE(GL_DELETE_STATUS) @@ -560,6 +575,27 @@ std::string GLenumToString(GLenum code) { #define GL_ENUM_TO_STRING(code) GLenumToString(code).c_str() #define GL_BOOL_TO_STRING(code) GLboolToString(code).c_str() +void logOpenGlDebugMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) { + const auto logLevel = severity == GL_DEBUG_SEVERITY_HIGH + ? IGLLogLevel::LOG_ERROR + : (severity == GL_DEBUG_SEVERITY_MEDIUM ? IGLLogLevel::LOG_WARNING + : IGLLogLevel::LOG_INFO); + IGLLog(logLevel, + "%s %s %u %s: %.*s\n", + GL_ENUM_TO_STRING(source), + GL_ENUM_TO_STRING(type), + id, + GL_ENUM_TO_STRING(severity), + static_cast(message ? length : 0), + message ? message : ""); +} + } // namespace #endif // defined(IGL_API_LOG) && (IGL_DEBUG || defined(IGL_FORCE_ENABLE_LOGS)) @@ -1175,6 +1211,25 @@ void IContext::cullFace(GLint mode) { GLCHECK_ERRORS(); } +void IContext::debugMessageCallback(PFNIGLDEBUGPROC callback, const void* userParam) { + if (debugMessageInsertProc_ == nullptr) { + if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::DebugMessageCallback)) { + if (deviceFeatureSet_.hasInternalRequirement( + InternalRequirement::DebugMessageCallbackExtReq)) { + if (deviceFeatureSet_.hasExtension(Extensions::Debug)) { + debugMessageCallbackProc_ = iglDebugMessageCallbackKHR; + } + } else { + debugMessageCallbackProc_ = iglDebugMessageCallback; + } + } + } + + GLCALL_PROC(debugMessageCallbackProc_, callback, userParam); + APILOG("glDebugMessageCallback(%p, %p)\n", callback, userParam); + GLCHECK_ERRORS(); +} + void IContext::debugMessageInsert(GLenum source, GLenum type, GLuint id, @@ -1182,8 +1237,8 @@ void IContext::debugMessageInsert(GLenum source, GLsizei length, const GLchar* buf) { if (debugMessageInsertProc_ == nullptr) { - if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::Debug)) { - if (deviceFeatureSet_.hasInternalRequirement(InternalRequirement::DebugExtReq)) { + if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::DebugMessage)) { + if (deviceFeatureSet_.hasInternalRequirement(InternalRequirement::DebugMessageExtReq)) { if (deviceFeatureSet_.hasExtension(Extensions::Debug)) { debugMessageInsertProc_ = iglDebugMessageInsertKHR; } else if (deviceFeatureSet_.hasExtension(Extensions::DebugMarker)) { @@ -2287,8 +2342,8 @@ void IContext::polygonOffset(GLfloat factor, GLfloat units) { void IContext::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar* message) { if (pushDebugGroupProc_ == nullptr) { - if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::Debug)) { - if (deviceFeatureSet_.hasInternalRequirement(InternalRequirement::DebugExtReq)) { + if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::DebugMessage)) { + if (deviceFeatureSet_.hasInternalRequirement(InternalRequirement::DebugMessageExtReq)) { if (deviceFeatureSet_.hasExtension(Extensions::Debug)) { pushDebugGroupProc_ = iglPushDebugGroupKHR; } else if (deviceFeatureSet_.hasExtension(Extensions::DebugMarker)) { @@ -2307,8 +2362,8 @@ void IContext::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GL void IContext::popDebugGroup() { if (popDebugGroupProc_ == nullptr) { - if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::Debug)) { - if (deviceFeatureSet_.hasInternalRequirement(InternalRequirement::DebugExtReq)) { + if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::DebugMessage)) { + if (deviceFeatureSet_.hasInternalRequirement(InternalRequirement::DebugMessageExtReq)) { if (deviceFeatureSet_.hasExtension(Extensions::Debug)) { popDebugGroupProc_ = iglPopDebugGroupKHR; } else if (deviceFeatureSet_.hasExtension(Extensions::DebugMarker)) { @@ -3400,6 +3455,13 @@ void IContext::initialize(Result* result) { if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::SeamlessCubeMap)) { enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); } + +#if defined(IGL_API_LOG) + enable(GL_DEBUG_OUTPUT); + if (deviceFeatureSet_.hasInternalFeature(InternalFeatures::DebugMessageCallback)) { + debugMessageCallback(logOpenGlDebugMessage, nullptr); + } +#endif } const DeviceFeatureSet& IContext::deviceFeatures() const { diff --git a/src/igl/opengl/IContext.h b/src/igl/opengl/IContext.h index 2d9977b6f3..1928840f53 100644 --- a/src/igl/opengl/IContext.h +++ b/src/igl/opengl/IContext.h @@ -176,6 +176,7 @@ class IContext { GLuint createProgram(); GLuint createShader(GLenum shaderType); virtual void cullFace(GLint mode); + void debugMessageCallback(PFNIGLDEBUGPROC callback, const void* userParam); void debugMessageInsert(GLenum source, GLenum type, GLuint id, @@ -613,6 +614,7 @@ class IContext { PFNIGLCLEARDEPTHFPROC clearDepthfProc_ = nullptr; PFNIGLCOMPRESSEDTEXIMAGE3DPROC compressedTexImage3DProc_ = nullptr; PFNIGLCOMPRESSEDTEXSUBIMAGE3DPROC compressedTexSubImage3DProc_ = nullptr; + PFNIGLDEBUGMESSAGECALLBACKPROC debugMessageCallbackProc_ = nullptr; PFNIGLDEBUGMESSAGEINSERTPROC debugMessageInsertProc_ = nullptr; PFNIGLDELETESYNCPROC deleteSyncProc_ = nullptr; PFNIGLDELETEVERTEXARRAYSPROC deleteVertexArraysProc_ = nullptr;