fix: reset VulkanUiWatchdog pong before SetFormat to prevent 7s kill - #357
Conversation
Root cause (confirmed from new logs, build 2026.523.248.0): The VulkanUiWatchdog fires at 7s (before the native watchdog at 10s). PR #356 reset the native watchdog via NativeWatchdog.Heartbeat() but did NOT reset lastPongMonotonicMs — the timestamp checked by the VulkanUiWatchdog. SetFormat blocks the UI thread for the entire SurfaceDestroyed→SurfaceCreated→SurfaceChanged cycle. During this window the Handler pong cannot run. With ANGLE-GC and Veldrid-AsyncPr threads active (extra GPU/JIT overhead on affected Adreno devices), the block exceeds 7s, the VulkanUiWatchdog fires, and killProcess() kills the app before the game ever renders a frame. Fix: - Promote lastPongMonotonicMs from a local lambda capture to an activity field (vulkanWatchdogLastPongMs). - Reset it via Volatile.Write alongside NativeWatchdog.Heartbeat() at every SetFormat call site (reactive guard + proactive lambda). This extends the effective watchdog window from 7s to 7s + (time since reset), which is always sufficient for SetFormat to complete and the draw thread to resume normally.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough
ChangesVulkan Watchdog Coordination During Surface Format Changes
Possibly Related PRs
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Root cause
PR #356 fixed the native watchdog (10s) via
NativeWatchdog.Heartbeat(), but missed the VulkanUiWatchdog (7s) which fires 3 seconds earlier and is the actual killer.SetFormatblocks the UI thread for the fullSurfaceDestroyed→SurfaceCreated→SurfaceChangedcycle. The Handler pong cannot run during this window. On this device (ANGLE-GC + Veldrid-AsyncPr threads adding GPU/JIT overhead), the block exceeds 7 seconds →killProcess()fires before the game ever renders.Confirmed from build
2026.523.248.0logs:last_tick_s=0: Update thread never ran (killed before first frame)ANGLE-GCthread present: extra Vulkan overheadVeldrid-AsyncPrthread present: async presenter stallsSDLActivity state=D: uninterruptible I/O sleep during SetFormatFix
lastPongMonotonicMsfrom local lambda capture →vulkanWatchdogLastPongMsactivity fieldVolatile.Writeto reset it alongsideNativeWatchdog.Heartbeat()at both SetFormat call sites (reactive guard + proactive DecorView.Post lambda)Files
osu.Android/OsuGameActivity.csSummary by CodeRabbit
Release Notes