From 6591d2536ea3db6d829c46389785024ec599502b Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 23 Mar 2026 21:08:50 +0100 Subject: [PATCH 1/3] Renderers: Cache pixel storage parameters. (#33227) --- ...webgl_materials_texture_partialupdate.html | 1 + examples/webgpu_textures_partialupdate.html | 1 + examples/webxr_vr_layers.html | 6 +-- src/renderers/WebGLRenderer.js | 38 +++++++------- .../webgl-fallback/utils/WebGLState.js | 43 ++++++++++++++- .../webgl-fallback/utils/WebGLTextureUtils.js | 52 ++++++++++--------- src/renderers/webgl/WebGLState.js | 43 +++++++++++++++ src/renderers/webgl/WebGLTextures.js | 34 ++++++------ 8 files changed, 153 insertions(+), 65 deletions(-) diff --git a/examples/webgl_materials_texture_partialupdate.html b/examples/webgl_materials_texture_partialupdate.html index 8d4b460dbe4f7b..95a01302dcf5fc 100644 --- a/examples/webgl_materials_texture_partialupdate.html +++ b/examples/webgl_materials_texture_partialupdate.html @@ -63,6 +63,7 @@ const data = new Uint8Array( width * height * 4 ); dataTexture = new THREE.DataTexture( data, width, height ); + dataTexture.colorSpace = THREE.SRGBColorSpace; // diff --git a/examples/webgpu_textures_partialupdate.html b/examples/webgpu_textures_partialupdate.html index 6abbea9ee70caf..c16b5a2d316401 100644 --- a/examples/webgpu_textures_partialupdate.html +++ b/examples/webgpu_textures_partialupdate.html @@ -72,6 +72,7 @@ const data = new Uint8Array( width * height * 4 ); dataTexture = new THREE.DataTexture( data, width, height ); + dataTexture.colorSpace = THREE.SRGBColorSpace; // diff --git a/examples/webxr_vr_layers.html b/examples/webxr_vr_layers.html index 15f5436a9f5671..5350080d89aa8d 100644 --- a/examples/webxr_vr_layers.html +++ b/examples/webxr_vr_layers.html @@ -401,7 +401,7 @@ const glayer = xr.getBinding().getSubImage( quadLayerPlain, frame ); renderer.state.bindTexture( gl.TEXTURE_2D, glayer.colorTexture ); - gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true ); + renderer.state.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true ); gl.texSubImage2D( gl.TEXTURE_2D, 0, ( snellenConfig.textureSizePx - snellenConfig.widthPx ) / 2, ( snellenConfig.textureSizePx - snellenConfig.heightPx ) / 2, @@ -415,7 +415,7 @@ const glayer = xr.getBinding().getSubImage( quadLayerMips, frame ); renderer.state.bindTexture( gl.TEXTURE_2D, glayer.colorTexture ); - gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true ); + renderer.state.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true ); gl.texSubImage2D( gl.TEXTURE_2D, 0, ( snellenConfig.textureSizePx - snellenConfig.widthPx ) / 2, ( snellenConfig.textureSizePx - snellenConfig.heightPx ) / 2, @@ -430,7 +430,7 @@ const glayer = xr.getBinding().getSubImage( guiLayer, frame ); renderer.state.bindTexture( gl.TEXTURE_2D, glayer.colorTexture ); - gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true ); + renderer.state.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true ); const canvas = guiMesh.material.map.image; gl.texSubImage2D( gl.TEXTURE_2D, 0, 0, 0, canvas.width, canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, canvas ); guiLayer.needsUpdate = false; diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 34f879df657140..ace8ecfbce2554 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -3289,22 +3289,22 @@ class WebGLRenderer { state.activeTexture( _gl.TEXTURE0 ); // see #33153 - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + 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 = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); - const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); - const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); - const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); - const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ ); + 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; @@ -3430,11 +3430,11 @@ class WebGLRenderer { } // reset values - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); + state.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + state.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + state.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + state.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); // Generate mipmaps only when copying level 0 if ( dstLevel === 0 && dstTexture.generateMipmaps ) { diff --git a/src/renderers/webgl-fallback/utils/WebGLState.js b/src/renderers/webgl-fallback/utils/WebGLState.js index c6afd06ec05365..adf1eae5944f91 100644 --- a/src/renderers/webgl-fallback/utils/WebGLState.js +++ b/src/renderers/webgl-fallback/utils/WebGLState.js @@ -50,6 +50,7 @@ class WebGLState { // documented for convenience reasons. this.enabled = {}; + this.parameters = {}; this.currentFlipSided = null; this.currentCullFace = null; this.currentProgram = null; @@ -1291,7 +1292,6 @@ class WebGLState { } - /** * Unbinds the current bound texture. * @@ -1315,6 +1315,47 @@ class WebGLState { } + /** + * Returns the value for the given parameter. + * + * @param {number} name - The paramter to get the value for. + * @return {any} The value for the given parameter. + */ + getParameter( name ) { + + const { gl, parameters } = this; + + if ( parameters[ name ] !== undefined ) { + + return parameters[ name ]; + + } else { + + return gl.getParameter( name ); + + } + + } + + /** + * Specifies a pixel storage mode. + * + * @param {number} name - The parameter to set. + * @param {any} value - A value to set the parameter to. + */ + pixelStorei( name, value ) { + + const { gl, parameters } = this; + + if ( parameters[ name ] !== value ) { + + gl.pixelStorei( name, value ); + parameters[ name ] = value; + + } + + } + } export default WebGLState; diff --git a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js index b3f356e79841f4..5fbf87aeedee4a 100644 --- a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +++ b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js @@ -320,15 +320,16 @@ class WebGLTextureUtils { setTextureParameters( textureType, texture ) { const { gl, extensions, backend } = this; + const { state } = this.backend; const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? gl.NONE : gl.BROWSER_DEFAULT_WEBGL; - gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); - gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); - gl.pixelStorei( gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); - gl.pixelStorei( gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); + state.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + state.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); + state.pixelStorei( gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); + state.pixelStorei( gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); gl.texParameteri( textureType, gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); gl.texParameteri( textureType, gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); @@ -470,6 +471,7 @@ class WebGLTextureUtils { copyBufferToTexture( buffer, texture ) { const { gl, backend } = this; + const { state } = backend; const { textureGPU, glTextureType, glFormat, glType } = backend.get( texture ); @@ -479,8 +481,8 @@ class WebGLTextureUtils { backend.state.bindTexture( glTextureType, textureGPU ); - gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false ); - gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false ); + state.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false ); + state.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false ); gl.texSubImage2D( glTextureType, 0, 0, 0, width, height, glFormat, glType, 0 ); gl.bindBuffer( gl.PIXEL_UNPACK_BUFFER, null ); @@ -832,22 +834,22 @@ class WebGLTextureUtils { } - gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + 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 = gl.getParameter( gl.UNPACK_ROW_LENGTH ); - const currentUnpackImageHeight = gl.getParameter( gl.UNPACK_IMAGE_HEIGHT ); - const currentUnpackSkipPixels = gl.getParameter( gl.UNPACK_SKIP_PIXELS ); - const currentUnpackSkipRows = gl.getParameter( gl.UNPACK_SKIP_ROWS ); - const currentUnpackSkipImages = gl.getParameter( gl.UNPACK_SKIP_IMAGES ); - - gl.pixelStorei( gl.UNPACK_ROW_LENGTH, image.width ); - gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, image.height ); - gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, minX ); - gl.pixelStorei( gl.UNPACK_SKIP_ROWS, minY ); - gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, minZ ); + 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 || dstTexture.isArrayTexture; @@ -981,11 +983,11 @@ class WebGLTextureUtils { } // reset values - gl.pixelStorei( gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); - gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); - gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); - gl.pixelStorei( gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); - gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); + state.pixelStorei( gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + state.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + state.pixelStorei( gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + state.pixelStorei( gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + state.pixelStorei( gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); // Generate mipmaps only when copying level 0 if ( dstLevel === 0 && dstTexture.generateMipmaps ) { diff --git a/src/renderers/webgl/WebGLState.js b/src/renderers/webgl/WebGLState.js index f36f0bbd8d99d0..12b39b301a422e 100644 --- a/src/renderers/webgl/WebGLState.js +++ b/src/renderers/webgl/WebGLState.js @@ -353,6 +353,7 @@ function WebGLState( gl, extensions ) { const uboProgramMap = new WeakMap(); let enabledCapabilities = {}; + let parameters = {}; let currentBoundFramebuffers = {}; let currentDrawbuffers = new WeakMap(); @@ -1112,6 +1113,31 @@ function WebGLState( gl, extensions ) { } + function getParameter( name ) { + + if ( parameters[ name ] !== undefined ) { + + return parameters[ name ]; + + } else { + + return gl.getParameter( name ); + + } + + } + + function pixelStorei( name, value ) { + + if ( parameters[ name ] !== value ) { + + gl.pixelStorei( name, value ); + parameters[ name ] = value; + + } + + } + // function scissor( scissor ) { @@ -1228,9 +1254,24 @@ function WebGLState( gl, extensions ) { gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); + gl.pixelStorei( gl.PACK_ALIGNMENT, 4 ); + gl.pixelStorei( gl.UNPACK_ALIGNMENT, 4 ); + gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false ); + gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false ); + gl.pixelStorei( gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.BROWSER_DEFAULT_WEBGL ); + gl.pixelStorei( gl.PACK_ROW_LENGTH, 0 ); + gl.pixelStorei( gl.PACK_SKIP_PIXELS, 0 ); + gl.pixelStorei( gl.PACK_SKIP_ROWS, 0 ); + gl.pixelStorei( gl.UNPACK_ROW_LENGTH, 0 ); + gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, 0 ); + gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, 0 ); + gl.pixelStorei( gl.UNPACK_SKIP_ROWS, 0 ); + gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, 0 ); + // reset internals enabledCapabilities = {}; + parameters = {}; currentTextureSlot = null; currentBoundTextures = {}; @@ -1304,6 +1345,8 @@ function WebGLState( gl, extensions ) { compressedTexImage3D: compressedTexImage3D, texImage2D: texImage2D, texImage3D: texImage3D, + pixelStorei: pixelStorei, + getParameter: getParameter, updateUBOMapping: updateUBOMapping, uniformBlockBinding: uniformBlockBinding, diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index e243ce3fd53cd2..fe7975b0d920f9 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -831,11 +831,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Trim the array to only contain the merged ranges. updateRanges.length = mergeIndex + 1; - const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); - const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); - const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const currentUnpackRowLen = state.getParameter( _gl.UNPACK_ROW_LENGTH ); + const currentUnpackSkipPixels = state.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = state.getParameter( _gl.UNPACK_SKIP_ROWS ); - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + state.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { @@ -851,8 +851,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const width = pixelCount; const height = 1; - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, x ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, y ); + state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, x ); + state.pixelStorei( _gl.UNPACK_SKIP_ROWS, y ); state.texSubImage2D( _gl.TEXTURE_2D, 0, x, y, width, height, glFormat, glType, image.data ); @@ -860,9 +860,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, texture.clearUpdateRanges(); - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + state.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + state.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + state.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); } @@ -894,13 +894,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); + state.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + state.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); + state.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); } - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); + state.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); let image = resizeImage( texture.image, false, capabilities.maxTextureSize ); image = verifyColorSpace( texture, image ); @@ -1328,10 +1328,10 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); - _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); + state.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + state.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); + state.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); + state.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); From 48301423ccfa37e09540972a71e7d6bff922103f Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Mon, 23 Mar 2026 21:24:31 +0100 Subject: [PATCH 2/3] Update NodeManager.js Fix typo. --- src/renderers/common/nodes/NodeManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderers/common/nodes/NodeManager.js b/src/renderers/common/nodes/NodeManager.js index 0881e2621075cc..9dc307093fb121 100644 --- a/src/renderers/common/nodes/NodeManager.js +++ b/src/renderers/common/nodes/NodeManager.js @@ -952,7 +952,7 @@ class NodeManager extends DataMap { /** * Triggers the call of `update()` methods - * for all nodes of the given compute node. + * for all nodes of the given render object. * * @param {RenderObject} renderObject - The render object. */ From 207740de065cf99a55930b2d24fe98206c15a392 Mon Sep 17 00:00:00 2001 From: sunag Date: Mon, 23 Mar 2026 19:39:04 -0300 Subject: [PATCH 3/3] WGSLNodeBuilder: Fix varying indexes (#33229) --- src/renderers/webgpu/nodes/WGSLNodeBuilder.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index d33cc95138c082..9aadc494186446 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -1807,13 +1807,15 @@ ${ flowData.code } const varyings = this.varyings; const vars = this.vars[ shaderStage ]; + let varyingIndex = 0; + for ( let index = 0; index < varyings.length; index ++ ) { const varying = varyings[ index ]; if ( varying.needsInterpolation ) { - let attributesSnippet = `@location( ${index} )`; + let attributesSnippet = `@location( ${ varyingIndex ++ } )`; if ( varying.interpolationType ) { @@ -2124,7 +2126,7 @@ ${ flowData.code } } else { - let structSnippet = '\t@location(0) color: vec4'; + let structSnippet = '\t@location( 0 ) color: vec4'; const builtins = this.getBuiltins( 'output' );