1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-13 18:07:25 +08:00

Better handle spikes and significant changes

This commit is contained in:
Dean Herbert 2022-07-21 12:50:39 +09:00
parent 285516b111
commit 705ff06ea5

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -22,8 +21,8 @@ namespace osu.Game.Graphics.UserInterface
{ {
public class FPSCounter : VisibilityContainer, IHasCustomTooltip public class FPSCounter : VisibilityContainer, IHasCustomTooltip
{ {
private RollingCounter<double> msCounter = null!; private RollingCounter<double> counterUpdateFrameTime = null!;
private RollingCounter<double> fpsCounter = null!; private RollingCounter<double> counterDrawFPS = null!;
private Container mainContent = null!; private Container mainContent = null!;
@ -68,14 +67,14 @@ namespace osu.Game.Graphics.UserInterface
}, },
} }
}, },
msCounter = new FrameTimeCounter counterUpdateFrameTime = new FrameTimeCounter
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
Margin = new MarginPadding(1), Margin = new MarginPadding(1),
Y = -2, Y = -2,
}, },
fpsCounter = new FramesPerSecondCounter counterDrawFPS = new FramesPerSecondCounter
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
@ -156,30 +155,47 @@ namespace osu.Game.Graphics.UserInterface
{ {
base.Update(); base.Update();
// TODO: this is wrong (elapsed clock time, not actual run time). double aimDrawFPS = gameHost.DrawThread.Clock.MaximumUpdateHz;
double newFrameTime = gameHost.UpdateThread.Clock.ElapsedFrameTime; double aimUpdateFPS = gameHost.UpdateThread.Clock.MaximumUpdateHz;
double newFps = gameHost.DrawThread.Clock.FramesPerSecond;
bool hasSignificantChanges = if (!gameHost.UpdateThread.Clock.Throttling)
Math.Abs(msCounter.Current.Value - newFrameTime) > 5 || {
Math.Abs(fpsCounter.Current.Value - newFps) > 10; aimUpdateFPS = aimDrawFPS = gameHost.InputThread.Clock.MaximumUpdateHz;
}
// TODO: this is wrong (elapsed clock time, not actual run time).
double newUpdateFrameTime = gameHost.UpdateThread.Clock.ElapsedFrameTime;
// use elapsed frame time rather then FramesPerSecond to better catch stutter frames.
double newDrawFps = 1000 / gameHost.DrawThread.Clock.ElapsedFrameTime;
const double spike_time_ms = 20;
bool hasUpdateSpike = counterUpdateFrameTime.Current.Value < spike_time_ms && newUpdateFrameTime > spike_time_ms;
bool hasDrawSpike = counterDrawFPS.Current.Value > (1000 / spike_time_ms) && newDrawFps <= (1000 / spike_time_ms);
// If the frame time spikes up, make sure it shows immediately on the counter.
if (hasUpdateSpike)
counterUpdateFrameTime.SetCountWithoutRolling(newUpdateFrameTime);
else
counterUpdateFrameTime.Current.Value = newUpdateFrameTime;
if (hasDrawSpike)
counterDrawFPS.SetCountWithoutRolling(newDrawFps);
else
counterDrawFPS.Current.Value = newDrawFps;
counterDrawFPS.Colour = getColour(counterDrawFPS.DisplayedCount / aimDrawFPS);
double displayedUpdateFPS = 1000 / counterUpdateFrameTime.DisplayedCount;
counterUpdateFrameTime.Colour = getColour(displayedUpdateFPS / aimUpdateFPS);
bool hasSignificantChanges = hasDrawSpike
|| hasUpdateSpike
|| counterDrawFPS.DisplayedCount < aimDrawFPS * 0.8
|| displayedUpdateFPS < aimUpdateFPS * 0.8;
if (hasSignificantChanges) if (hasSignificantChanges)
displayTemporarily(); displayTemporarily();
// If the frame time spikes up, make sure it shows immediately on the counter.
if (msCounter.Current.Value < 20 && newFrameTime > 20)
msCounter.SetCountWithoutRolling(newFrameTime);
else
msCounter.Current.Value = newFrameTime;
fpsCounter.Current.Value = newFps;
fpsCounter.Colour = getColour(fpsCounter.DisplayedCount / gameHost.DrawThread.Clock.MaximumUpdateHz);
double equivalentHz = 1000 / msCounter.DisplayedCount;
msCounter.Colour = getColour(equivalentHz / gameHost.UpdateThread.Clock.MaximumUpdateHz);
} }
private ColourInfo getColour(double performanceRatio) private ColourInfo getColour(double performanceRatio)
@ -196,7 +212,7 @@ namespace osu.Game.Graphics.UserInterface
public class FramesPerSecondCounter : RollingCounter<double> public class FramesPerSecondCounter : RollingCounter<double>
{ {
protected override double RollingDuration => 400; protected override double RollingDuration => 1000;
protected override OsuSpriteText CreateSpriteText() protected override OsuSpriteText CreateSpriteText()
{ {