/**
 * Owns the per-splat compute pass for the hybrid GSplat renderer (Pass B in the pipeline):
 *
 *   project + screen-space cull + sort key generation + compaction
 *
 * The pass reads the post-frustum-culled `compactedSplatIds` produced by
 * {@link GSplatIntervalCompaction} and writes a pre-projected raster-friendly
 * cache (see {@link CACHE_STRIDE}) plus a parallel array of depth-based sort
 * keys. A workgroup-local atomic compaction pattern (one global atomicAdd per
 * workgroup of 256 threads) keeps post-cull entries dense in the output buffers.
 *
 * Designed to live alongside the existing renderers without affecting them. The
 * cache layout is duplicated in `gsplat-projector-constants.js` (JS) and the
 * projector / hybrid VS WGSL chunks via the `{CACHE_STRIDE}` cdefine.
 *
 * @ignore
 */
export class GSplatProjector {
    /**
     * @param {GraphicsDevice} device - The graphics device (must support compute).
     */
    constructor(device: GraphicsDevice);
    /** @type {GraphicsDevice} */
    device: GraphicsDevice;
    /**
     * 32 B per splat (8 u32 slots), sized to the work-buffer capacity (not the
     * post-cull count) to avoid undersizing on transient cull-rate drops.
     *
     * @type {StorageBuffer|null}
     */
    projCache: StorageBuffer | null;
    /** @type {StorageBuffer|null} */
    sortKeys: StorageBuffer | null;
    /**
     * Single-element atomic counter; reset to 0 every frame and incremented by
     * the projector pass via per-workgroup atomicAdd.
     *
     * @type {StorageBuffer|null}
     */
    renderCounter: StorageBuffer | null;
    /**
     * Storage buffer holding interleaved bin weights {base, divider} consumed by
     * the projector for camera-relative sort key precision.
     *
     * @type {StorageBuffer|null}
     */
    binWeightsBuffer: StorageBuffer | null;
    /** @type {GSplatSortBinWeights} */
    binWeightsUtil: GSplatSortBinWeights;
    /**
     * Lazily-created projector compute variants keyed by `radial|pick|fisheye|aa`
     * combination (see `_projectorKey`). AA is mutually exclusive with pick, so up to
     * 12 variants exist; only the combinations actually needed by the running app are
     * compiled.
     *
     * @type {Map<string, Compute>}
     */
    _projectorComputes: Map<string, Compute>;
    /** @type {BindGroupFormat|null} */
    _projectorBindGroupFormat: BindGroupFormat | null;
    /**
     * Uniform buffer format for the non-fisheye projector variant.
     *
     * @type {UniformBufferFormat|null}
     */
    _projectorUniformBufferFormat: UniformBufferFormat | null;
    /**
     * Uniform buffer format for the fisheye projector variant. Adds 4 fisheye
     * scalar uniforms after the shared fields.
     *
     * @type {UniformBufferFormat|null}
     */
    _projectorUniformBufferFormatFisheye: UniformBufferFormat | null;
    /**
     * Uniform buffer format for the XR stereo projector variant. Adds the eye-1
     * view-projection matrix after the shared fields.
     *
     * @type {UniformBufferFormat|null}
     */
    _projectorUniformBufferFormatStereo: UniformBufferFormat | null;
    /** @type {Compute|null} */
    _writeIndirectArgsCompute: Compute | null;
    /** @type {BindGroupFormat|null} */
    _writeArgsBindGroupFormat: BindGroupFormat | null;
    /** @type {UniformBufferFormat|null} */
    _writeArgsUniformBufferFormat: UniformBufferFormat | null;
    /**
     * Cached work-buffer format version; changes invalidate the projector
     * compute (its bind group format is derived from the work-buffer format).
     */
    _formatVersion: number;
    /**
     * Change-detection key for the render-stage customization (user `gsplatModifyVS` chunk +
     * material defines). When it changes, the compiled projector variants are rebuilt.
     *
     * @type {string}
     */
    _materialKey: string;
    /**
     * The user's WGSL `gsplatModifyVS` chunk source, or null to use the default no-op chunk.
     *
     * @type {string|null}
     */
    _userModifySource: string | null;
    /**
     * Generated user varying streams chunks (declarations / set functions and projection cache
     * writes), or null when no varying streams are defined.
     *
     * @type {string|null}
     */
    _userVaryingsSource: string | null;
    /** @type {string|null} */
    _userCacheWriteSource: string | null;
    /**
     * Reference to the user material's defines map (read at compute-build time), or null.
     *
     * @type {Map<string, string>|null}
     */
    _userDefines: Map<string, string> | null;
    /**
     * Number of u32 words user varying streams add to the per-splat projection cache.
     *
     * @type {number}
     */
    _userCacheWords: number;
    /** @type {number} */
    _allocatedCacheCount: number;
    /** @type {number} */
    _allocatedCacheStride: number;
    /** @type {Float32Array} */
    cameraPositionData: Float32Array;
    /** @type {Float32Array} */
    cameraDirectionData: Float32Array;
    destroy(): void;
    /** @private */
    private _createUniformBufferFormats;
    /** @private */
    private _createWriteIndirectArgsCompute;
    /**
     * Destroys the projector compute pipelines so they are lazily rebuilt against the
     * current work-buffer format.
     *
     * @private
     */
    private _destroyProjectorComputes;
    /**
     * Builds the cache key for a projector variant combination.
     *
     * @param {boolean} radialSort - Radial vs linear sort.
     * @param {boolean} pickMode - Pick output mode.
     * @param {boolean} fisheyeMode - Fisheye projection mode.
     * @param {boolean} antiAlias - Anti-aliasing opacity compensation mode.
     * @param {boolean} stereo - XR stereo (2-view) projection mode.
     * @returns {string} The cache key.
     * @private
     */
    private _projectorKey;
    /**
     * Builds the projector Compute (one variant per sort/pick/fisheye combination).
     *
     * @param {GSplatWorkBuffer} workBuffer - The current work buffer (provides format).
     * @param {boolean} radialSort - Whether to compile the RADIAL_SORT variant.
     * @param {boolean} pickMode - Whether to write pcId into the cache for picking.
     * @param {boolean} fisheyeMode - Whether to compile the GSPLAT_FISHEYE variant.
     * @param {boolean} antiAlias - Whether to compile the GSPLAT_AA variant (bakes the
     * anti-aliasing opacity compensation into the cached alpha).
     * @param {boolean} stereo - Whether to compile the GSPLAT_XR (2-view stereo) variant.
     * @returns {Compute} The created compute instance.
     * @private
     */
    private _createProjectorCompute;
    /**
     * Returns the projector Compute for the requested sort/pick/fisheye combination,
     * lazily creating it. Recreates all compute instances when the work-buffer format
     * version changes.
     *
     * @param {GSplatWorkBuffer} workBuffer - The current work buffer.
     * @param {boolean} radialSort - Whether to use the radial sort variant.
     * @param {boolean} [pickMode] - Whether to use the pick-output variant.
     * @param {boolean} [fisheyeMode] - Whether to use the fisheye projection variant.
     * @param {boolean} [antiAlias] - Whether to use the anti-aliasing variant.
     * @param {boolean} [stereo] - Whether to use the XR stereo (2-view) variant.
     * @returns {Compute} The projector compute instance.
     * @private
     */
    private _getProjectorCompute;
    /**
     * Syncs the render-stage customization from `app.scene.gsplat.material`: the user-overridable
     * `gsplatModifyVS` chunk and the material defines are injected into the projector compute. A
     * change is detected via the material's shader-chunks key plus its defines, and rebuilds the
     * compiled variants. Call before {@link GSplatProjector#_getProjectorCompute}.
     *
     * @param {import('../materials/shader-material.js').ShaderMaterial|undefined} material - The
     * gsplat render material (carries the user modify chunk, defines and parameters).
     * @private
     */
    private _updateMaterial;
    /**
     * Ensures projCache and sortKeys storage buffers are sized to at least `capacity` splats.
     * Both buffers are sized to the work-buffer capacity (passed in by the caller) rather than
     * post-cull counts, mirroring `compactedSplatIds` allocation in interval compaction.
     *
     * @param {number} capacity - Required splat capacity (work-buffer total active splats).
     * @private
     */
    private _ensureCapacity;
    /**
     * Runs the project + cull + key-gen + compact compute pass.
     *
     * @param {object} params - Dispatch parameters.
     * @param {GSplatWorkBuffer} params.workBuffer - The current work buffer.
     * @param {GraphNode} params.cameraNode - The camera node (with attached CameraComponent).
     * @param {StorageBuffer} params.compactedSplatIds - Output of interval compaction.
     * @param {StorageBuffer} params.sortElementCountBuffer - GPU-written visible count from
     * interval compaction (single u32 element); the projector reads this to early-out
     * threads beyond the post-frustum-cull range.
     * @param {number} params.totalCapacity - Work-buffer capacity used to size projCache /
     * sortKeys (typically `worldState.totalActiveSplats`).
     * @param {boolean} params.radialSort - Whether to use the radial sort key variant.
     * @param {number} params.numBits - Sort key bit count (defines bucket count = 1 << numBits).
     * @param {number} params.minDist - Minimum distance for sort key normalisation.
     * @param {number} params.maxDist - Maximum distance for sort key normalisation.
     * @param {number} params.alphaClip - Alpha cull threshold.
     * @param {number} params.minPixelSize - Minimum on-screen pixel size before culling.
     * @param {number} params.minContribution - Minimum total contribution before culling.
     * @param {number} params.foveationStrength - Foveated culling strength added to
     * `minContribution` toward the screen edges (0 disables).
     * @param {number} params.foveationCenter - Protected centre radius (NDC units) within which
     * foveated culling has no effect.
     * @param {number} params.viewportWidth - Render viewport width in pixels.
     * @param {number} params.viewportHeight - Render viewport height in pixels.
     * @param {boolean} params.flipY - Whether the active render target uses `flipY` (must match
     * {@link Renderer#setCameraUniforms}).
     * @param {boolean} [params.pickMode] - Whether to write picking IDs into the cache.
     * @param {import('../graphics/fisheye-projection.js').FisheyeProjection} [params.fisheyeProj] -
     * Fisheye projection state. When `fisheyeProj.enabled` is true the projector picks the
     * GSPLAT_FISHEYE variant and writes NDC-style clip data; otherwise the linear path runs.
     * @param {boolean} [params.antiAlias] - Whether to bake anti-aliasing opacity
     * compensation into the cached alpha. Ignored in pick mode (picking only gates on a
     * binary opacity threshold), which keeps the projector variant count down.
     * @param {boolean} [params.isStereo] - Whether to project both XR eyes in a single pass
     * (GSPLAT_XR variant). Requires `cameraNode.camera.camera.xrViews` to have 2 views.
     * Mutually exclusive with pick and fisheye.
     */
    dispatch(params: {
        workBuffer: GSplatWorkBuffer;
        cameraNode: GraphNode;
        compactedSplatIds: StorageBuffer;
        sortElementCountBuffer: StorageBuffer;
        totalCapacity: number;
        radialSort: boolean;
        numBits: number;
        minDist: number;
        maxDist: number;
        alphaClip: number;
        minPixelSize: number;
        minContribution: number;
        foveationStrength: number;
        foveationCenter: number;
        viewportWidth: number;
        viewportHeight: number;
        flipY: boolean;
        pickMode?: boolean;
        fisheyeProj?: import("../graphics/fisheye-projection.js").FisheyeProjection;
        antiAlias?: boolean;
        isStereo?: boolean;
    }): void;
    /**
     * Writes per-frame indirect draw / dispatch arguments derived from `renderCounter[0]`.
     *
     * @param {number} drawSlot - Slot index in `device.indirectDrawBuffer`.
     * @param {number} sortSlotBase - Base slot index in `device.indirectDispatchBuffer`. The
     * radix sort backend uses `sortIndirectInfo[0]` consecutive slots starting here.
     * @param {StorageBuffer} numSplatsBuffer - Storage buffer the vertex shader reads for the
     * post-cull splat count (single u32 element).
     * @param {StorageBuffer} sortElementCountBuffer - Storage buffer the radix sort reads for
     * its element count (single u32 element).
     * @param {Uint32Array} sortIndirectInfo - Sorter-owned 4-element Uint32 array returned by
     * `ComputeRadixSort.prepareIndirect()`, used as a `vec4<u32>` uniform by the shader.
     */
    writeIndirectArgs(drawSlot: number, sortSlotBase: number, numSplatsBuffer: StorageBuffer, sortElementCountBuffer: StorageBuffer, sortIndirectInfo: Uint32Array): void;
}
import type { GraphicsDevice } from '../../platform/graphics/graphics-device.js';
import { StorageBuffer } from '../../platform/graphics/storage-buffer.js';
import { GSplatSortBinWeights } from './gsplat-sort-bin-weights.js';
import { Compute } from '../../platform/graphics/compute.js';
import { BindGroupFormat } from '../../platform/graphics/bind-group-format.js';
import { UniformBufferFormat } from '../../platform/graphics/uniform-buffer-format.js';
import type { GSplatWorkBuffer } from './gsplat-work-buffer.js';
import type { GraphNode } from '../graph-node.js';
