Skip to content

Commit

Permalink
interface updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress committed Jun 10, 2024
1 parent d29fbe9 commit c49810a
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export type GPUAggregatorSettings = {
* `void getBin(out int binId)`: if dimensions=1
* `void getBin(out ivec2 binId)`: if dimensions=2
* And a shader function with one of the signatures
* `void getWeight(out float weight)`: if numChannels=1
* `void getWeight(out vec2 weight)`: if numChannels=2
* `void getWeight(out vec3 weight)`: if numChannels=3
* `void getValue(out float value)`: if numChannels=1
* `void getValue(out vec2 value)`: if numChannels=2
* `void getValue(out vec3 value)`: if numChannels=3
*/
vs: string;
/** Shader modules
Expand Down Expand Up @@ -132,11 +132,13 @@ export class GPUAggregator implements Aggregator {
const count = pixel[3];
const value: number[] = [];
for (let channel = 0; channel < this.numChannels; channel++) {
if (count === 0) {
const operation = this.props.operations[channel];
if (operation === 'COUNT') {
value[channel] = count;
} else if (count === 0) {
value[channel] = NaN;
} else {
value[channel] =
this.props.operations[channel] === 'MEAN' ? pixel[channel] / count : pixel[channel];
value[channel] = operation === 'MEAN' ? pixel[channel] / count : pixel[channel];
}
}
return {id, value, count};
Expand Down Expand Up @@ -222,11 +224,13 @@ export class GPUAggregator implements Aggregator {
}
}

update() {}

/** Run aggregation */
update(
preDraw(
/** Parameters only available at runtime */
opts: {
moduleSettings?: ModelProps['moduleSettings'];
moduleSettings: any;
}
) {
if (!this.needsUpdate.some(Boolean)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class WebGLAggregationTransform {
const target = this.domainFBO;

transform.model.setUniforms({
isCount: Array.from({length: 3}, (_, i) => (operations[i] === 'COUNT' ? 1 : 0)),
isMean: Array.from({length: 3}, (_, i) => (operations[i] === 'MEAN' ? 1 : 0))
});
transform.model.setBindings({bins});
Expand All @@ -117,6 +118,7 @@ function createTransform(device: Device, settings: GPUAggregatorSettings): Buffe
#define SHADER_NAME gpu-aggregation-domain-vertex
uniform ivec4 binIdRange;
uniform bvec3 isCount;
uniform bvec3 isMean;
uniform float naN;
uniform sampler2D bins;
Expand All @@ -136,10 +138,14 @@ out vec3 values;
#endif
void main() {
int row = gl_VertexID / SAMEPLER_WIDTH;
int col = gl_VertexID - row * SAMEPLER_WIDTH;
int row = gl_VertexID / SAMPLER_WIDTH;
int col = gl_VertexID - row * SAMPLER_WIDTH;
vec4 weights = texelFetch(bins, ivec2(col, row), 0);
vec3 value3 = mix(weights.rgb, weights.rgb / max(weights.a, 1.0), isMean);
vec3 value3 = mix(
mix(weights.rgb, vec3(weights.a), isCount),
weights.rgb / max(weights.a, 1.0),
isMean
);
if (weights.a == 0.0) {
value3 = vec3(naN);
}
Expand All @@ -162,6 +168,8 @@ void main() {
#endif
gl_Position = vec4(0., 0., 0., 1.);
// This model renders into a 2x1 texture to obtain min and max simultaneously.
// See comments in fragment shader
gl_PointSize = 2.0;
}
`;
Expand Down Expand Up @@ -222,7 +230,7 @@ void main() {
defines: {
NUM_DIMS: settings.dimensions,
NUM_CHANNELS: settings.numChannels,
SAMEPLER_WIDTH: TEXTURE_WIDTH
SAMPLER_WIDTH: TEXTURE_WIDTH
},
uniforms: {
// Passed in as uniform because 1) there is no GLSL symbol for NaN 2) any expression that exploits undefined behavior to produces NaN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {AggregationOperation} from '../aggregator';

const COLOR_CHANNELS = [0x1, 0x2, 0x4, 0x8]; // GPU color mask RED, GREEN, BLUE, ALPHA
const MAX_FLOAT32 = 3e38;
const EMPTY_MASKS = {SUM: 0, MEAN: 0, MIN: 0, MAX: 0};
const EMPTY_MASKS = {SUM: 0, MEAN: 0, MIN: 0, MAX: 0, COUNT: 0};

export const TEXTURE_WIDTH = 1024;

Expand All @@ -23,8 +23,8 @@ export class WebGLBinSorter {
* A packed texture in which each pixel represents a bin.
* The index of the pixel in the memory layout is the bin index.
* Alpha value is the count of data points that fall into this bin
* R,G,B values are the aggregated weights of each channel:
* - Sum of all data points if operation is 'SUM' or 'MEAN'
* R,G,B values are the aggregated values of each channel:
* - Sum of all data points if operation is 'SUM', or 'MEAN'
* - Min of all data points if operation is 'MIN'
* - Max of all data points if operation is 'MAX'
*/
Expand Down Expand Up @@ -202,7 +202,7 @@ uniform ivec2 targetSize;
${userVs}
out vec3 v_Weight;
out vec3 v_Value;
void main() {
int binIndex;
Expand All @@ -219,11 +219,11 @@ void main() {
gl_PointSize = 1.0;
#if NUM_CHANNELS == 3
getWeight(v_Weight);
getValue(v_Value);
#elif NUM_CHANNELS == 2
getWeight(v_Weight.xy);
getValue(v_Value.xy);
#else
getWeight(v_Weight.x);
getValue(v_Value.x);
#endif
}
`;
Expand All @@ -233,11 +233,11 @@ void main() {
precision highp float;
in vec3 v_Weight;
in vec3 v_Value;
out vec4 fragColor;
void main() {
fragColor.xyz = v_Weight;
fragColor.xyz = v_Value;
#ifdef MODULE_GEOMETRY
geometry.uv = vec2(0.);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ test('GPUAggregator#resources', t => {
void getBin(out int binId) {
binId = int(education);
}
void getWeight(out float weight) {
weight = income;
void getValue(out float value) {
value = income;
}
`
});

t.doesNotThrow(() => aggregator.update({}), 'Calling update() without setting props');
t.doesNotThrow(() => aggregator.update(), 'Calling update() without setting props');
t.notOk(aggregator.getResult(0));
t.notOk(aggregator.getBin(0));

Expand All @@ -52,15 +52,15 @@ test('GPUAggregator#resources', t => {
operations: ['MEAN']
});

aggregator.update({});
aggregator.update();
t.ok(aggregator.getResult(0));
t.ok(aggregator.getBin(0));

// Resize buffers
aggregator.setProps({
binIdRange: [[0, 15]]
});
aggregator.update({});
aggregator.update();
t.ok(aggregator.getResult(0));
t.ok(aggregator.getBin(0));

Expand Down Expand Up @@ -93,8 +93,8 @@ test('GPUAggregator#1D', t => {
void getBin(out int binId) {
binId = int(floor(age / ageGroupSize));
}
void getWeight(out vec3 weight) {
weight = vec3(1.0, income, education);
void getValue(out vec3 value) {
value = vec3(1.0, income, education);
}
`
});
Expand All @@ -121,7 +121,8 @@ test('GPUAggregator#1D', t => {
binOptions: {ageGroupSize: 5}
});

aggregator.update({});
aggregator.update();
aggregator.preDraw({moduleSettings: {}});

t.is(aggregator.numBins, 15, 'numBins');

Expand Down Expand Up @@ -191,8 +192,8 @@ test('GPUAggregator#2D', t => {
binId.x = int(floor(age / ageGroupSize));
binId.y = int(education);
}
void getWeight(out vec2 weight) {
weight = vec2(1.0, income);
void getValue(out vec2 value) {
value = vec2(5.0, income);
}
`
});
Expand All @@ -218,11 +219,12 @@ test('GPUAggregator#2D', t => {
[1, 6]
], // age: 20..59, education: 1..5
attributes,
operations: ['SUM', 'MEAN'],
operations: ['COUNT', 'MEAN'],
binOptions: {ageGroupSize: 10}
});

aggregator.update({});
aggregator.update();
aggregator.preDraw({moduleSettings: {}});

t.is(aggregator.numBins, 20, 'numBins');

Expand Down Expand Up @@ -260,7 +262,7 @@ test('GPUAggregator#2D', t => {
t.deepEqual(aggregator.getResultDomain(1), [10, 320], 'getResultDomain() - mean income');

// Empty bin
t.deepEqual(aggregator.getBin(0), {id: [2, 1], count: 0, value: [NaN, NaN]}, 'getBin() - empty');
t.deepEqual(aggregator.getBin(0), {id: [2, 1], count: 0, value: [0, NaN]}, 'getBin() - empty');
// {age: 40, household: 4, income: 140, education: 4},
// {age: 44, household: 4, income: 500, education: 4},
t.deepEqual(aggregator.getBin(14), {id: [4, 4], count: 2, value: [2, 320]}, 'getBin()');
Expand Down

0 comments on commit c49810a

Please sign in to comment.