1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 09:27:29 +08:00

Avoid using RollingCounter in fps counter

It wasn't made to be updated every frame, and it shows. Inaccurate for
reasons I'm not really interested in investigating, because I don't want
to incur the `Transorm` overhead in the first place for an fps counter.

Was only used originally out of convenience.
This commit is contained in:
Dean Herbert 2022-07-21 22:27:22 +09:00
parent 5db4d9437a
commit 3fad481a96

View File

@ -22,8 +22,8 @@ namespace osu.Game.Graphics.UserInterface
{
public class FPSCounter : VisibilityContainer, IHasCustomTooltip
{
private RollingCounter<double> counterUpdateFrameTime = null!;
private RollingCounter<double> counterDrawFPS = null!;
private OsuSpriteText counterUpdateFrameTime = null!;
private OsuSpriteText counterDrawFPS = null!;
private Container mainContent = null!;
@ -35,6 +35,9 @@ namespace osu.Game.Graphics.UserInterface
private readonly BindableBool showFpsDisplay = new BindableBool(true);
private double displayedFpsCount;
private double displayedFrameTime;
[Resolved]
private OsuColour colours { get; set; } = null!;
@ -77,20 +80,23 @@ namespace osu.Game.Graphics.UserInterface
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
counterUpdateFrameTime = new FrameTimeCounter
counterUpdateFrameTime = new OsuSpriteText
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Margin = new MarginPadding(1),
Font = OsuFont.Default.With(fixedWidth: true, size: 16, weight: FontWeight.SemiBold),
Spacing = new Vector2(-1),
Y = -2,
},
counterDrawFPS = new FramesPerSecondCounter
counterDrawFPS = new OsuSpriteText
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Margin = new MarginPadding(2),
Font = OsuFont.Default.With(fixedWidth: true, size: 13, weight: FontWeight.SemiBold),
Spacing = new Vector2(-2),
Y = 10,
Scale = new Vector2(0.8f),
}
}
},
@ -183,37 +189,48 @@ namespace osu.Game.Graphics.UserInterface
const double spike_time_ms = 20;
bool hasUpdateSpike = counterUpdateFrameTime.Current.Value < spike_time_ms && newUpdateFrameTime > spike_time_ms;
bool hasUpdateSpike = displayedFrameTime < spike_time_ms && newUpdateFrameTime > spike_time_ms;
// use elapsed frame time rather then FramesPerSecond to better catch stutter frames.
bool hasDrawSpike = counterDrawFPS.Current.Value > (1000 / spike_time_ms) && newDrawFrameTime > spike_time_ms;
bool hasDrawSpike = displayedFpsCount > (1000 / spike_time_ms) && newDrawFrameTime > 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;
// note that we use an elapsed time here of 1 intentionally.
// this weights all updates equally. if we passed in the elapsed time, longer frames would be weighted incorrectly lower.
displayedFrameTime = Interpolation.DampContinuously(displayedFrameTime, newUpdateFrameTime, hasUpdateSpike ? 0 : 200, 1);
if (hasDrawSpike)
// show spike time using raw elapsed value, to account for `FramesPerSecond` being so averaged spike frames don't show.
counterDrawFPS.SetCountWithoutRolling(1000 / newDrawFrameTime);
displayedFpsCount = 1000 / newDrawFrameTime;
else
counterDrawFPS.Current.Value = newDrawFps;
displayedFpsCount = Interpolation.DampContinuously(displayedFpsCount, newDrawFps, 200, Time.Elapsed);
counterDrawFPS.Colour = getColour(counterDrawFPS.DisplayedCount / aimDrawFPS);
double displayedUpdateFPS = 1000 / counterUpdateFrameTime.DisplayedCount;
counterUpdateFrameTime.Colour = getColour(displayedUpdateFPS / aimUpdateFPS);
updateFpsDisplay();
updateFrameTimeDisplay();
bool hasSignificantChanges = aimRatesChanged
|| hasDrawSpike
|| hasUpdateSpike
|| counterDrawFPS.DisplayedCount < aimDrawFPS * 0.8
|| displayedUpdateFPS < aimUpdateFPS * 0.8;
|| displayedFpsCount < aimDrawFPS * 0.8
|| 1000 / displayedFrameTime < aimUpdateFPS * 0.8;
if (hasSignificantChanges)
displayTemporarily();
}
private void updateFpsDisplay()
{
counterDrawFPS.Colour = getColour(displayedFpsCount / aimDrawFPS);
counterDrawFPS.Text = $"{displayedFpsCount:#,0}fps";
}
private void updateFrameTimeDisplay()
{
counterUpdateFrameTime.Text = displayedFrameTime < 5
? $"{displayedFrameTime:N1}ms"
: $"{displayedFrameTime:N0}ms";
counterUpdateFrameTime.Colour = getColour((1000 / displayedFrameTime) / aimUpdateFPS);
}
private bool updateAimFPS()
{
if (gameHost.UpdateThread.Clock.Throttling)