Explorar o código

WebGPUTextures: Upload texture in the same frame if possible and cleanup. (#25821)

* WebGPUTextures: Upload texture in the same frame if possible and cleanup.

* WebGPUTextures: cleanup
sunag %!s(int64=2) %!d(string=hai) anos
pai
achega
a899471b48
Modificáronse 1 ficheiros con 60 adicións e 34 borrados
  1. 60 34
      examples/jsm/renderers/webgpu/WebGPUTextures.js

+ 60 - 34
examples/jsm/renderers/webgpu/WebGPUTextures.js

@@ -383,7 +383,7 @@ class WebGPUTextures {
 
 
 		let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST;
 		let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST;
 
 
-		if ( needsMipmaps === true ) {
+		if ( needsMipmaps ) {
 
 
 			// current mipmap generation requires RENDER_ATTACHMENT
 			// current mipmap generation requires RENDER_ATTACHMENT
 
 
@@ -421,33 +421,23 @@ class WebGPUTextures {
 
 
 		if ( texture.isDataTexture || texture.isDataArrayTexture || texture.isData3DTexture ) {
 		if ( texture.isDataTexture || texture.isDataArrayTexture || texture.isData3DTexture ) {
 
 
-			this._copyBufferToTexture( image, format, textureGPU );
-
-			if ( needsMipmaps === true ) this._generateMipmaps( textureGPU, textureGPUDescriptor );
+			this._copyBufferToTexture( image, textureGPU, textureGPUDescriptor, needsMipmaps );
 
 
 		} else if ( texture.isCompressedTexture ) {
 		} else if ( texture.isCompressedTexture ) {
 
 
-			this._copyCompressedBufferToTexture( texture.mipmaps, format, textureGPU );
+			this._copyCompressedBufferToTexture( texture.mipmaps, textureGPU, textureGPUDescriptor );
 
 
 		} else if ( texture.isCubeTexture ) {
 		} else if ( texture.isCubeTexture ) {
 
 
 			if ( image.length === 6 ) {
 			if ( image.length === 6 ) {
 
 
-				this._copyCubeMapToTexture( image, format, texture, textureGPU, textureGPUDescriptor, needsMipmaps );
+				this._copyCubeMapToTexture( image, texture, textureGPU, textureGPUDescriptor, needsMipmaps );
 
 
 			}
 			}
 
 
 		} else if ( texture.isDepthTexture !== true && image !== null ) {
 		} else if ( texture.isDepthTexture !== true && image !== null ) {
 
 
-			// assume HTMLImageElement, HTMLCanvasElement or ImageBitmap
-
-			this._getImageBitmap( image, texture ).then( imageBitmap => {
-
-				this._copyExternalImageToTexture( imageBitmap, textureGPU );
-
-				if ( needsMipmaps === true ) this._generateMipmaps( textureGPU, textureGPUDescriptor );
-
-			} );
+			this._copyImageToTexture( image, texture, textureGPU, textureGPUDescriptor, needsMipmaps );
 
 
 		}
 		}
 
 
@@ -460,21 +450,21 @@ class WebGPUTextures {
 
 
 	}
 	}
 
 
-	_copyBufferToTexture( image, format, textureGPU, origin = { x: 0, y: 0, z: 0 } ) {
+	_copyBufferToTexture( image, textureGPU, textureGPUDescriptor, needsMipmaps, originDepth = 0 ) {
 
 
 		// @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
 		// @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
 		// @TODO: Consider to support valid buffer layouts with other formats like RGB
 		// @TODO: Consider to support valid buffer layouts with other formats like RGB
 
 
 		const data = image.data;
 		const data = image.data;
 
 
-		const bytesPerTexel = this._getBytesPerTexel( format );
+		const bytesPerTexel = this._getBytesPerTexel( textureGPUDescriptor.format );
 		const bytesPerRow = image.width * bytesPerTexel;
 		const bytesPerRow = image.width * bytesPerTexel;
 
 
 		this.device.queue.writeTexture(
 		this.device.queue.writeTexture(
 			{
 			{
 				texture: textureGPU,
 				texture: textureGPU,
 				mipLevel: 0,
 				mipLevel: 0,
-				origin
+				origin: { x: 0, y: 0, z: originDepth }
 			},
 			},
 			data,
 			data,
 			{
 			{
@@ -487,9 +477,11 @@ class WebGPUTextures {
 				depthOrArrayLayers: ( image.depth !== undefined ) ? image.depth : 1
 				depthOrArrayLayers: ( image.depth !== undefined ) ? image.depth : 1
 			} );
 			} );
 
 
+		if ( needsMipmaps === true ) this._generateMipmaps( textureGPU, textureGPUDescriptor, originDepth );
+
 	}
 	}
 
 
-	_copyCubeMapToTexture( images, format, texture, textureGPU, textureGPUDescriptor, needsMipmaps ) {
+	_copyCubeMapToTexture( images, texture, textureGPU, textureGPUDescriptor, needsMipmaps ) {
 
 
 		for ( let i = 0; i < 6; i ++ ) {
 		for ( let i = 0; i < 6; i ++ ) {
 
 
@@ -497,19 +489,11 @@ class WebGPUTextures {
 
 
 			if ( image.isDataTexture ) {
 			if ( image.isDataTexture ) {
 
 
-				this._copyBufferToTexture( image.image, format, textureGPU, { z: i } );
-
-				if ( needsMipmaps === true ) this._generateMipmaps( textureGPU, textureGPUDescriptor, i );
+				this._copyBufferToTexture( image.image, textureGPU, textureGPUDescriptor, needsMipmaps, i );
 
 
 			} else {
 			} else {
 
 
-				this._getImageBitmap( image, texture ).then( imageBitmap => {
-
-					this._copyExternalImageToTexture( imageBitmap, textureGPU, { z: i } );
-
-					if ( needsMipmaps === true ) this._generateMipmaps( textureGPU, textureGPUDescriptor, i );
-
-				} );
+				this._copyImageToTexture( image, texture, textureGPU, textureGPUDescriptor, needsMipmaps, i );
 
 
 			}
 			}
 
 
@@ -517,7 +501,7 @@ class WebGPUTextures {
 
 
 	}
 	}
 
 
-	_copyExternalImageToTexture( image, textureGPU, origin = { x: 0, y: 0, z: 0 } ) {
+	_copyExternalImageToTexture( image, textureGPU, textureGPUDescriptor, needsMipmaps, originDepth = 0 ) {
 
 
 		this.device.queue.copyExternalImageToTexture(
 		this.device.queue.copyExternalImageToTexture(
 			{
 			{
@@ -525,7 +509,7 @@ class WebGPUTextures {
 			}, {
 			}, {
 				texture: textureGPU,
 				texture: textureGPU,
 				mipLevel: 0,
 				mipLevel: 0,
-				origin
+				origin: { x: 0, y: 0, z: originDepth }
 			}, {
 			}, {
 				width: image.width,
 				width: image.width,
 				height: image.height,
 				height: image.height,
@@ -533,13 +517,15 @@ class WebGPUTextures {
 			}
 			}
 		);
 		);
 
 
+		if ( needsMipmaps ) this._generateMipmaps( textureGPU, textureGPUDescriptor, originDepth );
+
 	}
 	}
 
 
-	_copyCompressedBufferToTexture( mipmaps, format, textureGPU ) {
+	_copyCompressedBufferToTexture( mipmaps, textureGPU, textureGPUDescriptor ) {
 
 
 		// @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
 		// @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture()
 
 
-		const blockData = this._getBlockData( format );
+		const blockData = this._getBlockData( textureGPUDescriptor.format );
 
 
 		for ( let i = 0; i < mipmaps.length; i ++ ) {
 		for ( let i = 0; i < mipmaps.length; i ++ ) {
 
 
@@ -732,6 +718,46 @@ class WebGPUTextures {
 
 
 	}
 	}
 
 
+	_isHTMLImage( image ) {
+
+		return ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement );
+
+	}
+
+	_copyImageToTexture( image, texture, textureGPU, textureGPUDescriptor, needsMipmaps, originDepth ) {
+
+		if ( this._isHTMLImage( image ) ) {
+
+			this._getImageBitmapFromHTML( image, texture ).then( imageBitmap => {
+
+				this._copyExternalImageToTexture( imageBitmap, textureGPU, textureGPUDescriptor, needsMipmaps, originDepth );
+
+			} );
+
+		} else {
+
+			// assume ImageBitmap
+
+			this._copyExternalImageToTexture( image, textureGPU, textureGPUDescriptor, needsMipmaps, originDepth );
+
+		}
+
+	}
+
+	_getImageBitmapFromHTML( image, texture ) {
+
+		const width = image.width;
+		const height = image.height;
+
+		const options = {};
+
+		options.imageOrientation = ( texture.flipY === true ) ? 'flipY' : 'none';
+		options.premultiplyAlpha = ( texture.premultiplyAlpha === true ) ? 'premultiply' : 'default';
+
+		return createImageBitmap( image, 0, 0, width, height, options );
+
+	}
+
 	_getImageBitmap( image, texture ) {
 	_getImageBitmap( image, texture ) {
 
 
 		const width = image.width;
 		const width = image.width;
@@ -765,7 +791,7 @@ class WebGPUTextures {
 
 
 			mipLevelCount = texture.mipmaps.length;
 			mipLevelCount = texture.mipmaps.length;
 
 
-		} else if ( needsMipmaps === true ) {
+		} else if ( needsMipmaps ) {
 
 
 			mipLevelCount = Math.floor( Math.log2( Math.max( width, height ) ) ) + 1;
 			mipLevelCount = Math.floor( Math.log2( Math.max( width, height ) ) ) + 1;