Commit 06dbef1
authored
Refactor WebGPU surface lifecycle to support latched attach (#426)
The SurfaceRegistry kept the sync getContext("webgpu") contract by falling
back to an offscreen texture when the native surface is not available yet,
but the reconciliation points were racy and crash-prone. This reworks the
lifecycle around explicit invariants:
- Registry entries now live exactly as long as their JS Canvas (contextIds
are never reused). Native view teardown (MetalView dealloc /
onDropViewInstance) retires the entry when a surface is attached;
RNWebGPU.destroyContext (Canvas unmount cleanup) covers entries that never
had one, which keeps StrictMode's simulated unmount from orphaning a live
surface. Surface destruction alone (backgrounding, TextureView teardown)
only detaches — fixing the orphaned-context black screen on the
transparent/TextureView path and the SurfaceView/TextureView asymmetry.
- Surface attaches are latched by the UI thread and adopted at frame
boundaries on the rendering thread (start of getCurrentTexture / end of
present), so a surface is never swapped mid-frame and Dawn surface
thread-affinity is preserved. A CallInvoker flush covers contexts that are
not actively rendering. Detaches stay immediate (the platform is
destroying the surface) and drop the in-flight frame at present().
- present() only presents frames whose texture was actually acquired from
the attached surface, eliminating present-without-acquire validation
errors around transitions.
- The offscreen->onscreen blit now checks SurfaceTexture.status, clamps the
copy extent to the shared region, presents from the rendering thread, and
no longer permanently widens the configured usage with CopyDst.
- getCurrentTexture checks SurfaceTexture.status (reconfigure + retry once,
then offscreen fallback), throws a catchable JS error when called before
configure() instead of dereferencing a null device, and clamps zero-sized
canvases to 1x1. unconfigure() is now implemented.
- viewFormats are deep-copied into SurfaceInfo; the stored configuration
previously kept a pointer into Convertor-owned memory that died with the
configure() call.
- ANativeWindow references are now released (acquire in onSurfaceCreate was
never paired), the registry is cleared on RNWebGPUManager teardown so dev
reloads cannot alias new canvases onto stale entries, and every registry
lookup on the native side is null-checked. Removes the unused
WebGPUBaseView (its JNI bindings never existed) and the dead
onSurfaceDestroy path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XLLf4VPzGb642Zp8EyNgpr
* fix(surface): close the races found by adversarial review of the attach model
Three defects confirmed by review of the latched-attach rework:
- Double-present race: between applyPendingAttach's blit submit and its
deferred Present(), a frame could start and complete on another runtime;
the !_frameInFlight guard missed frames that finished inside the gap and
Present() fired with no acquired texture. A _frameEpoch counter (bumped on
every acquire, present, configure/reconfigure/unconfigure, adoption, and
detach) is now revalidated before the deferred present.
- destroyContext TOCTOU: hasNativeSurface() (SurfaceInfo mutex) followed by
removeSurfaceInfo (registry mutex) was not atomic against the UI thread's
find-or-create + attach, so a StrictMode cleanup racing a native mount
could orphan a just-attached surface. SurfaceRegistry now provides
attachSurface (find-or-create + attach) and removeSurfaceInfoIfDetached
(lookup + check + erase), both atomic under the registry lock; lock order
is registry -> SurfaceInfo on every path.
- iOS CAMetalLayer use-after-free: the latched attach stored an unretained
layer pointer; on dev reload the registry is cleared before MetalView
dealloc runs, so dealloc could not cancel the pending attach and the
queued flush later touched a freed layer. The layer is now
CFBridgingRetain'd for the lifetime of the attach and released on the main
queue via the same releaser mechanism as Android's ANativeWindow ref.1 parent e4f7f7a commit 06dbef1
18 files changed
Lines changed: 673 additions & 255 deletions
File tree
- packages/webgpu
- android
- cpp
- src/main/java/com/webgpu
- apple
- cpp/rnwgpu
- api
- src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
29 | | - | |
| 28 | + | |
30 | 29 | | |
31 | 30 | | |
32 | 31 | | |
| |||
37 | 36 | | |
38 | 37 | | |
39 | 38 | | |
40 | | - | |
41 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
47 | 52 | | |
48 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
49 | 56 | | |
50 | 57 | | |
51 | 58 | | |
52 | 59 | | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
57 | 71 | | |
58 | 72 | | |
59 | 73 | | |
60 | 74 | | |
61 | 75 | | |
62 | 76 | | |
63 | | - | |
64 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
65 | 80 | | |
66 | 81 | | |
67 | | - | |
| 82 | + | |
68 | 83 | | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
69 | 88 | | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
70 | 92 | | |
71 | | - | |
| 93 | + | |
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
254 | 254 | | |
255 | 255 | | |
256 | 256 | | |
257 | | - | |
| 257 | + | |
258 | 258 | | |
259 | | - | |
| 259 | + | |
260 | 260 | | |
261 | 261 | | |
262 | 262 | | |
| |||
Lines changed: 7 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
7 | 14 | | |
8 | 15 | | |
9 | 16 | | |
| |||
14 | 21 | | |
15 | 22 | | |
16 | 23 | | |
17 | | - | |
18 | | - | |
19 | 24 | | |
20 | 25 | | |
Lines changed: 0 additions & 61 deletions
This file was deleted.
Lines changed: 3 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
25 | 27 | | |
26 | 28 | | |
27 | 29 | | |
| |||
Lines changed: 11 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
11 | | - | |
12 | 10 | | |
13 | 11 | | |
14 | 12 | | |
15 | 13 | | |
| 14 | + | |
16 | 15 | | |
17 | 16 | | |
18 | 17 | | |
| |||
23 | 22 | | |
24 | 23 | | |
25 | 24 | | |
26 | | - | |
27 | | - | |
| 25 | + | |
| 26 | + | |
28 | 27 | | |
29 | 28 | | |
30 | 29 | | |
31 | 30 | | |
32 | | - | |
33 | | - | |
| 31 | + | |
34 | 32 | | |
35 | 33 | | |
36 | 34 | | |
37 | 35 | | |
38 | | - | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
39 | 43 | | |
40 | 44 | | |
41 | 45 | | |
| |||
Lines changed: 10 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | 76 | | |
82 | 77 | | |
83 | 78 | | |
84 | 79 | | |
85 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
86 | 89 | | |
87 | 90 | | |
88 | 91 | | |
| |||
100 | 103 | | |
101 | 104 | | |
102 | 105 | | |
103 | | - | |
| 106 | + | |
104 | 107 | | |
105 | 108 | | |
106 | | - | |
| 109 | + | |
107 | 110 | | |
108 | 111 | | |
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
27 | 33 | | |
28 | 34 | | |
29 | 35 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
27 | 34 | | |
28 | 35 | | |
29 | 36 | | |
30 | 37 | | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
35 | 53 | | |
36 | 54 | | |
37 | 55 | | |
38 | 56 | | |
39 | 57 | | |
40 | | - | |
41 | | - | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
42 | 61 | | |
43 | 62 | | |
44 | 63 | | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
45 | 68 | | |
46 | | - | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
47 | 72 | | |
48 | 73 | | |
49 | 74 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
34 | 35 | | |
35 | 36 | | |
36 | | - | |
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| |||
237 | 237 | | |
238 | 238 | | |
239 | 239 | | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
240 | 249 | | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
241 | 254 | | |
242 | 255 | | |
243 | 256 | | |
| |||
0 commit comments