Skip to content

Commit be0f4f2

Browse files
committed
more setup
1 parent 2e2d403 commit be0f4f2

File tree

2 files changed

+84
-17
lines changed

2 files changed

+84
-17
lines changed

src/pages/particle-life-gpu/index.tsx

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function ParticleLifeGPUPage() {
2626
canvas.height = window.innerHeight * devicePixelRatio
2727

2828
const frameCounter = makeFrameCounter(60)
29-
start(controller.signal, canvas, (dt) => setFps(Math.round(frameCounter(dt / 1000))))
29+
start(controller, canvas, (dt) => setFps(Math.round(frameCounter(dt / 1000))))
3030

3131
return () => {
3232
controller.abort()
@@ -46,37 +46,40 @@ export default function ParticleLifeGPUPage() {
4646
}
4747

4848
async function start(
49-
signal: AbortSignal,
49+
controller: AbortController,
5050
canvas: HTMLCanvasElement,
5151
onFrame: (dt: number) => void,
5252
) {
5353
const adapter = await navigator.gpu.requestAdapter({ powerPreference: 'high-performance' })
5454
if (!adapter) throw new Error('No GPU adapter found')
55-
if (signal.aborted) return
55+
if (controller.signal.aborted) return
5656

5757
const device = await adapter.requestDevice()
5858
if (!device) throw new Error('No GPU device found')
59-
if (signal.aborted) return
60-
signal.addEventListener('abort', () => device.destroy(), { once: true })
59+
if (controller.signal.aborted) return
60+
controller.signal.addEventListener('abort', () => device.destroy(), { once: true })
61+
device.lost.then((info) => info.reason !== 'destroyed' && controller.abort())
62+
if (canvas.width > device.limits.maxTextureDimension2D || canvas.height > device.limits.maxTextureDimension2D)
63+
throw new Error(`Canvas size exceeds device limits: ${canvas.width}x${canvas.height} > ${device.limits.maxTextureDimension2D}`)
6164

6265
const ctx = canvas.getContext('webgpu')!
6366
if (!ctx) throw new Error('No WebGPU context found')
6467
const format = navigator.gpu.getPreferredCanvasFormat()
6568
ctx.configure({ device, format, alphaMode: 'opaque' })
66-
signal.addEventListener('abort', () => ctx.unconfigure(), { once: true })
69+
controller.signal.addEventListener('abort', () => ctx.unconfigure(), { once: true })
6770

68-
const module = device.createShaderModule({ code: shader, label: 'our hardcoded red triangle shaders' })
71+
const renderModule = device.createShaderModule({ code: shader, label: 'our hardcoded red triangle shaders' })
6972

70-
const pipeline = device.createRenderPipeline({
73+
const renderPipeline = device.createRenderPipeline({
7174
label: 'our hardcoded red triangle pipeline',
7275
layout: 'auto',
7376
vertex: {
7477
entryPoint: 'vs',
75-
module,
78+
module: renderModule,
7679
},
7780
fragment: {
7881
entryPoint: 'fs',
79-
module,
82+
module: renderModule,
8083
targets: [{ format }],
8184
},
8285
})
@@ -102,7 +105,7 @@ async function start(
102105

103106
const encoder = device.createCommandEncoder({ label: 'our encoder' })
104107
const pass = encoder.beginRenderPass(renderPassDescriptor)
105-
pass.setPipeline(pipeline)
108+
pass.setPipeline(renderPipeline)
106109
pass.draw(3)
107110
pass.end()
108111

@@ -112,15 +115,79 @@ async function start(
112115

113116
let lastTime = performance.now()
114117
let rafId = requestAnimationFrame(function frame(time) {
115-
if (signal.aborted) return
118+
if (controller.signal.aborted) return
116119
rafId = requestAnimationFrame(frame)
117120
const dt = time - lastTime
118121
lastTime = time
119122
onFrame(dt)
120123
render()
121124
})
122-
signal.addEventListener('abort', () => cancelAnimationFrame(rafId), { once: true })
125+
controller.signal.addEventListener('abort', () => cancelAnimationFrame(rafId), { once: true })
123126

124-
const width = ctx.canvas.width
125-
const height = ctx.canvas.height
127+
// const width = ctx.canvas.width
128+
// const height = ctx.canvas.height
129+
130+
const computeModule = device.createShaderModule({
131+
label: 'doubling compute module',
132+
code: compute,
133+
})
134+
135+
const computePipeline = device.createComputePipeline({
136+
label: 'doubling compute pipeline',
137+
layout: 'auto',
138+
compute: {
139+
module: computeModule,
140+
},
141+
})
142+
143+
const input = new Float32Array([1, 3, 5])
144+
const workBuffer = device.createBuffer({
145+
label: 'work buffer',
146+
size: input.byteLength,
147+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
148+
})
149+
device.queue.writeBuffer(workBuffer, 0, input)
150+
controller.signal.addEventListener('abort', () => workBuffer.destroy(), { once: true })
151+
152+
const resultBuffer = device.createBuffer({
153+
label: 'result buffer',
154+
size: input.byteLength,
155+
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
156+
})
157+
controller.signal.addEventListener('abort', () => resultBuffer.destroy(), { once: true })
158+
159+
const bindGroup = device.createBindGroup({
160+
label: 'bindGroup for work buffer',
161+
layout: computePipeline.getBindGroupLayout(0),
162+
entries: [
163+
{ binding: 0, resource: { buffer: workBuffer } },
164+
],
165+
})
166+
167+
exec: {
168+
const encoder = device.createCommandEncoder({
169+
label: 'doubling encoder',
170+
})
171+
172+
const pass = encoder.beginComputePass({
173+
label: 'doubling compute pass',
174+
})
175+
pass.setPipeline(computePipeline)
176+
pass.setBindGroup(0, bindGroup)
177+
pass.dispatchWorkgroups(input.length)
178+
pass.end()
179+
180+
encoder.copyBufferToBuffer(workBuffer, 0, resultBuffer, 0, resultBuffer.size)
181+
182+
const commandBuffer = encoder.finish()
183+
device.queue.submit([commandBuffer])
184+
}
185+
186+
await resultBuffer.mapAsync(GPUMapMode.READ)
187+
const result = new Float32Array(resultBuffer.getMappedRange())
188+
189+
console.log('input', input)
190+
console.log('result', result)
191+
192+
resultBuffer.unmap()
126193
}

src/router.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ export const ROUTES = {
234234
tags: ['simulation', 'webgpu', 'particles', 'wip'],
235235
},
236236
git: {
237-
lastModified: 0,
238-
firstAdded: 0
237+
lastModified: 1762551884000,
238+
firstAdded: 1762551884000
239239
},
240240
},
241241
"particle-life": {

0 commit comments

Comments
 (0)