Windows: run WebGL contexts on the WebGL thread - #177
Merged
Merged
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
WebGL on Windows ran on the JS thread, which is the UI thread, so every
ANGLE call blocked it: shader compiles and links (D3D HLSL compilation)
froze the UI, the more so with several WebGL views on a page.
An on-screen context (the default, getContext(..., { threaded: false })
opts out) is created, used, presented and dropped on the shared
"nsc-webgl" thread that Android's contexts use, reached through
WebGLState::post/sync like them:
- canvas_native_webgl_create_d3d_threaded makes it there. The panel's
swapchain is made there and bound on the UI thread; a transparent
canvas presents into its SurfaceImageSource through a XamlHandoff, as
threaded 2D does. Resizes and swapchain transforms are queued.
- The present is queued. The thread never waits on the display (a hidden
panel would stall every context on it): a frame the swapchain isn't
ready for is copied aside and shown from the thread's retries, unless a
newer frame comes first. A present that finds the context lost records
it, so isContextLost() needs no round trip.
- ANGLE's immediate context is multithread-protected: presents copy with
it outside ANGLE's lock while contexts on the UI thread call ANGLE.
- The napi bindings that reached the GL state directly (shader and
program queries, getExtension, WebGL 2 uniform blocks and invalidation)
go through sync, and their extensions follow the context's thread.
- CanvasModule.__canvasesBehind is exposed, so requestAnimationFrame is
held back while a threaded 2D or WebGL canvas is behind, as on Android.
triniwiz
force-pushed
the
feat/windows-webgl-thread
branch
from
September 30, 2026 21:43
d2e7d47 to
d2d807e
Compare
triniwiz
added a commit
that referenced
this pull request
Sep 30, 2026
* fix(canvas-core): require glutin 0.32.3 The Android GL context asks for a low priority with ContextAttributesBuilder::with_priority, which glutin 0.32.0 does not have. A lockfile still on 0.32.0 fails to build canvas-core. * chore: rebuild Android and Apple native libraries canvas-release.aar and CanvasNative.xcframework, canvassvg-release.aar and CanvasSVG.xcframework, rebuilt from f5424ba with the steps of build-native.yml, for #174, #175, #176 and #177. canvas_native.h catches up with declarations already in the source. * chore: 3.0.0-beta.0
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.
Summary
WebGL on Windows ran on the JS thread, which is the UI thread, so every ANGLE call blocked it. Shader compiles and links (D3D HLSL compilation) froze the UI, the more so with several WebGL views on a page. On-screen contexts now run on the shared
nsc-webglthread that Android (#174) and iOS (#176) contexts use, reached through the sameWebGLState::post/sync.getContext(..., { threaded: false })opts out, and offscreen contexts stay on the JS thread, as on Android.canvas_native_webgl_create_d3d_threadedmakes the context on the WebGL thread. The panel's swapchain is made there and bound on the UI thread; a transparent canvas presents into its SurfaceImageSource through aXamlHandoff, as threaded 2D does. Resizes and swapchain transforms are queued.isContextLost()needs no round trip.getExtension, WebGL 2 uniform blocks and invalidation) go throughsync, and their extensions follow the context's thread.CanvasModule.__canvasesBehindis exposed from the napi addon, sorequestAnimationFrameis held back while a threaded 2D or WebGL canvas is behind, as on Android and iOS.Canvas.threadedWebGL(defaulttrueon Windows) sets the default. Rebuilt x64 and arm64canvasnative.nodeare in the branch.Testing
crates/canvas-c/tests/threaded_webgl_d3d.rs(cargo test -p canvas-c --features 2d,webgl,gl,d3d --test threaded_webgl_d3d): threaded frames read back like unthreaded ones; presenting into a headless panel that never takes frames (held, then forced out), resizing, and dropping a context with a frame still held; four threaded contexts linking programs beside one on the calling thread.threaded_d3dstill passes.apps/demo, onmasterwith OffscreenCanvas #175 and iOS: threaded WebGL on a CAEAGLLayer, deleteProgram fix #176: webgl 83/83, offscreen 37/37 (an OffscreenCanvas's detached WebGL host is threaded now too), 2d 180/180; the WebGL perf demo runs on screen through the thread.canvas-busylays out nothing on Windows, threaded or not); the Rust test above covers several contexts on the thread.