Check a parked renderer's real WebGL context before reuse and rebuild it when the context is lost

This commit is contained in:
German Khokhlov committed 2026-11-03 22:56:24 +04:00
1 parent 01ae045346
commit 9f8381ff71
2 files changed
+15 -3

No files matched your search

+6 -1
View File
@@ -8,7 +8,12 @@ export function createRendererCache() {
const host = document.getElementById('cesiumContainer'); const host = document.getElementById('cesiumContainer');
let entry = idle.get(kind); let entry = idle.get(kind);
idle.delete(kind); idle.delete(kind);
if (entry?.lost) { // loseContext() takes effect before its queued DOM event is delivered.
// Check the existing context too, before resuming a parked render loop.
const canvas = entry?.scene.engine.host.canvas;
const context =
canvas?.getContext?.('webgl2') ?? canvas?.getContext?.('webgl');
if (entry && (entry.lost || context?.isContextLost())) {
entry.dispose(); entry.dispose();
entry = null; entry = null;
} }
+9 -2
View File
@@ -54,7 +54,8 @@ test('a parked renderer is reused, but a lost context is disposed before rebuild
assert.equal(first.engine.host.container.isConnected, true); assert.equal(first.engine.host.container.isConnected, true);
cache.retain('navara'); cache.retain('navara');
release(); release();
first.engine.host.canvas.dispatchEvent(new Event('webglcontextlost')); // The WebGL context is already lost, but its DOM event has not fired.
first.engine.host.canvas.getContext = () => ({ isContextLost: () => true });
const second = await open(); const second = await open();
assert.notEqual(second, first); assert.notEqual(second, first);
assert.equal(released, 1); assert.equal(released, 1);
@@ -66,7 +67,13 @@ test('a parked renderer is reused, but a lost context is disposed before rebuild
await assert.rejects(open(), /resume failed/); await assert.rejects(open(), /resume failed/);
assert.equal(second.engine.host.container.isConnected, false); assert.equal(second.engine.host.container.isConnected, false);
assert.equal(released, 2); assert.equal(released, 2);
const eventLost = await open();
cache.retain('navara');
release();
eventLost.engine.host.canvas.dispatchEvent(new Event('webglcontextlost'));
const third = await open(); const third = await open();
assert.notEqual(third, eventLost);
assert.equal(released, 3);
third.suspend = () => { third.suspend = () => {
throw new Error('suspend failed'); throw new Error('suspend failed');
}; };
@@ -74,5 +81,5 @@ test('a parked renderer is reused, but a lost context is disposed before rebuild
assert.throws(release, /suspend failed/); assert.throws(release, /suspend failed/);
assert.equal(third.engine.host.container.isConnected, false); assert.equal(third.engine.host.container.isConnected, false);
cache.clear(); cache.clear();
assert.equal(released, 3); assert.equal(released, 4);
}); });