Ver Fonte

TSL: Introduces cache hierarchy (#28585)

* fix multi-flow

* cleanup

* NodeCache: Rename getNodeData() to getData(), and set*()

* cleanup

* UniformNode: global as default

* BufferAttributeNode: Manage global as default

* revision
sunag há 1 ano atrás
pai
commit
133da7c0a3

+ 0 - 1
examples/jsm/nodes/accessors/BatchNode.js

@@ -46,7 +46,6 @@ class BatchNode extends Node {
 			textureLoad( matriceTexture, ivec2( x.add( 3 ), y ) )
 			textureLoad( matriceTexture, ivec2( x.add( 3 ), y ) )
 		);
 		);
 
 
-
 		const bm = mat3(
 		const bm = mat3(
 			batchingMatrix[ 0 ].xyz,
 			batchingMatrix[ 0 ].xyz,
 			batchingMatrix[ 1 ].xyz,
 			batchingMatrix[ 1 ].xyz,

+ 26 - 0
examples/jsm/nodes/accessors/BufferAttributeNode.js

@@ -21,6 +21,8 @@ class BufferAttributeNode extends InputNode {
 
 
 		this.attribute = null;
 		this.attribute = null;
 
 
+		this.global = true;
+
 		if ( value && value.isBufferAttribute === true ) {
 		if ( value && value.isBufferAttribute === true ) {
 
 
 			this.attribute = value;
 			this.attribute = value;
@@ -31,6 +33,30 @@ class BufferAttributeNode extends InputNode {
 
 
 	}
 	}
 
 
+	getHash( builder ) {
+
+		if ( this.bufferStride === 0 && this.bufferOffset === 0) {
+
+			let bufferData = builder.globalCache.getData( this.value );
+
+			if ( bufferData === undefined ) {
+
+				bufferData = {
+					node: this
+				};
+
+				builder.globalCache.setData( this.value, bufferData );
+
+			}
+
+			return bufferData.node.uuid;
+
+		}
+
+		return this.uuid;
+
+	}
+
 	getNodeType( builder ) {
 	getNodeType( builder ) {
 
 
 		if ( this.bufferType === null ) {
 		if ( this.bufferType === null ) {

+ 2 - 6
examples/jsm/nodes/accessors/TextureNode.js

@@ -245,12 +245,8 @@ class TextureNode extends UniformNode {
 
 
 				builder.addLineFlowCode( `${propertyName} = ${snippet}` );
 				builder.addLineFlowCode( `${propertyName} = ${snippet}` );
 
 
-				if ( builder.context.tempWrite !== false ) {
-
-					nodeData.snippet = snippet;
-					nodeData.propertyName = propertyName;
-
-				}
+				nodeData.snippet = snippet;
+				nodeData.propertyName = propertyName;
 
 
 			}
 			}
 
 

+ 2 - 6
examples/jsm/nodes/core/AttributeNode.js

@@ -10,13 +10,9 @@ class AttributeNode extends Node {
 
 
 		this.defaultNode = defaultNode;
 		this.defaultNode = defaultNode;
 
 
-		this._attributeName = attributeName;
-
-	}
+		this.global = true;
 
 
-	isGlobal() {
-
-		return true;
+		this._attributeName = attributeName;
 
 
 	}
 	}
 
 

+ 7 - 10
examples/jsm/nodes/core/CacheNode.js

@@ -1,17 +1,16 @@
 import Node, { addNodeClass } from './Node.js';
 import Node, { addNodeClass } from './Node.js';
-import NodeCache from './NodeCache.js';
-import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js';
+import { addNodeElement, nodeObject } from '../shadernode/ShaderNode.js';
 
 
 class CacheNode extends Node {
 class CacheNode extends Node {
 
 
-	constructor( node, cache = new NodeCache() ) {
+	constructor( node, parent = true ) {
 
 
 		super();
 		super();
 
 
-		this.isCacheNode = true;
-
 		this.node = node;
 		this.node = node;
-		this.cache = cache;
+		this.parent = parent;
+
+		this.isCacheNode = true;
 
 
 	}
 	}
 
 
@@ -24,7 +23,7 @@ class CacheNode extends Node {
 	build( builder, ...params ) {
 	build( builder, ...params ) {
 
 
 		const previousCache = builder.getCache();
 		const previousCache = builder.getCache();
-		const cache = this.cache || builder.globalCache;
+		const cache = builder.getCacheFromNode( this, parent );
 
 
 		builder.setCache( cache );
 		builder.setCache( cache );
 
 
@@ -40,10 +39,8 @@ class CacheNode extends Node {
 
 
 export default CacheNode;
 export default CacheNode;
 
 
-export const cache = nodeProxy( CacheNode );
-export const globalCache = ( node ) => cache( node, null );
+export const cache = ( node, ...params ) => nodeObject( new CacheNode( nodeObject( node ), ...params ) );
 
 
 addNodeElement( 'cache', cache );
 addNodeElement( 'cache', cache );
-addNodeElement( 'globalCache', globalCache );
 
 
 addNodeClass( 'CacheNode', CacheNode );
 addNodeClass( 'CacheNode', CacheNode );

+ 2 - 2
examples/jsm/nodes/core/Node.js

@@ -320,7 +320,7 @@ class Node extends EventDispatcher {
 
 
 			const properties = builder.getNodeProperties( this );
 			const properties = builder.getNodeProperties( this );
 
 
-			if ( properties.initialized !== true || builder.context.tempRead === false ) {
+			if ( properties.initialized !== true ) {
 
 
 				const stackNodesBeforeSetup = builder.stack.nodes.length;
 				const stackNodesBeforeSetup = builder.stack.nodes.length;
 
 
@@ -360,7 +360,7 @@ class Node extends EventDispatcher {
 
 
 				result = nodeData.snippet;
 				result = nodeData.snippet;
 
 
-				if ( result === undefined /*|| builder.context.tempRead === false*/ ) {
+				if ( result === undefined ) {
 
 
 					result = this.generate( builder ) || '';
 					result = this.generate( builder ) || '';
 
 

+ 11 - 2
examples/jsm/nodes/core/NodeBuilder.js

@@ -316,6 +316,15 @@ class NodeBuilder {
 
 
 	}
 	}
 
 
+	getCacheFromNode( node, parent = true ) {
+
+		const data = this.getDataFromNode( node );
+		if ( data.cache === undefined ) data.cache = new NodeCache( parent ? this.getCache() : null );
+
+		return data.cache;
+
+	}
+
 	isAvailable( /*name*/ ) {
 	isAvailable( /*name*/ ) {
 
 
 		return false;
 		return false;
@@ -639,13 +648,13 @@ class NodeBuilder {
 
 
 		cache = cache === null ? ( node.isGlobal( this ) ? this.globalCache : this.cache ) : cache;
 		cache = cache === null ? ( node.isGlobal( this ) ? this.globalCache : this.cache ) : cache;
 
 
-		let nodeData = cache.getNodeData( node );
+		let nodeData = cache.getData( node );
 
 
 		if ( nodeData === undefined ) {
 		if ( nodeData === undefined ) {
 
 
 			nodeData = {};
 			nodeData = {};
 
 
-			cache.setNodeData( node, nodeData );
+			cache.setData( node, nodeData );
 
 
 		}
 		}
 
 

+ 14 - 4
examples/jsm/nodes/core/NodeCache.js

@@ -2,20 +2,30 @@ let id = 0;
 
 
 class NodeCache {
 class NodeCache {
 
 
-	constructor() {
+	constructor( parent = null ) {
 
 
 		this.id = id ++;
 		this.id = id ++;
 		this.nodesData = new WeakMap();
 		this.nodesData = new WeakMap();
 
 
+		this.parent = parent;
+
 	}
 	}
 
 
-	getNodeData( node ) {
+	getData( node ) {
+
+		let data = this.nodesData.get( node );
+
+		if ( data === undefined && this.parent !== null ) {
+
+			data = this.parent.getData( node );
+
+		}
 
 
-		return this.nodesData.get( node );
+		return data;
 
 
 	}
 	}
 
 
-	setNodeData( node, data ) {
+	setData( node, data ) {
 
 
 		this.nodesData.set( node, data );
 		this.nodesData.set( node, data );
 
 

+ 2 - 2
examples/jsm/nodes/core/TempNode.js

@@ -25,11 +25,11 @@ class TempNode extends Node {
 			const type = builder.getVectorType( this.getNodeType( builder, output ) );
 			const type = builder.getVectorType( this.getNodeType( builder, output ) );
 			const nodeData = builder.getDataFromNode( this );
 			const nodeData = builder.getDataFromNode( this );
 
 
-			if ( builder.context.tempRead !== false && nodeData.propertyName !== undefined ) {
+			if ( nodeData.propertyName !== undefined ) {
 
 
 				return builder.format( nodeData.propertyName, type, output );
 				return builder.format( nodeData.propertyName, type, output );
 
 
-			} else if ( builder.context.tempWrite !== false && type !== 'void' && output !== 'void' && this.hasDependencies( builder ) ) {
+			} else if ( type !== 'void' && output !== 'void' && this.hasDependencies( builder ) ) {
 
 
 				const snippet = super.build( builder, type );
 				const snippet = super.build( builder, type );
 
 

+ 2 - 6
examples/jsm/nodes/core/VarNode.js

@@ -10,13 +10,9 @@ class VarNode extends Node {
 		this.node = node;
 		this.node = node;
 		this.name = name;
 		this.name = name;
 
 
-		this.isVarNode = true;
-
-	}
+		this.global = true;
 
 
-	isGlobal() {
-
-		return true;
+		this.isVarNode = true;
 
 
 	}
 	}
 
 

+ 2 - 1
examples/jsm/nodes/lighting/EnvironmentNode.js

@@ -57,12 +57,13 @@ class EnvironmentNode extends LightingNode {
 		const irradiance = context( envNode, createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity );
 		const irradiance = context( envNode, createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity );
 
 
 		const isolateRadiance = cache( radiance );
 		const isolateRadiance = cache( radiance );
+		const isolateIrradiance = cache( irradiance );
 
 
 		//
 		//
 
 
 		builder.context.radiance.addAssign( isolateRadiance );
 		builder.context.radiance.addAssign( isolateRadiance );
 
 
-		builder.context.iblIrradiance.addAssign( irradiance );
+		builder.context.iblIrradiance.addAssign( isolateIrradiance );
 
 
 		//
 		//
 
 

+ 1 - 1
examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js

@@ -157,7 +157,7 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 
 
 			} ).else( () => {
 			} ).else( () => {
 
 
-				anisotropyV.divAssign( anisotropy );
+				anisotropyV.divAssign( vec2( anisotropy ) );
 				anisotropy.assign( anisotropy.saturate() );
 				anisotropy.assign( anisotropy.saturate() );
 
 
 			} );
 			} );

+ 13 - 6
examples/jsm/nodes/math/CondNode.js

@@ -1,6 +1,5 @@
 import Node, { addNodeClass } from '../core/Node.js';
 import Node, { addNodeClass } from '../core/Node.js';
 import { property } from '../core/PropertyNode.js';
 import { property } from '../core/PropertyNode.js';
-import { context as contextNode } from '../core/ContextNode.js';
 import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js';
 import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js';
 
 
 class CondNode extends Node {
 class CondNode extends Node {
@@ -36,10 +35,18 @@ class CondNode extends Node {
 
 
 	}
 	}
 
 
+	setup( builder ) {
+
+		const properties = builder.getNodeProperties( this );
+		properties.condNode = this.condNode.cache();
+		properties.ifNode = this.ifNode.cache();
+		properties.elseNode = this.elseNode ? this.elseNode.cache() : null;
+
+	}
+
 	generate( builder, output ) {
 	generate( builder, output ) {
 
 
 		const type = this.getNodeType( builder );
 		const type = this.getNodeType( builder );
-		const context = { tempWrite: false };
 
 
 		const nodeData = builder.getDataFromNode( this );
 		const nodeData = builder.getDataFromNode( this );
 
 
@@ -49,18 +56,18 @@ class CondNode extends Node {
 
 
 		}
 		}
 
 
-		const { ifNode, elseNode } = this;
+		const { condNode, ifNode, elseNode } = builder.getNodeProperties( this );
 
 
 		const needsOutput = output !== 'void';
 		const needsOutput = output !== 'void';
 		const nodeProperty = needsOutput ? property( type ).build( builder ) : '';
 		const nodeProperty = needsOutput ? property( type ).build( builder ) : '';
 
 
 		nodeData.nodeProperty = nodeProperty;
 		nodeData.nodeProperty = nodeProperty;
 
 
-		const nodeSnippet = contextNode( this.condNode/*, context*/ ).build( builder, 'bool' );
+		const nodeSnippet = condNode.build( builder, 'bool' );
 
 
 		builder.addFlowCode( `\n${ builder.tab }if ( ${ nodeSnippet } ) {\n\n` ).addFlowTab();
 		builder.addFlowCode( `\n${ builder.tab }if ( ${ nodeSnippet } ) {\n\n` ).addFlowTab();
 
 
-		let ifSnippet = contextNode( ifNode, context ).build( builder, type );
+		let ifSnippet = ifNode.build( builder, type );
 
 
 		if ( ifSnippet ) {
 		if ( ifSnippet ) {
 
 
@@ -82,7 +89,7 @@ class CondNode extends Node {
 
 
 			builder.addFlowCode( ' else {\n\n' ).addFlowTab();
 			builder.addFlowCode( ' else {\n\n' ).addFlowTab();
 
 
-			let elseSnippet = contextNode( elseNode, context ).build( builder, type );
+			let elseSnippet = elseNode.build( builder, type );
 
 
 			if ( elseSnippet ) {
 			if ( elseSnippet ) {
 
 

+ 2 - 0
examples/jsm/nodes/shadernode/ShaderNode.js

@@ -351,6 +351,8 @@ class ShaderNodeInternal extends Node {
 		this.jsFunc = jsFunc;
 		this.jsFunc = jsFunc;
 		this.layout = null;
 		this.layout = null;
 
 
+		this.global = true;
+
 	}
 	}
 
 
 	get isArrayInput() {
 	get isArrayInput() {

+ 2 - 0
examples/jsm/nodes/utils/FunctionOverloadingNode.js

@@ -12,6 +12,8 @@ class FunctionOverloadingNode extends Node {
 
 
 		this._candidateFnCall = null;
 		this._candidateFnCall = null;
 
 
+		this.global = true;
+
 	}
 	}
 
 
 	getNodeType() {
 	getNodeType() {

+ 7 - 6
examples/jsm/nodes/utils/LoopNode.js

@@ -1,7 +1,6 @@
 import Node, { addNodeClass } from '../core/Node.js';
 import Node, { addNodeClass } from '../core/Node.js';
 import { expression } from '../code/ExpressionNode.js';
 import { expression } from '../code/ExpressionNode.js';
 import { bypass } from '../core/BypassNode.js';
 import { bypass } from '../core/BypassNode.js';
-import { context } from '../core/ContextNode.js';
 import { addNodeElement, nodeObject, nodeArray } from '../shadernode/ShaderNode.js';
 import { addNodeElement, nodeObject, nodeArray } from '../shadernode/ShaderNode.js';
 
 
 class LoopNode extends Node {
 class LoopNode extends Node {
@@ -41,8 +40,12 @@ class LoopNode extends Node {
 
 
 		}
 		}
 
 
-		properties.returnsNode = this.params[ this.params.length - 1 ]( inputs, builder.addStack(), builder );
-		properties.stackNode = builder.removeStack();
+		const stack = builder.addStack(); // TODO: cache() it
+
+		properties.returnsNode = this.params[ this.params.length - 1 ]( inputs, stack, builder );
+		properties.stackNode = stack;
+
+		builder.removeStack();
 
 
 		return properties;
 		return properties;
 
 
@@ -68,8 +71,6 @@ class LoopNode extends Node {
 
 
 		const properties = this.getProperties( builder );
 		const properties = this.getProperties( builder );
 
 
-		const contextData = { tempWrite: false };
-
 		const params = this.params;
 		const params = this.params;
 		const stackNode = properties.stackNode;
 		const stackNode = properties.stackNode;
 
 
@@ -169,7 +170,7 @@ class LoopNode extends Node {
 
 
 		}
 		}
 
 
-		const stackSnippet = context( stackNode, contextData ).build( builder, 'void' );
+		const stackSnippet = stackNode.build( builder, 'void' );
 
 
 		const returnsSnippet = properties.returnsNode ? properties.returnsNode.build( builder ) : '';
 		const returnsSnippet = properties.returnsNode ? properties.returnsNode.build( builder ) : '';
 
 

+ 1 - 2
examples/webgpu_skinning_instancing.html

@@ -140,8 +140,7 @@
 				renderer.setAnimationLoop( animate );
 				renderer.setAnimationLoop( animate );
 				document.body.appendChild( renderer.domElement );
 				document.body.appendChild( renderer.domElement );
 
 
-				// post processing ( just for WebGPUBackend for now )
-
+				// post processing
 
 
 				const scenePass = pass( scene, camera );
 				const scenePass = pass( scene, camera );
 				const scenePassColor = scenePass.getTextureNode();
 				const scenePassColor = scenePass.getTextureNode();