Skip to content

Commit 6cf71c1

Browse files
committed
temp - testing SPIR-V codegen fix
1 parent 2678ab3 commit 6cf71c1

File tree

2 files changed

+87
-53
lines changed

2 files changed

+87
-53
lines changed

src/nbody.ts

Lines changed: 81 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { mat4, vec3 } from 'gl-matrix'
2-
import shaders from './shaders.wgsl'
1+
import { mat4, vec3 } from "gl-matrix";
2+
import shaders from "./shaders.wgsl";
33

44
// Simulation parameters.
55
let numBodies;
@@ -26,25 +26,26 @@ let positionsOut: GPUBuffer = null;
2626
let velocities: GPUBuffer = null;
2727
let renderParams: GPUBuffer = null;
2828
let computeBindGroup: GPUBindGroup = null;
29+
let othergroup: GPUBindGroup = null;
2930
let renderBindGroup: GPUBindGroup = null;
3031

3132
const init = async () => {
3233
// Initialize the WebGPU device.
33-
const powerPref = <HTMLSelectElement>document.getElementById('powerpref');
34+
const powerPref = <HTMLSelectElement>document.getElementById("powerpref");
3435
const adapter = await navigator.gpu.requestAdapter({
3536
powerPreference: <GPUPowerPreference>powerPref.selectedOptions[0].value,
3637
});
37-
device = await adapter.requestDevice()
38+
device = await adapter.requestDevice();
3839
queue = device.queue;
3940

4041
// Set up the canvas context.
41-
canvas = <HTMLCanvasElement>document.getElementById('canvas');
42-
canvasContext = canvas.getContext('webgpu');
43-
}
42+
canvas = <HTMLCanvasElement>document.getElementById("canvas");
43+
canvasContext = canvas.getContext("webgpu");
44+
};
4445

