aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-07-12 14:03:52 -0300
committergdkchan <gab.dark.100@gmail.com>2018-07-12 14:03:52 -0300
commitcd18ab29dfacd1f7a3218d4ec73ce664bccc3887 (patch)
treec8bbe1c269e0cda16edfa3be0a061a90609abc57
parent37071285bcf14ef96b16b55cb6ed7c8c003489e0 (diff)
Loop GLScreen with custom method (#244)
* Loop GLScreen with custom method * Fix deadlocks * Fix screen resizing * Change event to bool * Try to fix quitting error * Set title from main thread * Queue max 1 vsync, fix high FPS after a slowdown
-rw-r--r--Ryujinx.HLE/Gpu/Engines/NvGpuFifo.cs7
-rw-r--r--Ryujinx.HLE/Switch.cs5
-rw-r--r--Ryujinx/Ui/GLScreen.cs110
-rw-r--r--Ryujinx/Ui/Program.cs2
4 files changed, 113 insertions, 11 deletions
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuFifo.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuFifo.cs
index 0bc682a7..7b999eae 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuFifo.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuFifo.cs
@@ -1,5 +1,6 @@
using Ryujinx.HLE.Gpu.Memory;
using System.Collections.Concurrent;
+using System.Threading;
namespace Ryujinx.HLE.Gpu.Engines
{
@@ -18,6 +19,8 @@ namespace Ryujinx.HLE.Gpu.Engines
private NvGpuEngine[] SubChannels;
+ public AutoResetEvent Event { get; private set; }
+
private struct CachedMacro
{
public int Position { get; private set; }
@@ -60,6 +63,8 @@ namespace Ryujinx.HLE.Gpu.Engines
Macros = new CachedMacro[MacrosCount];
Mme = new int[MmeWords];
+
+ Event = new AutoResetEvent(false);
}
public void PushBuffer(NvGpuVmm Vmm, NvGpuPBEntry[] Buffer)
@@ -68,6 +73,8 @@ namespace Ryujinx.HLE.Gpu.Engines
{
BufferQueue.Enqueue((Vmm, PBEntry));
}
+
+ Event.Set();
}
public void DispatchCalls()
diff --git a/Ryujinx.HLE/Switch.cs b/Ryujinx.HLE/Switch.cs
index f7b263cd..1946b187 100644
--- a/Ryujinx.HLE/Switch.cs
+++ b/Ryujinx.HLE/Switch.cs
@@ -71,6 +71,11 @@ namespace Ryujinx.HLE
Os.LoadProgram(FileName);
}
+ public bool WaitFifo()
+ {
+ return Gpu.Fifo.Event.WaitOne(8);
+ }
+
public void ProcessFrame()
{
Gpu.Fifo.DispatchCalls();
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index 7a4e42e9..9b5dda4f 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -5,6 +5,9 @@ using Ryujinx.Graphics.Gal;
using Ryujinx.HLE;
using Ryujinx.HLE.Input;
using System;
+using System.Threading;
+
+using Stopwatch = System.Diagnostics.Stopwatch;
namespace Ryujinx
{
@@ -16,6 +19,8 @@ namespace Ryujinx
private const float TouchScreenRatioX = (float)TouchScreenWidth / TouchScreenHeight;
private const float TouchScreenRatioY = (float)TouchScreenHeight / TouchScreenWidth;
+ private const int TargetFPS = 60;
+
private Switch Ns;
private IGalRenderer Renderer;
@@ -24,6 +29,14 @@ namespace Ryujinx
private MouseState? Mouse = null;
+ private Thread RenderThread;
+
+ private bool ResizeEvent;
+
+ private bool TitleEvent;
+
+ private string NewTitle;
+
public GLScreen(Switch Ns, IGalRenderer Renderer)
: base(1280, 720,
new GraphicsMode(), "Ryujinx", 0,
@@ -36,13 +49,85 @@ namespace Ryujinx
Location = new Point(
(DisplayDevice.Default.Width / 2) - (Width / 2),
(DisplayDevice.Default.Height / 2) - (Height / 2));
+
+ ResizeEvent = false;
+
+ TitleEvent = false;
+ }
+
+ private void RenderLoop()
+ {
+ MakeCurrent();
+
+ Stopwatch Chrono = new Stopwatch();
+
+ Chrono.Start();
+
+ long TicksPerFrame = Stopwatch.Frequency / TargetFPS;
+
+ long Ticks = 0;
+
+ while (Exists && !IsExiting)
+ {
+ if (Ns.WaitFifo())
+ {
+ Ns.ProcessFrame();
+ }
+
+ Renderer.RunActions();
+
+ if (ResizeEvent)
+ {
+ ResizeEvent = false;
+
+ Renderer.FrameBuffer.SetWindowSize(Width, Height);
+ }
+
+ Ticks += Chrono.ElapsedTicks;
+
+ Chrono.Restart();
+
+ if (Ticks >= TicksPerFrame)
+ {
+ RenderFrame();
+
+ //Queue max. 1 vsync
+ Ticks = Math.Min(Ticks - TicksPerFrame, TicksPerFrame);
+ }
+ }
}
- protected override void OnLoad(EventArgs e)
+ public void MainLoop()
{
- VSync = VSyncMode.On;
+ VSync = VSyncMode.Off;
+
+ Visible = true;
Renderer.FrameBuffer.SetWindowSize(Width, Height);
+
+ Context.MakeCurrent(null);
+
+ //OpenTK doesn't like sleeps in its thread, to avoid this a renderer thread is created
+ RenderThread = new Thread(RenderLoop);
+
+ RenderThread.Start();
+
+ while (Exists && !IsExiting)
+ {
+ ProcessEvents();
+
+ if (!IsExiting)
+ {
+ UpdateFrame();
+
+ if (TitleEvent)
+ {
+ TitleEvent = false;
+
+ Title = NewTitle;
+ }
+ }
+ }
}
private bool IsGamePadButtonPressedFromString(GamePadState GamePad, string Button)
@@ -99,7 +184,7 @@ namespace Ryujinx
}
}
- protected override void OnUpdateFrame(FrameEventArgs e)
+ private new void UpdateFrame()
{
HidControllerButtons CurrentButton = 0;
HidJoystickPosition LeftJoystick;
@@ -278,13 +363,9 @@ namespace Ryujinx
CurrentButton,
LeftJoystick,
RightJoystick);
-
- Ns.ProcessFrame();
-
- Renderer.RunActions();
}
- protected override void OnRenderFrame(FrameEventArgs e)
+ private new void RenderFrame()
{
Renderer.FrameBuffer.Render();
@@ -293,16 +374,25 @@ namespace Ryujinx
double HostFps = Ns.Statistics.GetSystemFrameRate();
double GameFps = Ns.Statistics.GetGameFrameRate();
- Title = $"Ryujinx | Host FPS: {HostFps:0.0} | Game FPS: {GameFps:0.0}";
+ NewTitle = $"Ryujinx | Host FPS: {HostFps:0.0} | Game FPS: {GameFps:0.0}";
+
+ TitleEvent = true;
SwapBuffers();
Ns.Os.SignalVsync();
}
+ protected override void OnUnload(EventArgs e)
+ {
+ RenderThread.Join();
+
+ base.OnUnload(e);
+ }
+
protected override void OnResize(EventArgs e)
{
- Renderer.FrameBuffer.SetWindowSize(Width, Height);
+ ResizeEvent = true;
}
protected override void OnKeyDown(KeyboardKeyEventArgs e)
diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs
index b1489769..5cacc622 100644
--- a/Ryujinx/Ui/Program.cs
+++ b/Ryujinx/Ui/Program.cs
@@ -67,7 +67,7 @@ namespace Ryujinx
Screen.Exit();
};
- Screen.Run(0.0, 60.0);
+ Screen.MainLoop();
}
Environment.Exit(0);