Android: bump framework to 2026.504.1; wire ADPF per-frame reporting via GameThread.FrameCompleted - #299
Merged
Conversation
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/6cf8f1f2-1fe4-4223-a084-6dc42511a3ec Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…shim Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/428d0670-2fa1-4d26-98a0-126ff08e5a7a Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…nlimited Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/428d0670-2fa1-4d26-98a0-126ff08e5a7a Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/428d0670-2fa1-4d26-98a0-126ff08e5a7a Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
…er-frame reporting Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/e803b44b-0f6a-4b3c-8e9d-0174b32842a1 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
winnerspiros
May 3, 2026 22:49
View session
winnerspiros
marked this pull request as ready for review
May 4, 2026 05:13
There was a problem hiding this comment.
Pull request overview
This PR updates the pinned ppy.osu.Framework packages to 2026.504.1 and extends the Android host integration to use the new GameThread.FrameCompleted event for ADPF per-frame work-duration reporting. It also adjusts Android-specific configuration defaults to support a second frame-sync migration pass and adds metadata to the stylus pressure threshold setting.
Changes:
- Bump
ppy.osu.Frameworkpackage references for core, Android, and iOS projects to2026.504.1. - Add Android ADPF session lifecycle/reporting for draw and update threads, plus target-duration updates on refresh-rate changes.
- Add a new Android config flag for a v2 frame-sync migration and give the stylus pressure threshold explicit slider bounds/step metadata.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
osu.iOS.props |
Updates the iOS framework package pin to 2026.504.1. |
osu.Game/osu.Game.csproj |
Updates the main framework package pin and aligns the nearby package-version comment. |
osu.Game/Configuration/OsuConfigManager.cs |
Adds the v2 migration config key and range metadata for the Android stylus pressure threshold. |
osu.Android/OsuGameAndroid.cs |
Wires ADPF session creation/reporting into Android draw/update threads, updates frame-sync migration logic/docs, and disposes ADPF sessions. |
osu.Android.props |
Updates the Android framework package pin to 2026.504.1. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+2014
to
+2022
| if (!LocalConfig.Get<bool>(OsuSetting.AndroidStartupFrameSyncV2MigrationApplied)) | ||
| { | ||
| var frameSync = frameworkConfig.GetBindable<FrameSync>(FrameworkSetting.FrameSync); | ||
| if (frameSync.Value == FrameSync.VSync) | ||
| { | ||
| frameSync.Value = FrameSync.ActualUnlimited; | ||
| Logger.Log("[osu!] Android FrameSync v2 migration: VSync → ActualUnlimited (IMMEDIATE present mode, lower latency)", LoggingTarget.Performance); | ||
| } | ||
| LocalConfig.SetValue(OsuSetting.AndroidStartupFrameSyncV2MigrationApplied, true); |
Comment on lines
+1493
to
+1495
| double elapsedMs = Host?.DrawThread?.Clock.ElapsedFrameTime ?? 0; | ||
| if (elapsedMs > 0) | ||
| OboeAudioBridge.nADPFReportActualDuration(adpfDrawSession, (long)(elapsedMs * 1_000_000.0)); |
Comment on lines
+1510
to
+1512
| double elapsedMs = Host?.UpdateThread?.Clock.ElapsedFrameTime ?? 0; | ||
| if (elapsedMs > 0) | ||
| OboeAudioBridge.nADPFReportActualDuration(adpfUpdateSession, (long)(elapsedMs * 1_000_000.0)); |
Comment on lines
+2494
to
+2502
| // Unsubscribe FrameCompleted FIRST so the callbacks don't fire with a stale | ||
| // (already-closed) session handle during the final frames of teardown. | ||
| try | ||
| { | ||
| if (Host?.DrawThread != null) | ||
| Host.DrawThread.FrameCompleted -= onDrawFrameCompleted; | ||
| if (Host?.UpdateThread != null) | ||
| Host.UpdateThread.FrameCompleted -= onUpdateFrameCompleted; | ||
|
|
Comment on lines
1973
to
+1995
| @@ -1860,11 +1986,14 @@ private void updateOrientation() | |||
| /// </para> | |||
| /// | |||
| /// <para> | |||
| /// <see cref="FrameSync.VSync"/> caps the draw thread to the display refresh and | |||
| /// bounds in-flight frames to one, eliminating the pile-up. The migration runs | |||
| /// exactly once per install (gated by <see cref="OsuSetting.AndroidStartupFrameSyncMigrationApplied"/>) | |||
| /// so a user who later prefers <c>Limit2x</c>/<c>Unlimited</c> from | |||
| /// Settings > Graphics > Renderer is not fought on every launch. | |||
| /// <see cref="FrameSync.ActualUnlimited"/> uses Vulkan IMMEDIATE present mode (VK_PRESENT_MODE_IMMEDIATE_KHR) | |||
| /// which presents each frame as soon as it is ready without waiting for vblank. | |||
| /// Combined with VK_GOOGLE_display_timing (skipping desiredPresentTime in IMMEDIATE mode), | |||
| /// this delivers the lowest possible input-to-display latency while avoiding the | |||
| /// vkAcquireNextImageKHR queue pile-up of Limit2x. The migration runs exactly once per | |||
| /// install (gated by <see cref="OsuSetting.AndroidStartupFrameSyncMigrationApplied"/>) | |||
| /// so a user who later prefers a different mode from Settings → Graphics → Renderer | |||
| </PackageReference> | ||
| <PackageReference Include="Realm" Version="20.1.0" /> | ||
| <PackageReference Include="ppy.osu.Framework" Version="2026.503.7" /> | ||
| <PackageReference Include="ppy.osu.Framework" Version="2026.504.1" /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Flickering black boxes (menu left panel) and gray slider rectangles on Adreno were caused by
loadOp=DontCareexposing stale tile RAM on sampled FBOs. FPS was limited by the CPU governor having no per-frame deadline signal despite ADPF sessions already being registered.Framework bump: 2026.503.8 → 2026.504.1
Pack run #32 (
ced82cfd) includes:loadOp=Clear(0,0,0,0)for sampled FBOs — fixes flickering black boxes and gray slider rectangles on Adreno TBDRGameThread.FrameCompleted— new event fired at the end of every frame, on the game thread itself, after clock throttleADPF per-frame reporting
Previously, ADPF sessions were created (registering thread TIDs) but never fed measured work durations, leaving the CPU governor flying blind. Now
FrameCompletedis subscribed on both Draw and Update threads immediately after session creation:In
ActualUnlimitedmode (no throttle sleep),ElapsedFrameTimeequals actual work time — the exact signal ADPF needs to pre-boost CPU frequency before the next frame begins.Disposenow unsubscribes both callbacks beforenADPFCloseSessionto avoid a late-firing callback racing against a closed handle.