From 18f95926919c3ed694a7382721d7eee416ed575e Mon Sep 17 00:00:00 2001 From: Riho Kirss Date: Thu, 3 Sep 2026 20:36:19 +0300 Subject: [PATCH] perf(FragmentsModels): fill tiles in size-sorted sample order to cut visibility runs A tile's index buffer is laid out in the order samples were appended and the per-sample LOD decision depends on screen size, so with file-ordered samples the geometry / wires / invisible cut through a tile produced dozens of interleaved visibility runs. Each run becomes a geometry.groups entry on the main thread, i.e. its own draw call. Feeding generate() the existing size-sorted _samplesDimensions order keeps the cut to one or two runs. Tile membership and geometry are unchanged. --- .../virtual-controllers/virtual-tiles-controller.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/fragments/src/FragmentsModels/src/virtual-model/virtual-controllers/virtual-tiles-controller.ts b/packages/fragments/src/FragmentsModels/src/virtual-model/virtual-controllers/virtual-tiles-controller.ts index c49fb51a..17374f76 100644 --- a/packages/fragments/src/FragmentsModels/src/virtual-model/virtual-controllers/virtual-tiles-controller.ts +++ b/packages/fragments/src/FragmentsModels/src/virtual-model/virtual-controllers/virtual-tiles-controller.ts @@ -195,8 +195,16 @@ export class VirtualTilesController { mesh.setupTemplates(); } const step = Math.max(1, Math.floor(this._sampleAmount / 20)); + // Fill tiles in descending sample-dimension order (the same order the + // cull sweep uses) instead of file order. A tile's index buffer is + // laid out in insertion order and the per-sample LOD decision is + // driven by screen size, so with size-sorted samples the geometry / + // wires / invisible cut through a tile becomes one or two contiguous + // runs instead of dozens of interleaved ones — and every visible run + // is a separate `geometry.groups` entry, i.e. a separate draw call on + // the main thread. Tile membership itself is unchanged. for (let i = 0; i < this._sampleAmount; i++) { - this.generateSampleInTiles(i); + this.generateSampleInTiles(this._samplesDimensions[i]); if (i % step === 0) { onProgress?.(i / this._sampleAmount); // Yield the worker thread so progress messages get dispatched