/**
 * Renders splats using a tiled compute pipeline with per-tile binning and local sorting.
 * Receives a compacted splat ID list from {@link GSplatIntervalCompaction}, projects each
 * splat into a projection cache, bins them into screen-space tiles via a fused
 * count+pair-write pass, classifies tiles by size, sorts each tile by depth (with bucket
 * pre-sort for large tiles), then rasterizes front-to-back. Pipeline:
 *
 *   1. Tile count: project each visible splat, write projection cache (screen pos, conic,
 *      color, depth). Iterate overlapping tiles twice: first to count intersections and
 *      build a 6x5 bitmask, then after a workgroup prefix sum + single global atomicAdd,
 *      to perform capped atomicAdd on per-tile counters and write (tileIdx, localOffset)
 *      pairs into a contiguous pair buffer. Large splats (AABB > 64 tiles) are deferred
 *      to a cooperative pass — their IDs are appended to a largeSplatIds buffer.
 *   1b. Large tile count: one workgroup (256 threads) per deferred large splat reads
 *      projCache, recomputes the AABB, and cooperatively iterates tiles. Same pair-buffer
 *      and tileSplatCounts writes as pass 1. Sets the high bit of splatPairCount to flag
 *      these splats for the cooperative place-entries pass.
 *   2. Prefix sum: exclusive prefix sum over per-tile counts produces offsets + total.
 *   3. Place entries: each thread reads its (tileIdx, localOffset) pairs from the pair
 *      buffer and writes its splat index into tileEntries at deterministic positions
 *      (prefix-summed offset + localOffset). No atomics, no projCache reads. Skips large
 *      splats (high bit of splatPairCount).
 *   3b. Large place entries: cooperative pass — one workgroup (256 threads) per large
 *      splat, same dispatch as 1b. Reads pairs and writes tileEntries in parallel.
 *   3.5. Classify: scan tiles, build small/large/rasterize tile lists, assign compact
 *        overflow scratch offsets for large tiles, write indirect args.
 *   4b. Bucket pre-sort: logarithmic-depth bucket histogram + scatter for large tiles
 *       (>4096 entries), using overflow scratch in the unified tileEntries buffer, packs
 *       whole buckets into <=4096 chunks (indirect dispatch).
 *   4b.5. Copy chunk sort indirect dispatch args (separate pass for inter-pass barrier).
 *   4a. Small tile sort: bitonic sort for tiles with 1..4096 entries (indirect dispatch).
 *   4c. Chunk sort: bitonic sort on each chunk from bucket pre-sort (indirect dispatch).
 *   5. Rasterize: one workgroup per non-empty tile reads its sorted entry range, loads
 *      from the projection cache via shared memory, and blends front-to-back with
 *      early-out (indirect dispatch).
 *
 * The tileEntries buffer is unified: main tile entry lists occupy [0, totalEntries),
 * overflow scratch for bucket sort occupies [totalEntries, totalEntries + overflowUsed).
 * Buffer capacity adapts dynamically via async GPU readback of actual usage.
 *
 * Supports both color and pick dispatch via two {@link GSplatLocalDispatchSet} instances.
 * Splat/entry-dependent buffers (projCache, tileEntries) are shared between dispatch sets
 * with a submitVersion guard to prevent resizing within the same command encoder.
 *
 * @ignore
 */
export class GSplatComputeLocalRenderer extends GSplatRenderer {
    /** @type {GSplatLocalDispatchSet} */
    _mainSet: GSplatLocalDispatchSet;
    /** @type {GSplatLocalDispatchSet|null} */
    _pickSet: GSplatLocalDispatchSet | null;
    /** @type {FramePassGSplatComputeLocal} */
    framePass: FramePassGSplatComputeLocal;
    /** @type {GSplatTileComposite} */
    tileComposite: GSplatTileComposite;
    /** @type {boolean} */
    _needsFramePassRegister: boolean;
    /** @type {number} */
    _textureSize: number;
    /** @type {number} */
    _minPixelSize: number;
    /** @type {number} */
    _minContribution: number;
    /** @type {number} */
    _alphaClip: number;
    /** @type {number} */
    _exposure: number;
    /** @type {number} */
    _numSplats: number;
    /** @type {StorageBuffer|null} */
    _compactedSplatIds: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    _sortElementCountBuffer: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    _projCacheBuffer: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    _tileEntriesBuffer: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    _pairBuffer: StorageBuffer | null;
    /**
     * Packed atomic counters: [0] = global pair counter, [1] = large splat count.
     *
     * @type {StorageBuffer|null}
     */
    _countersBuffer: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    _splatPairStartBuffer: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    _splatPairCountBuffer: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    _largeSplatIdsBuffer: StorageBuffer | null;
    /** @type {number} */
    _largeSplatIdsCapacity: number;
    /** @type {number} */
    _allocatedLargeSplatCapacity: number;
    /** @type {number} */
    _allocatedSplatCapacity: number;
    /** @type {number} */
    _allocatedEntryCapacity: number;
    /** @type {number} */
    _tileEntryMultiplier: number;
    /** @type {number} Last device.submitVersion when shared buffers were resized */
    _lastBufferSubmitVersion: number;
    /** @type {number} Last readback entry count (-1 = consumed / no fresh data) */
    _lastReadbackEntryCount: number;
    /** @type {number} Consecutive frames where usage < half capacity */
    _shrinkFrameCount: number;
    /** @type {number} */
    _fisheye: number;
    /**
     * Active data source providing format and texture access. When set via {@link setDataSource},
     * the renderer reads format and textures from this object instead of the inherited workBuffer.
     * Defaults to the workBuffer passed to the constructor.
     *
     * @type {{ format: GSplatFormat, getTexture: (name: string) => Texture }}
     * @private
     */
    private _dataSource;
    /** @type {Shader} */
    _placeEntriesShader: Shader;
    /** @type {BindGroupFormat} */
    _placeEntriesBindGroupFormat: BindGroupFormat;
    /** @type {Shader} */
    _placeEntryPrepShader: Shader;
    /** @type {BindGroupFormat} */
    _placeEntryPrepBindGroupFormat: BindGroupFormat;
    /** @type {StorageBuffer|null} */
    _placeEntryPrepDispatchBuffer: StorageBuffer | null;
    /** @type {Compute|null} */
    _placeEntryPrepCompute: Compute | null;
    /** @type {Shader} */
    _largeSplatShader: Shader;
    /** @type {BindGroupFormat} */
    _largeSplatBindGroupFormat: BindGroupFormat;
    /** @type {Shader} */
    _largeSplatPrepShader: Shader;
    /** @type {BindGroupFormat} */
    _largeSplatPrepBindGroupFormat: BindGroupFormat;
    /** @type {StorageBuffer|null} */
    _largeSplatDispatchBuffer: StorageBuffer | null;
    /** @type {Compute|null} */
    _largeSplatPrepCompute: Compute | null;
    /** @type {Shader} */
    _largePlaceEntriesShader: Shader;
    /** @type {BindGroupFormat} */
    _largePlaceEntriesBindGroupFormat: BindGroupFormat;
    /** @type {Shader} */
    _classifyShader: Shader;
    /** @type {BindGroupFormat} */
    _classifyBindGroupFormat: BindGroupFormat;
    /** @type {Shader} */
    _sortShader: Shader;
    /** @type {BindGroupFormat} */
    _sortBindGroupFormat: BindGroupFormat;
    /** @type {Shader} */
    _bucketSortShader: Shader;
    /** @type {BindGroupFormat} */
    _bucketSortBindGroupFormat: BindGroupFormat;
    /** @type {Shader} */
    _copyShader: Shader;
    /** @type {BindGroupFormat} */
    _copyBindGroupFormat: BindGroupFormat;
    /** @type {Shader} */
    _chunkSortShader: Shader;
    /** @type {BindGroupFormat} */
    _chunkSortBindGroupFormat: BindGroupFormat;
    setRenderMode(renderMode: any): void;
    frameUpdate(gsplat: any, exposure: any, fogParams: any): void;
    _fogParams: any;
    _debugMode: any;
    _formatHash: any;
    /**
     * @param {StorageBuffer} compactedSplatIds - Dense buffer of visible splat IDs.
     * @param {StorageBuffer} sortElementCountBuffer - Single-u32 buffer with visible count.
     * @param {number} textureSize - The work buffer texture size.
     * @param {number} numSplats - Upper bound on visible splats.
     */
    setCompactedData(compactedSplatIds: StorageBuffer, sortElementCountBuffer: StorageBuffer, textureSize: number, numSplats: number): void;
    /** @private */
    private _registerFramePass;
    /** @private */
    private _unregisterFramePass;
    resizeOutputTexture(width: any, height: any): void;
    /**
     * Ensure shared splat/entry buffers are large enough. Only resizes when
     * device.submitVersion has changed (preventing mid-encoder buffer destruction).
     *
     * @param {number} numSplats - Upper bound on visible splats.
     * @private
     */
    private _ensureSharedBuffers;
    _depthBuffer: StorageBuffer;
    /**
     * Main color dispatch.
     */
    dispatch(): void;
    /**
     * Pick dispatch: runs the compute pick pipeline and returns the configured pick mesh instance.
     *
     * @param {object} cam - The camera.
     * @param {number} width - Pick target width.
     * @param {number} height - Pick target height.
     * @returns {MeshInstance|null} The pick mesh instance ready for the picker's render list.
     */
    dispatchPick(cam: object, width: number, height: number): MeshInstance | null;
    /** @type {number} */
    _lastDrawSlot: number;
    /** @type {number} */
    _lastNumTilesX: number;
    /**
     * Unified dispatch pipeline used by both color and pick paths.
     *
     * @param {GSplatLocalDispatchSet} set - The dispatch set to use.
     * @param {number} width - Render target width.
     * @param {number} height - Render target height.
     * @param {boolean} pickMode - Whether this is a pick dispatch.
     * @private
     */
    private _dispatchPipeline;
    /**
     * @param {number} numSplats - Splat count at dispatch time.
     * @param {number} numTiles - Tile count at dispatch time.
     * @param {GSplatLocalDispatchSet} set - The dispatch set to readback from.
     * @private
     */
    private _scheduleReadback;
    /**
     * Invalidates all cached count resources on both dispatch sets. Called when the
     * work buffer format changes, making all compiled count shaders invalid.
     *
     * @private
     */
    private _invalidateCountCompute;
    /** @private */
    private _createCommonIncludes;
    /** @private */
    private _createBitonicIncludes;
    /**
     * Creates all shared shaders and bind group formats (called once in constructor).
     *
     * @private
     */
    private _createSharedShaders;
    /**
     * Creates the count shader + shared bind group format.
     *
     * @param {boolean} pickMode - Whether to create the pick variant.
     * @param {boolean} fisheyeEnabled - Whether to include the GSPLAT_FISHEYE define and fisheye uniforms.
     * @returns {{ shader: Shader, bindGroupFormat: BindGroupFormat }} The shader and format.
     * @private
     */
    private _createCountShaderAndFormat;
    /**
     * Creates a dispatch set with its 8 Compute instances.
     *
     * @param {boolean} pickMode - Whether this set is for picking.
     * @returns {GSplatLocalDispatchSet} The populated dispatch set.
     * @private
     */
    private _createDispatchSet;
}
import { GSplatRenderer } from './gsplat-renderer.js';
import { GSplatLocalDispatchSet } from './gsplat-local-dispatch-set.js';
import { FramePassGSplatComputeLocal } from './frame-pass-gsplat-compute-local.js';
import { GSplatTileComposite } from './gsplat-tile-composite.js';
import { StorageBuffer } from '../../platform/graphics/storage-buffer.js';
import { Shader } from '../../platform/graphics/shader.js';
import { BindGroupFormat } from '../../platform/graphics/bind-group-format.js';
import { Compute } from '../../platform/graphics/compute.js';
import type { MeshInstance } from '../mesh-instance.js';
