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