aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.HLE/HOS/Services
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2023-11-30 10:39:42 -0800
committerGitHub <noreply@github.com>2023-11-30 15:39:42 -0300
commit1be668e68a1937f2af239e2707ab914286018892 (patch)
treed3ecb590d444ab9b392928ae1e223930313615e6 /src/Ryujinx.HLE/HOS/Services
parent21cd4c0c00e4a06e399c93419c8f9eff0e663bfb (diff)
HLE: Add OS-specific precise sleep methods to reduce spinwaiting (#5948)
* feat: add nanosleep for linux and macos * Add Windows 0.5ms sleep - Imprecise waits for longer waits with clock alignment - 1/4 the spin time on vsync timer * Remove old experiment * Fix event leak * Tweaking for MacOS * Linux tweaks, nanosleep vsync improvement * Fix overbias * Cleanup * Fix realignment * Add some docs and some cleanup NanosleepPool needs more, Nanosleep has some benchmark code that needs removed. * Rename "Microsleep" to "PreciseSleep" Might have been confused with "microseconds", which no measurement is performed in. * Remove nanosleep measurement * Remove unused debug logging * Nanosleep Pool Documentation * More cleanup * Whitespace * Formatting * Address Feedback * Allow SleepUntilTimePoint to take EventWaitHandle * Remove `_chrono` stopwatch in SurfaceFlinger * Move spinwaiting logic to PreciseSleepHelper Technically, these achieve different things, but having them here makes them easier to reuse or tune.
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services')
-rw-r--r--src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs33
1 files changed, 13 insertions, 20 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
index d3d9dc03..712d640c 100644
--- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
+++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
@@ -1,5 +1,7 @@
-using Ryujinx.Common.Configuration;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
+using Ryujinx.Common.PreciseSleep;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
@@ -23,9 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
private readonly Thread _composerThread;
- private readonly Stopwatch _chrono;
-
- private readonly ManualResetEvent _event = new(false);
+ private readonly AutoResetEvent _event = new(false);
private readonly AutoResetEvent _nextFrameEvent = new(true);
private long _ticks;
private long _ticksPerFrame;
@@ -64,11 +64,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
_composerThread = new Thread(HandleComposition)
{
Name = "SurfaceFlinger.Composer",
+ Priority = ThreadPriority.AboveNormal
};
- _chrono = new Stopwatch();
- _chrono.Start();
-
_ticks = 0;
_spinTicks = Stopwatch.Frequency / 500;
_1msTicks = Stopwatch.Frequency / 1000;
@@ -299,11 +297,11 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
_isRunning = true;
- long lastTicks = _chrono.ElapsedTicks;
+ long lastTicks = PerformanceCounter.ElapsedTicks;
while (_isRunning)
{
- long ticks = _chrono.ElapsedTicks;
+ long ticks = PerformanceCounter.ElapsedTicks;
if (_swapInterval == 0)
{
@@ -336,21 +334,16 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
}
// Sleep if possible. If the time til the next frame is too low, spin wait instead.
- long diff = _ticksPerFrame - (_ticks + _chrono.ElapsedTicks - ticks);
+ long diff = _ticksPerFrame - (_ticks + PerformanceCounter.ElapsedTicks - ticks);
if (diff > 0)
{
+ PreciseSleepHelper.SleepUntilTimePoint(_event, PerformanceCounter.ElapsedTicks + diff);
+
+ diff = _ticksPerFrame - (_ticks + PerformanceCounter.ElapsedTicks - ticks);
+
if (diff < _spinTicks)
{
- do
- {
- // SpinWait is a little more HT/SMT friendly than aggressively updating/checking ticks.
- // The value of 5 still gives us quite a bit of precision (~0.0003ms variance at worst) while waiting a reasonable amount of time.
- Thread.SpinWait(5);
-
- ticks = _chrono.ElapsedTicks;
- _ticks += ticks - lastTicks;
- lastTicks = ticks;
- } while (_ticks < _ticksPerFrame);
+ PreciseSleepHelper.SpinWaitUntilTimePoint(PerformanceCounter.ElapsedTicks + diff);
}
else
{