WGSL supports packed data; instead of sending vec4f32 (16 bytes) we can send a single u32 (4 bytes) for our vertex attributes:
struct VertexInput {
@builtin(vertex_index) vertexIndex: u32,
@builtin(instance_index) instanceIndex: u32,
};
struct VertexOutput {
@builtin(position) position: vec4f,
@location(0) color: vec4f,
};
// vertex attributes are packed
struct VertexSSBO {
position: u32,
color: u32,
};
// per-instance data can also be packed,
// but here I left it as vec4f
struct TransformSSBO {
offset: vec4f,
};
@group(0) @binding(0) var<storage, read> transforms: array<TransformSSBO>;
@group(0) @binding(1) var<storage, read> vertices: array<VertexSSBO>;
@vertex
fn vertex_main(input: VertexInput) -> VertexOutput {
var vertexPos = unpack4x8snorm(vertices[input.vertexIndex].position);
var vertexColor = unpack4x8snorm(vertices[input.vertexIndex].color);
var output: VertexOutput;
output.position = vertexPos + transforms[input.instanceIndex].offset;
output.color = vertexColor;
return output;
}
We can define a simple function that can pack vec4<f32> values to u32 values:
function packVec4F32ToU32(x: number,
y: number,
z: number,
w: number): number {
x = Math.round((Math.max(-1.0, Math.min(1.0, x)) * 127.0) & 0xFF);
y = Math.round((Math.max(-1.0, Math.min(1.0, y)) * 127.0) & 0xFF);
z = Math.round((Math.max(-1.0, Math.min(1.0, z)) * 127.0) & 0xFF);
w = Math.round((Math.max(-1.0, Math.min(1.0, w)) * 127.0) & 0xFF);
return (x << 0 |
y << 8 |
z << 16 |
w << 24) >>> 0;
}
What do you think?
WGSL supports packed data; instead of sending vec4f32 (16 bytes) we can send a single u32 (4 bytes) for our vertex attributes:
We can define a simple function that can pack
vec4<f32>values tou32values:What do you think?