|
33 | 33 |
|
34 | 34 | import * as THREE from 'three/webgpu'; |
35 | 35 |
|
36 | | - import { Fn, If, Return, instancedArray, instanceIndex, uniform, attribute, uint, float, clamp, struct, atomicStore, int, ivec3, array, vec3, atomicAdd, Loop, atomicLoad, max, pow, mat3, vec4, cross, step } from 'three/tsl'; |
| 36 | + import { Fn, If, Return, instancedArray, instanceIndex, uniform, attribute, uint, float, clamp, struct, atomicStore, int, ivec3, array, vec3, atomicAdd, Loop, atomicLoad, max, pow, mat3, vec4, cross, step, storage } from 'three/tsl'; |
37 | 37 |
|
38 | 38 | import { Inspector } from 'three/addons/inspector/Inspector.js'; |
39 | 39 |
|
|
48 | 48 |
|
49 | 49 | const maxParticles = 8192 * 16; |
50 | 50 | const gridSize1d = 64; |
| 51 | + const workgroupSize = 64; |
51 | 52 | const gridSize = new THREE.Vector3( gridSize1d, gridSize1d, gridSize1d ); |
52 | 53 | const fixedPointMultiplier = 1e7; |
53 | 54 |
|
54 | 55 | let particleCountUniform, stiffnessUniform, restDensityUniform, dynamicViscosityUniform, dtUniform, gravityUniform, gridSizeUniform; |
55 | 56 | let particleBuffer, cellBuffer, cellBufferFloat; |
56 | | - let clearGridKernel, p2g1Kernel, p2g2Kernel, updateGridKernel, g2pKernel; |
| 57 | + let clearGridKernel, p2g1Kernel, p2g2Kernel, updateGridKernel, g2pKernel, workgroupKernel; |
| 58 | + let p2g1KernelWorkgroupBuffer, p2g2KernelWorkgroupBuffer, g2pKernelWorkgroupBuffer; |
57 | 59 | let particleMesh; |
58 | 60 | const mouseCoord = new THREE.Vector3(); |
59 | 61 | const prevMouseCoord = new THREE.Vector3(); |
|
105 | 107 | setupParticles(); |
106 | 108 |
|
107 | 109 | const gui = renderer.inspector.createParameters( 'Settings' ); |
| 110 | + |
| 111 | + const numWorkgroups = Math.ceil( params.particleCount / workgroupSize ); |
| 112 | + |
| 113 | + p2g1KernelWorkgroupBuffer = new THREE.IndirectStorageBufferAttribute( new Uint32Array( [ numWorkgroups, 1, 1 ] ), 1 ); |
| 114 | + p2g2KernelWorkgroupBuffer = new THREE.IndirectStorageBufferAttribute( new Uint32Array( [ numWorkgroups, 1, 1 ] ), 1 ); |
| 115 | + g2pKernelWorkgroupBuffer = new THREE.IndirectStorageBufferAttribute( new Uint32Array( [ numWorkgroups, 1, 1 ] ), 1 ); |
| 116 | + |
| 117 | + const p2g1WorkgroupStorage = storage( p2g1KernelWorkgroupBuffer, 'uint', 3 ); |
| 118 | + const p2g2WorkgroupStorage = storage( p2g2KernelWorkgroupBuffer, 'uint', 3 ); |
| 119 | + const g2pWorkgroupStorage = storage( g2pKernelWorkgroupBuffer, 'uint', 3 ); |
| 120 | + |
| 121 | + workgroupKernel = Fn( () => { |
| 122 | + |
| 123 | + const workgroupsToDispatch = ( particleCountUniform.sub( 1 ) ).div( workgroupSize ).add( 1 ); |
| 124 | + |
| 125 | + p2g1WorkgroupStorage.element( 0 ).assign( workgroupsToDispatch ); |
| 126 | + p2g2WorkgroupStorage.element( 0 ).assign( workgroupsToDispatch ); |
| 127 | + g2pWorkgroupStorage.element( 0 ).assign( workgroupsToDispatch ); |
| 128 | + |
| 129 | + } )().compute( 1 ); |
108 | 130 |
|
109 | 131 | gui.add( params, 'particleCount', 4096, maxParticles, 4096 ).onChange( value => { |
110 | 132 |
|
111 | | - p2g1Kernel.count = value; |
112 | | - p2g2Kernel.count = value; |
113 | | - g2pKernel.count = value; |
114 | 133 | particleMesh.count = value; |
115 | 134 | particleCountUniform.value = value; |
116 | 135 |
|
|
258 | 277 |
|
259 | 278 | } ); |
260 | 279 |
|
261 | | - } )().compute( params.particleCount ).setName( 'p2g1Kernel' ); |
| 280 | + } )().compute( params.particleCount, [ workgroupSize, 1, 1 ] ).setName( 'p2g1Kernel' ); |
262 | 281 |
|
263 | 282 | p2g2Kernel = Fn( () => { |
264 | 283 |
|
|
329 | 348 |
|
330 | 349 | } ); |
331 | 350 |
|
332 | | - } )().compute( params.particleCount ).setName( 'p2g2Kernel' ); |
| 351 | + } )().compute( params.particleCount, [ workgroupSize, 1, 1 ] ).setName( 'p2g2Kernel' ); |
333 | 352 |
|
334 | 353 | updateGridKernel = Fn( () => { |
335 | 354 |
|
|
477 | 496 | particleBuffer.element( instanceIndex ).get( 'position' ).assign( particlePosition ); |
478 | 497 | particleBuffer.element( instanceIndex ).get( 'velocity' ).assign( particleVelocity ); |
479 | 498 |
|
480 | | - } )().compute( params.particleCount ).setName( 'g2pKernel' ); |
| 499 | + } )().compute( params.particleCount, [ workgroupSize, 1, 1 ] ).setName( 'g2pKernel' ); |
481 | 500 |
|
482 | 501 | } |
483 | 502 |
|
|
561 | 580 |
|
562 | 581 | prevMouseCoord.copy( mouseCoord ); |
563 | 582 |
|
| 583 | + renderer.compute( workgroupKernel ); |
| 584 | + |
564 | 585 | //renderer.compute( [ clearGridKernel, p2g1Kernel, p2g2Kernel, updateGridKernel, g2pKernel ] ); |
565 | 586 | renderer.compute( clearGridKernel ); |
566 | | - renderer.compute( p2g1Kernel ); |
567 | | - renderer.compute( p2g2Kernel ); |
| 587 | + renderer.compute( p2g1Kernel, p2g1KernelWorkgroupBuffer ); |
| 588 | + renderer.compute( p2g2Kernel, p2g2KernelWorkgroupBuffer ); |
568 | 589 | renderer.compute( updateGridKernel ); |
569 | | - renderer.compute( g2pKernel ); |
| 590 | + renderer.compute( g2pKernel, g2pKernelWorkgroupBuffer ); |
570 | 591 |
|
571 | 592 | renderer.render( scene, camera ); |
572 | 593 |
|
|
0 commit comments