fix(infrastructure): stop idle republishing and respect settled terrain

Skip unchanged overlay cohorts while detecting moved positions and lifecycle changes. Defer ground sampling until visible terrain settles, retain the loaded surface as a floor, and preserve roof heights and bounded retries. Keep regression and idle-render gates intact.
This commit is contained in:
Sameh Khamis committed 2026-09-11 08:59:32 -07:00
1 parent 6dd00d1e76
commit b5568de9fa
6 files changed
+122 -5

No files matched your search

+4
View File
@@ -13,6 +13,10 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
## [Unreleased]
- Unchanged local infrastructure overlays no longer sustain idle rendering.
Ground samples wait for visible terrain to settle and cannot place a marker
below its loaded surface; roofs and valid below-sea-level heights are retained.
- Datacenter and dam marker stems use bounded, zoom-dependent active sets with
stable selection during camera motion. Close-up stems scale to the actual
camera distance; source totals and submarine cables remain unchanged.
+5
View File
@@ -8,6 +8,11 @@ and 420 below 200 km. Selection favors existing label priority and nearby
features, retains stable choices across small camera movements, and refreshes
during continuous motion. Disable/re-enable resets selection cleanly.
Close-up stem sizing uses camera-to-feature distance without a 5 km minimum.
Unchanged overlay entries do not request another frame; moved positions,
changed membership and re-enabling still publish. Ground sampling waits for
visible globe tiles to settle and uses valid loaded terrain as a floor while
retaining rooftop and below-sea-level elevations. A hidden globe does not
constrain photoreal geometry, and retry work remains bounded.
The submarine-cable renderer is unchanged. These limits bound active stem work;
they do not reduce the materialized entity count or establish an FPS gain.
+19 -4
View File
@@ -296,12 +296,27 @@ try {
// ── parked-idle honesty: the LOD walk must not force continuous render ─
await new Promise((r) => setTimeout(r, 4_000));
const idle = await page.evaluate(() => new Promise((resolve) => {
const idle = await page.evaluate(async () => {
const { getRenderGovernorDiagnostics } = await import('/src/renderGovernor.js');
return new Promise((resolve) => {
const scene = window.__godsEyeView.viewer.scene;
const startedAt = Date.now();
const tilesLoadedBefore = scene.globe.tilesLoaded;
let renders = 0;
const remove = scene.postRender.addEventListener(() => { renders += 1; });
setTimeout(() => { remove(); resolve({ renders }); }, 5_000);
}));
let framesWithPendingTiles = 0;
const remove = scene.postRender.addEventListener(() => {
renders += 1;
if (!scene.globe.tilesLoaded) framesWithPendingTiles += 1;
});
setTimeout(() => {
remove();
const governor = getRenderGovernorDiagnostics();
resolve({ renders, tilesLoadedBefore, tilesLoadedAfter: scene.globe.tilesLoaded,
framesWithPendingTiles, mode: governor.mode, holds: governor.holds,
requests: governor.recentRequests.filter(request => request.at >= startedAt) });
}, 5_000);
});
});
report(CONTROL
? 'parked idle, control (postRender fires / 5s)'
: 'parked idle with infra ON (postRender fires / 5s)', idle);
+28
View File
@@ -225,6 +225,11 @@ export function createLocalInfrastructureOverlayPublisher({
let visible = false;
let published = false;
let destroyed = false;
// Local entries have immutable metadata and a mutable Cartesian position.
// Snapshot coordinates: retaining only the entry reference would miss a
// stem tip moving in place. Republishing an unchanged cohort invalidates
// the host and can sustain a render loop when frames exceed the 450 ms walk.
let lastPublication = null;
const sourceOptions = {
cohortLimit: LOCAL_OVERLAY_COHORT_LIMIT,
collisionCapacity: LOCAL_OVERLAY_COLLISION_CAPACITY,
@@ -239,7 +244,18 @@ export function createLocalInfrastructureOverlayPublisher({
},
publish(entries) {
if (destroyed || !visible) return;
if (lastPublication && entries.length === lastPublication.length
&& entries.every((entry, index) => {
const previous = lastPublication[index];
return entry === previous.entry
&& entry.position?.x === previous.x
&& entry.position?.y === previous.y
&& entry.position?.z === previous.z;
})) return;
host.setEntries(sourceId, entries, sourceOptions);
lastPublication = entries.map(entry => ({
entry, x: entry.position?.x, y: entry.position?.y, z: entry.position?.z,
}));
published = entries.length > 0;
},
hide() {
@@ -248,6 +264,7 @@ export function createLocalInfrastructureOverlayPublisher({
if (visible) host.setVisible(sourceId, false);
visible = false;
published = false;
lastPublication = null;
},
destroy() {
if (destroyed) return;
@@ -255,6 +272,7 @@ export function createLocalInfrastructureOverlayPublisher({
if (visible) host.setVisible(sourceId, false);
visible = false;
published = false;
lastPublication = null;
destroyed = true;
},
};
@@ -897,6 +915,8 @@ function sampleLocalGroundHeight(viewer, record, now) {
if (record.groundSampled || !viewer.scene.sampleHeightSupported) return false;
if (now - record.lastGroundSampleMs < GROUND_SAMPLE_RETRY_MS) return false;
record.lastGroundSampleMs = now;
const globe = viewer.scene.globe;
if (globe?.show && globe.tilesLoaded === false) return false;
let sampled;
try {
sampled = viewer.scene.sampleHeight(record.carto, [record.entity]);
@@ -904,6 +924,14 @@ function sampleLocalGroundHeight(viewer, record, now) {
return false; // tiles not ready; retry on a later bounded update
}
if (!Number.isFinite(sampled) || Math.abs(sampled) > GROUND_SAMPLE_MAX_ABS_HEIGHT_M) return false;
// A coarse scene-depth sample can lie below the terrain already loaded by
// the visible globe. Keep that terrain as a floor while allowing roofs and
// valid below-sea-level elevations. Photoreal scenes hide the globe, so its
// inactive terrain must not constrain their geometry.
const terrainHeight = globe?.show ? globe.getHeight?.(record.carto) : undefined;
if (Number.isFinite(terrainHeight) && Math.abs(terrainHeight) <= GROUND_SAMPLE_MAX_ABS_HEIGHT_M) {
sampled = Math.max(sampled, terrainHeight);
}
record.groundSampled = true;
record.groundHeight = sampled;
Cesium.Cartesian3.fromRadians(
+65
View File
@@ -314,6 +314,33 @@ test('local overlay publisher owns add/remove/visibility lifecycle and becomes i
assert.deepEqual(calls[7], ['visible', 'local-datacenters', false]);
});
test('slow parked frames do not keep republishing the same local overlay cohort', async (t) => {
const env = await createRealLocalLayerHarness();
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
const publications = () => env.hostCalls.filter(([type]) => type === 'entries');
env.preRender.raise();
assert.equal(publications().length, 1);
assert.ok(publications()[0][2].length > 0, 'the initial cohort must be populated');
for (let i = 0; i < 6; i++) {
clock.advance(1_000); // Every slow frame passes the 450 ms source throttle.
env.preRender.raise();
}
assert.equal(publications().length, 1,
'unchanged publication invalidates the real host and requests another slow frame');
const camera = env.viewer.camera.positionWC;
env.viewer.camera.positionWC = Cesium.Cartesian3.add(camera,
new Cesium.Cartesian3(10_000, 0, 0), new Cesium.Cartesian3());
env.moveEnd.raise();
env.preRender.raise();
assert.equal(publications().length, 2, 'changed stem positions must still reach the host');
env.layer.disable(env.viewer);
await env.layer.enable(env.viewer);
env.preRender.raise();
assert.equal(publications().length, 3, 're-enable must republish after clearing the host');
});
test('real layer disable clears its published host entries and balances settle listeners', async () => {
const env = await createRealLocalLayerHarness();
env.preRender.raise();
@@ -683,6 +710,44 @@ function governorReasons() {
return getRenderGovernorDiagnostics().recentRequests.map((entry) => entry.reason);
}
test('ground sampling waits for visible globe tiles before caching a height', async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 117,
});
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
env.viewer.scene.globe = { show: true, tilesLoaded: false, getHeight: () => 117 };
setCameraAltitude(env, 20_000);
env.preRender.raise();
assert.equal(env.sampleCalls.count, 0, 'streaming terrain must not become a permanent coarse sample');
assert.ok(Math.abs(baseHeightM(env)) < 0.01);
env.viewer.scene.globe.tilesLoaded = true;
clock.advance(2_100);
env.preRender.raise();
assert.equal(env.sampleCalls.count, 1, 'the existing retry must sample the settled scene');
assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01);
});
for (const [terrainHeight, sampledHeight, expectedHeight, globeShown] of [
[117, -2238, 117, true],
[-400, -410, -400, true],
[117, 180, 180, true],
[117, -20, -20, false],
]) {
test(`ground sampling respects terrain ${terrainHeight} and geometry ${sampledHeight} with globe ${globeShown}`, async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => sampledHeight,
});
installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
env.viewer.scene.globe = { show: globeShown, getHeight: () => terrainHeight };
setCameraAltitude(env, 20_000);
env.preRender.raise();
assert.ok(Math.abs(baseHeightM(env) - expectedHeight) < 0.01,
`base ${baseHeightM(env)} must respect the visible terrain without flattening roofs or below-sea-level terrain`);
});
}
test('a failed ground sample schedules the retry frame the idle governor would never produce', async (t) => {
const env = await createRealLocalLayerHarness({ sampleHeightSupported: true });
_resetRenderGovernorForTest();
+1 -1
View File
@@ -58,7 +58,7 @@ test('infraLodBudget band boundaries are inclusive at the lower edge', () => {
assert.deepEqual(infraLodBudget(INFRA_LOD_REGIONAL_HEIGHT_M - 1), { activeLimit: INFRA_LOD_ACTIVE_MAX });
});
test('infraLodBudget treats non-finite / negative height as the global (cheapest) band', () => {
test('infraLodBudget uses the global band for non-finite height and clamps negative height to zero', () => {
assert.deepEqual(infraLodBudget(undefined), { activeLimit: INFRA_LOD_ACTIVE_MIN });
assert.deepEqual(infraLodBudget(NaN), { activeLimit: INFRA_LOD_ACTIVE_MIN });
assert.deepEqual(infraLodBudget(Number.POSITIVE_INFINITY), { activeLimit: INFRA_LOD_ACTIVE_MIN });