Explorar o código

Renderer: Call ID (#27101)

* Renderer Call ID

* Update Animation.js

update after init

* Replace requestAnimationFrame() -> setAnimationLoop()

* fix screenshots

* show grid

* add shadertoy screenshot

* preserve screenshot but ignore webgpu_particles for now

* using time instead of frame

* add frame info

* rename info.call -> info.calls
sunag hai 1 ano
pai
achega
6d7566e5e4

+ 10 - 21
examples/jsm/renderers/common/Animation.js

@@ -1,23 +1,18 @@
 class Animation {
 
-	constructor() {
+	constructor( nodes, info ) {
 
-		this.nodes = null;
+		this.nodes = nodes;
+		this.info = info;
 
 		this.animationLoop = null;
 		this.requestId = null;
 
-		this.isAnimating = false;
-
-		this.context = self;
+		this._init();
 
 	}
 
-	start() {
-
-		if ( this.isAnimating === true || this.animationLoop === null || this.nodes === null ) return;
-
-		this.isAnimating = true;
+	_init() {
 
 		const update = ( time, frame ) => {
 
@@ -25,20 +20,20 @@ class Animation {
 
 			this.nodes.nodeFrame.update();
 
-			this.animationLoop( time, frame );
+			this.info.frame = this.nodes.nodeFrame.frameId;
+
+			if ( this.animationLoop !== null ) this.animationLoop( time, frame );
 
 		};
 
-		this.requestId = self.requestAnimationFrame( update );
+		update();
 
 	}
 
-	stop() {
+	dispose() {
 
 		self.cancelAnimationFrame( this.requestId );
 
-		this.isAnimating = false;
-
 	}
 
 	setAnimationLoop( callback ) {
@@ -47,12 +42,6 @@ class Animation {
 
 	}
 
-	setNodes( nodes ) {
-
-		this.nodes = nodes;
-
-	}
-
 }
 
 export default Animation;

+ 3 - 3
examples/jsm/renderers/common/Bindings.js

@@ -101,7 +101,7 @@ class Bindings extends DataMap {
 		const { backend } = this;
 
 		const updateMap = this.updateMap;
-		const frame = this.info.render.frame;
+		const callId = this.info.calls;
 
 		let needsBindingsUpdate = false;
 
@@ -109,7 +109,7 @@ class Bindings extends DataMap {
 
 		for ( const binding of bindings ) {
 
-			const isUpdated = updateMap.get( binding ) === frame;
+			const isUpdated = updateMap.get( binding ) === callId;
 
 			if ( isUpdated ) continue;
 
@@ -137,7 +137,7 @@ class Bindings extends DataMap {
 
 			}
 
-			updateMap.set( binding, frame );
+			updateMap.set( binding, callId );
 
 		}
 

+ 4 - 4
examples/jsm/renderers/common/Geometries.js

@@ -76,7 +76,7 @@ class Geometries extends DataMap {
 		this.info = info;
 
 		this.wireframes = new WeakMap();
-		this.attributeFrame = new WeakMap();
+		this.attributeCall = new WeakMap();
 
 	}
 
@@ -162,13 +162,13 @@ class Geometries extends DataMap {
 
 	updateAttribute( attribute, type ) {
 
-		const frame = this.info.render.frame;
+		const callId = this.info.render.calls;
 
-		if ( this.attributeFrame.get( attribute ) !== frame ) {
+		if ( this.attributeCall.get( attribute ) !== callId ) {
 
 			this.attributes.update( attribute, type );
 
-			this.attributeFrame.set( attribute, frame );
+			this.attributeCall.set( attribute, callId );
 
 		}
 

+ 12 - 2
examples/jsm/renderers/common/Info.js

@@ -4,14 +4,21 @@ class Info {
 
 		this.autoReset = true;
 
+		this.frame = 0;
+		this.calls = 0;
+
 		this.render = {
-			frame: 0,
+			calls: 0,
 			drawCalls: 0,
 			triangles: 0,
 			points: 0,
 			lines: 0
 		};
 
+		this.compute = {
+			calls: 0
+		};
+
 		this.memory = {
 			geometries: 0,
 			textures: 0
@@ -60,7 +67,10 @@ class Info {
 
 		this.reset();
 
-		this.render.frame = 0;
+		this.calls = 0;
+
+		this.render.calls = 0;
+		this.compute.calls = 0;
 
 		this.memory.geometries = 0;
 		this.memory.textures = 0;

+ 24 - 16
examples/jsm/renderers/common/Renderer.js

@@ -62,6 +62,7 @@ class Renderer {
 		this._attributes = null;
 		this._geometries = null;
 		this._nodes = null;
+		this._animation = null;
 		this._bindings = null;
 		this._objects = null;
 		this._pipelines = null;
@@ -70,8 +71,6 @@ class Renderer {
 		this._textures = null;
 		this._background = null;
 
-		this._animation = new Animation();
-
 		this._currentRenderContext = null;
 		this._lastRenderContext = null;
 
@@ -136,6 +135,7 @@ class Renderer {
 			}
 
 			this._nodes = new Nodes( this, backend );
+			this._animation = new Animation( this._nodes, this.info );
 			this._attributes = new Attributes( backend );
 			this._background = new Background( this, this._nodes );
 			this._geometries = new Geometries( this._attributes, this.info );
@@ -148,9 +148,6 @@ class Renderer {
 
 			//
 
-			this._animation.setNodes( this._nodes );
-			this._animation.start();
-
 			this._initialized = true;
 
 			resolve();
@@ -197,8 +194,13 @@ class Renderer {
 		this._currentRenderContext = renderContext;
 		this._currentRenderObjectFunction = this._renderObjectFunction || this.renderObject;
 
+		//
+
 		nodeFrame.renderId ++;
 
+		this.info.calls ++;
+		this.info.render.calls ++;
+
 		//
 
 		const coordinateSystem = this.coordinateSystem;
@@ -213,16 +215,12 @@ class Renderer {
 
 		//
 
-		if ( this._animation.isAnimating === false ) nodeFrame.update();
-
 		if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
 
 		if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
 
 		if ( this.info.autoReset === true ) this.info.reset();
 
-		this.info.render.frame ++;
-
 		//
 
 		let viewport = this._viewport;
@@ -361,15 +359,11 @@ class Renderer {
 
 	}
 
-	setAnimationLoop( callback ) {
-
-		if ( this._initialized === false ) this.init();
+	async setAnimationLoop( callback ) {
 
-		const animation = this._animation;
-
-		animation.setAnimationLoop( callback );
+		if ( this._initialized === false ) await this.init();
 
-		( callback === null ) ? animation.stop() : animation.start();
+		this._animation.setAnimationLoop( callback );
 
 	}
 
@@ -621,6 +615,7 @@ class Renderer {
 
 		this.info.dispose();
 
+		this._animation.dispose();
 		this._objects.dispose();
 		this._properties.dispose();
 		this._pipelines.dispose();
@@ -665,12 +660,25 @@ class Renderer {
 
 		if ( this._initialized === false ) await this.init();
 
+		//
+
+		this.info.calls ++;
+		this.info.compute.calls ++;
+
+		//
+
 		const backend = this.backend;
 		const pipelines = this._pipelines;
 		const bindings = this._bindings;
 		const nodes = this._nodes;
 		const computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ];
 
+		if ( computeList[ 0 ] === undefined || computeList[ 0 ].isComputeNode !== true ) {
+
+			throw new Error( 'THREE.Renderer: .compute() expects a ComputeNode.' );
+
+		}
+
 		backend.beginCompute( computeNodes );
 
 		for ( const computeNode of computeList ) {

+ 6 - 6
examples/jsm/renderers/common/nodes/Nodes.js

@@ -14,7 +14,7 @@ class Nodes extends DataMap {
 		this.backend = backend;
 		this.nodeFrame = new NodeFrame();
 		this.nodeBuilderCache = new Map();
-		this.frameHashCache = new ChainMap();
+		this.callHashCache = new ChainMap();
 
 	}
 
@@ -148,11 +148,11 @@ class Nodes extends DataMap {
 	getCacheKey( scene, lightsNode ) {
 
 		const chain = [ scene, lightsNode ];
-		const frameId = this.nodeFrame.frameId;
+		const callId = this.renderer.info.calls;
 
-		let cacheKeyData = this.frameHashCache.get( chain );
+		let cacheKeyData = this.callHashCache.get( chain );
 
-		if ( cacheKeyData === undefined || cacheKeyData.frameId !== frameId ) {
+		if ( cacheKeyData === undefined || cacheKeyData.callId !== callId ) {
 
 			const environmentNode = this.getEnvironmentNode( scene );
 			const fogNode = this.getFogNode( scene );
@@ -166,11 +166,11 @@ class Nodes extends DataMap {
 			if ( toneMappingNode ) cacheKey.push( toneMappingNode.getCacheKey() );
 
 			cacheKeyData = {
-				frameId,
+				callId,
 				cacheKey: cacheKey.join( ',' )
 			};
 
-			this.frameHashCache.set( chain, cacheKeyData );
+			this.callHashCache.set( chain, cacheKeyData );
 
 		}
 

BIN=BIN
examples/screenshots/webgpu_instance_points.jpg


BIN=BIN
examples/screenshots/webgpu_lines_fat.jpg


BIN=BIN
examples/screenshots/webgpu_particles.jpg


+ 1 - 3
examples/webgpu_clearcoat.html

@@ -42,7 +42,6 @@
 			let group;
 
 			init();
-			animate();
 
 			function init() {
 
@@ -187,6 +186,7 @@
 				renderer = new WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
 				container.appendChild( renderer.domElement );
 
 				//
@@ -227,8 +227,6 @@
 
 			function animate() {
 
-				requestAnimationFrame( animate );
-
 				render();
 
 				stats.update();

+ 9 - 2
examples/webgpu_compute_texture_pingpong.html

@@ -35,6 +35,8 @@
 			let pingTexture, pongTexture;
 			let material;
 			let phase = true;
+			let lastUpdate = - 1;
+
 			const seed = uniform( new THREE.Vector2() );
 
 			init();
@@ -184,14 +186,19 @@
 
 			function render() {
 
-				// reset every 200 frames
+				const time = performance.now();
+				const seconds = Math.floor( time / 1000 );
+
+				// reset every second
 
-				if ( renderer.info.render.frame % 200 === 0 ) {
+				if ( phase && seconds !== lastUpdate ) {
 
 					seed.value.set( Math.random(), Math.random() );
 
 					renderer.compute( computeInitNode );
 
+					lastUpdate = seconds;
+
 				}
 
 				// compute step

+ 1 - 3
examples/webgpu_instance_points.html

@@ -54,7 +54,6 @@
 			let insetHeight;
 
 			init();
-			animate();
 
 			function init() {
 
@@ -69,6 +68,7 @@
 				renderer = new WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
 				document.body.appendChild( renderer.domElement );
 
 				scene = new THREE.Scene();
@@ -161,8 +161,6 @@
 
 			function animate() {
 
-				requestAnimationFrame( animate );
-
 				stats.update();
 
 				// main scene

+ 1 - 3
examples/webgpu_lines_fat.html

@@ -52,7 +52,6 @@
 			let insetHeight;
 
 			init();
-			animate();
 
 			function init() {
 
@@ -68,6 +67,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setClearColor( 0x000000, 0.0 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
 				document.body.appendChild( renderer.domElement );
 
 				scene = new THREE.Scene();
@@ -173,8 +173,6 @@
 
 			function animate() {
 
-				requestAnimationFrame( animate );
-
 				stats.update();
 
 				// main scene

+ 1 - 3
examples/webgpu_loader_gltf_sheen.html

@@ -43,7 +43,6 @@
 			let camera, scene, renderer, controls;
 
 			init();
-			animate();
 
 			function init() {
 
@@ -84,6 +83,7 @@
 				renderer = new WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
 				renderer.toneMappingExposure = 1;
 				container.appendChild( renderer.domElement );
@@ -126,8 +126,6 @@
 
 			function animate() {
 
-				requestAnimationFrame( animate );
-
 				controls.update(); // required if damping enabled
 
 				render();

+ 0 - 1
examples/webgpu_particles.html

@@ -122,7 +122,6 @@
 				//
 
 				const helper = new THREE.GridHelper( 3000, 40, 0x303030, 0x303030 );
-				helper.material.colorNode = attribute( 'color' );
 				helper.position.y = - 75;
 				scene.add( helper );
 

+ 1 - 2
examples/webgpu_video_panorama.html

@@ -52,7 +52,6 @@
 			const distance = .5;
 
 			init();
-			animate();
 
 			function init() {
 
@@ -87,6 +86,7 @@
 				renderer = new WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
 				container.appendChild( renderer.domElement );
 
 				document.addEventListener( 'pointerdown', onPointerDown );
@@ -139,7 +139,6 @@
 
 			function animate() {
 
-				requestAnimationFrame( animate );
 				update();
 
 			}

+ 1 - 0
test/e2e/puppeteer.js

@@ -126,6 +126,7 @@ const exceptionList = [
 	'webgpu_video_panorama',
 
 	// WebGPURenderer: Unknown problem
+	'webgpu_particles',
 	'webgpu_shadertoy',
 	'webgpu_tsl_editor',
 	'webgpu_tsl_transpiler'