From f0c91d9efb7eff0b8bbe8fc8d4901af5a9d59005 Mon Sep 17 00:00:00 2001
From: mageven <62494521+mageven@users.noreply.github.com>
Date: Sun, 2 Aug 2020 20:11:24 +0530
Subject: [PATCH] Facilitate OpenGL debug logging via GUI (#1373)
* Allow printing GL Debug logs with GUI options
Improve GL Debugger
Make the new option persistent
Address gdkchan's comments
- Rename enum to GraphicsDebugLevel
- Move Debugger Init to Renderer Init
- Fix formatting
* nit: newlines
---
.../Configuration/ConfigurationFileFormat.cs | 8 +-
.../Configuration/ConfigurationState.cs | 37 ++++--
.../Configuration/GraphicsDebugLevel.cs | 10 ++
Ryujinx.Graphics.GAL/IRenderer.cs | 3 +-
Ryujinx.Graphics.OpenGL/Debugger.cs | 73 +++++++++--
Ryujinx.Graphics.OpenGL/Renderer.cs | 5 +-
Ryujinx/Ui/GLRenderer.cs | 13 +-
Ryujinx/Ui/MainWindow.cs | 2 +-
Ryujinx/Ui/SettingsWindow.cs | 10 ++
Ryujinx/Ui/SettingsWindow.glade | 114 +++++++++++++++---
10 files changed, 231 insertions(+), 44 deletions(-)
create mode 100644 Ryujinx.Common/Configuration/GraphicsDebugLevel.cs
diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
index 13dad62c..ae3fa493 100644
--- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
+++ b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.IO;
+using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
@@ -13,7 +14,7 @@ namespace Ryujinx.Configuration
///
/// The current version of the file format
///
- public const int CurrentVersion = 11;
+ public const int CurrentVersion = 12;
public int Version { get; set; }
@@ -77,6 +78,11 @@ namespace Ryujinx.Configuration
///
public LogClass[] LoggingFilteredClasses { get; set; }
+ ///
+ /// Change Graphics API debug log level
+ ///
+ public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; }
+
///
/// Enables or disables logging to a file on disk
///
diff --git a/Ryujinx.Common/Configuration/ConfigurationState.cs b/Ryujinx.Common/Configuration/ConfigurationState.cs
index 3149f250..dc9dd659 100644
--- a/Ryujinx.Common/Configuration/ConfigurationState.cs
+++ b/Ryujinx.Common/Configuration/ConfigurationState.cs
@@ -1,4 +1,5 @@
using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Logging;
using Ryujinx.Configuration.Hid;
@@ -141,17 +142,23 @@ namespace Ryujinx.Configuration
///
public ReactiveObject EnableFileLog { get; private set; }
+ ///
+ /// Controls which OpenGL log messages are recorded in the log
+ ///
+ public ReactiveObject GraphicsDebugLevel { get; private set; }
+
public LoggerSection()
{
- EnableDebug = new ReactiveObject();
- EnableStub = new ReactiveObject();
- EnableInfo = new ReactiveObject();
- EnableWarn = new ReactiveObject();
- EnableError = new ReactiveObject();
- EnableGuest = new ReactiveObject();
- EnableFsAccessLog = new ReactiveObject();
- FilteredClasses = new ReactiveObject();
- EnableFileLog = new ReactiveObject();
+ EnableDebug = new ReactiveObject();
+ EnableStub = new ReactiveObject();
+ EnableInfo = new ReactiveObject();
+ EnableWarn = new ReactiveObject();
+ EnableError = new ReactiveObject();
+ EnableGuest = new ReactiveObject();
+ EnableFsAccessLog = new ReactiveObject();
+ FilteredClasses = new ReactiveObject();
+ EnableFileLog = new ReactiveObject();
+ GraphicsDebugLevel = new ReactiveObject();
}
}
@@ -378,6 +385,7 @@ namespace Ryujinx.Configuration
LoggingEnableGuest = Logger.EnableGuest,
LoggingEnableFsAccessLog = Logger.EnableFsAccessLog,
LoggingFilteredClasses = Logger.FilteredClasses,
+ LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel,
EnableFileLog = Logger.EnableFileLog,
SystemLanguage = System.Language,
SystemRegion = System.Region,
@@ -436,6 +444,7 @@ namespace Ryujinx.Configuration
Logger.EnableGuest.Value = true;
Logger.EnableFsAccessLog.Value = false;
Logger.FilteredClasses.Value = new LogClass[] { };
+ Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None;
Logger.EnableFileLog.Value = true;
System.Language.Value = Language.AmericanEnglish;
System.Region.Value = Region.USA;
@@ -678,6 +687,15 @@ namespace Ryujinx.Configuration
configurationFileUpdated = true;
}
+ if (configurationFileFormat.Version < 12)
+ {
+ Common.Logging.Logger.PrintWarning(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12.");
+
+ configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None;
+
+ configurationFileUpdated = true;
+ }
+
List inputConfig = new List();
inputConfig.AddRange(configurationFileFormat.ControllerConfig);
inputConfig.AddRange(configurationFileFormat.KeyboardConfig);
@@ -694,6 +712,7 @@ namespace Ryujinx.Configuration
Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;
+ Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel;
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
System.Language.Value = configurationFileFormat.SystemLanguage;
System.Region.Value = configurationFileFormat.SystemRegion;
diff --git a/Ryujinx.Common/Configuration/GraphicsDebugLevel.cs b/Ryujinx.Common/Configuration/GraphicsDebugLevel.cs
new file mode 100644
index 00000000..1bef4a7e
--- /dev/null
+++ b/Ryujinx.Common/Configuration/GraphicsDebugLevel.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.Common.Configuration
+{
+ public enum GraphicsDebugLevel
+ {
+ None,
+ Error,
+ Performance,
+ All
+ }
+}
diff --git a/Ryujinx.Graphics.GAL/IRenderer.cs b/Ryujinx.Graphics.GAL/IRenderer.cs
index 6fd3feba..fec8d3be 100644
--- a/Ryujinx.Graphics.GAL/IRenderer.cs
+++ b/Ryujinx.Graphics.GAL/IRenderer.cs
@@ -1,3 +1,4 @@
+using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.Shader;
using System;
@@ -32,6 +33,6 @@ namespace Ryujinx.Graphics.GAL
void ResetCounter(CounterType type);
- void Initialize();
+ void Initialize(GraphicsDebugLevel logLevel);
}
}
diff --git a/Ryujinx.Graphics.OpenGL/Debugger.cs b/Ryujinx.Graphics.OpenGL/Debugger.cs
index ff9fcd85..9d0a1f59 100644
--- a/Ryujinx.Graphics.OpenGL/Debugger.cs
+++ b/Ryujinx.Graphics.OpenGL/Debugger.cs
@@ -1,7 +1,9 @@
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
{
@@ -9,15 +11,43 @@ namespace Ryujinx.Graphics.OpenGL
{
private static DebugProc _debugCallback;
- public static void Initialize()
+ 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);
- GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DontCare, DebugSeverityControl.DontCare, 0, (int[])null, true);
+ if (logLevel == GraphicsDebugLevel.Error)
+ {
+ GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypeError, DebugSeverityControl.DontCare, 0, (int[])null, true);
+ }
+ else if (logLevel == GraphicsDebugLevel.Performance)
+ {
+ 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.PrintWarning(LogClass.Gpu, "OpenGL Debugging is enabled. Performance will be negatively impacted.");
}
private static void GLDebugHandler(
@@ -29,20 +59,43 @@ namespace Ryujinx.Graphics.OpenGL
IntPtr message,
IntPtr userParam)
{
- string fullMessage = $"{type} {severity} {source} {Marshal.PtrToStringAnsi(message)}";
+ string msg = Marshal.PtrToStringUTF8(message).Replace('\n', ' ');
switch (type)
{
- case DebugType.DebugTypeError:
- Logger.PrintError(LogClass.Gpu, fullMessage);
- break;
- case DebugType.DebugTypePerformance:
- Logger.PrintWarning(LogClass.Gpu, fullMessage);
- break;
+ case DebugType.DebugTypeError : Logger.PrintError(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR"); break;
+ case DebugType.DebugTypePerformance: Logger.PrintWarning(LogClass.Gpu, $"{severity}: {msg}", "GLPERF"); break;
+ case DebugType.DebugTypePushGroup : Logger.PrintInfo(LogClass.Gpu, $"{{ ({id}) {severity}: {msg}", "GLINFO"); break;
+ case DebugType.DebugTypePopGroup : Logger.PrintInfo(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO"); break;
default:
- Logger.PrintDebug(LogClass.Gpu, fullMessage);
+ if (source == DebugSource.DebugSourceApplication)
+ {
+ Logger.PrintInfo(LogClass.Gpu, $"{type} {severity}: {msg}", "GLINFO");
+ }
+ else
+ {
+ Logger.PrintDebug(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);
+ }
}
}
diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs
index 49324637..e7a8a96b 100644
--- a/Ryujinx.Graphics.OpenGL/Renderer.cs
+++ b/Ryujinx.Graphics.OpenGL/Renderer.cs
@@ -1,4 +1,5 @@
using OpenTK.Graphics.OpenGL;
+using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image;
@@ -96,8 +97,10 @@ namespace Ryujinx.Graphics.OpenGL
return _counters.QueueReport(type, resultHandler);
}
- public void Initialize()
+ public void Initialize(GraphicsDebugLevel glLogLevel)
{
+ Debugger.Initialize(glLogLevel);
+
PrintGpuInformation();
_counters.Initialize();
diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs
index a8ed9156..867401ad 100644
--- a/Ryujinx/Ui/GLRenderer.cs
+++ b/Ryujinx/Ui/GLRenderer.cs
@@ -5,6 +5,7 @@ using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using Ryujinx.Configuration;
+using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.HLE;
@@ -47,10 +48,14 @@ namespace Ryujinx.Ui
private HotkeyButtons _prevHotkeyButtons;
- public GlRenderer(Switch device)
+ private GraphicsDebugLevel _glLogLevel;
+
+ public GlRenderer(Switch device, GraphicsDebugLevel glLogLevel)
: base (GetGraphicsMode(),
3, 3,
- GraphicsContextFlags.ForwardCompatible)
+ glLogLevel == GraphicsDebugLevel.None
+ ? GraphicsContextFlags.ForwardCompatible
+ : GraphicsContextFlags.ForwardCompatible | GraphicsContextFlags.Debug)
{
WaitEvent = new ManualResetEvent(false);
@@ -73,6 +78,8 @@ namespace Ryujinx.Ui
| EventMask.KeyReleaseMask));
this.Shown += Renderer_Shown;
+
+ _glLogLevel = glLogLevel;
}
private static GraphicsMode GetGraphicsMode()
@@ -304,7 +311,7 @@ namespace Ryujinx.Ui
// First take exclusivity on the OpenGL context.
GraphicsContext.MakeCurrent(WindowInfo);
- _renderer.Initialize();
+ _renderer.Initialize(_glLogLevel);
// Make sure the first frame is not transparent.
GL.ClearColor(OpenTK.Color.Black);
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index 92e0c956..42870107 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -501,7 +501,7 @@ namespace Ryujinx.Ui
}
).ToArray());
- _glWidget = new GlRenderer(_emulationContext);
+ _glWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
Application.Invoke(delegate
{
diff --git a/Ryujinx/Ui/SettingsWindow.cs b/Ryujinx/Ui/SettingsWindow.cs
index b488fdbb..5fe51854 100644
--- a/Ryujinx/Ui/SettingsWindow.cs
+++ b/Ryujinx/Ui/SettingsWindow.cs
@@ -1,6 +1,7 @@
using Gtk;
using Ryujinx.Audio;
using Ryujinx.Configuration;
+using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Configuration.System;
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
@@ -35,6 +36,7 @@ namespace Ryujinx.Ui
[GUI] CheckButton _guestLogToggle;
[GUI] CheckButton _fsAccessLogToggle;
[GUI] Adjustment _fsLogSpinAdjustment;
+ [GUI] ComboBoxText _graphicsDebugLevel;
[GUI] CheckButton _dockedModeToggle;
[GUI] CheckButton _discordToggle;
[GUI] CheckButton _vSyncToggle;
@@ -149,6 +151,13 @@ namespace Ryujinx.Ui
_fsAccessLogToggle.Click();
}
+ foreach (GraphicsDebugLevel level in Enum.GetValues(typeof(GraphicsDebugLevel)))
+ {
+ _graphicsDebugLevel.Append(level.ToString(), level.ToString());
+ }
+
+ _graphicsDebugLevel.SetActiveId(ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value.ToString());
+
if (ConfigurationState.Instance.System.EnableDockedMode)
{
_dockedModeToggle.Click();
@@ -496,6 +505,7 @@ namespace Ryujinx.Ui
ConfigurationState.Instance.Logger.EnableGuest.Value = _guestLogToggle.Active;
ConfigurationState.Instance.Logger.EnableFsAccessLog.Value = _fsAccessLogToggle.Active;
ConfigurationState.Instance.Logger.EnableFileLog.Value = _fileLogToggle.Active;
+ ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value = Enum.Parse(_graphicsDebugLevel.ActiveId);
ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;
diff --git a/Ryujinx/Ui/SettingsWindow.glade b/Ryujinx/Ui/SettingsWindow.glade
index 384fed4d..33ea05b7 100644
--- a/Ryujinx/Ui/SettingsWindow.glade
+++ b/Ryujinx/Ui/SettingsWindow.glade
@@ -2007,24 +2007,6 @@
1
-
-
-
- False
- True
- 2
-
-
+
+
+
+ False
+ True
+ 5
+ 22
+
+
4