diff options
Diffstat (limited to 'src/Ryujinx.Graphics.OpenGL/Debugger.cs')
-rw-r--r-- | src/Ryujinx.Graphics.OpenGL/Debugger.cs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.OpenGL/Debugger.cs b/src/Ryujinx.Graphics.OpenGL/Debugger.cs new file mode 100644 index 00000000..9f67cfc6 --- /dev/null +++ b/src/Ryujinx.Graphics.OpenGL/Debugger.cs @@ -0,0 +1,101 @@ +using OpenTK.Graphics.OpenGL; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Logging; +using System; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Ryujinx.Graphics.OpenGL +{ + public static class Debugger + { + private static DebugProc _debugCallback; + + private static int _counter; + + public static void Initialize(GraphicsDebugLevel logLevel) + { + // Disable everything + GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DontCare, DebugSeverityControl.DontCare, 0, (int[])null, false); + + if (logLevel == GraphicsDebugLevel.None) + { + GL.Disable(EnableCap.DebugOutputSynchronous); + GL.DebugMessageCallback(null, IntPtr.Zero); + + return; + } + + GL.Enable(EnableCap.DebugOutputSynchronous); + + if (logLevel == GraphicsDebugLevel.Error) + { + GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypeError, DebugSeverityControl.DontCare, 0, (int[])null, true); + } + else if (logLevel == GraphicsDebugLevel.Slowdowns) + { + GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypeError, DebugSeverityControl.DontCare, 0, (int[])null, true); + GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypePerformance, DebugSeverityControl.DontCare, 0, (int[])null, true); + } + else + { + GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DontCare, DebugSeverityControl.DontCare, 0, (int[])null, true); + } + + _counter = 0; + _debugCallback = GLDebugHandler; + + GL.DebugMessageCallback(_debugCallback, IntPtr.Zero); + + Logger.Warning?.Print(LogClass.Gpu, "OpenGL Debugging is enabled. Performance will be negatively impacted."); + } + + private static void GLDebugHandler( + DebugSource source, + DebugType type, + int id, + DebugSeverity severity, + int length, + IntPtr message, + IntPtr userParam) + { + string msg = Marshal.PtrToStringUTF8(message).Replace('\n', ' '); + + switch (type) + { + case DebugType.DebugTypeError : Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR"); break; + case DebugType.DebugTypePerformance: Logger.Warning?.Print(LogClass.Gpu, $"{severity}: {msg}", "GLPERF"); break; + case DebugType.DebugTypePushGroup : Logger.Info?.Print(LogClass.Gpu, $"{{ ({id}) {severity}: {msg}", "GLINFO"); break; + case DebugType.DebugTypePopGroup : Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO"); break; + default: + if (source == DebugSource.DebugSourceApplication) + { + Logger.Info?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLINFO"); + } + else + { + Logger.Debug?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLDEBUG"); + } + break; + } + } + + // Useful debug helpers + public static void PushGroup(string dbgMsg) + { + int counter = Interlocked.Increment(ref _counter); + + GL.PushDebugGroup(DebugSourceExternal.DebugSourceApplication, counter, dbgMsg.Length, dbgMsg); + } + + public static void PopGroup() + { + GL.PopDebugGroup(); + } + + public static void Print(string dbgMsg, DebugType type = DebugType.DebugTypeMarker, DebugSeverity severity = DebugSeverity.DebugSeverityNotification, int id = 999999) + { + GL.DebugMessageInsert(DebugSourceExternal.DebugSourceApplication, type, id, severity, dbgMsg.Length, dbgMsg); + } + } +} |