Skip to content

Commit 0495650

Browse files
committed
tweaks
1 parent 0ca514e commit 0495650

3 files changed

Lines changed: 27 additions & 20 deletions

File tree

‎sample/packedIntegerDotProduct/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
color-scheme: light dark;
1010
}
1111
body {
12-
min-height: 100vh;
12+
min-height: 20em;
1313
}
1414
pre {
1515
white-space: pre-wrap;

‎sample/packedIntegerDotProduct/main.ts‎

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,17 @@ const kSampleCases = [
88
{ lhs: [1, 2, 3, 4], rhs: [4, 3, 2, 1] },
99
] as const;
1010

11-
const kWorkgroupSize = 64; // Same as in packed.wgsl
11+
const kWorkgroupSize = 64; // Must match packed.wgsl
12+
13+
type vec4i = readonly [number, number, number, number];
14+
// Pack four signed 8-bit components into a u32, low byte first.
15+
function pack4xI8([x, y, z, w]: vec4i): number {
16+
// `&` operator applies sign extension to i32 before operating.
17+
// `>>> 0` converts the final i32 to u32.
18+
return (
19+
(x & 0xff) | ((y & 0xff) << 8) | ((z & 0xff) << 16) | ((w & 0xff) << 24)
20+
) >>> 0;
21+
}
1222

1323
const result = document.querySelector('#result') as HTMLElement;
1424
if (
@@ -23,20 +33,8 @@ if (
2333
const device = await adapter?.requestDevice();
2434
quitIfWebGPUNotAvailableOrMissingFeatures(adapter, device);
2535

26-
function createInputBuffer(
27-
vectors: ReadonlyArray<readonly [number, number, number, number]>
28-
) {
29-
// Pack four signed 8-bit components into each u32, low byte first.
30-
// Masking preserves the two's-complement representation of negative values.
31-
const packed = new Uint32Array(
32-
vectors.map(
33-
([x, y, z, w]) =>
34-
(x & 0xff) |
35-
((y & 0xff) << 8) |
36-
((z & 0xff) << 16) |
37-
((w & 0xff) << 24)
38-
)
39-
);
36+
function createInputBuffer(vectors: vec4i[]) {
37+
const packed = new Uint32Array(vectors.map(pack4xI8));
4038
const buffer = device.createBuffer({
4139
size: packed.byteLength,
4240
usage: GPUBufferUsage.STORAGE,
@@ -85,15 +83,24 @@ if (
8583
readbackBuffer.unmap();
8684

8785
for (const [i, sample] of kSampleCases.entries()) {
86+
// Result should be the same in JS, show that for comparison.
8887
const expected =
8988
sample.lhs[0] * sample.rhs[0] +
9089
sample.lhs[1] * sample.rhs[1] +
9190
sample.lhs[2] * sample.rhs[2] +
9291
sample.lhs[3] * sample.rhs[3];
93-
const lhs = sample.lhs.map((x) => x.toString().padStart(4)).join(', ');
94-
const rhs = sample.rhs.map((x) => x.toString().padStart(4)).join(', ');
92+
93+
const lhs = `[${sample.lhs
94+
.map((x) => x.toString().padStart(4))
95+
.join(', ')}] (0x${pack4xI8(sample.lhs).toString(16).padStart(8, '0')})`;
96+
const rhs = `[${sample.rhs
97+
.map((x) => x.toString().padStart(4))
98+
.join(', ')}] (0x${pack4xI8(sample.rhs).toString(16).padStart(8, '0')})`;
9599
const out = results[i].toString().padStart(6);
96100
const exp = expected.toString().padStart(6);
97-
result.textContent += `\ndot4I8Packed of [${lhs}] by [${rhs}] gave ${out} (expecting ${exp})`;
101+
result.textContent += `
102+
103+
WGSL dot4I8Packed of ${lhs}
104+
by ${rhs} gave ${out} (JS gave ${exp})`;
98105
}
99106
}

‎sample/packedIntegerDotProduct/packed.wgsl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ struct Case { lhs: u32, rhs: u32 }
55
@group(0) @binding(0) var<storage, read> input: array<Case>;
66
@group(0) @binding(1) var<storage, read_write> output: array<i32>;
77

8-
const kWorkgroupSize: u32 = 64; // Same as in main.ts
8+
const kWorkgroupSize: u32 = 64; // Must match main.ts
99

1010
@compute @workgroup_size(kWorkgroupSize)
1111
fn main(@builtin(global_invocation_id) id: vec3<u32>) {

0 commit comments

Comments
 (0)