diff --git a/Ryujinx.HLE/PerformanceStatistics.cs b/Ryujinx.HLE/PerformanceStatistics.cs
index 408e5d72ad..be86584aa3 100644
--- a/Ryujinx.HLE/PerformanceStatistics.cs
+++ b/Ryujinx.HLE/PerformanceStatistics.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using Ryujinx.Common;
+using System.Diagnostics;
using System.Timers;
namespace Ryujinx.HLE
@@ -7,36 +8,44 @@ namespace Ryujinx.HLE
{
private const double FrameRateWeight = 0.5;
- private const int FrameTypeSystem = 0;
- private const int FrameTypeGame = 1;
+ private const int FrameTypeGame = 0;
+ private const int PercentTypeFifo = 0;
private double[] _averageFrameRate;
private double[] _accumulatedFrameTime;
private double[] _previousFrameTime;
+ private double[] _averagePercent;
+ private double[] _accumulatedPercent;
+ private double[] _percentLastEndTime;
+ private double[] _percentStartTime;
+
private long[] _framesRendered;
+ private long[] _percentCount;
private object[] _frameLock;
+ private object[] _percentLock;
private double _ticksToSeconds;
- private Stopwatch _executionTime;
-
private Timer _resetTimer;
public PerformanceStatistics()
{
- _averageFrameRate = new double[2];
- _accumulatedFrameTime = new double[2];
- _previousFrameTime = new double[2];
+ _averageFrameRate = new double[1];
+ _accumulatedFrameTime = new double[1];
+ _previousFrameTime = new double[1];
- _framesRendered = new long[2];
+ _averagePercent = new double[1];
+ _accumulatedPercent = new double[1];
+ _percentLastEndTime = new double[1];
+ _percentStartTime = new double[1];
- _frameLock = new object[] { new object(), new object() };
+ _framesRendered = new long[1];
+ _percentCount = new long[1];
- _executionTime = new Stopwatch();
-
- _executionTime.Start();
+ _frameLock = new object[] { new object() };
+ _percentLock = new object[] { new object() };
_resetTimer = new Timer(1000);
@@ -46,26 +55,26 @@ namespace Ryujinx.HLE
_resetTimer.Start();
- _ticksToSeconds = 1.0 / Stopwatch.Frequency;
+ _ticksToSeconds = 1.0 / PerformanceCounter.TicksPerSecond;
}
private void ResetTimerElapsed(object sender, ElapsedEventArgs e)
{
- CalculateAverageFrameRate(FrameTypeSystem);
CalculateAverageFrameRate(FrameTypeGame);
+ CalculateAveragePercent(PercentTypeFifo);
}
private void CalculateAverageFrameRate(int frameType)
{
double frameRate = 0;
- if (_accumulatedFrameTime[frameType] > 0)
- {
- frameRate = _framesRendered[frameType] / _accumulatedFrameTime[frameType];
- }
-
lock (_frameLock[frameType])
{
+ if (_accumulatedFrameTime[frameType] > 0)
+ {
+ frameRate = _framesRendered[frameType] / _accumulatedFrameTime[frameType];
+ }
+
_averageFrameRate[frameType] = LinearInterpolate(_averageFrameRate[frameType], frameRate);
_framesRendered[frameType] = 0;
@@ -74,14 +83,30 @@ namespace Ryujinx.HLE
}
}
- private double LinearInterpolate(double old, double New)
+ private void CalculateAveragePercent(int percentType)
{
- return old * (1.0 - FrameRateWeight) + New * FrameRateWeight;
+ // If start time is non-zero, a percent reading is still being measured.
+ // If there aren't any readings, the default should be 100% if still being measured, or 0% if not.
+ double percent = (_percentStartTime[percentType] == 0) ? 0 : 100;
+
+ lock (_percentLock[percentType])
+ {
+ if (_percentCount[percentType] > 0)
+ {
+ percent = _accumulatedPercent[percentType] / _percentCount[percentType];
+ }
+
+ _averagePercent[percentType] = percent;
+
+ _percentCount[percentType] = 0;
+
+ _accumulatedPercent[percentType] = 0;
+ }
}
- public void RecordSystemFrameTime()
+ private double LinearInterpolate(double lhs, double rhs)
{
- RecordFrameTime(FrameTypeSystem);
+ return lhs * (1.0 - FrameRateWeight) + rhs * FrameRateWeight;
}
public void RecordGameFrameTime()
@@ -89,9 +114,46 @@ namespace Ryujinx.HLE
RecordFrameTime(FrameTypeGame);
}
+ public void RecordFifoStart()
+ {
+ StartPercentTime(PercentTypeFifo);
+ }
+
+ public void RecordFifoEnd()
+ {
+ EndPercentTime(PercentTypeFifo);
+ }
+
+ private void StartPercentTime(int percentType)
+ {
+ double currentTime = PerformanceCounter.ElapsedTicks * _ticksToSeconds;
+
+ _percentStartTime[percentType] = currentTime;
+ }
+
+ private void EndPercentTime(int percentType)
+ {
+ double currentTime = PerformanceCounter.ElapsedTicks * _ticksToSeconds;
+
+ double elapsedTime = currentTime - _percentLastEndTime[percentType];
+ double elapsedActiveTime = currentTime - _percentStartTime[percentType];
+
+ double percentActive = (elapsedActiveTime / elapsedTime) * 100;
+
+ lock (_percentLock[percentType])
+ {
+ _accumulatedPercent[percentType] += percentActive;
+
+ _percentCount[percentType]++;
+ }
+
+ _percentLastEndTime[percentType] = currentTime;
+ _percentStartTime[percentType] = 0;
+ }
+
private void RecordFrameTime(int frameType)
{
- double currentFrameTime = _executionTime.ElapsedTicks * _ticksToSeconds;
+ double currentFrameTime = PerformanceCounter.ElapsedTicks * _ticksToSeconds;
double elapsedFrameTime = currentFrameTime - _previousFrameTime[frameType];
@@ -105,14 +167,14 @@ namespace Ryujinx.HLE
}
}
- public double GetSystemFrameRate()
- {
- return _averageFrameRate[FrameTypeSystem];
- }
-
public double GetGameFrameRate()
{
return _averageFrameRate[FrameTypeGame];
}
+
+ public double GetFifoPercent()
+ {
+ return _averagePercent[PercentTypeFifo];
+ }
}
}
diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs
index d8fc3e152b..edf37bb9b8 100644
--- a/Ryujinx/Ui/GLRenderer.cs
+++ b/Ryujinx/Ui/GLRenderer.cs
@@ -339,7 +339,9 @@ namespace Ryujinx.Ui
if (_device.WaitFifo())
{
+ _device.Statistics.RecordFifoStart();
_device.ProcessFrame();
+ _device.Statistics.RecordFifoEnd();
}
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? "Docked" : "Handheld";
@@ -353,13 +355,11 @@ namespace Ryujinx.Ui
{
_device.PresentFrame(SwapBuffers);
- _device.Statistics.RecordSystemFrameTime();
-
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
_device.EnableDeviceVsync,
dockedMode,
- $"Host: {_device.Statistics.GetSystemFrameRate():00.00} FPS",
$"Game: {_device.Statistics.GetGameFrameRate():00.00} FPS",
+ $"FIFO: {_device.Statistics.GetFifoPercent():0.00} %",
$"GPU: {_renderer.GpuVendor}"));
_ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame);
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index f6c88a7988..10042143cc 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -59,7 +59,7 @@ namespace Ryujinx.Ui
[GUI] CheckMenuItem _favToggle;
[GUI] MenuItem _firmwareInstallDirectory;
[GUI] MenuItem _firmwareInstallFile;
- [GUI] Label _hostStatus;
+ [GUI] Label _fifoStatus;
[GUI] CheckMenuItem _iconToggle;
[GUI] CheckMenuItem _developerToggle;
[GUI] CheckMenuItem _appToggle;
@@ -792,8 +792,8 @@ namespace Ryujinx.Ui
{
Application.Invoke(delegate
{
- _hostStatus.Text = args.HostStatus;
_gameStatus.Text = args.GameStatus;
+ _fifoStatus.Text = args.FifoStatus;
_gpuName.Text = args.GpuName;
_dockedMode.Text = args.DockedMode;
diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade
index 26a7d75adb..87946e20b8 100644
--- a/Ryujinx/Ui/MainWindow.glade
+++ b/Ryujinx/Ui/MainWindow.glade
@@ -521,7 +521,7 @@
-
-
+
True
False
start
diff --git a/Ryujinx/Ui/StatusUpdatedEventArgs.cs b/Ryujinx/Ui/StatusUpdatedEventArgs.cs
index 8c59f086d5..4b19415752 100644
--- a/Ryujinx/Ui/StatusUpdatedEventArgs.cs
+++ b/Ryujinx/Ui/StatusUpdatedEventArgs.cs
@@ -6,16 +6,16 @@ namespace Ryujinx.Ui
{
public bool VSyncEnabled;
public string DockedMode;
- public string HostStatus;
public string GameStatus;
+ public string FifoStatus;
public string GpuName;
- public StatusUpdatedEventArgs(bool vSyncEnabled, string dockedMode, string hostStatus, string gameStatus, string gpuName)
+ public StatusUpdatedEventArgs(bool vSyncEnabled, string dockedMode, string gameStatus, string fifoStatus, string gpuName)
{
VSyncEnabled = vSyncEnabled;
DockedMode = dockedMode;
- HostStatus = hostStatus;
GameStatus = gameStatus;
+ FifoStatus = fifoStatus;
GpuName = gpuName;
}
}