fix(webgl2): keep earlier dynamic mesh draws intact on Firefox native GL - #777
Merged
Merged
Conversation
Bundle ReportChanges will decrease total bundle size by 20.82MB (-38.04%) ⬇️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: exo-iife-min-Exo-iifeAssets Changed:
Files in
view changes for bundle: site-server-esmAssets Changed:
App Routes Affected:
view changes for bundle: exo-esm-modules-esmAssets Changed:
Files in
view changes for bundle: exo-iife-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-full-iife-min-Exo-iifeAssets Changed:
view changes for bundle: exo-esm-esmAssets Changed:
Files in
view changes for bundle: exo-full-iife-Exo-iifeAssets Changed:
|
Exoridus
enabled auto-merge (squash)
September 26, 2026 05:07
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
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
The Firefox WebGL lane failed intermittently on CI: two tests in
webgl2-worker-host.test.tstimed out on one run, and the retry was green. The cause is contention, not the worker host. Firefox serves WebGL for every file from one GPU process, so files running in parallel queue behind each other's GPU work there. A worker's first synchronous WebGL query stalled for ~10 s behind its neighbours.Running that lane on native OpenGL then exposed a real rendering bug: in Firefox on native GL, meshes drawn earlier in a flush could be replaced by the geometry of a later one, so a stroked rectangle lost its first edge.
Graphicsstroke segment, every array-vertexMesh) rewrote offset 0 of the same shared buffers withbufferSubData. That is legal WebGL, but Firefox's native-GL path does not synchronize it with draws still pending, so an earlier draw read the later draw's vertices. The vertex stream now usesStreamDrawand is re-specified withbufferDataon each upload; the index and instance streams stay as they were.fileParallelism: false). Locally, the whole lane took ~330 s in parallel with 32 tests past their 15 s timeout, and ~160 s sequentially with none. On CI the sequential Firefox job took 2:25 min, against 3:21 to 4:09 min for the parallel runs onnext. The Chromium lane's existing setting moves from the deprecatedbrowser.fileParallelismto the project level; its behaviour is unchanged.webgl.disable-anglereplaceswebgl.angle.force-warp). Both prefs only matter on Windows, where Firefox translates WebGL to Direct3D through ANGLE. On Linux and macOS, including the CI runner, this is a no-op. Through ANGLE, every new context spent ~5 s compiling the lighting shaders (35 ms natively), which pushed the tests that build several contexts past their timeout. WARP also has no MSAA, which the pixel-snap control case needs.The native-GL buffer race
The failure is independent of ExoJS: a 40-line raw WebGL2 page reproduces it. It needs Firefox with
webgl.disable-angle(tested on Windows, Firefox 153, NVIDIA RTX 5070 Ti, driver 617.14) and an element buffer that is allocated empty and filled withbufferSubData. Firefox's default ANGLE path and Chromium with--use-angle=glon the same driver draw correctly, and so does the same GL call sequence replayed natively without a browser, so the fault sits in Firefox's native-GL layer rather than in the driver. AgetError()orfinish()after each draw also avoids it; aflush()only moves which draw is lost. Firefox on Linux always uses native GL, so NVIDIA users there may have been affected; the CI runner renders in software and never showed it.A new test draws four meshes in one flush that differ in vertices, indices and tint, so a draw reading any later mesh's stream fails it. It fails without the fix and passes with it.
Performance
2000 dynamic stroke draws per frame, median of three interleaved runs per variant, headed browsers on Windows with an RTX 5070 Ti. "cpu" is
app.update()alone, "cpu+gpu" adds a 1-pixelreadPixelsper frame.On ANGLE, which every Windows browser uses by default, the cost is about 1 %. On Firefox's native-GL path it is about 15 %, measured against a baseline that renders incorrectly there. Orphaning only the vertex stream is correct for all three streams and costs a third of orphaning all four. Sprites, text and batched static-geometry meshes do not use this path.
Validation
pnpm gates typecheckandpnpm gates lintpass, andgit diff --checkis clean.Graphicsbrowser test files pass in Chromium and in Firefox on native GL (45/45 each), andwebgl2-untextured-mesh.test.tspassed three runs in a row on Firefox native GL. The mesh andGraphicsunit tests pass.The Firefox lane is
ciOnlyand does not run in the pre-push hook.