Skip to content

Commit e190a41

Browse files
sunagRuthySheffi
authored andcommitted
TSL: Fix .toVarying() analyze for optimization (mrdoob#31090)
* fix cache of varying inside a conditional of fragment stage * add `isAssignNode` * improve optimization system for varyings * cleanup * second approach * Update StackNode.js
1 parent 55b6c2b commit e190a41

File tree

6 files changed

+93
-13
lines changed

6 files changed

+93
-13
lines changed

src/nodes/core/AssignNode.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ class AssignNode extends TempNode {
4040
*/
4141
this.sourceNode = sourceNode;
4242

43+
/**
44+
* This flag can be used for type testing.
45+
*
46+
* @type {boolean}
47+
* @readonly
48+
* @default true
49+
*/
50+
this.isAssignNode = true;
51+
4352
}
4453

4554
/**

src/nodes/core/Node.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -506,11 +506,21 @@ class Node extends EventDispatcher {
506506
* This stage analyzes the node hierarchy and ensures descendent nodes are built.
507507
*
508508
* @param {NodeBuilder} builder - The current node builder.
509+
* @param {?Node} output - The target output node.
509510
*/
510-
analyze( builder ) {
511+
analyze( builder, output = null ) {
511512

512513
const usageCount = builder.increaseUsage( this );
513514

515+
if ( this.parents === true ) {
516+
517+
const nodeData = builder.getDataFromNode( this, 'any' );
518+
nodeData.stages = nodeData.stages || {};
519+
nodeData.stages[ builder.shaderStage ] = nodeData.stages[ builder.shaderStage ] || [];
520+
nodeData.stages[ builder.shaderStage ].push( output );
521+
522+
}
523+
514524
if ( usageCount === 1 ) {
515525

516526
// node flow children
@@ -521,7 +531,7 @@ class Node extends EventDispatcher {
521531

522532
if ( childNode && childNode.isNode === true ) {
523533

524-
childNode.build( builder );
534+
childNode.build( builder, this );
525535

526536
}
527537

@@ -600,7 +610,7 @@ class Node extends EventDispatcher {
600610
* - **generate**: Generates the shader code for the node. Returns the generated shader string.
601611
*
602612
* @param {NodeBuilder} builder - The current node builder.
603-
* @param {?string} [output=null] - Can be used to define the output type.
613+
* @param {string|Node|null} [output=null] - Can be used to define the output type.
604614
* @return {Node|string|null} The result of the build process, depending on the build stage.
605615
*/
606616
build( builder, output = null ) {
@@ -669,7 +679,7 @@ class Node extends EventDispatcher {
669679

670680
} else if ( buildStage === 'analyze' ) {
671681

672-
this.analyze( builder );
682+
this.analyze( builder, output );
673683

674684
} else if ( buildStage === 'generate' ) {
675685

src/nodes/core/NodeBuilder.js

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,27 +2285,53 @@ class NodeBuilder {
22852285
* @param {Node} node - The node to execute.
22862286
* @param {?string} output - Expected output type. For example 'vec3'.
22872287
* @param {?string} propertyName - The property name to assign the result.
2288-
* @return {Object}
2288+
* @return {Object|Node|null} The code flow or node.build() result.
22892289
*/
22902290
flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) {
22912291

2292+
const previousTab = this.tab;
2293+
const previousCache = this.cache;
22922294
const previousShaderStage = this.shaderStage;
2295+
const previousContext = this.context;
22932296

22942297
this.setShaderStage( shaderStage );
22952298

2296-
const flowData = this.flowChildNode( node, output );
2299+
const context = { ...this.context };
2300+
delete context.nodeBlock;
22972301

2298-
if ( propertyName !== null ) {
2302+
this.cache = this.globalCache;
2303+
this.tab = '\t';
2304+
this.context = context;
22992305

2300-
flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`;
2306+
let result = null;
23012307

2302-
}
2308+
if ( this.buildStage === 'generate' ) {
2309+
2310+
const flowData = this.flowChildNode( node, output );
2311+
2312+
if ( propertyName !== null ) {
23032313

2304-
this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code;
2314+
flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`;
2315+
2316+
}
2317+
2318+
this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code;
2319+
2320+
result = flowData;
2321+
2322+
} else {
2323+
2324+
result = node.build( this );
2325+
2326+
}
23052327

23062328
this.setShaderStage( previousShaderStage );
23072329

2308-
return flowData;
2330+
this.cache = previousCache;
2331+
this.tab = previousTab;
2332+
this.context = previousContext;
2333+
2334+
return result;
23092335

23102336
}
23112337

src/nodes/core/StackNode.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,32 @@ class StackNode extends Node {
251251

252252
setCurrentStack( this );
253253

254+
const buildStage = builder.buildStage;
255+
254256
for ( const node of this.nodes ) {
255257

256-
node.build( builder, 'void' );
258+
if ( buildStage === 'setup' ) {
259+
260+
node.build( builder );
261+
262+
} else if ( buildStage === 'analyze' ) {
263+
264+
node.build( builder, this );
265+
266+
} else if ( buildStage === 'generate' ) {
267+
268+
const stages = builder.getDataFromNode( node, 'any' ).stages;
269+
const parents = stages && stages[ builder.shaderStage ];
270+
271+
if ( node.isVarNode && parents && parents.length === 1 && parents[ 0 ] && parents[ 0 ].isStackNode ) {
272+
273+
continue; // skip var nodes that are only used in .toVarying()
274+
275+
}
276+
277+
node.build( builder, 'void' );
278+
279+
}
257280

258281
}
259282

src/nodes/core/VarNode.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ class VarNode extends Node {
7272
*/
7373
this.readOnly = readOnly;
7474

75+
/**
76+
*
77+
* Add this flag to the node system to indicate that this node require parents.
78+
*
79+
* @type {boolean}
80+
* @default true
81+
*/
82+
this.parents = true;
83+
7584
}
7685

7786
getMemberType( builder, name ) {

src/nodes/core/VaryingNode.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class VaryingNode extends Node {
9797

9898
this.interpolationType = type;
9999
this.interpolationSampling = sampling;
100+
100101
return this;
101102

102103
}
@@ -150,13 +151,15 @@ class VaryingNode extends Node {
150151

151152
this.setupVarying( builder );
152153

154+
builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
155+
153156
}
154157

155158
analyze( builder ) {
156159

157160
this.setupVarying( builder );
158161

159-
return this.node.analyze( builder );
162+
builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
160163

161164
}
162165

0 commit comments

Comments
 (0)