Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change frame stable catch-up method to allow for much faster sync #26600

Merged
merged 3 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,8 @@ public void TestRatePreservedWhenTimeNotProgressing()
checkRate(1);
}

private const int max_frames_catchup = 50;

private void createStabilityContainer(double gameplayStartTime = double.MinValue) => AddStep("create container", () =>
mainContainer.Child = new FrameStabilityContainer(gameplayStartTime) { MaxCatchUpFrames = max_frames_catchup }
mainContainer.Child = new FrameStabilityContainer(gameplayStartTime)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stress tested both tests which had custom overrides and they still pass. For whatever that's worth.

.WithChild(consumer = new ClockConsumingChild()));

private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time);
Expand Down
12 changes: 11 additions & 1 deletion osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Linq;
using System.Threading;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
Expand Down Expand Up @@ -47,7 +48,7 @@ private void load()
{
Child = frameStabilityContainer = new FrameStabilityContainer
{
MaxCatchUpFrames = 1
Child = new FakeLoad()
}
}
});
Expand All @@ -56,6 +57,15 @@ private void load()
Dependencies.CacheAs<IFrameStableClock>(frameStabilityContainer);
}

private partial class FakeLoad : Drawable
{
protected override void Update()
{
base.Update();
Thread.Sleep(1);
}
}

[SetUpSteps]
public void SetupSteps()
{
Expand Down
10 changes: 6 additions & 4 deletions osu.Game/Rulesets/UI/FrameStabilityContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public sealed partial class FrameStabilityContainer : Container, IHasReplayHandl
public ReplayInputHandler? ReplayInputHandler { get; set; }

/// <summary>
/// The number of frames (per parent frame) which can be run in an attempt to catch-up to real-time.
/// The number of CPU milliseconds to spend at most during seek catch-up.
/// </summary>
public int MaxCatchUpFrames { get; set; } = 5;
private const double max_catchup_milliseconds = 10;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value is just a ballpark good place to be. The game should always maintain at least 60 fps, and this will give enough headroom to allow that.


/// <summary>
/// Whether to enable frame-stable playback.
Expand Down Expand Up @@ -59,6 +59,8 @@ public sealed partial class FrameStabilityContainer : Container, IHasReplayHandl
/// </summary>
private readonly FramedClock framedClock;

private readonly Stopwatch stopwatch = new Stopwatch();

/// <summary>
/// The current direction of playback to be exposed to frame stable children.
/// </summary>
Expand Down Expand Up @@ -97,7 +99,7 @@ private void load(IGameplayClock? gameplayClock)

public override bool UpdateSubTree()
{
int loops = MaxCatchUpFrames;
stopwatch.Restart();

do
{
Expand All @@ -110,7 +112,7 @@ public override bool UpdateSubTree()

base.UpdateSubTree();
UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat);
} while (state == PlaybackState.RequiresCatchUp && loops-- > 0);
} while (state == PlaybackState.RequiresCatchUp && stopwatch.ElapsedMilliseconds < max_catchup_milliseconds);

return true;
}
Expand Down
Loading