diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index e824e216d6..1a2e2a9f7d 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -157,7 +157,6 @@ Device::Device() : base_bindings{BuildBaseBindings()} {
     has_precise_bug = TestPreciseBug();
     has_broken_compute = is_intel_proprietary;
     has_fast_buffer_sub_data = is_nvidia;
-    has_debug_tool = HasExtension(extensions, "GL_EXT_debug_tool");
 
     LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
     LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 7aaa3a077f..d73b099d01 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -84,10 +84,6 @@ public:
         return has_fast_buffer_sub_data;
     }
 
-    bool HasDebugTool() const {
-        return has_debug_tool;
-    }
-
 private:
     static bool TestVariableAoffi();
     static bool TestPreciseBug();
@@ -106,7 +102,6 @@ private:
     bool has_precise_bug{};
     bool has_broken_compute{};
     bool has_fast_buffer_sub_data{};
-    bool has_debug_tool{};
 };
 
 } // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index c91658cd1b..d8ecd090b0 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -5,8 +5,11 @@
 #include <algorithm>
 #include <cstddef>
 #include <cstdlib>
+#include <cstring>
 #include <memory>
+
 #include <glad/glad.h>
+
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "common/microprofile.h"
@@ -25,6 +28,24 @@
 
 namespace OpenGL {
 
+/// Returns true if any debug tool is attached
+bool HasDebugTool() {
+    const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED");
+    if (nsight) {
+        return true;
+    }
+
+    GLint num_extensions;
+    glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
+    for (GLuint index = 0; index < static_cast<GLuint>(num_extensions); ++index) {
+        const auto name = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, index));
+        if (!std::strcmp(name, "GL_EXT_debug_tool")) {
+            return true;
+        }
+    }
+    return false;
+}
+
 // If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have
 // to wait on available presentation frames.
 constexpr std::size_t SWAP_CHAIN_SIZE = 3;
@@ -56,7 +77,7 @@ public:
     std::deque<Frame*> present_queue;
     Frame* previous_frame{};
 
-    FrameMailbox() : has_debug_tool{Device().HasDebugTool()} {
+    FrameMailbox() : has_debug_tool{HasDebugTool()} {
         for (auto& frame : swap_chain) {
             free_queue.push(&frame);
         }