2020-02-06 12:25:47 +01:00
|
|
|
|
using Ryujinx.Debugger.Profiler;
|
2019-04-26 06:53:10 +02:00
|
|
|
|
using System.Diagnostics;
|
2018-03-06 21:18:49 +01:00
|
|
|
|
using System.Timers;
|
|
|
|
|
|
2018-06-11 02:46:42 +02:00
|
|
|
|
namespace Ryujinx.HLE
|
2018-03-06 21:18:49 +01:00
|
|
|
|
{
|
|
|
|
|
public class PerformanceStatistics
|
|
|
|
|
{
|
2018-06-24 02:39:25 +02:00
|
|
|
|
private const double FrameRateWeight = 0.5;
|
|
|
|
|
|
|
|
|
|
private const int FrameTypeSystem = 0;
|
|
|
|
|
private const int FrameTypeGame = 1;
|
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private double[] _averageFrameRate;
|
|
|
|
|
private double[] _accumulatedFrameTime;
|
|
|
|
|
private double[] _previousFrameTime;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private long[] _framesRendered;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private object[] _frameLock;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private double _ticksToSeconds;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private Stopwatch _executionTime;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private Timer _resetTimer;
|
2018-03-06 21:18:49 +01:00
|
|
|
|
|
|
|
|
|
public PerformanceStatistics()
|
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_averageFrameRate = new double[2];
|
|
|
|
|
_accumulatedFrameTime = new double[2];
|
|
|
|
|
_previousFrameTime = new double[2];
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_framesRendered = new long[2];
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_frameLock = new object[] { new object(), new object() };
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_executionTime = new Stopwatch();
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_executionTime.Start();
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_resetTimer = new Timer(1000);
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_resetTimer.Elapsed += ResetTimerElapsed;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_resetTimer.AutoReset = true;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_resetTimer.Start();
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_ticksToSeconds = 1.0 / Stopwatch.Frequency;
|
2018-03-06 21:18:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ResetTimerElapsed(object sender, ElapsedEventArgs e)
|
|
|
|
|
{
|
2018-06-24 02:39:25 +02:00
|
|
|
|
CalculateAverageFrameRate(FrameTypeSystem);
|
|
|
|
|
CalculateAverageFrameRate(FrameTypeGame);
|
2018-03-06 21:18:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private void CalculateAverageFrameRate(int frameType)
|
2018-03-06 21:18:49 +01:00
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
double frameRate = 0;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
if (_accumulatedFrameTime[frameType] > 0)
|
2018-06-24 02:39:25 +02:00
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
frameRate = _framesRendered[frameType] / _accumulatedFrameTime[frameType];
|
2018-06-24 02:39:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
lock (_frameLock[frameType])
|
2018-06-24 02:39:25 +02:00
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_averageFrameRate[frameType] = LinearInterpolate(_averageFrameRate[frameType], frameRate);
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_framesRendered[frameType] = 0;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_accumulatedFrameTime[frameType] = 0;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
}
|
2018-03-06 21:18:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private double LinearInterpolate(double old, double New)
|
2018-03-06 21:18:49 +01:00
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
return old * (1.0 - FrameRateWeight) + New * FrameRateWeight;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RecordSystemFrameTime()
|
|
|
|
|
{
|
|
|
|
|
RecordFrameTime(FrameTypeSystem);
|
2019-04-26 06:53:10 +02:00
|
|
|
|
Profile.FlagTime(TimingFlagType.SystemFrame);
|
2018-03-06 21:18:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RecordGameFrameTime()
|
|
|
|
|
{
|
2018-06-24 02:39:25 +02:00
|
|
|
|
RecordFrameTime(FrameTypeGame);
|
2019-04-26 06:53:10 +02:00
|
|
|
|
Profile.FlagTime(TimingFlagType.FrameSwap);
|
2018-06-24 02:39:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
private void RecordFrameTime(int frameType)
|
2018-06-24 02:39:25 +02:00
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
double currentFrameTime = _executionTime.ElapsedTicks * _ticksToSeconds;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
double elapsedFrameTime = currentFrameTime - _previousFrameTime[frameType];
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_previousFrameTime[frameType] = currentFrameTime;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
lock (_frameLock[frameType])
|
2018-06-24 02:39:25 +02:00
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_accumulatedFrameTime[frameType] += elapsedFrameTime;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
|
_framesRendered[frameType]++;
|
2018-06-24 02:39:25 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double GetSystemFrameRate()
|
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
return _averageFrameRate[FrameTypeSystem];
|
2018-03-06 21:18:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-24 02:39:25 +02:00
|
|
|
|
public double GetGameFrameRate()
|
2018-03-06 21:18:49 +01:00
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
|
return _averageFrameRate[FrameTypeGame];
|
2018-03-06 21:18:49 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|