Skip to content

Android: bump framework to 2026.504.1; wire ADPF per-frame reporting via GameThread.FrameCompleted - #299

Merged
winnerspiros merged 5 commits into
masterfrom
copilot/fix-vulkan-texture-artifacts
May 4, 2026
Merged

Android: bump framework to 2026.504.1; wire ADPF per-frame reporting via GameThread.FrameCompleted#299
winnerspiros merged 5 commits into
masterfrom
copilot/fix-vulkan-texture-artifacts

Conversation

Copilot AI commented May 3, 2026

Copy link
Copy Markdown

Flickering black boxes (menu left panel) and gray slider rectangles on Adreno were caused by loadOp=DontCare exposing 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:

  • Veldrid: loadOp=Clear(0,0,0,0) for sampled FBOs — fixes flickering black boxes and gray slider rectangles on Adreno TBDR
  • GameThread.FrameCompleted — new event fired at the end of every frame, on the game thread itself, after clock throttle

ADPF per-frame reporting

Previously, ADPF sessions were created (registering thread TIDs) but never fed measured work durations, leaving the CPU governor flying blind. Now FrameCompleted is subscribed on both Draw and Update threads immediately after session creation:

Host!.DrawThread!.FrameCompleted += onDrawFrameCompleted;
// ...
private void onDrawFrameCompleted()
{
    double elapsedMs = Host?.DrawThread?.Clock.ElapsedFrameTime ?? 0;
    if (elapsedMs > 0)
        OboeAudioBridge.nADPFReportActualDuration(adpfDrawSession, (long)(elapsedMs * 1_000_000.0));
}

In ActualUnlimited mode (no throttle sleep), ElapsedFrameTime equals actual work time — the exact signal ADPF needs to pre-boost CPU frequency before the next frame begins.

Dispose now unsubscribes both callbacks before nADPFCloseSession to avoid a late-firing callback racing against a closed handle.

Copilot AI and others added 5 commits May 3, 2026 21:08
…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>
@winnerspiros
winnerspiros marked this pull request as ready for review May 4, 2026 05:13
Copilot AI review requested due to automatic review settings May 4, 2026 05:13
@winnerspiros
winnerspiros merged commit 198bfbc into master May 4, 2026
20 of 22 checks passed
@gitar-bot

gitar-bot Bot commented May 4, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.Framework package references for core, Android, and iOS projects to 2026.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 &gt; Graphics &gt; 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
Comment thread osu.Game/osu.Game.csproj
</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" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants