//#region src/pipeline/BucketedDirtyTracker.d.ts /** * Anything that exposes the BufferAttribute / InterleavedBuffer write-range * API. Both `InstancedBufferAttribute` (per-attribute buffer) and * `InstancedInterleavedBuffer` (shared interleaved buffer fronted by * multiple `InterleavedBufferAttribute` views) implement these — letting * one tracker drive uploads for either layout. */ interface UploadTarget { addUpdateRange(start: number, count: number): void; clearUpdateRanges(): void; needsUpdate: boolean; } /** * Adaptive dirty-range tracker for a single instanced buffer attribute. * * Replaces the per-attribute `dirtyMin` / `dirtyMax` pattern with a * bucketed dirty-set. At flush time, the tracker chooses between: * * - **Bucketed range upload** — one `addUpdateRange` per dirty bucket. * Tight upload bandwidth when changes are spatially clustered or * sparse, even when the global min..max spans the whole buffer. * - **Full-buffer upload** — `clearUpdateRanges` + `needsUpdate = true`. * Three then takes the `bufferData` fast path (single large upload). * Chosen when enough buckets are dirty that the per-range overhead * would exceed the cost of just re-uploading everything. * * Strictly dominates the single-min/max approach: at worst-case * (everything dirty) it matches by falling into the full-upload branch; * in every other case it does better. * * Bucket size MUST be a power of 2 so `slot >>> bucketShift` resolves * the bucket index. Per-slot markDirty is ~5 ns: one shift, one compare * on `bucketState[bucket]`, optional store + count increment. */ declare class BucketedDirtyTracker { private readonly attr; private readonly stride; private readonly fullThreshold; private readonly bucketShift; private readonly bucketCount; private readonly bucketState; private readonly bucketLastSlot; private bucketDirtyCount; constructor(attr: UploadTarget, maxSize: number, bucketSize: number, stride: number, fullThreshold: number); /** * Mark a slot as dirty. Called from buffer write methods on every * write — must be cheap. Five ops in the hot path. */ markDirty(slot: number): void; /** * Flush dirty state to the attribute. Called once per frame after all * writes for this attribute have completed. Decides per-flush whether * to upload as ranges or as a single full-buffer write. */ flush(): void; /** * Whether the tracker has unflushed dirty state. Used by tests and * for telemetry — not on the hot path. */ get isDirty(): boolean; /** * Snapshot of the current dirty-bucket count. Used by telemetry and * the per-phase threshold calibration pass — not on the hot path. */ get dirtyBucketCount(): number; private resetState; } //#endregion export { BucketedDirtyTracker }; //# sourceMappingURL=BucketedDirtyTracker.d.ts.map