Fix PerformanceStatistics calculating the wrong host fps, remove wait event on PFIFO as this wasn't exactly was causing the freezes (may replace with an exception later)

This commit is contained in:
gdkchan 2018-06-21 16:38:57 -03:00
commit 4c3db79ebb
4 changed files with 80 additions and 71 deletions

View file

@ -1,5 +1,4 @@
using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal;
using System.Threading;
namespace Ryujinx.HLE.Gpu namespace Ryujinx.HLE.Gpu
{ {

View file

@ -1,5 +1,4 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading;
namespace Ryujinx.HLE.Gpu namespace Ryujinx.HLE.Gpu
{ {
@ -53,8 +52,6 @@ namespace Ryujinx.HLE.Gpu
private int[] Mme; private int[] Mme;
private ManualResetEvent FifoWait;
public NvGpuFifo(NvGpu Gpu) public NvGpuFifo(NvGpu Gpu)
{ {
this.Gpu = Gpu; this.Gpu = Gpu;
@ -66,19 +63,10 @@ namespace Ryujinx.HLE.Gpu
Macros = new CachedMacro[MacrosCount]; Macros = new CachedMacro[MacrosCount];
Mme = new int[MmeWords]; Mme = new int[MmeWords];
FifoWait = new ManualResetEvent(true);
} }
public void PushBuffer(NvGpuVmm Vmm, NvGpuPBEntry[] Buffer) public void PushBuffer(NvGpuVmm Vmm, NvGpuPBEntry[] Buffer)
{ {
if (BufferQueue.Count + Buffer.Length > FifoCapacity)
{
FifoWait.Reset();
}
FifoWait.WaitOne();
foreach (NvGpuPBEntry PBEntry in Buffer) foreach (NvGpuPBEntry PBEntry in Buffer)
{ {
BufferQueue.Enqueue((Vmm, PBEntry)); BufferQueue.Enqueue((Vmm, PBEntry));
@ -88,8 +76,6 @@ namespace Ryujinx.HLE.Gpu
public void DispatchCalls() public void DispatchCalls()
{ {
while (Step()); while (Step());
FifoWait.Set();
} }
public bool Step() public bool Step()

View file

@ -5,80 +5,106 @@ namespace Ryujinx.HLE
{ {
public class PerformanceStatistics public class PerformanceStatistics
{ {
Stopwatch ExecutionTime = new Stopwatch(); private const double FrameRateWeight = 0.5;
Timer ResetTimer = new Timer(1000);
long CurrentGameFrameEnded; private const int FrameTypeSystem = 0;
long CurrentSystemFrameEnded; private const int FrameTypeGame = 1;
long CurrentSystemFrameStart;
long LastGameFrameEnded;
long LastSystemFrameEnded;
double AccumulatedGameFrameTime; private double[] AverageFrameRate;
double AccumulatedSystemFrameTime; private double[] AccumulatedFrameTime;
double CurrentGameFrameTime; private double[] PreviousFrameTime;
double CurrentSystemFrameTime;
double PreviousGameFrameTime; private long[] FramesRendered;
double PreviousSystemFrameTime;
public double GameFrameRate { get; private set; } private object[] FrameLock;
public double SystemFrameRate { get; private set; }
public long SystemFramesRendered; private double TicksToSeconds;
public long GameFramesRendered;
public long ElapsedMilliseconds => ExecutionTime.ElapsedMilliseconds; private Stopwatch ExecutionTime;
public long ElapsedMicroseconds => (long)
(((double)ExecutionTime.ElapsedTicks / Stopwatch.Frequency) * 1000000); private Timer ResetTimer;
public long ElapsedNanoseconds => (long)
(((double)ExecutionTime.ElapsedTicks / Stopwatch.Frequency) * 1000000000);
public PerformanceStatistics() public PerformanceStatistics()
{ {
AverageFrameRate = new double[2];
AccumulatedFrameTime = new double[2];
PreviousFrameTime = new double[2];
FramesRendered = new long[2];
ExecutionTime = new Stopwatch();
ExecutionTime.Start(); ExecutionTime.Start();
ResetTimer = new Timer(1000);
ResetTimer.Elapsed += ResetTimerElapsed; ResetTimer.Elapsed += ResetTimerElapsed;
ResetTimer.AutoReset = true; ResetTimer.AutoReset = true;
ResetTimer.Start(); ResetTimer.Start();
TicksToSeconds = 1.0 / Stopwatch.Frequency;
} }
private void ResetTimerElapsed(object sender, ElapsedEventArgs e) private void ResetTimerElapsed(object sender, ElapsedEventArgs e)
{ {
ResetStatistics(); CalculateAverageFrameRate(FrameTypeSystem);
CalculateAverageFrameRate(FrameTypeGame);
} }
public void StartSystemFrame() private void CalculateAverageFrameRate(int FrameType)
{ {
PreviousSystemFrameTime = CurrentSystemFrameTime; double FrameRate = 0;
LastSystemFrameEnded = CurrentSystemFrameEnded;
CurrentSystemFrameStart = ElapsedMicroseconds; if (AccumulatedFrameTime[FrameType] > 0)
{
FrameRate = FramesRendered[FrameType] / AccumulatedFrameTime[FrameType];
} }
public void EndSystemFrame() AverageFrameRate[FrameType] = Mix(AverageFrameRate[FrameType], FrameRate);
FramesRendered[FrameType] = 0;
AccumulatedFrameTime[FrameType] = 0;
}
private double Mix(double Old, double New)
{ {
CurrentSystemFrameEnded = ElapsedMicroseconds; return Old * (1.0 - FrameRateWeight) + New * FrameRateWeight;
CurrentSystemFrameTime = CurrentSystemFrameEnded - CurrentSystemFrameStart; }
AccumulatedSystemFrameTime += CurrentSystemFrameTime;
SystemFramesRendered++; public void RecordSystemFrameTime()
{
RecordFrameTime(FrameTypeSystem);
} }
public void RecordGameFrameTime() public void RecordGameFrameTime()
{ {
CurrentGameFrameEnded = ElapsedMicroseconds; RecordFrameTime(FrameTypeGame);
CurrentGameFrameTime = CurrentGameFrameEnded - LastGameFrameEnded;
PreviousGameFrameTime = CurrentGameFrameTime;
LastGameFrameEnded = CurrentGameFrameEnded;
AccumulatedGameFrameTime += CurrentGameFrameTime;
GameFramesRendered++;
} }
public void ResetStatistics() private void RecordFrameTime(int FrameType)
{ {
GameFrameRate = 1000 / ((AccumulatedGameFrameTime / GameFramesRendered) / 1000); double CurrentFrameTime = ExecutionTime.ElapsedTicks * TicksToSeconds;
GameFrameRate = double.IsNaN(GameFrameRate) ? 0 : GameFrameRate;
SystemFrameRate = 1000 / ((AccumulatedSystemFrameTime / SystemFramesRendered) / 1000);
SystemFrameRate = double.IsNaN(SystemFrameRate) ? 0 : SystemFrameRate;
GameFramesRendered = 0; double ElapsedFrameTime = CurrentFrameTime - PreviousFrameTime[FrameType];
SystemFramesRendered = 0;
AccumulatedGameFrameTime = 0; PreviousFrameTime[FrameType] = CurrentFrameTime;
AccumulatedSystemFrameTime = 0;
AccumulatedFrameTime[FrameType] += ElapsedFrameTime;
FramesRendered[FrameType]++;
}
public double GetSystemFrameRate()
{
return AverageFrameRate[FrameTypeSystem];
}
public double GetGameFrameRate()
{
return AverageFrameRate[FrameTypeGame];
} }
} }
} }

View file

@ -179,27 +179,25 @@ namespace Ryujinx
CurrentButton, CurrentButton,
LeftJoystick, LeftJoystick,
RightJoystick); RightJoystick);
Ns.ProcessFrame();
Renderer.RunActions();
} }
protected override void OnRenderFrame(FrameEventArgs e) protected override void OnRenderFrame(FrameEventArgs e)
{ {
Renderer.RunActions();
Renderer.FrameBuffer.Render(); Renderer.FrameBuffer.Render();
Ns.Statistics.EndSystemFrame(); Ns.Statistics.RecordSystemFrameTime();
double HostFps = Ns.Statistics.SystemFrameRate; double HostFps = Ns.Statistics.GetSystemFrameRate();
double GameFps = Ns.Statistics.GameFrameRate; double GameFps = Ns.Statistics.GetGameFrameRate();
Title = $"Ryujinx | Host FPS: {HostFps:0.0} | Game FPS: {GameFps:0.0}"; Title = $"Ryujinx | Host FPS: {HostFps:0.0} | Game FPS: {GameFps:0.0}";
SwapBuffers(); SwapBuffers();
Ns.Statistics.StartSystemFrame();
Ns.ProcessFrame();
Ns.Os.SignalVsync(); Ns.Os.SignalVsync();
} }