fix(render): release the atmosphere probe's WebGL context

Lose the throwaway WebGL2 probe context right after the link probe instead
of leaving it for GC; browsers (Safari especially) cap live contexts. Note
that affected devices also lose globe-basemap fog, credit the changelog
entry and move it to the top.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Sameh KhamisandClaude Opus 5.5 committed 2026-09-24 21:53:06 -07:00
1 parent 351b5fcaa4
commit 20a03aad87
4 files changed
+42 -16

No files matched your search

+14 -13
View File
@@ -1,5 +1,19 @@
# Changelog
- Render on iPad and iPhone instead of stopping with "An error occurred while
rendering." Cesium's per-vertex model atmosphere binds shader `out`
parameters directly to varyings, which Apple's Metal/ANGLE backend cannot
link, so the program failed and the render loop was torn down. The stage is
now kept out of the pipeline on affected devices by clearing
`scene.fog.renderable`, which leaves `fog.enabled` — and the fog density that
drives 3D Tiles refinement — untouched. Detection is a WebGL2 link probe of
the same pattern, so a future driver fix restores the effect with no code
change, with iOS/iPadOS detection as a backstop. Sky atmosphere and the
ground-atmosphere fragment path route through locals and are unaffected;
affected devices lose distance fog on 3D tiles and on the globe basemaps.
`src/app/atmosphereCompat.test.mjs` pins the probe, the platform matrix and
the `renderable`-not-`enabled` choice (KnottyDyes, #705).
- Region scopes in voice analyst queries ("in the Gulf of Mexico", "over
the Alps") work again in the dev server: the bundled Natural Earth and
neighborhood packs are fetched as JSON in the browser
@@ -196,19 +210,6 @@ Analyst records for loaded satellites, datacenters and dams, with explicit bound
retain geometry; incident-link checks abort on disable or selection change,
and the row includes a containment legend.
- Render on iPad and iPhone instead of stopping with "An error occurred while
rendering." Cesium's per-vertex model atmosphere binds shader `out`
parameters directly to varyings, which Apple's Metal/ANGLE backend cannot
link, so the program failed and the render loop was torn down. The stage is
now kept out of the pipeline on affected devices by clearing
`scene.fog.renderable`, which leaves `fog.enabled` — and the fog density that
drives 3D Tiles refinement — untouched. Detection is a WebGL2 link probe of
the same pattern, so a future driver fix restores the effect with no code
change, with iOS/iPadOS detection as a backstop. Sky atmosphere and the
ground-atmosphere fragment path route through locals and are unaffected.
`src/app/atmosphereCompat.test.mjs` pins the probe, the platform matrix and
the `renderable`-not-`enabled` choice.
- Remove the spurious scrollbars that appeared on both panel stacks at narrow
widths (720px and below) as soon as a panel was expanded. The stacks scroll
vertically there, and each panel's decorative glow, absolutely positioned
+3 -2
View File
@@ -701,7 +701,6 @@ snapshots, lifecycle actions and row descriptors. Remount and teardown remove
listeners and row subscriptions; obsolete completions do not repaint old rows.
The clear control presents busy state while its existing action owns the transaction.
## Model atmosphere on Apple Metal
Cesium's per-vertex model atmosphere is kept out of the pipeline on devices
@@ -712,13 +711,15 @@ attaches that stage only when `fog.enabled && fog.renderable`, so the viewer
clears `scene.fog.renderable` and leaves `fog.enabled` — and the fog density
that drives 3D Tiles screen-space-error scaling — intact. Sky atmosphere and the
ground-atmosphere fragment path route through locals and are unaffected.
Affected devices lose distance fog on 3D tiles and on globe basemaps (Esri,
Bing, keyless), since the globe fog shader uses the same `renderable` flag.
The probe releases its throwaway WebGL2 context immediately.
Detection is a WebGL2 link probe of the same out-parameter/varying pattern, so a
future driver fix restores the effect with no code change; iOS/iPadOS platform
detection is the backstop for when no probe context can be created. Applied
during viewer construction, before any tile builds a draw command.
## Map Source control ownership
Map Source controls own chip listeners, source-state subscriptions and selection
+13 -1
View File
@@ -154,7 +154,19 @@ export function shouldDisableModelAtmosphere({
} = {}) {
const gl = createProbeContext();
if (gl) {
if (probeOutParamVaryingLinkFailure(gl)) return true;
let linkFails;
try {
linkFails = probeOutParamVaryingLinkFailure(gl);
} finally {
// Browsers cap live WebGL contexts (Safari especially); release the
// throwaway probe context now rather than waiting for GC.
try {
gl.getExtension?.('WEBGL_lose_context')?.loseContext();
} catch {
// A context that cannot be released is left to GC.
}
}
if (linkFails) return true;
// Probe ran and the driver accepted the pattern. Apple mobile is still
// quarantined: the probe program is far simpler than Cesium's, and a
// false negative there costs the entire scene.
+12
View File
@@ -207,3 +207,15 @@ test('tolerates a scene with no fog object', () => {
assert.equal(applyModelAtmosphereWorkaround({}, {}), false);
assert.equal(applyModelAtmosphereWorkaround(null, {}), false);
});
test('releases the throwaway probe context after probing', () => {
let lost = 0;
const gl = fakeGl({ linkOk: true });
gl.getExtension = (name) =>
name === 'WEBGL_lose_context' ? { loseContext: () => (lost += 1) } : null;
shouldDisableModelAtmosphere({
navigatorLike: LINUX_DESKTOP,
createProbeContext: () => gl,
});
assert.equal(lost, 1, 'probe context must not linger until GC');
});