From 90159e6cf16802cea7011e93cfbc5b74f1d2171f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 17 Aug 2018 23:36:26 -0300 Subject: [PATCH] Add config entry to enable OpenGL debug context and callbacks --- Ryujinx.Graphics/Gal/IGalRenderer.cs | 2 + Ryujinx.Graphics/Gal/OpenGL/OGLExtension.cs | 9 ++++ Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs | 45 +++++++++++++++++++ .../Gal/OpenGL/OpenGLException.cs | 11 +++++ Ryujinx.Graphics/GraphicsConfig.cs | 6 +++ Ryujinx/Config.cs | 5 ++- Ryujinx/Ryujinx.conf | 9 ++++ Ryujinx/Ui/GLScreen.cs | 5 ++- 8 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 Ryujinx.Graphics/Gal/OpenGL/OpenGLException.cs diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index b47ac71d0b..5822cc393a 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -4,6 +4,8 @@ namespace Ryujinx.Graphics.Gal { public interface IGalRenderer { + void Initialize(); + void QueueAction(Action ActionMthd); void RunActions(); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLExtension.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLExtension.cs index 69fce6d31d..f39a8c7c2a 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLExtension.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLExtension.cs @@ -6,8 +6,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL { private static bool Initialized = false; + private static bool Debug; private static bool EnhancedLayouts; + public static bool HasDebug() + { + EnsureInitialized(); + + return Debug; + } + public static bool HasEnhancedLayouts() { EnsureInitialized(); @@ -22,6 +30,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL return; } + Debug = HasExtension("GL_KHR_debug"); EnhancedLayouts = HasExtension("GL_ARB_enhanced_layouts"); } diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs index b0f6da45e5..7b4185fac8 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs @@ -1,5 +1,8 @@ +using OpenTK; +using OpenTK.Graphics.OpenGL; using System; using System.Collections.Concurrent; +using System.Text; namespace Ryujinx.Graphics.Gal.OpenGL { @@ -19,6 +22,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL private ConcurrentQueue ActionsQueue; + private DebugProc DebugProcDelegate; + public OGLRenderer() { Buffer = new OGLConstBuffer(); @@ -36,6 +41,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL ActionsQueue = new ConcurrentQueue(); } + public void Initialize() + { + if (GraphicsConfig.DebugMode && OGLExtension.HasDebug()) + { + DebugProcDelegate = DebugCallback; + + GL.DebugMessageCallback(DebugProcDelegate, IntPtr.Zero); + } + } + public void QueueAction(Action ActionMthd) { ActionsQueue.Enqueue(ActionMthd); @@ -50,5 +65,35 @@ namespace Ryujinx.Graphics.Gal.OpenGL RenderAction(); } } + + private static unsafe void DebugCallback( + DebugSource Source, + DebugType Type, + int Id, + DebugSeverity Severity, + int Length, + IntPtr Message, + IntPtr UserParam) + { + bool IsError = Type == DebugType.DebugTypeError || Type == DebugType.DebugTypeDeprecatedBehavior; + + if (!IsError && !GraphicsConfig.DebugEnableInfo) + { + return; + } + + string MessageLog = Encoding.UTF8.GetString((byte*)Message, Length); + + Console.ForegroundColor = IsError ? ConsoleColor.Red : ConsoleColor.Cyan; + + Console.WriteLine(MessageLog); + + Console.ResetColor(); + + if (IsError && GraphicsConfig.DebugFatalErrors) + { + throw new OpenGLException(MessageLog); + } + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLException.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLException.cs new file mode 100644 index 0000000000..8910f301b6 --- /dev/null +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Ryujinx.Graphics.Gal.OpenGL +{ + class OpenGLException : Exception + { + public OpenGLException() : base() { } + + public OpenGLException(string Message) : base(Message) { } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/GraphicsConfig.cs b/Ryujinx.Graphics/GraphicsConfig.cs index 3e3ef4ffa7..9e5197a15e 100644 --- a/Ryujinx.Graphics/GraphicsConfig.cs +++ b/Ryujinx.Graphics/GraphicsConfig.cs @@ -1,4 +1,10 @@ public static class GraphicsConfig { + public static bool DebugMode; + + public static bool DebugFatalErrors; + + public static bool DebugEnableInfo; + public static string ShadersDumpPath; } diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs index 2c02c50f19..9000846f69 100644 --- a/Ryujinx/Config.cs +++ b/Ryujinx/Config.cs @@ -23,7 +23,10 @@ namespace Ryujinx IniParser Parser = new IniParser(IniPath); - GraphicsConfig.ShadersDumpPath = Parser.Value("Graphics_Shaders_Dump_Path"); + GraphicsConfig.DebugMode = Convert.ToBoolean(Parser.Value("Graphics_Enable_Debug")); + GraphicsConfig.DebugFatalErrors = Convert.ToBoolean(Parser.Value("Graphics_Debug_Fatal_Errors")); + GraphicsConfig.DebugEnableInfo = Convert.ToBoolean(Parser.Value("Graphics_Debug_Enable_Info")); + GraphicsConfig.ShadersDumpPath = Parser.Value("Graphics_Shaders_Dump_Path"); Device.Log.SetEnable(LogLevel.Debug, Convert.ToBoolean(Parser.Value("Logging_Enable_Debug"))); Device.Log.SetEnable(LogLevel.Stub, Convert.ToBoolean(Parser.Value("Logging_Enable_Stub"))); diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf index 6e15a6ac29..969d0c7c4c 100644 --- a/Ryujinx/Ryujinx.conf +++ b/Ryujinx/Ryujinx.conf @@ -1,6 +1,15 @@ #Enable cpu memory checks (slow) Enable_Memory_Checks = false +#Enable graphics API debug functionality +Graphics_Enable_Debug = false + +#Graphics errors are fatal +Graphics_Debug_Fatal_Errors = true + +#Show graphics info messages +Graphics_Debug_Enable_Info = false + #Dump shaders in local directory (e.g. `C:\ShaderDumps`) Graphics_Shaders_Dump_Path = diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 2c683f5efb..7a5e027b3e 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -38,7 +38,8 @@ namespace Ryujinx : base(1280, 720, new GraphicsMode(), "Ryujinx", 0, DisplayDevice.Default, 3, 3, - GraphicsContextFlags.ForwardCompatible) + GraphicsContextFlags.ForwardCompatible | + (GraphicsConfig.DebugMode ? GraphicsContextFlags.Debug : 0)) { this.Device = Device; this.Renderer = Renderer; @@ -96,6 +97,8 @@ namespace Ryujinx Visible = true; + Renderer.Initialize(); + Renderer.FrameBuffer.SetWindowSize(Width, Height); Context.MakeCurrent(null);