mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
Release stale Cesium command references after disabling a layer while preserving current-frame commands. Contribution by @quanticsoul4772.
138 lines
4.9 KiB
JavaScript
138 lines
4.9 KiB
JavaScript
// A turned-off layer's draw commands must not stay reachable through Cesium's
|
|
// reused per-pass command arrays (src/sceneCommandRelease.js).
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { createRequire } from 'node:module';
|
|
import { pathToFileURL } from 'node:url';
|
|
import {
|
|
installLayerReleaseTrim,
|
|
trimStaleSceneCommands,
|
|
} from './sceneCommandRelease.js';
|
|
|
|
const frustum = (lists, counts) => ({
|
|
commands: lists.map((list) => [...list]),
|
|
indices: [...counts],
|
|
});
|
|
|
|
test('the main view keeps what the last frame drew and drops the stale tail', () => {
|
|
const view = {
|
|
frustumCommandsList: [frustum([['a', 'b', 'stale'], ['c'], []], [2, 1, 0])],
|
|
};
|
|
trimStaleSceneCommands({ _defaultView: view });
|
|
assert.deepEqual(view.frustumCommandsList[0].commands, [
|
|
['a', 'b'],
|
|
['c'],
|
|
[],
|
|
]);
|
|
assert.deepEqual(view.frustumCommandsList[0].indices, [2, 1, 0]);
|
|
});
|
|
|
|
test('the offscreen pick view is emptied, since every pick rebuilds it', () => {
|
|
const extents = [{ command: 'x' }, { command: 'y' }];
|
|
const pick = {
|
|
frustumCommandsList: [frustum([['p', 'q'], ['r']], [2, 1])],
|
|
_commandExtents: extents,
|
|
};
|
|
trimStaleSceneCommands({
|
|
_defaultView: { frustumCommandsList: [] },
|
|
_picking: { _pickOffscreenView: pick },
|
|
});
|
|
assert.deepEqual(pick.frustumCommandsList[0].commands, [[], []]);
|
|
assert.deepEqual(pick.frustumCommandsList[0].indices, [0, 0]);
|
|
assert.deepEqual(
|
|
extents.map((e) => e.command),
|
|
[undefined, undefined],
|
|
);
|
|
});
|
|
|
|
test('a layer disable renders one frame and trims after it', () => {
|
|
const listeners = new Set();
|
|
const postRender = new Set();
|
|
const requests = [];
|
|
const view = { frustumCommandsList: [frustum([['a', 'stale']], [1])] };
|
|
const scene = {
|
|
_defaultView: view,
|
|
postRender: {
|
|
addEventListener(fn) {
|
|
postRender.add(fn);
|
|
return () => postRender.delete(fn);
|
|
},
|
|
},
|
|
};
|
|
const uninstall = installLayerReleaseTrim({
|
|
scene,
|
|
dataManager: {
|
|
subscribe(fn) {
|
|
listeners.add(fn);
|
|
return () => listeners.delete(fn);
|
|
},
|
|
},
|
|
requestRender: (reason) => requests.push(reason),
|
|
});
|
|
const emit = (change) => listeners.forEach((fn) => fn(change));
|
|
|
|
emit({ type: 'visibility', layerId: 'x', enabled: true });
|
|
assert.equal(requests.length, 0, 'enabling trims nothing');
|
|
emit({ type: 'visibility', layerId: 'x', enabled: false });
|
|
emit({ type: 'visibility', layerId: 'y', enabled: false });
|
|
assert.deepEqual(
|
|
requests,
|
|
['layer-release-trim'],
|
|
'one frame for back-to-back disables',
|
|
);
|
|
assert.equal(
|
|
view.frustumCommandsList[0].commands[0].length,
|
|
2,
|
|
'not before the frame',
|
|
);
|
|
postRender.forEach((fn) => fn());
|
|
assert.deepEqual(view.frustumCommandsList[0].commands, [['a']]);
|
|
assert.equal(postRender.size, 0, 'the frame listener is one-shot');
|
|
uninstall();
|
|
assert.equal(listeners.size, 0);
|
|
});
|
|
|
|
// The workaround reads private Cesium fields. Pin the shape it relies on, and
|
|
// fail when Cesium starts clearing the tail itself so the module can go.
|
|
test('Cesium still reuses per-pass command arrays without clearing their tail', () => {
|
|
const require = createRequire(import.meta.url);
|
|
const enginePkg = require.resolve('@cesium/engine/package.json');
|
|
const read = (rel) =>
|
|
readFileSync(new URL(rel, pathToFileURL(enginePkg)), 'utf8');
|
|
const scene = read('./Source/Scene/Scene.js');
|
|
const view = read('./Source/Scene/View.js');
|
|
const frustumCommands = read('./Source/Scene/FrustumCommands.js');
|
|
const picking = read('./Source/Scene/Picking.js');
|
|
// Every private field the trim reads. A rename would otherwise turn the
|
|
// trim into a silent no-op (it reaches them through `?.` and `|| []`).
|
|
assert.match(scene, /this\._picking = new Picking\(this\);/);
|
|
assert.match(scene, /this\._defaultView = new View\(/);
|
|
assert.match(picking, /this\._pickOffscreenView = new View\(/);
|
|
assert.match(view, /this\.frustumCommandsList = \[\];/);
|
|
assert.match(view, /frustumCommandsList\[n\]\.indices\[p\] = 0;/);
|
|
assert.match(view, /this\._commandExtents = \[\];/);
|
|
assert.match(
|
|
frustumCommands,
|
|
/this\.commands = commands;\s*this\.indices = indices;/,
|
|
);
|
|
// Cesium truncates only the voxel, Gaussian-splat and translucent passes,
|
|
// each in its own draw step; the opaque and other passes keep their tail.
|
|
// A change here means Cesium's handling moved: re-check whether this
|
|
// module is still needed.
|
|
assert.doesNotMatch(
|
|
view,
|
|
/\.length\s*=\s*[^;]*indices\[/,
|
|
'View.js now truncates the per-pass arrays: remove src/sceneCommandRelease.js',
|
|
);
|
|
assert.deepEqual(
|
|
[
|
|
...scene.matchAll(
|
|
/commands\.length = frustumCommands\.indices\[Pass\.(\w+)\];/g,
|
|
),
|
|
].map((match) => match[1]),
|
|
['VOXELS', 'GAUSSIAN_SPLATS', 'TRANSLUCENT'],
|
|
'Scene.js truncates a different set of passes: re-check src/sceneCommandRelease.js',
|
|
);
|
|
});
|