Просмотр исходного кода

WebGLUniformsGroups: Optimize UBO updates to avoid GC churn. (#33704)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mrdoob 3 недель назад
Родитель
Сommit
a40eb17a0c
1 измененных файлов с 66 добавлено и 38 удалено
  1. 66 38
      src/renderers/webgl/WebGLUniformsGroups.js

+ 66 - 38
src/renderers/webgl/WebGLUniformsGroups.js

@@ -98,73 +98,101 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) {
 
 		for ( let i = 0, il = uniforms.length; i < il; i ++ ) {
 
-			const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ];
+			const uniformItem = uniforms[ i ];
 
-			for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) {
+			if ( Array.isArray( uniformItem ) ) {
 
-				const uniform = uniformArray[ j ];
+				for ( let j = 0, jl = uniformItem.length; j < jl; j ++ ) {
 
-				if ( hasUniformChanged( uniform, i, j, cache ) === true ) {
+					updateUniform( uniformItem[ j ], i, j, cache );
 
-					const offset = uniform.__offset;
+				}
 
-					const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
+			} else {
 
-					let arrayOffset = 0;
+				updateUniform( uniformItem, i, 0, cache );
 
-					for ( let k = 0; k < values.length; k ++ ) {
+			}
 
-						const value = values[ k ];
+		}
 
-						const info = getUniformSize( value );
+		gl.bindBuffer( gl.UNIFORM_BUFFER, null );
 
-						// TODO add integer and struct support
-						if ( typeof value === 'number' || typeof value === 'boolean' ) {
+	}
 
-							uniform.__data[ 0 ] = value;
-							gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data );
+	function updateUniform( uniform, index, indexArray, cache ) {
 
-						} else if ( value.isMatrix3 ) {
+		if ( hasUniformChanged( uniform, index, indexArray, cache ) === true ) {
 
-							// manually converting 3x3 to 3x4
+			const offset = uniform.__offset;
+			const value = uniform.value;
 
-							uniform.__data[ 0 ] = value.elements[ 0 ];
-							uniform.__data[ 1 ] = value.elements[ 1 ];
-							uniform.__data[ 2 ] = value.elements[ 2 ];
-							uniform.__data[ 3 ] = 0;
-							uniform.__data[ 4 ] = value.elements[ 3 ];
-							uniform.__data[ 5 ] = value.elements[ 4 ];
-							uniform.__data[ 6 ] = value.elements[ 5 ];
-							uniform.__data[ 7 ] = 0;
-							uniform.__data[ 8 ] = value.elements[ 6 ];
-							uniform.__data[ 9 ] = value.elements[ 7 ];
-							uniform.__data[ 10 ] = value.elements[ 8 ];
-							uniform.__data[ 11 ] = 0;
+			if ( Array.isArray( value ) ) {
 
-						} else if ( ArrayBuffer.isView( value ) ) {
+				let arrayOffset = 0;
 
-							// copy the buffer data using "set"
-							uniform.__data.set( new value.constructor( value.buffer, value.byteOffset, uniform.__data.length ) );
+				for ( let k = 0; k < value.length; k ++ ) {
 
-						} else {
+					const val = value[ k ];
+					const info = getUniformSize( val );
 
-							value.toArray( uniform.__data, arrayOffset );
+					writeUniformValue( val, uniform.__data, arrayOffset );
 
-							arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
+					// only toArray() values advance arrayOffset
+					if ( typeof val !== 'number' && typeof val !== 'boolean' && ! val.isMatrix3 && ! ArrayBuffer.isView( val ) ) {
 
-						}
+						arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
 
 					}
 
-					gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data );
-
 				}
 
+			} else {
+
+				writeUniformValue( value, uniform.__data, 0 );
+
 			}
 
+			gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data );
+
 		}
 
-		gl.bindBuffer( gl.UNIFORM_BUFFER, null );
+	}
+
+	function writeUniformValue( value, data, offset ) {
+
+		// TODO add integer and struct support
+		if ( typeof value === 'number' || typeof value === 'boolean' ) {
+
+			data[ 0 ] = value;
+
+		} else if ( value.isMatrix3 ) {
+
+			// manually converting 3x3 to 3x4
+
+			data[ 0 ] = value.elements[ 0 ];
+			data[ 1 ] = value.elements[ 1 ];
+			data[ 2 ] = value.elements[ 2 ];
+			data[ 3 ] = 0;
+			data[ 4 ] = value.elements[ 3 ];
+			data[ 5 ] = value.elements[ 4 ];
+			data[ 6 ] = value.elements[ 5 ];
+			data[ 7 ] = 0;
+			data[ 8 ] = value.elements[ 6 ];
+			data[ 9 ] = value.elements[ 7 ];
+			data[ 10 ] = value.elements[ 8 ];
+			data[ 11 ] = 0;
+
+		} else if ( ArrayBuffer.isView( value ) ) {
+
+			// copy the buffer data using "set"
+			data.set( new value.constructor( value.buffer, value.byteOffset, data.length ) );
+
+		} else {
+
+			value.toArray( data, offset );
+
+		}
 
 	}
 

粤ICP备19079148号