diff --git a/Ryujinx.Profiler/Profile.cs b/Ryujinx.Profiler/Profile.cs index 8f808c2868..25b10c498d 100644 --- a/Ryujinx.Profiler/Profile.cs +++ b/Ryujinx.Profiler/Profile.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Profiler private static InternalProfile ProfileInstance; private static ProfilerSettings Settings; - private static bool ProfilingEnabled() + public static bool ProfilingEnabled() { if (!Settings.Enabled) return false; diff --git a/Ryujinx.Profiler/Ryujinx.Profiler.csproj b/Ryujinx.Profiler/Ryujinx.Profiler.csproj index 4833752b3a..3fc6117096 100644 --- a/Ryujinx.Profiler/Ryujinx.Profiler.csproj +++ b/Ryujinx.Profiler/Ryujinx.Profiler.csproj @@ -5,6 +5,10 @@ win10-x64;osx-x64;linux-x64 + + + + diff --git a/Ryujinx.Profiler/UI/ProfileWindow.cs b/Ryujinx.Profiler/UI/ProfileWindow.cs new file mode 100644 index 0000000000..1912013c86 --- /dev/null +++ b/Ryujinx.Profiler/UI/ProfileWindow.cs @@ -0,0 +1,117 @@ +using OpenTK; +using OpenTK.Graphics.OpenGL; +using System; +using System.ComponentModel; + +namespace Ryujinx +{ + public class ProfileWindow : GameWindow + { + private bool visible = true; + public bool visibleChanged; + + public ProfileWindow() + : base(400, 720) + { + //Keyboard.KeyDown += Keyboard_KeyDown; + Location = new Point(DisplayDevice.Default.Width - 400, (DisplayDevice.Default.Height - 720) / 2); + Title = "Profiler"; + } + + #region Public Methods + public void ToggleVisible() + { + visible = !visible; + visibleChanged = true; + } + #endregion + + #region OnLoad + /// + /// Setup OpenGL and load resources + /// + /// Not used. + protected override void OnLoad(EventArgs e) + { + GL.ClearColor(Color.MidnightBlue); + } + #endregion + + #region OnResize + /// + /// Respond to resize events + /// + /// Contains information on the new GameWindow size. + /// There is no need to call the base implementation. + protected override void OnResize(EventArgs e) + { + GL.Viewport(0, 0, Width, Height); + + GL.MatrixMode(MatrixMode.Projection); + GL.LoadIdentity(); + GL.Ortho(0, Width, 0, Height, 0.0, 4.0); + } + #endregion + + #region OnClose + /// + /// Intercept close event and hide instead + /// + protected override void OnClosing(CancelEventArgs e) + { + visible = false; + visibleChanged = true; + e.Cancel = true; + base.OnClosing(e); + } + #endregion + + #region OnUpdateFrame + /// + /// Profile Update Loop + /// + /// Contains timing information. + /// There is no need to call the base implementation. + protected override void OnUpdateFrame(FrameEventArgs e) + { + // Nothing to do! + } + #endregion + + #region OnRenderFrame + /// + /// Profile Render Loop + /// + /// Contains timing information. + /// There is no need to call the base implementation. + protected override void OnRenderFrame(FrameEventArgs e) + { + if (visibleChanged) + { + Visible = visible; + visibleChanged = false; + } + + if (!visible) + { + return; + } + + GL.Clear(ClearBufferMask.ColorBufferBit); + + GL.Begin(BeginMode.Triangles); + + GL.Color3(Color.MidnightBlue); + GL.Vertex2(0.0f, 0.0f); + GL.Color3(Color.SpringGreen); + GL.Vertex2(50.0f, 100.0f); + GL.Color3(Color.Ivory); + GL.Vertex2(100.0f, 0.0f); + + GL.End(); + + this.SwapBuffers(); + } + #endregion + } +} \ No newline at end of file diff --git a/Ryujinx.Profiler/UI/ProfileWindowManager.cs b/Ryujinx.Profiler/UI/ProfileWindowManager.cs new file mode 100644 index 0000000000..1273a5a37f --- /dev/null +++ b/Ryujinx.Profiler/UI/ProfileWindowManager.cs @@ -0,0 +1,30 @@ +using System.Threading; + +namespace Ryujinx.Profiler.UI +{ + public class ProfileWindowManager + { + private ProfileWindow window; + + public ProfileWindowManager() + { + if (Profile.ProfilingEnabled()) + { + Thread profileThread = new Thread(() => + { + window = new ProfileWindow(); + window.Run(60, 60); + }); + profileThread.Start(); + } + } + + public void ToggleVisible() + { + if (Profile.ProfilingEnabled()) + { + window.ToggleVisible(); + } + } + } +} diff --git a/Ryujinx/Config.cs b/Ryujinx/Config.cs index 8807357cfa..629d65493a 100644 --- a/Ryujinx/Config.cs +++ b/Ryujinx/Config.cs @@ -11,6 +11,7 @@ using System.IO; using System.Linq; using System.Reflection; using Ryujinx.Profiler; +using Ryujinx.Ui; namespace Ryujinx { @@ -18,6 +19,7 @@ namespace Ryujinx { public static NpadKeyboard NpadKeyboard { get; private set; } public static NpadController NpadController { get; private set; } + public static NPadDebug NPadDebug { get; private set; } public static void Read(Switch device) { @@ -159,6 +161,12 @@ namespace Ryujinx ButtonR = ToId(parser.Value("Controls_Right_JoyConController_Button_R")), ButtonZr = ToId(parser.Value("Controls_Right_JoyConController_Button_ZR")) }); + + NPadDebug = new NPadDebug( + new NPadDebugButtons() + { + ToggleProfiler = Convert.ToInt16(parser.Value(("Controls_Debug_Toggle_Profiler"))), + }); } private static ControllerInputId ToId(string key) diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf index 9e755d6243..2e15aac4d9 100644 --- a/Ryujinx/Ryujinx.conf +++ b/Ryujinx/Ryujinx.conf @@ -107,4 +107,7 @@ Controls_Right_JoyConController_Button_R = RShoulder Controls_Right_JoyConController_Button_ZR = RTrigger Controls_Left_JoyConController_Stick = LJoystick -Controls_Right_JoyConController_Stick = RJoystick \ No newline at end of file +Controls_Right_JoyConController_Stick = RJoystick + +#Debug Controls +Controls_Debug_Toggle_Profiler = 10 diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 478c5887f2..23857d8a8b 100644 --- a/Ryujinx/Ui/GLScreen.cs +++ b/Ryujinx/Ui/GLScreen.cs @@ -4,6 +4,8 @@ using OpenTK.Input; using Ryujinx.Graphics.Gal; using Ryujinx.HLE; using Ryujinx.HLE.Input; +using Ryujinx.Profiler; +using Ryujinx.Profiler.UI; using System; using System.Threading; @@ -28,6 +30,8 @@ namespace Ryujinx private Thread _renderThread; + private ProfileWindowManager _profileWindow; + private bool _resizeEvent; private bool _titleEvent; @@ -46,6 +50,9 @@ namespace Ryujinx Location = new Point( (DisplayDevice.Default.Width / 2) - (Width / 2), (DisplayDevice.Default.Height / 2) - (Height / 2)); + + // Start profile window, it will handle itself from there + _profileWindow = new ProfileWindowManager(); } private void RenderLoop() @@ -142,6 +149,14 @@ namespace Ryujinx { KeyboardState keyboard = _keyboard.Value; + // Debug + if (Config.NPadDebug.TogglePressed(keyboard)) + { + _profileWindow.ToggleVisible(); + } + Config.NPadDebug.SetPrevKeyboardState(keyboard); + + // Normal Input currentButton = Config.NpadKeyboard.GetButtons(keyboard); (leftJoystickDx, leftJoystickDy) = Config.NpadKeyboard.GetLeftStick(keyboard); diff --git a/Ryujinx/Ui/NPadDebug.cs b/Ryujinx/Ui/NPadDebug.cs new file mode 100644 index 0000000000..415e5035cd --- /dev/null +++ b/Ryujinx/Ui/NPadDebug.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OpenTK.Input; + +namespace Ryujinx.Ui +{ + public struct NPadDebugButtons + { + public int ToggleProfiler; + } + + public class NPadDebug + { + public NPadDebugButtons Buttons; + private KeyboardState prevKeyboard; + + public NPadDebug(NPadDebugButtons buttons) + { + Buttons = buttons; + } + + public bool TogglePressed(KeyboardState keyboard) => !keyboard[(Key) Buttons.ToggleProfiler] && prevKeyboard[(Key) Buttons.ToggleProfiler]; + + public void SetPrevKeyboardState(KeyboardState keyboard) + { + prevKeyboard = keyboard; + } + } +}