R/Ryujinx.HLE/PerformanceStatistics.cs
gdkchan c393cdf8e3
More flexible memory manager (#307)
* Keep track mapped buffers with fixed offsets

* Started rewriting the memory manager

* Initial support for MapPhysicalMemory and UnmapPhysicalMemory, other tweaks

* MapPhysicalMemory/UnmapPhysicalMemory support, other tweaks

* Rebased

* Optimize the map/unmap physical memory svcs

* Integrate shared font support

* Fix address space reserve alignment

* Some fixes related to gpu memory mapping

* Some cleanup

* Only try uploading const buffers that are really used

* Check if memory region is contiguous

* Rebased

* Add missing count increment on IsRegionModified

* Check for reads/writes outside of the address space, optimize translation with a tail call
2018-08-15 15:59:51 -03:00

118 lines
3 KiB
C#

using System.Diagnostics;
using System.Timers;
namespace Ryujinx.HLE
{
public class PerformanceStatistics
{
private const double FrameRateWeight = 0.5;
private const int FrameTypeSystem = 0;
private const int FrameTypeGame = 1;
private double[] AverageFrameRate;
private double[] AccumulatedFrameTime;
private double[] PreviousFrameTime;
private long[] FramesRendered;
private object[] FrameLock;
private double TicksToSeconds;
private Stopwatch ExecutionTime;
private Timer ResetTimer;
public PerformanceStatistics()
{
AverageFrameRate = new double[2];
AccumulatedFrameTime = new double[2];
PreviousFrameTime = new double[2];
FramesRendered = new long[2];
FrameLock = new object[] { new object(), new object() };
ExecutionTime = new Stopwatch();
ExecutionTime.Start();
ResetTimer = new Timer(1000);
ResetTimer.Elapsed += ResetTimerElapsed;
ResetTimer.AutoReset = true;
ResetTimer.Start();
TicksToSeconds = 1.0 / Stopwatch.Frequency;
}
private void ResetTimerElapsed(object sender, ElapsedEventArgs e)
{
CalculateAverageFrameRate(FrameTypeSystem);
CalculateAverageFrameRate(FrameTypeGame);
}
private void CalculateAverageFrameRate(int FrameType)
{
double FrameRate = 0;
if (AccumulatedFrameTime[FrameType] > 0)
{
FrameRate = FramesRendered[FrameType] / AccumulatedFrameTime[FrameType];
}
lock (FrameLock[FrameType])
{
AverageFrameRate[FrameType] = LinearInterpolate(AverageFrameRate[FrameType], FrameRate);
FramesRendered[FrameType] = 0;
AccumulatedFrameTime[FrameType] = 0;
}
}
private double LinearInterpolate(double Old, double New)
{
return Old * (1.0 - FrameRateWeight) + New * FrameRateWeight;
}
public void RecordSystemFrameTime()
{
RecordFrameTime(FrameTypeSystem);
}
public void RecordGameFrameTime()
{
RecordFrameTime(FrameTypeGame);
}
private void RecordFrameTime(int FrameType)
{
double CurrentFrameTime = ExecutionTime.ElapsedTicks * TicksToSeconds;
double ElapsedFrameTime = CurrentFrameTime - PreviousFrameTime[FrameType];
PreviousFrameTime[FrameType] = CurrentFrameTime;
lock (FrameLock[FrameType])
{
AccumulatedFrameTime[FrameType] += ElapsedFrameTime;
FramesRendered[FrameType]++;
}
}
public double GetSystemFrameRate()
{
return AverageFrameRate[FrameTypeSystem];
}
public double GetGameFrameRate()
{
return AverageFrameRate[FrameTypeGame];
}
}
}