Repository navigation
fix(🍏): don't talk to the GPU when the app is in the background - #580
Merged
Merged
Conversation
RuntimeContext takes main's side: #598 replaced the ProcessEvents pump the gate paused with a waiter thread, so the tick hold has no place any more, and onSubmittedWorkDone keeps main's WaitAnyOnly registration, which returns the future the waiter sleeps on.
iOS refuses GPU work from an app in the background, and Dawn 157 turns the refused Metal command buffer into a device loss. The gate this branch put in front of Dawn (GpuWorkGate) could not see every commit: Dawn commits from inside WaitAny and ProcessEvents too, and a drain from outside races with the hold the same notification sets inside Dawn. react-native-skia now ships a Dawn with a device toggle for exactly this, metal_suspend_submissions_in_background (react-native-webgpu-dawn 157.1.0, scripts/dawn-patches in react-native-skia): while the app is in the background Dawn encodes the submissions but commits nothing, drops the presents, and commits the held work when the app comes back; on entering the background the pending work is committed and waited on to be scheduled, as Apple asks. Nothing is lost, reordered or refused, and a promise on held work settles once the app is back, from the waiter thread that sleeps on it. Every device requestDevice makes on Apple platforms asks for the toggle (Dawn applies it on iOS and tvOS only, a Dawn without it drops the name), unless the caller disables it through dawnToggles. A device imported from Skia already has it. The gate, its drain, the held call sites and the pump hold are gone; the docs describe the hold and the Dawn version it needs.
react-native-webgpu-dawn 157.1.0 is the same Dawn commit (ada567700e) with react-native-skia's hold of command buffer commits while the app is in the background, behind the metal_suspend_submissions_in_background toggle requestDevice now asks for (published by react-native-skia's binaries workflow, run 41422364356). The example installs react-native-skia 3.7.0, which pins react-native-webgpu-dawn 157.0.0 exactly; its podspec and Gradle refuse an app whose two packages resolve different versions. Until a react-native-skia release depends on 157.1.0 (its binaries link unchanged against it), the workspace resolves the package to 157.1.0 for both. Drop the resolution when the example moves to that release.
wcandillon
marked this pull request as ready for review
November 2, 2026 11:33
…fest The manifest refused a react-native-skia whose package.json pins another react-native-webgpu-dawn than this package, which fails the SwiftPM example on every Dawn bump until a react-native-skia release pins the new version: here 157.1.0 against react-native-skia 3.7.0's 157.0.0, although the workspace resolves the package to 157.1.0 for both and the app links one Dawn. The podspec compares the versions the two packages resolve, not the ones they declare; the manifest now does the same: the copy nested under react-native-skia when the package manager could not hoist it, else the one next to it. A nested copy of another version still fails the evaluation, with both the resolved and the pinned version in the message. Verified with `swift package --manifest-cache none dump-package`: the old manifest fails on this tree, the new one passes, and a nested 157.0.0 under react-native-skia fails it; the SwiftPM example builds for the simulator.
|
🎉 This PR is included in version 0.20.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
wcandillon
added a commit
that referenced
this pull request
Nov 2, 2026
….0 (#605) * chore(⬆️): move the example and the docs app to react-native-skia 3.9.0 react-native-skia 3.9.0 depends on react-native-webgpu-dawn 157.1.0, the version this package pins since #580, so the workspace no longer needs to resolve the package for both: the example resolves one Dawn on its own. The compatibility table gets the 0.20.0 / 3.9.0 row. Verified on the iPhone 17 simulator: pod install reports one Dawn (157.1.0) without the resolution, check-dawn and the Swift manifest pass, the example builds and the full e2e suite passes (45 suites, 231 tests). * fix(🧠): await the MNIST demo's pixel readback react-native-skia 3.9 reads pixels asynchronously: readPixels() returns a promise, which settles on the runtime that asked, the UI runtime here. The inference is scheduled from its callback, as it was from the value.
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.
iOS refuses GPU work from an app in the background, and Dawn 157 turns the refused Metal command buffer into a device loss (wcandillon/react-native-skia#4290). This PR enables Dawn's
metal_suspend_submissions_in_backgrounddevice toggle on every devicerequestDevicecreates on Apple platforms: Dawn applies it on iOS and tvOS only, drops the name when it does not know it, and the caller opts out throughdawnToggles.disabledToggles. A device imported from Skia already carries it.The toggle ships in
react-native-webgpu-dawn157.1.0, built by react-native-skia from its Dawn patch (scripts/dawn-patches/metal-suspend-submissions-in-background.patch, wcandillon/react-native-skia#4373). Under it, Dawn commits the pending work and waits for it to be scheduled when the app enters the background (Apple's guidance), then encodes every submission without committing it, drops the presents, and commits the held work when the app comes back. Nothing is lost, reordered or refused; a promise on held work settles once the app is back, from the waiter thread that sleeps on it.The gate this branch first put in front of Dawn (
GpuWorkGate) is gone: Dawn commits from insideWaitAnyandProcessEventstoo, so only a hold inside Dawn sees every commit, and a drain from outside raced with the hold the same notification sets inside Dawn.The bump to
react-native-webgpu-dawn157.1.0 is part of the PR (published by wcandillon/react-native-skia run 41422364356). The example'sreact-native-skia3.7.0 pins 157.0.0 exactly, so the workspace resolves the package to 157.1.0 for both until a react-native-skia release depends on it, as react-native-skia did at the 157.0.0 bump (wcandillon/react-native-skia#4268, dropped in #4271).Verification (iPhone 17 simulator, Dawn 157.1.0 from that run's artifact): the full e2e suite passes (45 suites, 231 tests); a submit loop on a
navigator.gpudevice driven over the inspector runs at about 65 iterations per second, holds at zero while the app is in the background and resumes on return, with no error and no device loss.