@@ -51,6 +51,8 @@ function rendererWebGPU(p5, fn) {
5151 this . uniformBufferAlignment = 256 ;
5252 this . activeUniformBuffers = [ ] ;
5353 this . currentUniformBuffer = undefined ;
54+ this . uniformBufferPool = [ ] ;
55+ this . resettingUniformBuffers = [ ] ;
5456
5557 // Cache for current frame's canvas texture view
5658 this . currentCanvasColorTexture = null ;
@@ -660,7 +662,11 @@ function rendererWebGPU(p5, fn) {
660662
661663 shader . _groupEntries = groupEntries ;
662664 shader . _bindGroupLayouts = [ ...bindGroupLayouts . values ( ) ] ;
665+ // Reuse bind groups if they don't change
663666 shader . _cachedBindGroup = { } ;
667+ // Remember which dynamic buffer we last used, so that we can
668+ // possibly cache bind groups if unchanged
669+ shader . _lastDynamicBuffer = { } ;
664670 shader . _pipelineLayout = this . device . createPipelineLayout ( {
665671 bindGroupLayouts : shader . _bindGroupLayouts ,
666672 } ) ;
@@ -1194,6 +1200,9 @@ function rendererWebGPU(p5, fn) {
11941200 ) {
11951201 // We can fit this next block of uniforms into the current active memory chunk
11961202 buffer = this . currentUniformBuffer ;
1203+ } else if ( this . uniformBufferPool . length > 0 ) {
1204+ buffer = this . uniformBufferPool . pop ( ) ;
1205+ this . activeUniformBuffers . push ( buffer ) ;
11971206 } else {
11981207 // Kinda arbitrary. Each dynamic offset has to be in groups of 256, but then
11991208 // we can choose how many things we want to be able to fit into a block.
@@ -1208,10 +1217,14 @@ function rendererWebGPU(p5, fn) {
12081217 offset : 0 ,
12091218 size,
12101219 buffer : this . device . createBuffer ( {
1211- size : size ,
1212- usage : GPUBufferUsage . UNIFORM ,
1220+ size,
1221+ usage : GPUBufferUsage . MAP_WRITE | GPUBufferUsage . COPY_SRC ,
12131222 mappedAtCreation : true ,
12141223 } ) ,
1224+ uniformBuffer : this . device . createBuffer ( {
1225+ size,
1226+ usage : GPUBufferUsage . UNIFORM | GPUBufferUsage . COPY_DST ,
1227+ } ) ,
12151228 }
12161229
12171230 buffer . data = new Float32Array ( buffer . buffer . getMappedRange ( ) ) ;
@@ -1239,10 +1252,14 @@ function rendererWebGPU(p5, fn) {
12391252 bufferGroup . bufferPool . push ( bufferGroup . nextBufferPool . pop ( ) ) ;
12401253 }
12411254 for ( const bufferInfo of bufferGroup . buffersInUse . keys ( ) ) {
1242- bufferGroup . nextBufferPool . push ( bufferInfo ) ;
1255+ if ( bufferInfo !== bufferGroup . currentBuffer ) {
1256+ bufferGroup . nextBufferPool . push ( bufferInfo ) ;
1257+ }
12431258 }
1244- bufferGroup . currentBuffer = null ;
12451259 bufferGroup . buffersInUse . clear ( ) ;
1260+ if ( bufferGroup . currentBuffer ) {
1261+ bufferGroup . buffersInUse . add ( bufferGroup . currentBuffer ) ;
1262+ }
12461263 }
12471264 }
12481265 }
@@ -1256,13 +1273,37 @@ function rendererWebGPU(p5, fn) {
12561273 this . _pendingCommandEncoders = [ ] ;
12571274 this . _hasPendingDraws = false ;
12581275
1259- for ( const bufferInfo of this . activeUniformBuffers ) {
1260- bufferInfo . buffer . unmap ( ) ;
1276+ if ( this . activeUniformBuffers . length > 0 ) {
1277+ const encoder = this . device . createCommandEncoder ( ) ;
1278+ for ( const bufferInfo of this . activeUniformBuffers ) {
1279+ bufferInfo . buffer . unmap ( ) ;
1280+ encoder . copyBufferToBuffer (
1281+ bufferInfo . buffer ,
1282+ bufferInfo . uniformBuffer ,
1283+ ) ;
1284+ }
1285+ commandsToSubmit . unshift ( encoder . finish ( ) ) ;
12611286 }
12621287
12631288 // Submit the commands
12641289 this . queue . submit ( commandsToSubmit ) ;
12651290
1291+ for ( const buf of this . activeUniformBuffers ) {
1292+ // buf.buffer = this.device.createBuffer({
1293+ // size: buf.size,
1294+ // usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC,
1295+ // mappedAtCreation: true,
1296+ // });
1297+ buf . offset = 0 ;
1298+ buf . lastOffset = 0 ;
1299+ this . resettingUniformBuffers . push (
1300+ buf . buffer . mapAsync ( GPUMapMode . WRITE ) . then ( ( ) => {
1301+ buf . data = new Float32Array ( buf . buffer . getMappedRange ( ) ) ;
1302+ buf . dataView = new DataView ( buf . data . buffer ) ;
1303+ return buf ;
1304+ } )
1305+ )
1306+ }
12661307 this . activeUniformBuffers = [ ] ;
12671308 this . currentUniformBuffer = undefined ;
12681309
@@ -1339,6 +1380,9 @@ function rendererWebGPU(p5, fn) {
13391380 this . _markGeometryBuffersForReturn ( geometry ) ;
13401381 }
13411382
1383+ this . uniformBufferPool . push ( ...( await Promise . all ( this . resettingUniformBuffers ) ) ) ;
1384+ this . resettingUniformBuffers = [ ] ;
1385+
13421386 // Return all vertex buffers to their pools
13431387 this . _returnVertexBuffersToPool ( ) ;
13441388
@@ -1409,13 +1453,16 @@ function rendererWebGPU(p5, fn) {
14091453 // Bind uniforms into a part of a big dynamic memory block because
14101454 // the group changes often
14111455 const uniformBufferInfo = this . _getDynamicUniformBufferFromPool ( bufferGroup ) ;
1456+ if ( currentShader . _lastDynamicBuffer [ bufferGroup . cacheKey ] !== uniformBufferInfo ) {
1457+ currentShader . _cachedBindGroup [ bufferGroup . group ] = undefined ;
1458+ currentShader . _lastDynamicBuffer [ bufferGroup . cacheKey ] = uniformBufferInfo ;
1459+ }
14121460 this . _packUniformGroup ( currentShader , bufferGroup . uniforms , uniformBufferInfo ) ;
14131461 uniformBufferInfo . lastOffset = uniformBufferInfo . offset ;
14141462 uniformBufferInfo . offset += Math . ceil ( bufferGroup . size / this . uniformBufferAlignment ) * this . uniformBufferAlignment ;
14151463
14161464 // Make a shallow copy so that we keep track of the last offset for this uniform
14171465 this . _uniformBuffersForBinding . set ( bufferGroup . cacheKey , { ...uniformBufferInfo } ) ;
1418- currentShader . _cachedBindGroup [ bufferGroup . group ] = undefined ;
14191466 } else {
14201467 // Bind uniforms to a binding-specific buffer, which may be cached for performance
14211468 let bufferInfo ;
@@ -1453,20 +1500,27 @@ function rendererWebGPU(p5, fn) {
14531500 for ( const [ group , entries ] of currentShader . _groupEntries ) {
14541501 const bgEntries = entries . map ( entry => {
14551502 // Check if this is a uniform buffer binding
1456- const uniformBufferInfo = this . _uniformBuffersForBinding . get ( group + ',' + entry . binding ) ;
1503+ const uniformBufferInfo = entry . bufferGroup &&
1504+ this . _uniformBuffersForBinding . get ( entry . bufferGroup . cacheKey ) ;
14571505 if ( uniformBufferInfo && entry . bufferGroup ) {
14581506 return {
14591507 binding : entry . binding ,
14601508 resource : entry . bufferGroup . dynamic
14611509 ? {
1462- buffer : uniformBufferInfo . buffer ,
1510+ buffer : uniformBufferInfo . uniformBuffer ,
14631511 offset : 0 ,
14641512 size : Math . ceil ( entry . bufferGroup . size / this . uniformBufferAlignment ) * this . uniformBufferAlignment ,
14651513 }
14661514 : { buffer : uniformBufferInfo . buffer } ,
14671515 } ;
14681516 }
14691517
1518+ const key = entry . uniform . group + ',' + entry . uniform . binding ;
1519+ if ( currentShader . buffersDirty [ key ] ) {
1520+ currentShader . _cachedBindGroup [ group ] = undefined ;
1521+ currentShader . buffersDirty [ key ] = false ;
1522+ }
1523+
14701524 return {
14711525 binding : entry . binding ,
14721526 resource : entry . uniform . type === 'sampler'
@@ -1483,13 +1537,11 @@ function rendererWebGPU(p5, fn) {
14831537 entries : bgEntries ,
14841538 } ) ;
14851539 }
1540+ currentShader . _cachedBindGroup [ group ] = bindGroup ;
14861541 const dynamicEntryOffsets = entries
14871542 . map ( e => e . bufferGroup && this . _uniformBuffersForBinding . get ( e . bufferGroup . cacheKey ) )
14881543 . filter ( b => b ?. dynamic )
14891544 . map ( b => b . lastOffset ) ;
1490- if ( dynamicEntryOffsets . length === 0 ) {
1491- currentShader . _cachedBindGroup [ group ] = bindGroup ;
1492- }
14931545 passEncoder . setBindGroup (
14941546 group ,
14951547 bindGroup ,
@@ -1821,10 +1873,9 @@ function rendererWebGPU(p5, fn) {
18211873 if ( uniform . isSampler ) {
18221874 uniform . texture =
18231875 data instanceof Texture ? data : this . getTexture ( data ) ;
1824- } else {
1825- shader . buffersDirty = shader . buffersDirty || { } ;
1826- shader . buffersDirty [ uniform . group + ',' + uniform . binding ] = true ;
18271876 }
1877+ shader . buffersDirty = shader . buffersDirty || { } ;
1878+ shader . buffersDirty [ uniform . group + ',' + uniform . binding ] = true ;
18281879 }
18291880
18301881 _updateTexture ( uniform , tex ) {
0 commit comments