diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index b7b97e9f2..b907caf9c 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -530,8 +530,6 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform) m_UsesVRMarkers = false; - m_RealDebugFunc = NULL; - m_RealDebugFuncParam = NULL; m_SuppressDebugMessages = false; m_DrawcallStack.push_back(&m_ParentDrawcall); @@ -1247,8 +1245,18 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) // this extension is something RenderDoc will support even if the impl // doesn't. https://renderdoc.org/debug_tool.txt ctxdata.glExts.push_back("GL_EXT_debug_tool"); - ctxdata.glExts.push_back("GL_GREMEDY_frame_terminator"); - ctxdata.glExts.push_back("GL_GREMEDY_string_marker"); + + // similarly we report all the debug extensions so that applications can use them freely - we + // don't call into the driver so we don't need to care if the driver supports them + ctxdata.glExts.push_back("GL_KHR_debug"); + ctxdata.glExts.push_back("GL_EXT_debug_label"); + ctxdata.glExts.push_back("GL_EXT_debug_marker"); + + if(!IsGLES) + { + ctxdata.glExts.push_back("GL_GREMEDY_frame_terminator"); + ctxdata.glExts.push_back("GL_GREMEDY_string_marker"); + } merge(ctxdata.glExts, ctxdata.glExtsString, ' '); @@ -2641,8 +2649,9 @@ void WrappedOpenGL::DebugSnoop(GLenum source, GLenum type, GLuint id, GLenum sev } } - if(m_RealDebugFunc && !RenderDoc::Inst().GetCaptureOptions().debugOutputMute) - m_RealDebugFunc(source, type, id, severity, length, message, m_RealDebugFuncParam); + if(GetCtxData().m_RealDebugFunc && !RenderDoc::Inst().GetCaptureOptions().debugOutputMute) + GetCtxData().m_RealDebugFunc(source, type, id, severity, length, message, + GetCtxData().m_RealDebugFuncParam); } void WrappedOpenGL::AddResource(ResourceId id, ResourceType type, const char *defaultNamePrefix) diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 1b0c39852..5ddb34b7e 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -86,8 +86,6 @@ private: void Serialise_DebugMessages(SerialiserType &ser); vector GetDebugMessages(); - GLDEBUGPROC m_RealDebugFunc; - const void *m_RealDebugFuncParam; string m_DebugMsgContext; bool m_SuppressDebugMessages; @@ -318,6 +316,9 @@ private: ctx = NULL; shareGroup = NULL; + m_RealDebugFunc = NULL; + m_RealDebugFuncParam = NULL; + built = ready = false; attribsCreate = false; version = 0; @@ -341,6 +342,9 @@ private: void *shareGroup; + GLDEBUGPROC m_RealDebugFunc; + const void *m_RealDebugFuncParam; + bool built; bool ready; diff --git a/renderdoc/driver/gl/gl_hooks.cpp b/renderdoc/driver/gl/gl_hooks.cpp index b09b1f727..fb1a17f2a 100644 --- a/renderdoc/driver/gl/gl_hooks.cpp +++ b/renderdoc/driver/gl/gl_hooks.cpp @@ -153,8 +153,30 @@ DefineUnsupportedHooks(); // implementation. bool FullyImplementedFunction(const char *funcname) { - return !strcmp(funcname, "glFrameTerminatorGREMEDY") || - !strcmp(funcname, "glStringMarkerGREMEDY"); + return + // GL_GREMEDY_frame_terminator + !strcmp(funcname, "glFrameTerminatorGREMEDY") || + // GL_GREMEDY_string_marker + !strcmp(funcname, "glStringMarkerGREMEDY") || + // GL_EXT_debug_label + !strcmp(funcname, "glLabelObjectEXT") || !strcmp(funcname, "glGetObjectLabelEXT") || + // GL_EXT_debug_marker + !strcmp(funcname, "glInsertEventMarkerEXT") || !strcmp(funcname, "glPushGroupMarkerEXT") || + !strcmp(funcname, "glPopGroupMarkerEXT") || + // GL_KHR_debug (Core variants) + !strcmp(funcname, "DebugMessageControl") || !strcmp(funcname, "DebugMessageInsert") || + !strcmp(funcname, "DebugMessageCallback") || !strcmp(funcname, "GetDebugMessageLog") || + !strcmp(funcname, "GetPointerv") || !strcmp(funcname, "PushDebugGroup") || + !strcmp(funcname, "PopDebugGroup") || !strcmp(funcname, "ObjectLabel") || + !strcmp(funcname, "GetObjectLabel") || !strcmp(funcname, "ObjectPtrLabel") || + !strcmp(funcname, "GetObjectPtrLabel") || + // GL_KHR_debug (KHR variants) + !strcmp(funcname, "DebugMessageControlKHR") || !strcmp(funcname, "DebugMessageInsertKHR") || + !strcmp(funcname, "DebugMessageCallbackKHR") || !strcmp(funcname, "GetDebugMessageLogKHR") || + !strcmp(funcname, "GetPointervKHR") || !strcmp(funcname, "PushDebugGroupKHR") || + !strcmp(funcname, "PopDebugGroupKHR") || !strcmp(funcname, "ObjectLabelKHR") || + !strcmp(funcname, "GetObjectLabelKHR") || !strcmp(funcname, "ObjectPtrLabelKHR") || + !strcmp(funcname, "GetObjectPtrLabelKHR"); } void *HookedGetProcAddress(const char *func, void *realFunc) diff --git a/renderdoc/driver/gl/gl_manager.h b/renderdoc/driver/gl/gl_manager.h index 3cf35c13b..7929cd243 100644 --- a/renderdoc/driver/gl/gl_manager.h +++ b/renderdoc/driver/gl/gl_manager.h @@ -163,6 +163,8 @@ public: auto it = m_CurrentResourceIds.find(res); if(it != m_CurrentResourceIds.end()) { + m_Names.erase(it->second); + ReleaseCurrentResource(it->second); m_CurrentResourceIds.erase(res); } @@ -228,9 +230,11 @@ public: GLsync GetSync(GLuint name) { return m_CurrentSyncs[name]; } ResourceId GetSyncID(GLsync sync) { return m_SyncIDs[sync]; } - // KHR_debug storage on replay + // KHR_debug storage const std::string &GetName(ResourceId id) { return m_Names[id]; } void SetName(ResourceId id, const std::string &name) { m_Names[id] = name; } + void SetName(GLResource res, const std::string &name) { SetName(GetID(res), name); } + std::string GetName(GLResource res) { return GetName(GetID(res)); } // we need to find all the children bound to VAOs/FBOs and mark them referenced. The reason for // this is that say a VAO became high traffic and we stopped serialising buffer binds, but then it // is never modified in a frame and none of the buffers are ever referenced. They would be diff --git a/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp index a92d87ed6..af0e44cf7 100644 --- a/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_debug_funcs.cpp @@ -27,6 +27,59 @@ #include "common/common.h" #include "strings/string_utils.h" +static std::string DecodeObjectLabel(GLsizei length, const GLchar *label) +{ + // we share implementations between KHR_debug and EXT_debug_label, however KHR_debug follows the + // pattern elsewhere (e.g. in glShaderSource) of a length of -1 meaning indeterminate + // NULL-terminated length, but EXT_debug_label takes length of 0 to mean that. + GLsizei realLength = length; + if(gl_CurChunk == GLChunk::glLabelObjectEXT && length == 0) + realLength = -1; + + // if length is negative (after above twiddling), it's taken from strlen and the label must be + // NULL-terminated + if(realLength < 0) + realLength = label ? (GLsizei)strlen(label) : 0; + + if(realLength == 0 || label == NULL) + return ""; + + return std::string(label, label + realLength); +} + +static void ReturnObjectlabel(std::string name, GLsizei bufSize, GLsizei *length, GLchar *label) +{ + // If