Skip to content

fix: keep a frame's surface texture alive through a detach - #558

Draft
YevheniiKotyrlo wants to merge 4 commits into
wcandillon:mainfrom
YevheniiKotyrlo:fix/keep-frame-texture-through-detach
Draft

YevheniiKotyrlo wants to merge 4 commits into
wcandillon:mainfrom
YevheniiKotyrlo:fix/keep-frame-texture-through-detach

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #550, whose host tests carry this fix's test; the first commit here is #550's.

Problem

A canvas whose surface detaches while a frame is in flight, on the JS or a worklet thread while the UI thread tears the view down, logs an uncaptured validation error:

Destroyed texture [Texture "of [Surface]"] used in a submit.

SurfaceInfo's detach drops the Dawn surface at once, and Dawn destroys a surface's current texture with it, so the frame's submit uses a destroyed texture. The detach already skips that frame's present; the texture has to last until the frame ends too, as a canvas texture does on the web.

Solution

SurfaceInfo keeps the surface of a frame in flight past a detach until the frame ends: presentFrame(), which still presents nothing for it, or the next getCurrentTexture() superseding it. The native window is released at once as before. On Android releaseSurfaceForDevice drops it as well, so its swapchain never outlives a destroyed device.

Tests

The host fake now destroys the texture a surface hands out when the surface presents it, is configured again or is destroyed, and rejects a submit that uses a destroyed texture. SurfaceInfoTest.KeepsTheTextureOfAFrameInFlightThroughADetach hands the surface over, acquires a frame, detaches, copies into the frame's texture and presents: before the fix it fails with Queue.Submit with a destroyed texture, with it all 27 host tests pass.

Verification

yarn test:cpp (WSL Ubuntu, g++ 13.3) · :react-native-webgpu:externalNativeBuildDebug · yarn lint · yarn tsc · the package and web-template builds · yarn test:plugin · yarn check-dawn · yarn build:docs · the example's iOS build for the simulator SDK. CI's Android e2e step (debug build, Metro with CI=true) on an Android 15 emulator: 219 of 221, as on main; the two failures, the YUV cases of ExternalTextureColorSpace and NativeBufferWrapper, fail on main there too. On devices the whole suite passes, 221 of 221: on a Galaxy S23 (Android 14), and on an iPhone 12 Pro Max (iOS 27.0.1) built and run as CI's iOS job does on a simulator (Debug build, Metro with CI=true). main passes 221 of 221 on both.

…dence on the host

SurfaceRegistry.h and AnimationReporter had no unit tests: CI built them
and the e2e suite on a device was the only check. tests/cpp compiles the
registry for the host against FakeWebGPU.cpp, a stand-in for the WebGPU C
functions it calls that records every call Dawn would reject, and
`yarn test:cpp` builds and runs it with CMake and GoogleTest.
AnimationReporter's timing rule moves unchanged into AnimationCadence,
which takes the time as an argument, so the same tests drive it. The
Android CI job runs them before the Gradle build.
SurfaceInfo's detach dropped the Dawn surface at once, and Dawn destroys a
surface's current texture with it, so a frame that acquired the texture
before the UI thread detached the surface submitted a destroyed texture:
an uncaptured validation error, "Destroyed texture [Texture "of
[Surface]"] used in a submit". The surface now lives until that frame
ends, still presenting nothing, or the next frame supersedes it; the
native window is released at once as before.

The host tests' fake now destroys the texture a surface hands out when the
surface presents it, is configured again or is destroyed, and rejects a
submit that uses one, as Dawn does.
@YevheniiKotyrlo
YevheniiKotyrlo force-pushed the fix/keep-frame-texture-through-detach branch from e9ce30a to f86d1cd Compare October 16, 2026 14:10

This branch has not been deployed

No deployments
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.

1 participant