/ src / Ryujinx.Graphics.OpenGL / Debugger.cs
Debugger.cs
  1  using OpenTK.Graphics.OpenGL;
  2  using Ryujinx.Common.Configuration;
  3  using Ryujinx.Common.Logging;
  4  using System;
  5  using System.Runtime.InteropServices;
  6  using System.Threading;
  7  
  8  namespace Ryujinx.Graphics.OpenGL
  9  {
 10      public static class Debugger
 11      {
 12          private static DebugProc _debugCallback;
 13  
 14          private static int _counter;
 15  
 16          public static void Initialize(GraphicsDebugLevel logLevel)
 17          {
 18              // Disable everything
 19              GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DontCare, DebugSeverityControl.DontCare, 0, (int[])null, false);
 20  
 21              if (logLevel == GraphicsDebugLevel.None)
 22              {
 23                  GL.Disable(EnableCap.DebugOutputSynchronous);
 24                  GL.DebugMessageCallback(null, IntPtr.Zero);
 25  
 26                  return;
 27              }
 28  
 29              GL.Enable(EnableCap.DebugOutputSynchronous);
 30  
 31              if (logLevel == GraphicsDebugLevel.Error)
 32              {
 33                  GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypeError, DebugSeverityControl.DontCare, 0, (int[])null, true);
 34              }
 35              else if (logLevel == GraphicsDebugLevel.Slowdowns)
 36              {
 37                  GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypeError, DebugSeverityControl.DontCare, 0, (int[])null, true);
 38                  GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypePerformance, DebugSeverityControl.DontCare, 0, (int[])null, true);
 39              }
 40              else
 41              {
 42                  GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DontCare, DebugSeverityControl.DontCare, 0, (int[])null, true);
 43              }
 44  
 45              _counter = 0;
 46              _debugCallback = GLDebugHandler;
 47  
 48              GL.DebugMessageCallback(_debugCallback, IntPtr.Zero);
 49  
 50              Logger.Warning?.Print(LogClass.Gpu, "OpenGL Debugging is enabled. Performance will be negatively impacted.");
 51          }
 52  
 53          private static void GLDebugHandler(
 54              DebugSource source,
 55              DebugType type,
 56              int id,
 57              DebugSeverity severity,
 58              int length,
 59              IntPtr message,
 60              IntPtr userParam)
 61          {
 62              string msg = Marshal.PtrToStringUTF8(message).Replace('\n', ' ');
 63  
 64              switch (type)
 65              {
 66                  case DebugType.DebugTypeError:
 67                      Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR");
 68                      break;
 69                  case DebugType.DebugTypePerformance:
 70                      Logger.Warning?.Print(LogClass.Gpu, $"{severity}: {msg}", "GLPERF");
 71                      break;
 72                  case DebugType.DebugTypePushGroup:
 73                      Logger.Info?.Print(LogClass.Gpu, $"{{ ({id}) {severity}: {msg}", "GLINFO");
 74                      break;
 75                  case DebugType.DebugTypePopGroup:
 76                      Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO");
 77                      break;
 78                  default:
 79                      if (source == DebugSource.DebugSourceApplication)
 80                      {
 81                          Logger.Info?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLINFO");
 82                      }
 83                      else
 84                      {
 85                          Logger.Debug?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLDEBUG");
 86                      }
 87                      break;
 88              }
 89          }
 90  
 91          // Useful debug helpers
 92          public static void PushGroup(string dbgMsg)
 93          {
 94              int counter = Interlocked.Increment(ref _counter);
 95  
 96              GL.PushDebugGroup(DebugSourceExternal.DebugSourceApplication, counter, dbgMsg.Length, dbgMsg);
 97          }
 98  
 99          public static void PopGroup()
100          {
101              GL.PopDebugGroup();
102          }
103  
104          public static void Print(string dbgMsg, DebugType type = DebugType.DebugTypeMarker, DebugSeverity severity = DebugSeverity.DebugSeverityNotification, int id = 999999)
105          {
106              GL.DebugMessageInsert(DebugSourceExternal.DebugSourceApplication, type, id, severity, dbgMsg.Length, dbgMsg);
107          }
108      }
109  }