From 2558b2cdea925336fee00407ecb90a19e61e4094 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 24 Apr 2015 22:11:44 +0200 Subject: [PATCH] Add ways to detect RenderDoc being injected in D3D11 and OpenGL * D3D11 you query for interface with UUID of {A7AA6116-9C8D-4BBA-9083-B4D816B71B78}. It's just IUnknown* * GL implements GL_EXT_debug_tool with spec here: https://renderdoc.org/debug_tool.txt with DEBUG_TOOL_EXT #define'd to 0x6789, DEBUG_TOOL_NAME_EXT to 0x678A and DEBUG_TOOL_PURPOSE_EXT to 0x678B. For now, reporting this ext is enough to identify RenderDoc. --- docs/FAQ.aml | 39 +++++++++++++++- docs/TipsNTricks.aml | 18 ++++++++ renderdoc/driver/d3d11/d3d11_device.cpp | 9 ++++ renderdoc/driver/gl/gl_common.cpp | 3 ++ renderdoc/driver/gl/gl_driver.cpp | 5 +++ renderdoc/driver/gl/gl_enum.h | 8 ++++ renderdoc/driver/gl/official/glext.h | 14 ++++++ renderdoc/driver/gl/wrappers/gl_get_funcs.cpp | 44 +++++++++++++++++-- 8 files changed, 136 insertions(+), 4 deletions(-) diff --git a/docs/FAQ.aml b/docs/FAQ.aml index 680cfaf2a..ee182f3e1 100644 --- a/docs/FAQ.aml +++ b/docs/FAQ.aml @@ -341,7 +341,7 @@ -
+
RenderDoc is complaining about my OpenGL app in the overlay - what gives? @@ -363,5 +363,42 @@
+
+ Can I tell via the graphics APIs if RenderDoc is present at runtime? + + + Yes indeed. Some APIs offer ways to do this already - D3DPERF_GetStatus(), + ID3DUserDefinedAnnotation::GetStatus() and ID3D11DeviceContext2::IsAnnotationEnabled(). + + + In addition to those: + + + Querying an ID3D11Device for UUID {A7AA6116-9C8D-4BBA-9083-B4D816B71B78} + will return an IUnknown* and S_OK when RenderDoc is present. + + + +GL_EXT_debug_tool +GL_EXT_debug_tool +https://renderdoc.org/debug_tool.txt +_blank + + is implemented on RenderDoc, which is an extension I've proposed for this purpose + (identifying when and which tool is injected in your program). It allows you to query + for the presence name and type of a debug tool that's currently hooked. At the + time of writing only RenderDoc implements this as I've only just proposed the + extension publicly, but in future you can use the queries described in that spec. + + Alert text Until enumerants are assigned (if that ever happens): + + #define GL_DEBUG_TOOL_EXT 0x6789 + #define GL_DEBUG_TOOL_NAME_EXT 0x678A + #define GL_DEBUG_TOOL_PURPOSE_EXT 0x678B + + + + +
diff --git a/docs/TipsNTricks.aml b/docs/TipsNTricks.aml index 4e9ef1349..f3179d240 100644 --- a/docs/TipsNTricks.aml +++ b/docs/TipsNTricks.aml @@ -69,6 +69,24 @@ triggerFunc(); perform precise refinements with the arrow keys to nudge the selection in each direction. To get API debug or error messages, enable "Create Debug Device" when capturing then check out the window. + Detecting RenderDoc from your code can either be done by trying to load and + use the renderdoc in-program API, or through API specific ways: + +// For D3D11: +ID3D11Device *devicePointer = ...; +IUnknown *unk = NULL; +HRESULT hr = devicePointer->QueryInterface(MAKE_GUID({A7AA6116-9C8D-4BBA-9083-B4D816B71B78}), &unk); +if(SUCCEEDED(hr)) { /* renderdoc is present; */ } + +// For OpenGL: +// if GL_EXT_debug_tool is present (see https://renderdoc.org/debug_tool.txt) +glIsEnabled(GL_DEBUG_TOOL_EXT); + +// Until enumerants are assigned (if that ever happens): +#define GL_DEBUG_TOOL_EXT 0x6789 +#define GL_DEBUG_TOOL_NAME_EXT 0x678A +#define GL_DEBUG_TOOL_PURPOSE_EXT 0x678B + More coming soon hopefully :). diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index b56e6dac6..86021d0cc 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -525,6 +525,9 @@ HRESULT WrappedID3D11Device::QueryInterface(REFIID riid, void **ppvObject) // DEFINE_GUID(IID_IDirect3DDevice9, 0xd0223b96, 0xbf7a, 0x43fd, 0x92, 0xbd, 0xa4, 0x3b, 0xd, 0x82, 0xb9, 0xeb); static const GUID IDirect3DDevice9_uuid = { 0xd0223b96, 0xbf7a, 0x43fd, { 0x92, 0xbd, 0xa4, 0x3b, 0xd, 0x82, 0xb9, 0xeb } }; + // RenderDoc UUID {A7AA6116-9C8D-4BBA-9083-B4D816B71B78} + static const GUID IRenderDoc_uuid = { 0xa7aa6116, 0x9c8d, 0x4bba, { 0x90, 0x83, 0xb4, 0xd8, 0x16, 0xb7, 0x1b, 0x78 } }; + HRESULT hr = S_OK; if(riid == __uuidof(IDXGIDevice)) @@ -668,6 +671,12 @@ HRESULT WrappedID3D11Device::QueryInterface(REFIID riid, void **ppvObject) return E_NOINTERFACE; } } + else if(riid == IRenderDoc_uuid) + { + AddRef(); + *ppvObject = this; + return S_OK; + } else { string guid = ToStr::Get(riid); diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index e314ded1d..f80998aa7 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -3993,6 +3993,9 @@ string ToStrHelper::Get(const RDCGLenum &el) TOSTR_CASE_STRINGIZE_GLENUM(GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT) TOSTR_CASE_STRINGIZE_GLENUM(GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT) TOSTR_CASE_STRINGIZE_GLENUM(GL_SYNC_X11_FENCE_EXT) + TOSTR_CASE_STRINGIZE_GLENUM(GL_DEBUG_TOOL_EXT) + TOSTR_CASE_STRINGIZE_GLENUM(GL_DEBUG_TOOL_NAME_EXT) + TOSTR_CASE_STRINGIZE_GLENUM(GL_DEBUG_TOOL_PURPOSE_EXT) TOSTR_CASE_STRINGIZE_GLENUM(GL_IGNORE_BORDER_HP) TOSTR_CASE_STRINGIZE_GLENUM(GL_IMAGE_SCALE_X_HP) TOSTR_CASE_STRINGIZE_GLENUM(GL_IMAGE_SCALE_Y_HP) diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 0b238cff2..01526e522 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -1109,6 +1109,11 @@ 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"); + merge(ctxdata.glExts, ctxdata.glExtsString, ' '); if(gl.glGetIntegerv) diff --git a/renderdoc/driver/gl/gl_enum.h b/renderdoc/driver/gl/gl_enum.h index 3b6c54c5c..e4890910d 100644 --- a/renderdoc/driver/gl/gl_enum.h +++ b/renderdoc/driver/gl/gl_enum.h @@ -3204,6 +3204,14 @@ enum RDCGLenum eGL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT = 0x850F, eGL_VERTEX_WEIGHT_ARRAY_POINTER_EXT = 0x8510, eGL_SYNC_X11_FENCE_EXT = 0x90E1, + eGL_DEBUG_TOOL_EXT = 0x6789, + eGL_DEBUG_TOOL_NAME_EXT = 0x678A, + eGL_DEBUG_TOOL_PURPOSE_EXT = 0x678B, + eGL_DEBUG_TOOL_FRAME_CAPTURE_BIT_EXT = 0x0001, + eGL_DEBUG_TOOL_TRACE_CAPTURE_BIT_EXT = 0x0002, + eGL_DEBUG_TOOL_API_CALL_LOG_BIT_EXT = 0x0004, + eGL_DEBUG_TOOL_PROFILING_BIT_EXT = 0x0008, + eGL_DEBUG_TOOL_VALIDATION_BIT_EXT = 0x0010, eGL_IGNORE_BORDER_HP = 0x8150, eGL_CONSTANT_BORDER_HP = 0x8151, eGL_REPLICATE_BORDER_HP = 0x8153, diff --git a/renderdoc/driver/gl/official/glext.h b/renderdoc/driver/gl/official/glext.h index 26881f1bf..347efcc2e 100644 --- a/renderdoc/driver/gl/official/glext.h +++ b/renderdoc/driver/gl/official/glext.h @@ -8458,6 +8458,20 @@ GLAPI GLsync APIENTRY glImportSyncEXT (GLenum external_sync_type, GLintptr exter #endif #endif /* GL_EXT_x11_sync_object */ +// Manually added for ease of running scripts on this header to generate +// prototypes/enum etc. https://renderdoc.org/debug_tool.txt +#ifndef GL_EXT_debug_tool +#define GL_EXT_debug_tool 1 +#define GL_DEBUG_TOOL_EXT 0x6789 +#define GL_DEBUG_TOOL_NAME_EXT 0x678A +#define GL_DEBUG_TOOL_PURPOSE_EXT 0x678B +#define GL_DEBUG_TOOL_FRAME_CAPTURE_BIT_EXT 0x0001 +#define GL_DEBUG_TOOL_TRACE_CAPTURE_BIT_EXT 0x0002 +#define GL_DEBUG_TOOL_API_CALL_LOG_BIT_EXT 0x0004 +#define GL_DEBUG_TOOL_PROFILING_BIT_EXT 0x0008 +#define GL_DEBUG_TOOL_VALIDATION_BIT_EXT 0x0010 +#endif /* GL_EXT_debug_tool */ + #ifndef GL_GREMEDY_frame_terminator #define GL_GREMEDY_frame_terminator 1 typedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void); diff --git a/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp index 264954bd8..60f3917b7 100644 --- a/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp @@ -59,6 +59,9 @@ void WrappedOpenGL::glFinish() GLboolean WrappedOpenGL::glIsEnabled(GLenum cap) { + if(cap == eGL_DEBUG_TOOL_EXT) + return true; + return m_Real.glIsEnabled(cap); } @@ -69,6 +72,9 @@ GLboolean WrappedOpenGL::glIsTexture(GLuint texture) GLboolean WrappedOpenGL::glIsEnabledi(GLenum target, GLuint index) { + if(target == eGL_DEBUG_TOOL_EXT) + return true; + return m_Real.glIsEnabledi(target, index); } @@ -160,12 +166,18 @@ void WrappedOpenGL::glGetIntegerv(GLenum pname, GLint *params) *params = (GLint)64; return; } - if(pname == eGL_NUM_EXTENSIONS) + else if(pname == eGL_NUM_EXTENSIONS) { if(params) *params = (GLint)GetCtxData().glExts.size(); return; } + else if(pname == eGL_DEBUG_TOOL_PURPOSE_EXT) + { + if(params) + *params = GLint(eGL_DEBUG_TOOL_FRAME_CAPTURE_BIT_EXT); + return; + } m_Real.glGetIntegerv(pname, params); } @@ -180,7 +192,13 @@ void WrappedOpenGL::glGetInteger64v(GLenum pname, GLint64 *data) if(pname == eGL_MIN_MAP_BUFFER_ALIGNMENT) { if(data) - *data = (GLint)64; + *data = (GLint64)64; + return; + } + else if(pname == eGL_DEBUG_TOOL_PURPOSE_EXT) + { + if(data) + *data = GLint64(eGL_DEBUG_TOOL_FRAME_CAPTURE_BIT_EXT); return; } m_Real.glGetInteger64v(pname, data); @@ -199,6 +217,12 @@ void WrappedOpenGL::glGetIntegeri_v(GLenum pname, GLuint index, GLint *data) *data = (GLint)64; return; } + else if(pname == eGL_DEBUG_TOOL_PURPOSE_EXT) + { + if(data) + *data = GLint(eGL_DEBUG_TOOL_FRAME_CAPTURE_BIT_EXT); + return; + } m_Real.glGetIntegeri_v(pname, index, data); } @@ -217,7 +241,13 @@ void WrappedOpenGL::glGetInteger64i_v(GLenum pname, GLuint index, GLint64 *data) if(pname == eGL_MIN_MAP_BUFFER_ALIGNMENT) { if(data) - *data = (GLint)64; + *data = (GLint64)64; + return; + } + else if(pname == eGL_DEBUG_TOOL_PURPOSE_EXT) + { + if(data) + *data = GLint64(eGL_DEBUG_TOOL_FRAME_CAPTURE_BIT_EXT); return; } m_Real.glGetInteger64i_v(pname, index, data); @@ -477,6 +507,10 @@ const GLubyte *WrappedOpenGL::glGetString(GLenum name) { return (const GLubyte *)GetCtxData().glExtsString.c_str(); } + else if(name == eGL_DEBUG_TOOL_NAME_EXT) + { + return (const GLubyte *)"RenderDoc"; + } return m_Real.glGetString(name); } @@ -489,6 +523,10 @@ const GLubyte *WrappedOpenGL::glGetStringi(GLenum name, GLuint i) return (const GLubyte *)""; } + else if(name == eGL_DEBUG_TOOL_NAME_EXT) + { + return (const GLubyte *)"RenderDoc"; + } return m_Real.glGetStringi(name, i); }