aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs71
1 files changed, 69 insertions, 2 deletions
diff --git a/Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs b/Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs
index 953316a6..4e2a9d6b 100644
--- a/Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs
+++ b/Ryujinx.Graphics.Vulkan/AutoFlushCounter.cs
@@ -1,4 +1,5 @@
-using System;
+using Ryujinx.Common.Logging;
+using System;
using System.Diagnostics;
using System.Linq;
@@ -7,12 +8,26 @@ namespace Ryujinx.Graphics.Vulkan
internal class AutoFlushCounter
{
// How often to flush on framebuffer change.
- private readonly static long FramebufferFlushTimer = Stopwatch.Frequency / 1000;
+ private readonly static long FramebufferFlushTimer = Stopwatch.Frequency / 1000; // (1ms)
+
+ // How often to flush on draw when fast flush mode is enabled.
+ private readonly static long DrawFlushTimer = Stopwatch.Frequency / 666; // (1.5ms)
+
+ // Average wait time that triggers fast flush mode to be entered.
+ private readonly static long FastFlushEnterThreshold = Stopwatch.Frequency / 666; // (1.5ms)
+
+ // Average wait time that triggers fast flush mode to be exited.
+ private readonly static long FastFlushExitThreshold = Stopwatch.Frequency / 10000; // (0.1ms)
+
+ // Number of frames to average waiting times over.
+ private const int SyncWaitAverageCount = 20;
private const int MinDrawCountForFlush = 10;
private const int MinConsecutiveQueryForFlush = 10;
private const int InitialQueryCountForFlush = 32;
+ private readonly VulkanRenderer _gd;
+
private long _lastFlush;
private ulong _lastDrawCount;
private bool _hasPendingQuery;
@@ -23,6 +38,16 @@ namespace Ryujinx.Graphics.Vulkan
private int _queryCountHistoryIndex;
private int _remainingQueries;
+ private long[] _syncWaitHistory = new long[SyncWaitAverageCount];
+ private int _syncWaitHistoryIndex;
+
+ private bool _fastFlushMode;
+
+ public AutoFlushCounter(VulkanRenderer gd)
+ {
+ _gd = gd;
+ }
+
public void RegisterFlush(ulong drawCount)
{
_lastFlush = Stopwatch.GetTimestamp();
@@ -69,6 +94,32 @@ namespace Ryujinx.Graphics.Vulkan
return _hasPendingQuery;
}
+ public bool ShouldFlushDraw(ulong drawCount)
+ {
+ if (_fastFlushMode)
+ {
+ long draws = (long)(drawCount - _lastDrawCount);
+
+ if (draws < MinDrawCountForFlush)
+ {
+ if (draws == 0)
+ {
+ _lastFlush = Stopwatch.GetTimestamp();
+ }
+
+ return false;
+ }
+
+ long flushTimeout = DrawFlushTimer;
+
+ long now = Stopwatch.GetTimestamp();
+
+ return now > _lastFlush + flushTimeout;
+ }
+
+ return false;
+ }
+
public bool ShouldFlushAttachmentChange(ulong drawCount)
{
_queryCount = 0;
@@ -102,11 +153,27 @@ namespace Ryujinx.Graphics.Vulkan
public void Present()
{
+ // Query flush prediction.
+
_queryCountHistoryIndex = (_queryCountHistoryIndex + 1) % 3;
_remainingQueries = _queryCountHistory.Max() + 10;
_queryCountHistory[_queryCountHistoryIndex] = 0;
+
+ // Fast flush mode toggle.
+
+ _syncWaitHistory[_syncWaitHistoryIndex] = _gd.SyncManager.GetAndResetWaitTicks();
+
+ _syncWaitHistoryIndex = (_syncWaitHistoryIndex + 1) % SyncWaitAverageCount;
+
+ long averageWait = (long)_syncWaitHistory.Average();
+
+ if (_fastFlushMode ? averageWait < FastFlushExitThreshold : averageWait > FastFlushEnterThreshold)
+ {
+ _fastFlushMode = !_fastFlushMode;
+ Logger.Debug?.PrintMsg(LogClass.Gpu, $"Switched fast flush mode: ({_fastFlushMode})");
+ }
}
}
}