From d84e80f539f98dc7de9d418f526dfae28d11384a Mon Sep 17 00:00:00 2001 From: RenaudRohlinger Date: Sun, 19 Apr 2026 15:08:53 +0900 Subject: [PATCH 1/2] Optimize compressed array texture layer updates --- .../webgpu/utils/WebGPUTextureUtils.js | 51 +++++++++++++++---- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/src/renderers/webgpu/utils/WebGPUTextureUtils.js b/src/renderers/webgpu/utils/WebGPUTextureUtils.js index cc452d9fefc9b3..1f070d17fb6a4f 100644 --- a/src/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/src/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -560,7 +560,17 @@ class WebGPUTextureUtils { } else if ( texture.isCompressedTexture || texture.isCompressedArrayTexture ) { - this._copyCompressedBufferToTexture( texture.mipmaps, textureData.texture, textureDescriptorGPU ); + if ( texture.isCompressedArrayTexture && texture.layerUpdates.size > 0 ) { + + this._copyCompressedBufferToTexture( texture.mipmaps, textureData.texture, textureDescriptorGPU, texture.layerUpdates ); + + texture.clearLayerUpdates(); + + } else { + + this._copyCompressedBufferToTexture( texture.mipmaps, textureData.texture, textureDescriptorGPU ); + + } } else if ( texture.isCubeTexture ) { @@ -914,8 +924,9 @@ class WebGPUTextureUtils { * @param {Array} mipmaps - An array with mipmap data. * @param {GPUTexture} textureGPU - The GPU texture. * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {?Set} [layerUpdates=null] - The layer indices to update. */ - _copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU ) { + _copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU, layerUpdates = null ) { // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() @@ -923,6 +934,7 @@ class WebGPUTextureUtils { const blockData = this._getBlockData( textureDescriptorGPU.format ); const isArrayTexture = textureDescriptorGPU.size.depthOrArrayLayers > 1; + const activeLayerUpdates = layerUpdates && layerUpdates.size > 0 ? layerUpdates : null; for ( let i = 0; i < mipmaps.length; i ++ ) { @@ -933,29 +945,50 @@ class WebGPUTextureUtils { const depth = isArrayTexture ? textureDescriptorGPU.size.depthOrArrayLayers : 1; const bytesPerRow = Math.ceil( width / blockData.width ) * blockData.byteLength; - const bytesPerImage = bytesPerRow * Math.ceil( height / blockData.height ); + const rowsPerImage = Math.ceil( height / blockData.height ); + const bytesPerImage = bytesPerRow * rowsPerImage; + const textureWidth = Math.ceil( width / blockData.width ) * blockData.width; + const textureHeight = rowsPerImage * blockData.height; - for ( let j = 0; j < depth; j ++ ) { + const writeTextureLayer = ( layerIndex ) => { device.queue.writeTexture( { texture: textureGPU, mipLevel: i, - origin: { x: 0, y: 0, z: j } + origin: { x: 0, y: 0, z: layerIndex } }, mipmap.data, { - offset: j * bytesPerImage, + offset: layerIndex * bytesPerImage, bytesPerRow, - rowsPerImage: Math.ceil( height / blockData.height ) + rowsPerImage }, { - width: Math.ceil( width / blockData.width ) * blockData.width, - height: Math.ceil( height / blockData.height ) * blockData.height, + width: textureWidth, + height: textureHeight, depthOrArrayLayers: 1 } ); + }; + + if ( activeLayerUpdates !== null ) { + + for ( const layerIndex of activeLayerUpdates ) { + + writeTextureLayer( layerIndex ); + + } + + } else { + + for ( let layerIndex = 0; layerIndex < depth; layerIndex ++ ) { + + writeTextureLayer( layerIndex ); + + } + } } From 132d2d0eb2eb0733c85785e858710e7a12530304 Mon Sep 17 00:00:00 2001 From: RenaudRohlinger Date: Sun, 19 Apr 2026 17:20:54 +0900 Subject: [PATCH 2/2] Move compressed texture layer writer to module scope --- .../webgpu/utils/WebGPUTextureUtils.js | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/renderers/webgpu/utils/WebGPUTextureUtils.js b/src/renderers/webgpu/utils/WebGPUTextureUtils.js index 1f070d17fb6a4f..0b093e98a94285 100644 --- a/src/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/src/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -35,6 +35,29 @@ const _compareToWebGPU = { const _flipMap = [ 0, 1, 3, 2, 4, 5 ]; +function writeTextureLayer( device, textureGPU, mipLevel, layerIndex, mipmap, bytesPerImage, bytesPerRow, rowsPerImage, textureWidth, textureHeight ) { + + device.queue.writeTexture( + { + texture: textureGPU, + mipLevel, + origin: { x: 0, y: 0, z: layerIndex } + }, + mipmap.data, + { + offset: layerIndex * bytesPerImage, + bytesPerRow, + rowsPerImage + }, + { + width: textureWidth, + height: textureHeight, + depthOrArrayLayers: 1 + } + ); + +} + /** * A WebGPU backend utility module for managing textures. * @@ -950,34 +973,11 @@ class WebGPUTextureUtils { const textureWidth = Math.ceil( width / blockData.width ) * blockData.width; const textureHeight = rowsPerImage * blockData.height; - const writeTextureLayer = ( layerIndex ) => { - - device.queue.writeTexture( - { - texture: textureGPU, - mipLevel: i, - origin: { x: 0, y: 0, z: layerIndex } - }, - mipmap.data, - { - offset: layerIndex * bytesPerImage, - bytesPerRow, - rowsPerImage - }, - { - width: textureWidth, - height: textureHeight, - depthOrArrayLayers: 1 - } - ); - - }; - if ( activeLayerUpdates !== null ) { for ( const layerIndex of activeLayerUpdates ) { - writeTextureLayer( layerIndex ); + writeTextureLayer( device, textureGPU, i, layerIndex, mipmap, bytesPerImage, bytesPerRow, rowsPerImage, textureWidth, textureHeight ); } @@ -985,7 +985,7 @@ class WebGPUTextureUtils { for ( let layerIndex = 0; layerIndex < depth; layerIndex ++ ) { - writeTextureLayer( layerIndex ); + writeTextureLayer( device, textureGPU, i, layerIndex, mipmap, bytesPerImage, bytesPerRow, rowsPerImage, textureWidth, textureHeight ); }