<!-- SOLIDIVISM · part 493 -->
deleteBuffer( glBuffer );
					_gl.deleteSync( sync );

					return buffer;

				} else {

					throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.' );

				}

			}

		};

		/**
		 * Copies pixels from the current bound framebuffer into the given texture.
		 *
		 * @param {FramebufferTexture} texture - The texture.
		 * @param {?Vector2} [position=null] - The start position of the copy operation.
		 * @param {number} [level=0] - The mip level. The default represents the base mip.
		 */
		this.copyFramebufferToTexture = function ( texture, position = null, level = 0 ) {

			const levelScale = Math.pow( 2, - level );
			const width = Math.floor( texture.image.width * levelScale );
			const height = Math.floor( texture.image.height * levelScale );

			const x = position !== null ? position.x : 0;
			const y = position !== null ? position.y : 0;

			textures.setTexture2D( texture, 0 );

			_gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, x, y, width, height );

			state.unbindTexture();

		};


		/**
		 * Copies data of the given source texture into a destination texture.
		 *
		 * When using render target textures as `srcTexture` and `dstTexture`, you must make sure both render targets are initialized
		 * {@link WebGLRenderer#initRenderTarget}.
		 *
		 * @param {Texture} srcTexture - The source texture.
		 * @param {Texture} dstTexture - The destination texture.
		 * @param {?(Box2|Box3)} [srcRegion=null] - A bounding box which describes the source region. Can be two or three-dimensional.
		 * @param {?(Vector2|Vector3)} [dstPosition=null] - A vector that represents the origin of the destination region. Can be two or three-dimensional.
		 * @param {number} [srcLevel=0] - The source mipmap level to copy.
		 * @param {?number} [dstLevel=0] - The destination mipmap level.
		 */
		this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {

			// gather the necessary dimensions to copy
			let width, height, depth, minX, minY, minZ;
			let dstX, dstY, dstZ;
			const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ dstLevel ] : srcTexture.image;
			if ( srcRegion !== null ) {

				width = srcRegion.max.x - srcRegion.min.x;
				height = srcRegion.max.y - srcRegion.min.y;
				depth = srcRegion.isBox3 ? srcRegion.max.z - srcRegion.min.z : 1;
				minX = srcRegion.min.x;
				minY = srcRegion.min.y;
				minZ = srcRegion.isBox3 ? srcRegion.min.z : 0;

			} else {

				const levelScale = Math.pow( 2, - srcLevel );
				width = Math.floor( image.width * levelScale );
				height = Math.floor( image.height * levelScale );
				if ( srcTexture.isDataArrayTexture ) {

					depth = image.depth;

				} else if ( srcTexture.isData3DTexture ) {

					depth = Math.floor( image.depth * levelScale );

				} else {

					depth = 1;

				}

				minX = 0;
				minY = 0;
				minZ = 0;

			}

			if ( dstPosition !== null ) {

				dstX = dstPosition.x;
				dstY = dstPosition.y;
				dstZ = dstPosition.z;

			} else {

				dstX = 0;
				dstY = 0;
				dstZ = 0;

			}

			// Set up the destination target
			const glFormat = utils.convert( dstTexture.format );
			const glType = utils.convert( dstTexture.type );
			let glTarget;

			if ( dstTexture.isData3DTexture ) {

				textures.setTexture3D( dstTexture, 0 );
				glTarget = _gl.TEXTURE_3D;

			} else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) {

				textures.setTexture2DArray( dstTexture, 0 );
				glTarget = _gl.TEXTURE_2D_ARRAY;

			} else {

				textures.setTexture2D( dstTexture, 0 );
				glTarget = _gl.TEXTURE_2D;

			}

			state.activeTexture( _gl.TEXTURE0 ); // see #33153

			state.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
			state.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
			state.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );

			// used for copying data from cpu
			const currentUnpackRowLen = state.getParameter( _gl.UNPACK_ROW_LENGTH );
			const currentUnpackImageHeight = state.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
			const currentUnpackSkipPixels = state.getParameter( _gl.UNPACK_SKIP_PIXELS );
			const currentUnpackSkipRows = state.getParameter( _gl.UNPACK_SKIP_ROWS );
			const currentUnpackSkipImages = state.getParameter( _gl.UNPACK_SKIP_IMAGES );

			state.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
			state.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
			state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
			state.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
			state.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ );

			// set up the src texture
			const isSrc3D = srcTexture.isDataArrayTexture || srcTexture.isData3DTexture;
			const isDst3D = dstTexture.isDataArrayTexture || dstTexture.isData3DTexture;
			if ( srcTexture.isDepthTexture ) {

				const srcTextureProperties = properties.get( srcTexture