GPUGridAggregation
Overview
GPUGridAggregation computes sum, minimum, maximum, or mean statistics for paired float32
weights in a row-major two-dimensional grid. It is the weighted counterpart to GPUGridBinning:
binning answers “how many points are in each cell?”, while aggregation describes their values.
Concepts
Every input row contains a position and one weight. The bounds and grid dimensions map the
position to a cell, then operation chooses the statistic. Non-finite or out-of-bounds positions
and non-finite weights are ignored. Exact maximum coordinates enter the final column or row.
When to use it
Grid aggregation answers spatial questions where every point carries a measurement. Examples include mean temperature per map cell, total bytes transferred per screen tile, maximum particle speed in a simulation region, and minimum elevation in a terrain overview. The fixed grid produces a compact texture-like summary that can drive heatmaps, labels, or a later compute decision.
Use GPUGridBinning for population or occupancy alone. Use
GPUGroupAggregation when rows already carry categorical IDs rather
than continuous positions, and use a spatial index when the application needs the individual
objects in a queried region instead of one statistic per cell.
'sum' is the default. Sum and mean use an atomic compare/exchange addition, so ordinary
float32 rounding applies but cross-invocation accumulation order is not promised. Finite inputs
may overflow a sum or mean to infinity, or produce NaN after opposite-sign overflow. Mean owns one
transient uint32 count per cell and divides after all aligned chunks have contributed; total
input length must therefore fit in uint32.
Minimum and maximum encode each finite float as a monotonically ordered uint32 and use native
integer atomics. This makes their value independent of invocation order and preserves the expected
signed-zero order: minimum prefers -0, maximum prefers +0.
Empty sum cells contain positive zero. Empty minimum, maximum, and mean cells contain a canonical quiet NaN, making “no accepted rows” distinct from a real zero-valued statistic.
For vectors, positions and weights must have identical ordered chunk lengths. Each encoding clears the output once, then accumulates non-empty chunk pairs without concatenating or repacking either input. This keeps table batches aligned while producing one grid-wide result.
Usage
new GPUGridAggregation({
positions,
weights: temperatures,
output: cellTemperatureMeans,
operation: 'mean',
gridSize: [32, 16],
bounds: [-180, -90, 180, 90]
}).addToGraph(graph);
Constructor
type GPUGridAggregationProps = {
id?: string;
positions: GraphDataView<'float32x2'> | GraphVectorView<'float32x2'>;
weights: GraphDataView<'float32'> | GraphVectorView<'float32'>;
output: GraphDataView<'float32'>;
operation?: 'sum' | 'min' | 'max' | 'mean';
gridSize: readonly [number, number];
bounds: readonly [number, number, number, number] | GraphDataView<'float32x4'>;
};
output.length must equal width * height. Inputs and output are caller-owned and must use
separate output storage. The graph owns no persistent result buffer, performs no submission, and
does not read the sums back.
Counts remain independently available from GPUGridBinning when an
application needs both population and value statistics. Irregular spatial bins,
higher-dimensional aggregates, variance, and custom associative operations remain future work.