2
0
Эх сурвалжийг харах

BufferAttribute: Add support for multiple update ranges (#27103)

* Replace "updateRange" with "updateRanges"

* Fix upload logic

* Add updateRanges support to BufferGeometryLoader

* Clear attributes after upload, fix update condition

* Update warnings, update InterleavedBuffer

* Update tests

* Update examples

* Fix example

* Fix upload logic

* Update webgpu support

* Clear update ranges

* Update comment

* Update logs

* Switch "offset" to "start"

* Remove toJSON values

* Fix interleavedBuffer and WebGPUAttributeUtils

* Remove use of updateRange from tests, BufferGeometryLoader

* Remove update ranges from loader test
Garrett Johnson 1 жил өмнө
parent
commit
4f6ecee04d

+ 3 - 6
examples/jsm/misc/TubePainter.js

@@ -176,16 +176,13 @@ function TubePainter() {
 
 		if ( start === end ) return;
 
-		positions.updateRange.offset = start * 3;
-		positions.updateRange.count = ( end - start ) * 3;
+		positions.addUpdateRange( start * 3, ( end - start ) * 3 );
 		positions.needsUpdate = true;
 
-		normals.updateRange.offset = start * 3;
-		normals.updateRange.count = ( end - start ) * 3;
+		normals.addUpdateRange( start * 3, ( end - start ) * 3 );
 		normals.needsUpdate = true;
 
-		colors.updateRange.offset = start * 3;
-		colors.updateRange.count = ( end - start ) * 3;
+		colors.addUpdateRange( start * 3, ( end - start ) * 3 );
 		colors.needsUpdate = true;
 
 		count = geometry.drawRange.count;

+ 15 - 10
examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js

@@ -72,9 +72,9 @@ class WebGPUAttributeUtils {
 		const buffer = backend.get( bufferAttribute ).buffer;
 
 		const array = bufferAttribute.array;
-		const updateRange = bufferAttribute.updateRange;
+		const updateRanges = bufferAttribute.updateRanges;
 
-		if ( updateRange.count === - 1 ) {
+		if ( updateRanges.length === 0 ) {
 
 			// Not using update ranges
 
@@ -87,15 +87,20 @@ class WebGPUAttributeUtils {
 
 		} else {
 
-			device.queue.writeBuffer(
-				buffer,
-				0,
-				array,
-				updateRange.offset * array.BYTES_PER_ELEMENT,
-				updateRange.count * array.BYTES_PER_ELEMENT
-			);
+			for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
+
+				const range = updateRanges[ i ];
+				device.queue.writeBuffer(
+					buffer,
+					0,
+					array,
+					range.start * array.BYTES_PER_ELEMENT,
+					range.count * array.BYTES_PER_ELEMENT
+				);
+
+			}
 
-			updateRange.count = - 1; // reset range
+			bufferAttribute.clearUpdateRanges();
 
 		}
 

+ 1 - 2
examples/webgl_simple_gi.html

@@ -128,8 +128,7 @@
 
 					}
 
-					attributes.color.updateRange.offset = startVertex * 3;
-					attributes.color.updateRange.count = ( currentVertex - startVertex ) * 3;
+					attributes.color.addUpdateRange( startVertex * 3, ( currentVertex - startVertex ) * 3 );
 					attributes.color.needsUpdate = true;
 
 					if ( currentVertex >= totalVertex ) {

+ 21 - 2
src/core/BufferAttribute.js

@@ -27,7 +27,8 @@ class BufferAttribute {
 		this.normalized = normalized;
 
 		this.usage = StaticDrawUsage;
-		this.updateRange = { offset: 0, count: - 1 };
+		this._updateRange = { offset: 0, count: - 1 };
+		this.updateRanges = [];
 		this.gpuType = FloatType;
 
 		this.version = 0;
@@ -42,6 +43,13 @@ class BufferAttribute {
 
 	}
 
+	get updateRange() {
+
+		console.warn( 'THREE.BufferAttribute: "updateRange" is deprecated and removed in r169. Use "addUpdateRange()" instead.' );
+		return this._updateRange;
+
+	}
+
 	setUsage( value ) {
 
 		this.usage = value;
@@ -50,6 +58,18 @@ class BufferAttribute {
 
 	}
 
+	addUpdateRange( start, count ) {
+
+		this.updateRanges.push( { start, count } );
+
+	}
+
+	clearUpdateRanges() {
+
+		this.updateRanges.length = 0;
+
+	}
+
 	copy( source ) {
 
 		this.name = source.name;
@@ -360,7 +380,6 @@ class BufferAttribute {
 
 		if ( this.name !== '' ) data.name = this.name;
 		if ( this.usage !== StaticDrawUsage ) data.usage = this.usage;
-		if ( this.updateRange.offset !== 0 || this.updateRange.count !== - 1 ) data.updateRange = this.updateRange;
 
 		return data;
 

+ 21 - 1
src/core/InterleavedBuffer.js

@@ -12,7 +12,8 @@ class InterleavedBuffer {
 		this.count = array !== undefined ? array.length / stride : 0;
 
 		this.usage = StaticDrawUsage;
-		this.updateRange = { offset: 0, count: - 1 };
+		this._updateRange = { offset: 0, count: - 1 };
+		this.updateRanges = [];
 
 		this.version = 0;
 
@@ -28,6 +29,13 @@ class InterleavedBuffer {
 
 	}
 
+	get updateRange() {
+
+		console.warn( 'THREE.InterleavedBuffer: "updateRange" is deprecated and removed in r169. Use "addUpdateRange()" instead.' );
+		return this._updateRange;
+
+	}
+
 	setUsage( value ) {
 
 		this.usage = value;
@@ -36,6 +44,18 @@ class InterleavedBuffer {
 
 	}
 
+	addUpdateRange( start, count ) {
+
+		this.updateRanges.push( { start, count } );
+
+	}
+
+	clearUpdateRanges() {
+
+		this.updateRanges.length = 0;
+
+	}
+
 	copy( source ) {
 
 		this.array = new source.array.constructor( source.array );

+ 0 - 7
src/loaders/BufferGeometryLoader.js

@@ -125,13 +125,6 @@ class BufferGeometryLoader extends Loader {
 			if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
 			if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
 
-			if ( attribute.updateRange !== undefined ) {
-
-				bufferAttribute.updateRange.offset = attribute.updateRange.offset;
-				bufferAttribute.updateRange.count = attribute.updateRange.count;
-
-			}
-
 			geometry.setAttribute( key, bufferAttribute );
 
 		}

+ 30 - 4
src/renderers/webgl/WebGLAttributes.js

@@ -84,17 +84,43 @@ function WebGLAttributes( gl, capabilities ) {
 	function updateBuffer( buffer, attribute, bufferType ) {
 
 		const array = attribute.array;
-		const updateRange = attribute.updateRange;
+		const updateRange = attribute._updateRange; // deprecated
+		const updateRanges = attribute.updateRanges;
 
 		gl.bindBuffer( bufferType, buffer );
 
-		if ( updateRange.count === - 1 ) {
+		if ( updateRange.count === - 1 && updateRanges.length === 0 ) {
 
 			// Not using update ranges
-
 			gl.bufferSubData( bufferType, 0, array );
 
-		} else {
+		}
+
+		if ( updateRanges.length !== 0 ) {
+
+			for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
+
+				const range = updateRanges[ i ];
+				if ( isWebGL2 ) {
+
+					gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
+						array, range.start, range.count );
+
+				} else {
+
+					gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
+						array.subarray( range.start, range.start + range.count ) );
+
+				}
+
+			}
+
+			attribute.clearUpdateRanges();
+
+		}
+
+		// deprecated
+		if ( updateRange.count !== - 1 ) {
 
 			if ( isWebGL2 ) {
 

+ 2 - 4
test/unit/src/core/BufferAttribute.tests.js

@@ -74,7 +74,7 @@ export default QUnit.module( 'Core', () => {
 
 		} );
 
-		QUnit.todo( 'updateRange', ( assert ) => {
+		QUnit.todo( 'updateRanges', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 
@@ -296,8 +296,7 @@ export default QUnit.module( 'Core', () => {
 			const attr2 = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3, true );
 			attr2.name = 'attributeName';
 			attr2.setUsage( DynamicDrawUsage );
-			attr2.updateRange.offset = 1;
-			attr2.updateRange.count = 2;
+			attr2.addUpdateRange( 1, 2 );
 			assert.deepEqual( attr2.toJSON(), {
 				itemSize: 3,
 				type: 'Float32Array',
@@ -305,7 +304,6 @@ export default QUnit.module( 'Core', () => {
 				normalized: true,
 				name: 'attributeName',
 				usage: DynamicDrawUsage,
-				updateRange: { offset: 1, count: 2 }
 			}, 'Serialized to JSON as expected with non-default values' );
 
 		} );

+ 1 - 1
test/unit/src/core/InterleavedBuffer.tests.js

@@ -56,7 +56,7 @@ export default QUnit.module( 'Core', () => {
 
 		} );
 
-		QUnit.todo( 'updateRange', ( assert ) => {
+		QUnit.todo( 'updateRanges', ( assert ) => {
 
 			assert.ok( false, 'everything\'s gonna be alright' );
 

+ 0 - 2
test/unit/src/loaders/BufferGeometryLoader.tests.js

@@ -51,8 +51,6 @@ export default QUnit.module( 'Loaders', () => {
 			const attr = new BufferAttribute( new Float32Array( [ 7, 8, 9, 10, 11, 12 ] ), 2, true );
 			attr.name = 'attribute';
 			attr.setUsage( DynamicDrawUsage );
-			attr.updateRange.offset = 1;
-			attr.updateRange.count = 2;
 
 			geometry.setAttribute( 'attr', attr );