Browse Source

WebGPUPipelines: Improve reuse programs. (#26305)

* WGSLNodeBuilder: Fix VideoTexture NoColorSpace

* Pipelines: Improve reuse programs.

* Improve performance.

* cleanup
sunag 2 years ago
parent
commit
40d18fda17

+ 0 - 1
examples/jsm/nodes/display/ColorSpaceNode.js

@@ -66,7 +66,6 @@ class ColorSpaceNode extends TempNode {
 		super( 'vec4' );
 
 		this.method = method;
-
 		this.node = node;
 
 	}

+ 22 - 14
examples/jsm/renderers/common/Pipelines.js

@@ -33,7 +33,7 @@ class Pipelines extends DataMap {
 
 			// release previous cache
 
-			this._releasePipeline( computeNode );
+			const previousPipeline = this._releasePipeline( computeNode );
 
 			// get shader
 
@@ -45,6 +45,8 @@ class Pipelines extends DataMap {
 
 			if ( stageCompute === undefined ) {
 
+				if ( previousPipeline ) this._releaseProgram( previousPipeline.computeShader );
+
 				stageCompute = new ProgrammableStage( nodeBuilder.computeShader, 'compute' );
 				this.programs.compute.set( nodeBuilder.computeShader, stageCompute );
 
@@ -81,7 +83,7 @@ class Pipelines extends DataMap {
 
 			// release previous cache
 
-			this._releasePipeline( renderObject );
+			const previousPipeline = this._releasePipeline( renderObject );
 
 			// get shader
 
@@ -93,6 +95,8 @@ class Pipelines extends DataMap {
 
 			if ( stageVertex === undefined ) {
 
+				if ( previousPipeline ) this._releaseProgram( previousPipeline.vertexProgram );
+
 				stageVertex = new ProgrammableStage( nodeBuilder.vertexShader, 'vertex' );
 				this.programs.vertex.set( nodeBuilder.vertexShader, stageVertex );
 
@@ -104,6 +108,8 @@ class Pipelines extends DataMap {
 
 			if ( stageFragment === undefined ) {
 
+				if ( previousPipeline ) this._releaseProgram( previousPipeline.fragmentShader );
+
 				stageFragment = new ProgrammableStage( nodeBuilder.fragmentShader, 'fragment' );
 				this.programs.fragment.set( nodeBuilder.fragmentShader, stageFragment );
 
@@ -133,7 +139,18 @@ class Pipelines extends DataMap {
 
 	delete( object ) {
 
-		this._releasePipeline( object );
+		const pipeline = this._releasePipeline( object );
+
+		if ( pipeline.isComputePipeline ) {
+
+			this._releaseProgram( pipeline.computeProgram );
+
+		} else {
+
+			this._releaseProgram( pipeline.vertexProgram );
+			this._releaseProgram( pipeline.fragmentProgram );
+
+		}
 
 		super.delete( object );
 
@@ -236,19 +253,10 @@ class Pipelines extends DataMap {
 
 			this.caches.delete( pipeline.cacheKey );
 
-			if ( pipeline.isComputePipeline ) {
-
-				this._releaseProgram( pipeline.computeProgram );
-
-			} else {
-
-				this._releaseProgram( pipeline.vertexProgram );
-				this._releaseProgram( pipeline.fragmentProgram );
-
-			}
-
 		}
 
+		return pipeline;
+
 	}
 
 	_releaseProgram( program ) {

+ 7 - 9
examples/jsm/renderers/common/RenderObject.js

@@ -1,13 +1,9 @@
-import { EventDispatcher } from 'three';
-
 let id = 0;
 
-export default class RenderObject extends EventDispatcher {
+export default class RenderObject {
 
 	constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode ) {
 
-		super();
-
 		this._nodes = nodes;
 		this._geometries = geometries;
 
@@ -29,15 +25,15 @@ export default class RenderObject extends EventDispatcher {
 		this._materialVersion = - 1;
 		this._materialCacheKey = '';
 
-		const onDispose = () => {
+		this.onDispose = null;
 
-			this.material.removeEventListener( 'dispose', onDispose );
+		this.onMaterialDispose = () => {
 
 			this.dispose();
 
 		};
 
-		this.material.addEventListener( 'dispose', onDispose );
+		this.material.addEventListener( 'dispose', this.onMaterialDispose );
 
 	}
 
@@ -108,7 +104,9 @@ export default class RenderObject extends EventDispatcher {
 
 	dispose() {
 
-		this.dispatchEvent( { type: 'dispose' } );
+		this.material.removeEventListener( 'dispose', this.onMaterialDispose );
+
+		this.onDispose();
 
 	}
 

+ 12 - 18
examples/jsm/renderers/common/RenderObjects.js

@@ -26,9 +26,7 @@ class RenderObjects extends ChainMap {
 
 		if ( renderObject === undefined ) {
 
-			renderObject = new RenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode );
-
-			this._initRenderObject( renderObject );
+			renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode );
 
 			this.set( chainArray, renderObject );
 
@@ -59,29 +57,25 @@ class RenderObjects extends ChainMap {
 
 	}
 
-	_initRenderObject( renderObject ) {
-
-		const data = this.dataMap.get( renderObject );
-
-		if ( data.initialized !== true ) {
+	createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode ) {
 
-			data.initialized = true;
-			data.cacheKey = renderObject.getCacheKey();
+		const renderObject = new RenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode );
 
-			const onDispose = () => {
+		const data = this.dataMap.get( renderObject );
+		data.cacheKey = renderObject.getCacheKey();
 
-				renderObject.removeEventListener( 'dispose', onDispose );
+		renderObject.onDispose = () => {
 
-				this.pipelines.delete( renderObject );
-				this.nodes.delete( renderObject );
+			this.dataMap.delete( renderObject );
 
-				this.delete( renderObject.getChainArray() );
+			this.pipelines.delete( renderObject );
+			this.nodes.delete( renderObject );
 
-			};
+			this.delete( renderObject.getChainArray() );
 
-			renderObject.addEventListener( 'dispose', onDispose );
+		};
 
-		}
+		return renderObject;
 
 	}
 

+ 3 - 1
examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js

@@ -1,3 +1,5 @@
+import { NoColorSpace } from 'three';
+
 import UniformsGroup from '../../common/UniformsGroup.js';
 import {
 	FloatNodeUniform, Vector2NodeUniform, Vector3NodeUniform, Vector4NodeUniform,
@@ -133,7 +135,7 @@ class WGSLNodeBuilder extends NodeBuilder {
 
 	needsColorSpaceToLinear( texture ) {
 
-		return texture.isVideoTexture === true;
+		return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace;
 
 	}