From 6308d78cd4b4600e2db54f63e418799850c2fe49 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 2 Nov 2014 10:51:59 +0000 Subject: [PATCH] Implement debug device/debug api message tracking for GL --- renderdoc/api/replay/replay_enums.h | 6 +- renderdoc/driver/d3d11/d3d11_device.cpp | 8 +- renderdoc/driver/gl/gl_common.h | 2 + renderdoc/driver/gl/gl_driver.cpp | 140 +++++++++++++++++- renderdoc/driver/gl/gl_driver.h | 3 + .../driver/gl/wrappers/gl_draw_funcs.cpp | 60 ++++++++ renderdoc/hooks/gl_linux_hooks.cpp | 42 +++++- renderdoc/hooks/gl_win32_hooks.cpp | 42 +++++- renderdocui/Interop/Enums.cs | 6 +- 9 files changed, 295 insertions(+), 14 deletions(-) diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index bd1e00d77..7fc9871bc 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -275,9 +275,9 @@ enum DebugMessageCategory enum DebugMessageSeverity { - eDbgSeverity_Corruption = 0, - eDbgSeverity_Error, - eDbgSeverity_Warning, + eDbgSeverity_High = 0, + eDbgSeverity_Medium, + eDbgSeverity_Low, eDbgSeverity_Info, }; diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 2dd0990a5..41c0efbe0 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -644,7 +644,7 @@ vector WrappedID3D11Device::GetDebugMessages() DebugMessage msg; msg.category = eDbgCategory_Miscellaneous; - msg.severity = eDbgSeverity_Error; + msg.severity = eDbgSeverity_Medium; switch(message->Category) { @@ -691,13 +691,13 @@ vector WrappedID3D11Device::GetDebugMessages() switch(message->Severity) { case D3D11_MESSAGE_SEVERITY_CORRUPTION: - msg.severity = eDbgSeverity_Corruption; + msg.severity = eDbgSeverity_High; break; case D3D11_MESSAGE_SEVERITY_ERROR: - msg.severity = eDbgSeverity_Error; + msg.severity = eDbgSeverity_Medium; break; case D3D11_MESSAGE_SEVERITY_WARNING: - msg.severity = eDbgSeverity_Warning; + msg.severity = eDbgSeverity_Low; break; case D3D11_MESSAGE_SEVERITY_INFO: msg.severity = eDbgSeverity_Info; diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index ae19090a4..88de18314 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -240,6 +240,8 @@ enum GLChunkType SET_MARKER, END_EVENT, + DEBUG_MESSAGES, + CAPTURE_SCOPE, CONTEXT_CAPTURE_HEADER, CONTEXT_CAPTURE_FOOTER, diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 0551572cd..e7f1f16e9 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -193,6 +193,8 @@ const char *GLChunkNames[] = "glPushDebugGroup", "glDebugMessageInsert", "glPopDebugGroup", + + "DebugMessageList", "Capture", "BeginCapture", @@ -536,14 +538,20 @@ void WrappedOpenGL::ActivateContext(void *windowHandle, void *contextHandle) if(contextHandle) { + const GLHookSet &gl = m_Real; + + if(gl.glDebugMessageCallback && RenderDoc::Inst().GetCaptureOptions().DebugDeviceMode) + { + gl.glDebugMessageCallback(&DebugSnoopStatic, this); + gl.glEnable(eGL_DEBUG_OUTPUT_SYNCHRONOUS); + } + FontData &font = m_Fonts[contextHandle]; if(!font.built) { font.built = true; - const GLHookSet &gl = m_Real; - if(gl.glGenTextures && gl.glTextureStorage2DEXT && gl.glTextureSubImage2DEXT && gl.glGenVertexArrays && gl.glBindVertexArray && gl.glGenBuffers && gl.glNamedBufferStorageEXT && @@ -1112,6 +1120,8 @@ void WrappedOpenGL::AttemptCapture() { m_State = WRITING_CAPFRAME; + m_DebugMessages.clear(); + { RDCDEBUG("Immediate Context %llu Attempting capture", GetContextResourceID()); @@ -1163,9 +1173,84 @@ void WrappedOpenGL::FinishCapture() { m_State = WRITING_IDLE; + m_DebugMessages.clear(); + //m_SuccessfulCapture = false; } +vector WrappedOpenGL::Serialise_DebugMessages() +{ + SCOPED_SERIALISE_CONTEXT(DEBUG_MESSAGES); + + vector debugMessages; + + if(m_State == WRITING_CAPFRAME) + { + debugMessages = m_DebugMessages; + m_DebugMessages.clear(); + } + + SERIALISE_ELEMENT(bool, HasCallstack, RenderDoc::Inst().GetCaptureOptions().CaptureCallstacksOnlyDraws != 0); + + if(HasCallstack) + { + if(m_State >= WRITING) + { + Callstack::Stackwalk *call = Callstack::Collect(); + + RDCASSERT(call->NumLevels() < 0xff); + + size_t numLevels = call->NumLevels(); + uint64_t *stack = call->GetAddrs(); + + m_pSerialiser->Serialise("callstack", stack, numLevels); + + delete call; + } + else + { + size_t numLevels = 0; + uint64_t *stack = NULL; + + m_pSerialiser->Serialise("callstack", stack, numLevels); + + m_pSerialiser->SetCallstack(stack, numLevels); + + SAFE_DELETE_ARRAY(stack); + } + } + + SERIALISE_ELEMENT(uint32_t, NumMessages, (uint32_t)debugMessages.size()); + + for(uint32_t i=0; i < NumMessages; i++) + { + ScopedContext scope(m_pSerialiser, NULL, "DebugMessage", "DebugMessage", 0, false); + + string desc; + if(m_State >= WRITING) + desc = debugMessages[i].description.elems; + + SERIALISE_ELEMENT(uint32_t, Category, debugMessages[i].category); + SERIALISE_ELEMENT(uint32_t, Severity, debugMessages[i].severity); + SERIALISE_ELEMENT(uint32_t, ID, debugMessages[i].messageID); + SERIALISE_ELEMENT(string, Description, desc); + + if(m_State == READING) + { + DebugMessage msg; + msg.category = (DebugMessageCategory)Category; + msg.severity = (DebugMessageSeverity)Severity; + msg.messageID = ID; + msg.description = Description; + + debugMessages.push_back(msg); + } + } + + return debugMessages; +} + + void WrappedOpenGL::DebugSnoop(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message) { if(type != eGL_DEBUG_TYPE_OTHER || severity != eGL_DEBUG_SEVERITY_NOTIFICATION) @@ -1174,6 +1259,57 @@ void WrappedOpenGL::DebugSnoop(GLenum source, GLenum type, GLuint id, GLenum sev ToStr::Get(source).c_str(), ToStr::Get(type).c_str(), id, ToStr::Get(severity).c_str(), message); } + if(m_State == WRITING_CAPFRAME && + type != eGL_DEBUG_TYPE_PUSH_GROUP && type != eGL_DEBUG_TYPE_POP_GROUP) + { + DebugMessage msg; + + msg.messageID = id; + msg.description = string(message, message+length); + + switch(severity) + { + case eGL_DEBUG_SEVERITY_HIGH: + msg.severity = eDbgSeverity_High; break; + case eGL_DEBUG_SEVERITY_MEDIUM: + msg.severity = eDbgSeverity_Medium; break; + case eGL_DEBUG_SEVERITY_LOW: + msg.severity = eDbgSeverity_Low; break; + case eGL_DEBUG_SEVERITY_NOTIFICATION: + default: + msg.severity = eDbgSeverity_Info; break; + } + + if(source == eGL_DEBUG_SOURCE_APPLICATION || type == eGL_DEBUG_TYPE_MARKER) + { + msg.category = eDbgCategory_Application_Defined; + } + else if(source == eGL_DEBUG_SOURCE_SHADER_COMPILER) + { + msg.category = eDbgCategory_Shaders; + } + else + { + switch(type) + { + case eGL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + msg.category = eDbgCategory_Deprecated; break; + case eGL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + msg.category = eDbgCategory_Undefined; break; + case eGL_DEBUG_TYPE_PORTABILITY: + msg.category = eDbgCategory_Portability; break; + case eGL_DEBUG_TYPE_PERFORMANCE: + msg.category = eDbgCategory_Performance; break; + case eGL_DEBUG_TYPE_ERROR: + case eGL_DEBUG_TYPE_OTHER: + default: + msg.category = eDbgCategory_Miscellaneous; break; + } + } + + m_DebugMessages.push_back(msg); + } + if(m_RealDebugFunc) m_RealDebugFunc(source, type, id, severity, length, message, m_RealDebugFuncParam); } diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index b2441d293..be94d295f 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -93,6 +93,9 @@ class WrappedOpenGL const GLHookSet &GetHookset() { return m_Real; } + vector m_DebugMessages; + vector Serialise_DebugMessages(); + GLDEBUGPROC m_RealDebugFunc; const void *m_RealDebugFuncParam; diff --git a/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp index 39ba376a2..3ad4a8fcf 100644 --- a/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp @@ -38,6 +38,8 @@ bool WrappedOpenGL::Serialise_glDrawArrays(GLenum mode, GLint first, GLsizei cou } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -57,6 +59,8 @@ bool WrappedOpenGL::Serialise_glDrawArrays(GLenum mode, GLint first, GLsizei cou draw.flags |= eDraw_Drawcall; + draw.debugMessages = debugMessages; + m_LastDrawMode = Mode; AddDrawcall(draw, true); @@ -91,6 +95,8 @@ bool WrappedOpenGL::Serialise_glDrawArraysInstanced(GLenum mode, GLint first, GL } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -110,6 +116,8 @@ bool WrappedOpenGL::Serialise_glDrawArraysInstanced(GLenum mode, GLint first, GL draw.instanceOffset = 0; draw.flags |= eDraw_Drawcall|eDraw_Instanced; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; @@ -146,6 +154,8 @@ bool WrappedOpenGL::Serialise_glDrawArraysInstancedBaseInstance(GLenum mode, GLi } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -166,6 +176,8 @@ bool WrappedOpenGL::Serialise_glDrawArraysInstancedBaseInstance(GLenum mode, GLi draw.instanceOffset = BaseInstance; draw.flags |= eDraw_Drawcall|eDraw_Instanced; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; @@ -201,6 +213,8 @@ bool WrappedOpenGL::Serialise_glDrawElements(GLenum mode, GLsizei count, GLenum } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -220,6 +234,8 @@ bool WrappedOpenGL::Serialise_glDrawElements(GLenum mode, GLsizei count, GLenum draw.instanceOffset = 0; draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; m_LastIndexSize = Type; @@ -259,6 +275,8 @@ bool WrappedOpenGL::Serialise_glDrawRangeElements(GLenum mode, GLuint start, GLu } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -278,6 +296,8 @@ bool WrappedOpenGL::Serialise_glDrawRangeElements(GLenum mode, GLuint start, GLu draw.instanceOffset = 0; draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; m_LastIndexSize = Type; @@ -316,6 +336,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsBaseVertex(GLenum mode, GLsizei coun } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -336,6 +358,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsBaseVertex(GLenum mode, GLsizei coun draw.instanceOffset = 0; draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; m_LastIndexSize = Type; @@ -374,6 +398,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstanced(GLenum mode, GLsizei count } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -394,6 +420,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstanced(GLenum mode, GLsizei count draw.instanceOffset = 0; draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; m_LastIndexSize = Type; @@ -433,6 +461,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseInstance(GLenum mode, G } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -454,6 +484,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseInstance(GLenum mode, G draw.instanceOffset = BaseInstance; draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; m_LastIndexSize = Type; @@ -493,6 +525,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertex(GLenum mode, GLs } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -514,6 +548,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertex(GLenum mode, GLs draw.instanceOffset = 0; draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; m_LastIndexSize = Type; @@ -554,6 +590,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertexBaseInstance(GLen } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -576,6 +614,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertexBaseInstance(GLen draw.instanceOffset = BaseInstance; draw.flags |= eDraw_Drawcall|eDraw_UseIBuffer; + + draw.debugMessages = debugMessages; m_LastDrawMode = Mode; m_LastIndexSize = Type; @@ -624,6 +664,8 @@ bool WrappedOpenGL::Serialise_glClearBufferfv(GLenum buffer, GLint drawbuffer, c } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -635,6 +677,8 @@ bool WrappedOpenGL::Serialise_glClearBufferfv(GLenum buffer, GLint drawbuffer, c FetchDrawcall draw; draw.name = widen(name); draw.flags |= eDraw_Clear; + + draw.debugMessages = debugMessages; AddDrawcall(draw, true); } @@ -680,6 +724,8 @@ bool WrappedOpenGL::Serialise_glClearBufferiv(GLenum buffer, GLint drawbuffer, c } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -691,6 +737,8 @@ bool WrappedOpenGL::Serialise_glClearBufferiv(GLenum buffer, GLint drawbuffer, c FetchDrawcall draw; draw.name = widen(name); draw.flags |= eDraw_Clear; + + draw.debugMessages = debugMessages; AddDrawcall(draw, true); } @@ -728,6 +776,8 @@ bool WrappedOpenGL::Serialise_glClearBufferuiv(GLenum buffer, GLint drawbuffer, } const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -739,6 +789,8 @@ bool WrappedOpenGL::Serialise_glClearBufferuiv(GLenum buffer, GLint drawbuffer, FetchDrawcall draw; draw.name = widen(name); draw.flags |= eDraw_Clear; + + draw.debugMessages = debugMessages; AddDrawcall(draw, true); } @@ -770,6 +822,8 @@ bool WrappedOpenGL::Serialise_glClearBufferfi(GLenum buffer, GLint drawbuffer, G m_Real.glClearBufferfi(buf, draw, d, s); const string desc = m_pSerialiser->GetDebugStr(); + + vector debugMessages = Serialise_DebugMessages(); if(m_State == READING) { @@ -781,6 +835,8 @@ bool WrappedOpenGL::Serialise_glClearBufferfi(GLenum buffer, GLint drawbuffer, G FetchDrawcall draw; draw.name = widen(name); draw.flags |= eDraw_Clear; + + draw.debugMessages = debugMessages; AddDrawcall(draw, true); } @@ -810,6 +866,8 @@ bool WrappedOpenGL::Serialise_glClear(GLbitfield mask) const string desc = m_pSerialiser->GetDebugStr(); + vector debugMessages = Serialise_DebugMessages(); + if(m_State == READING) { AddEvent(CLEARBUFFERF, desc); @@ -833,6 +891,8 @@ bool WrappedOpenGL::Serialise_glClear(GLbitfield mask) FetchDrawcall draw; draw.name = widen(name); draw.flags |= eDraw_Clear; + + draw.debugMessages = debugMessages; AddDrawcall(draw, true); } diff --git a/renderdoc/hooks/gl_linux_hooks.cpp b/renderdoc/hooks/gl_linux_hooks.cpp index 5b83be1b8..f989693e5 100644 --- a/renderdoc/hooks/gl_linux_hooks.cpp +++ b/renderdoc/hooks/gl_linux_hooks.cpp @@ -328,7 +328,47 @@ void glXDestroyContext(Display *dpy, GLXContext ctx) __attribute__ ((visibility ("default"))) GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, GLXContext shareList, Bool direct, const int *attribList) { - GLXContext ret = OpenGLHook::glhooks.glXCreateContextAttribsARB_real(dpy, config, shareList, direct, attribList); + const int *attribs = attribList; + vector attribVec; + + if(RenderDoc::Inst().GetCaptureOptions().DebugDeviceMode) + { + bool flagsNext = false; + bool flagsFound = false; + const int *a = attribList; + while(*a) + { + int val = *a; + + if(flagsNext) + { + val |= GLX_CONTEXT_DEBUG_BIT_ARB; + flagsNext = false; + } + + if(val == GLX_CONTEXT_FLAGS_ARB) + { + flagsNext = true; + flagsFound = true; + } + + attribVec.push_back(val); + + a++; + } + + if(!flagsFound) + { + attribVec.push_back(GLX_CONTEXT_FLAGS_ARB); + attribVec.push_back(GLX_CONTEXT_DEBUG_BIT_ARB); + } + + attribVec.push_back(0); + + attribs = &attribVec[0]; + } + + GLXContext ret = OpenGLHook::glhooks.glXCreateContextAttribsARB_real(dpy, config, shareList, direct, attribs); XVisualInfo *vis = OpenGLHook::glhooks.glXGetVisualFromFBConfig_real(dpy, config); diff --git a/renderdoc/hooks/gl_win32_hooks.cpp b/renderdoc/hooks/gl_win32_hooks.cpp index b9d014498..d57d6e815 100644 --- a/renderdoc/hooks/gl_win32_hooks.cpp +++ b/renderdoc/hooks/gl_win32_hooks.cpp @@ -333,8 +333,48 @@ class OpenGLHook : LibraryHook static HGLRC WINAPI wglCreateContextAttribsARB_hooked(HDC dc, HGLRC hShareContext, const int *attribList) { - HGLRC ret = glhooks.wglCreateContextAttribsARB_realfunc(dc, hShareContext, attribList); + const int *attribs = attribList; + vector attribVec; + + if(RenderDoc::Inst().GetCaptureOptions().DebugDeviceMode) + { + bool flagsNext = false; + bool flagsFound = false; + const int *a = attribList; + while(*a) + { + int val = *a; + + if(flagsNext) + { + val |= WGL_CONTEXT_DEBUG_BIT_ARB; + flagsNext = false; + } + + if(val == WGL_CONTEXT_FLAGS_ARB) + { + flagsNext = true; + flagsFound = true; + } + + attribVec.push_back(val); + + a++; + } + + if(!flagsFound) + { + attribVec.push_back(WGL_CONTEXT_FLAGS_ARB); + attribVec.push_back(WGL_CONTEXT_DEBUG_BIT_ARB); + } + + attribVec.push_back(0); + + attribs = &attribVec[0]; + } + HGLRC ret = glhooks.wglCreateContextAttribsARB_realfunc(dc, hShareContext, attribs); + glhooks.GetDriver()->CreateContext(WindowFromDC(dc), ret, hShareContext, GetInitParamsForDC(dc)); return ret; diff --git a/renderdocui/Interop/Enums.cs b/renderdocui/Interop/Enums.cs index 81e1c7f43..db10b7eb3 100644 --- a/renderdocui/Interop/Enums.cs +++ b/renderdocui/Interop/Enums.cs @@ -279,9 +279,9 @@ namespace renderdoc public enum DebugMessageSeverity { - Corruption = 0, - Error, - Warning, + High = 0, + Medium, + Low, Info, };