4546
// Generate WGSL shader source.
4647
function getShaders() {
47-
let preamble = ''
48+
let preamble = "";
4849
preamble += `const kWorkgroupSize = ${workgroupSize};\n`;
4950
preamble += `const kNumBodies = ${numBodies};\n`;
5051
return preamble + shaders;
@@ -69,8 +70,7 @@ const updateRenderParams = async () => {
6970
// Generate the view projection matrix.
7071
let projectionMatrix = mat4.create();
7172
let viewProjectionMatrix = mat4.create();
72-
mat4.perspectiveZO(projectionMatrix,
73-
1.0, canvas.width / canvas.height, 0.1, 50.0);
73+
mat4.perspectiveZO(projectionMatrix, 1.0, canvas.width / canvas.height, 0.1, 50.0);
7474
mat4.translate(viewProjectionMatrix, viewProjectionMatrix, eyePosition);
7575
mat4.multiply(viewProjectionMatrix, projectionMatrix, viewProjectionMatrix);
7676

@@ -79,7 +79,7 @@ const updateRenderParams = async () => {
7979
let viewProjectionMatrixHost = new Float32Array(renderParamsHost);
8080
viewProjectionMatrixHost.set(viewProjectionMatrix);
8181
queue.writeBuffer(renderParams, 0, renderParamsHost);
82-
}
82+
};
8383

8484
function initPipelines() {
8585
// Reset pipelines.
@@ -104,42 +104,44 @@ function initPipelines() {
104104
const positionsAttribute: GPUVertexAttribute = {
105105
shaderLocation: 0,
106106
offset: 0,
107-
format: 'float32x4',
107+
format: "float32x4",
108108
};
109109
const positionsLayout: GPUVertexBufferLayout = {
110110
attributes: [positionsAttribute],
111111
arrayStride: 4 * 4,
112-
stepMode: 'instance',
112+
stepMode: "instance",
113113
};
114114
renderPipeline = device.createRenderPipeline({
115115
vertex: {
116116
module: module,
117-
entryPoint: 'vs_main',
117+
entryPoint: "vs_main",
118118
buffers: [positionsLayout],
119119
},
120120
fragment: {
121121
module: module,
122-
entryPoint: 'fs_main',
123-
targets: [{
124-
format: navigator.gpu.getPreferredCanvasFormat(),
125-
blend: {
126-
color: {
127-
operation: "add",
128-
srcFactor: "one",
129-
dstFactor: "one",
130-
},
131-
alpha: {
132-
operation: "add",
133-
srcFactor: "one",
134-
dstFactor: "one",
122+
entryPoint: "fs_main",
123+
targets: [
124+
{
125+
format: navigator.gpu.getPreferredCanvasFormat(),
126+
blend: {
127+
color: {
128+
operation: "add",
129+
srcFactor: "one",
130+
dstFactor: "one",
131+
},
132+
alpha: {
133+
operation: "add",
134+
srcFactor: "one",
135+
dstFactor: "one",
136+
},
135137
},
136-
}
137-
}],
138+
},
139+
],
138140
},
139141
primitive: {
140-
frontFace: 'cw',
141-
cullMode: 'none',
142-
topology: 'triangle-list',
142+
frontFace: "cw",
143+
cullMode: "none",
144+
topology: "triangle-list",
143145
},
144146
layout: "auto",
145147
});
@@ -148,9 +150,9 @@ function initPipelines() {
148150
computePipeline = device.createComputePipeline({
149151
compute: {
150152
module: module,
151-
entryPoint: 'cs_main',
153+
entryPoint: "cs_main",
152154
},
153-
layout: "auto"
155+
layout: "auto",
154156
});
155157
}
156158

@@ -159,25 +161,25 @@ function initBodies() {
159161
positionsIn = device.createBuffer({
160162
size: numBodies * 4 * 4,
161163
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX,
162-
mappedAtCreation: true
164+
mappedAtCreation: true,
163165
});
164166
positionsOut = device.createBuffer({
165167
size: numBodies * 4 * 4,
166168
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX,
167-
mappedAtCreation: false
169+
mappedAtCreation: false,
168170
});
169171
velocities = device.createBuffer({
170172
size: numBodies * 4 * 4,
171173
usage: GPUBufferUsage.STORAGE,
172-
mappedAtCreation: false
174+
mappedAtCreation: false,
173175
});
174176

175177
// Generate initial positions on the surface of a sphere.
176178
const kRadius = 0.6;
177179
let positions = new Float32Array(positionsIn.getMappedRange());
178180
for (let i = 0; i < numBodies; i++) {
179181
let longitude = 2.0 * Math.PI * Math.random();
180-
let latitude = Math.acos((2.0 * Math.random() - 1.0));
182+
let latitude = Math.acos(2.0 * Math.random() - 1.0);
181183
positions[i * 4 + 0] = kRadius * Math.sin(latitude) * Math.cos(longitude);
182184
positions[i * 4 + 1] = kRadius * Math.sin(latitude) * Math.sin(longitude);
183185
positions[i * 4 + 2] = kRadius * Math.cos(latitude);
@@ -203,7 +205,7 @@ function draw() {
203205
const timeSinceLastLog = now - lastFpsUpdateTime;
204206
if (timeSinceLastLog >= kFpsUpdateInterval) {
205207
const fps = numFramesSinceFpsUpdate / (timeSinceLastLog / 1000.0);
206-
document.getElementById("fps").innerHTML = fps.toFixed(1) + ' FPS';
208+
document.getElementById("fps").innerHTML = fps.toFixed(1) + " FPS";
207209
lastFpsUpdateTime = performance.now();
208210
numFramesSinceFpsUpdate = 0;
209211
}
@@ -215,9 +217,9 @@ function draw() {
215217
// Update render parameters based on key presses.
216218
if (currentKey) {
217219
let zInc = 0.025;
218-
if (currentKey.key == 'ArrowUp') {
220+
if (currentKey.key == "ArrowUp") {
219221
eyePosition[2] += zInc;
220-
} else if (currentKey.key == 'ArrowDown') {
222+
} else if (currentKey.key == "ArrowDown") {
221223
eyePosition[2] -= zInc;
222224
}
223225
updateRenderParams();
@@ -250,6 +252,31 @@ function draw() {
250252
],
251253
});
252254

255+
let image_a = device.createTexture({
256+
format: "r32uint",
257+
size: [16, 16],
258+
usage: GPUTextureUsage.STORAGE_BINDING,
259+
});
260+
let image_b = device.createTexture({
261+
format: "r32uint",
262+
size: [16, 16],
263+
usage: GPUTextureUsage.STORAGE_BINDING,
264+
});
265+
266+
othergroup = device.createBindGroup({
267+
layout: computePipeline.getBindGroupLayout(1),
268+
entries: [
269+
{
270+
binding: 0,
271+
resource: image_a.createView(),
272+
},
273+
{
274+
binding: 1,
275+
resource: image_b.createView(),
276+
},
277+
],
278+
});
279+
253280
// Create the bind group for the compute shader.
254281
renderBindGroup = device.createBindGroup({
255282
layout: renderPipeline.getBindGroupLayout(0),
@@ -268,6 +295,7 @@ function draw() {
268295
const computePassEncoder = commandEncoder.beginComputePass();
269296
computePassEncoder.setPipeline(computePipeline);
270297
computePassEncoder.setBindGroup(0, computeBindGroup);
298+
computePassEncoder.setBindGroup(1, othergroup);
271299
computePassEncoder.dispatchWorkgroups(numBodies / workgroupSize);
272300
computePassEncoder.end();
273301

@@ -282,7 +310,7 @@ function draw() {
282310
view: colorTextureView,
283311
loadOp: "clear",
284312
clearValue: { r: 0, g: 0, b: 0.1, a: 1 },
285-
storeOp: 'store'
313+
storeOp: "store",
286314
};
287315
const renderPassEncoder = commandEncoder.beginRenderPass({
288316
colorAttachments: [colorAttachment],
@@ -317,43 +345,43 @@ const reset = async () => {
317345
initPipelines();
318346

319347
paused = false;
320-
}
348+
};
321349

322350
function pause() {
323351
paused = !paused;
324-
document.getElementById("pause").innerText = paused ? 'Unpause' : 'Pause';
352+
document.getElementById("pause").innerText = paused ? "Unpause" : "Pause";
325353
}
326354

327355
reset();
328356
draw();
329357

330358
// Set up button onclick handlers.
331-
document.querySelector('#reset').addEventListener('click', reset);
332-
document.querySelector('#pause').addEventListener('click', pause);
359+
document.querySelector("#reset").addEventListener("click", reset);
360+
document.querySelector("#pause").addEventListener("click", pause);
333361

334362
// Automatically reset when the number of bodies is changed.
335-
document.querySelector('#numbodies').addEventListener('change', reset);
363+
document.querySelector("#numbodies").addEventListener("change", reset);
336364

337365
// Automatically reset when the power preference is changed.
338-
document.querySelector('#powerpref').addEventListener('change', () => {
366+
document.querySelector("#powerpref").addEventListener("change", () => {
339367
device = null;
340368
computePipeline = null;
341369
reset();
342370
});
343371

344372
// Automatically rebuild the pipelines when the workgroup size is changed.
345-
document.querySelector('#wgsize').addEventListener('change', initPipelines);
373+
document.querySelector("#wgsize").addEventListener("change", initPipelines);
346374

347375
// Add an event handler to update render parameters when the window is resized.
348-
window.addEventListener('resize', updateRenderParams);
376+
window.addEventListener("resize", updateRenderParams);
349377

350378
// Handle key presses for user controls.
351-
document.addEventListener('keydown', (e: KeyboardEvent) => {
352-
if (e.key == ' ') {
379+
document.addEventListener("keydown", (e: KeyboardEvent) => {
380+
if (e.key == " ") {
353381
pause();
354382
}
355383
currentKey = e;
356384
});
357-
document.addEventListener('keyup', (e: KeyboardEvent) => {
385+
document.addEventListener("keyup", (e: KeyboardEvent) => {
358386
currentKey = null;
359387
});

src/shaders.wgsl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ fn computeForce(ipos : vec4<f32>,
2121
return coeff * d;
2222
}
2323

24+
@group(1) @binding(0) var image_a: texture_storage_2d<r32uint,read>;
25+
@group(1) @binding(1) var image_b: texture_storage_2d<r32uint,write>;
26+
2427
@compute @workgroup_size(kWorkgroupSize)
2528
fn cs_main(
2629
@builtin(global_invocation_id) gid : vec3<u32>,
@@ -39,6 +42,9 @@ fn cs_main(
3942
velocity = velocity + force * kDelta;
4043
velocities[idx] = velocity;
4144

45+
_ = image_a;
46+
_ = image_b;
47+
4248
// Update position.
4349
positionsOut[idx] = pos + velocity * kDelta;
4450
}

0 commit comments

Comments
 (0)