@@ -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
4848async 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}
0 commit comments