fix(🧵): isolate WebGPU state across runtime reloads#427
Conversation
|
This is a great suggestion thank you! Now #426 which is ready to ship and fixes many substancials will create a lot of conflict with this PR but we can do it. |
|
@copilot resolve the merge conflicts in this pull request |
|
Thanks! Yes — the example is the ReloadLifecycle diagnostic in apps/example. It starts pending WebGPU work and triggers DevSettings.reload() to recreate the React Native runtime, so it is a minimal lifecycle regression case rather than a full expo Updates.reloadAsync() E2E test. |
Fix WebGPU runtime lifecycle across Expo Updates reloads
Summary
Fixes WebGPU becoming unusable after
expo-updates.reloadAsync().Applications use WebGPU when they need direct and deterministic control over rendering and image quality. Reloading an update should replace the JavaScript runtime without leaving native GPU resources attached to the previous runtime.
Previously, the React Native runtime could be destroyed while process-wide WebGPU state survived. Depending on timing, the new runtime could encounter stale contexts, surfaces, JSI objects, or asynchronous callbacks owned by the previous runtime. This could result in a lost or black canvas after reload and introduced lifetime and thread-safety risks around runtime teardown.
Root cause
An Expo Updates reload recreates the React Native runtime without restarting the application process.
Several WebGPU objects could live longer than the runtime that created them:
CallInvokerinstances;These objects were not consistently associated with a specific runtime generation. A newly installed runtime could therefore observe state belonging to the previous one, while pending native work could still attempt to dispatch callbacks to an invalid runtime.
Key changes
Runtime session ownership
RNWebGPUSessionfor every native module installation.Deterministic invalidation
JSI and async lifetime safety
jsi::Runtime.CallInvoker.Native surface stabilization
Stability guarantees
The lifecycle now follows a small set of explicit invariants:
The public WebGPU API remains unchanged. The session identifier is an internal lifecycle detail used by the native bridge and canvas implementation.
Diagnostics
Adds a runtime reload diagnostic to the example application.
The diagnostic:
device.lostcallback;After a healthy reload, reopening the diagnostic should show a new session identifier and successfully create a fresh adapter and device.
Verification
git diff --check— clean.yarn workspace react-native-webgpu tsc— passed.react-native-webgpuscheme — succeeded.:app:assembleDebug -x lint -x test— succeeded.Not covered here: an on-device end-to-end run using an actual
expo-updates.reloadAsync()update. The included diagnostic currently exercises the same React Native runtime invalidation lifecycle throughDevSettings.reload; an Expo Updates smoke test is recommended before merge.