/** * Dynamic Gaussian-splat playback KPI harness. * * Drives a {@link SplatSequence} through its deterministic `renderFrames` path and records a per-frame * KPI row — bytes, stage timings (fetch / decode / upload / sort / raster), frame time / FPS, and PSNR * vs the source frame. The recorder is a pure aggregator (no GPU, fully offline-testable); the * benchmark reads what `splats.stats` exposes each frame and lets the caller enrich rows with signals * only the GPU can produce (PSNR, GPU-timestamped stage costs) via a `measure` hook. * * @module SplatSequenceBench */ /** The per-frame KPI fields aggregated by {@link SequenceKpiRecorder}. */ export declare const SEQUENCE_KPI_METRICS: readonly ["bytes", "fetchMs", "decodeMs", "uploadMs", "sortMs", "rasterMs", "frameMs", "psnr", "drawSplats", "sourceSplats"]; export type SequenceKpiMetric = (typeof SEQUENCE_KPI_METRICS)[number]; /** One raw benchmark row. Extra caller-owned measurements are retained. */ export type SequenceKpiSample = Partial> & { frame?: number | undefined; [field: string]: unknown; }; /** Aggregate order statistics for one recorded metric. */ export interface SequenceKpiMetricSummary { count: number; min: number; max: number; mean: number; median: number; p95: number; } /** Aggregate result returned by the recorder and benchmark helper. */ export interface SequenceKpiSummary { frameCount: number; totalBytes: number; fps: number | null; metrics: Partial>; } /** Frame range forwarded to deterministic sequence rendering. */ export interface SequenceKpiFrameRange { start?: number | undefined; end?: number | undefined; step?: number | undefined; } /** Narrow splat mesh surface observed by KPI collection. */ export interface SequenceKpiSplats { stats?: Readonly> | undefined; } /** Context passed to the optional GPU-measurement hook. */ export interface SequenceKpiMeasureContext { frame: number; splats: SequenceKpiSplats | null | undefined; stats: Readonly>; } /** Callable render seam accepted from SplatSequence and deterministic test stand-ins. */ export interface SequenceKpiTarget { renderFrames: (...arguments_: never[]) => Promise; } /** Benchmark dependencies and hooks. */ export interface BenchmarkSplatSequenceOptions { renderer?: unknown; scene?: unknown; camera?: unknown; range?: SequenceKpiFrameRange | undefined; recorder?: SequenceKpiRecorder | undefined; measure?: ((context: SequenceKpiMeasureContext) => Promise | SequenceKpiSample | null) | null | undefined; now?: (() => number) | undefined; } /** * Collects per-frame KPI samples and produces aggregate statistics. Stateless beyond the recorded * rows; safe to inspect at any time and to share across a benchmark run. * * @class SequenceKpiRecorder */ export declare class SequenceKpiRecorder { samples: SequenceKpiSample[]; constructor(); /** * Record one frame's KPI row. Unknown/extra fields are kept on the raw sample; only the metrics * in {@link SEQUENCE_KPI_METRICS} are aggregated. * * @param {Object} sample - Per-frame measurements (any subset of the KPI metrics, plus `frame`). * @returns {Object} The stored sample. */ record(sample: SequenceKpiSample): SequenceKpiSample; /** * Aggregate the recorded rows. * * @returns {Object} `{ frameCount, totalBytes, fps, metrics: { : { count,min,max,mean,median,p95 } } }`. */ summary(): SequenceKpiSummary; } /** * Benchmark a SplatSequence over its deterministic offline render path, recording one KPI row per * frame. Reads `splats.stats` for bytes/upload/draw counts and times each frame's wall-clock cost; * the caller's `measure` hook can attach GPU-only signals (PSNR, sort/raster GPU time). * * @param {SplatSequence} sequence - The sequence to play back. * @param {Object} options - Benchmark options. * @param {Object} options.renderer - The WebGPU renderer (or a deterministic stand-in for tests). * @param {Object} options.scene - The scene containing the sequence. * @param {Object} options.camera - The camera. * @param {Object} [options.range] - `{ start, end, step }` forwarded to `renderFrames`. * @param {SequenceKpiRecorder} [options.recorder] - Recorder to fill (a fresh one is created if omitted). * @param {Function} [options.measure] - `async ({ frame, splats, stats }) => extraFields` to enrich rows. * @param {Function} [options.now] - Clock returning milliseconds (defaults to performance.now); injectable for tests. * @returns {Promise} The recorder's `summary()`. */ export declare function benchmarkSplatSequence(sequence: SequenceKpiTarget, options?: BenchmarkSplatSequenceOptions): Promise;