Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Inputs the byte-budget pass needs to operate on.

    interface EvictorCtx {
        pointBuffers: Map<number, PooledBuffer[]>;
        lineBuffers: Map<number, PooledBuffer[]>;
        gsplatBuffers: Map<number, PooledBuffer[]>;
        maxPoolBytes: number;
        maxPoolSize: number;
        graceFrame: number;
        typeEvictionCounters: {
            points: { evictions: number };
            lines: { evictions: number };
            gsplats: { evictions: number };
        };
    }
    Index
    pointBuffers: Map<number, PooledBuffer[]>
    lineBuffers: Map<number, PooledBuffer[]>
    gsplatBuffers: Map<number, PooledBuffer[]>
    maxPoolBytes: number
    maxPoolSize: number
    graceFrame: number

    Same-frame grace for ACQUIRE-triggered sweeps: buffers whose lastUsedFrame equals this value are exempt from the byte pass. Without it, a release followed by same-frame acquires would dispose the just-released buffers before those acquires can best-fit them — alloc/dispose churn replacing free reuse. releaseGeometry stamps lastUsedFrame with the release frame so the grace actually matches (an acquire-time stamp alone would carry a stale frame into the release). Release-triggered sweeps pass -1 (never matches) — byte enforcement on release is unconditional, which is also the backstop bounding the grace: if the frame counter is not advancing (no render loop), acquire sweeps may keep sparing released buffers, but every release re-enforces the budget without grace.

    THIS GRACE IS VESTIGIAL AS FAR AS ANYONE HAS BEEN ABLE TO MEASURE. Both candidate justifications were checked and neither survives (#2426, #2436):

    • DATASET SWITCH, which this comment used to name outright. Cannot be it: the pool is disposed and reconstructed per dataset (lifecycle/dispose.ts → gpuBufferPool.dispose(); scene-loader.ts nulls the field and rebuilds it on the next load), so no buffer survives a switch to be adopted after one. The comment asserted a scenario the lifecycle prevents, and it misdirected a review before anyone checked.
    • LOD DEMOTION, the plausible replacement: releaseLazyGSplats / releaseLazyPoints / releaseLazyLines return a level's buffer expecting re-promotion to adopt it back. MEASURED under a binding budget: re-promotion allocates fresh either way (alloc +1, reuses +0, with and without the post-grow sweep). The demoted buffer is already gone — releaseGeometry's own sweep runs at graceFrame -1 and takes it at demotion time — so the grace never gets the chance to protect it.

    KEPT ANYWAY, DELIBERATELY. "Protects no case we could construct" is not "protects nothing": some unmeasured same-frame release-then- reacquire may still rely on it, and proving that negative is its own piece of work. Removal is a separate, optional cleanup — do not delete this on the strength of the paragraph above.

    typeEvictionCounters: {
        points: { evictions: number };
        lines: { evictions: number };
        gsplats: { evictions: number };
    }

    Per-type eviction counters; mutated as buffers dispose.