From 9641add693fe9e2e919b40a9ec196f39b068a263 Mon Sep 17 00:00:00 2001 From: sunag Date: Sun, 30 Nov 2025 03:50:58 -0300 Subject: [PATCH] TSL: Fix non-stack function call with loops (#32420) --- src/nodes/core/AssignNode.js | 4 +-- src/nodes/core/StackNode.js | 64 +++++++++++++++++++++++++++++----- src/nodes/core/VarNode.js | 67 +++++++++++++++++++++++++----------- 3 files changed, 104 insertions(+), 31 deletions(-) diff --git a/src/nodes/core/AssignNode.js b/src/nodes/core/AssignNode.js index 68bf5d96ded639..c6cca706b58cd3 100644 --- a/src/nodes/core/AssignNode.js +++ b/src/nodes/core/AssignNode.js @@ -99,8 +99,8 @@ class AssignNode extends TempNode { const scope = targetNode.getScope(); - const targetProperties = builder.getNodeProperties( scope ); - targetProperties.assign = true; + const scopeData = builder.getDataFromNode( scope ); + scopeData.assign = true; const properties = builder.getNodeProperties( this ); properties.sourceNode = sourceNode; diff --git a/src/nodes/core/StackNode.js b/src/nodes/core/StackNode.js index fcd7dc06bd5bdc..14419218375065 100644 --- a/src/nodes/core/StackNode.js +++ b/src/nodes/core/StackNode.js @@ -68,6 +68,15 @@ class StackNode extends Node { */ this._expressionNode = null; + /** + * The current node being processed. + * + * @private + * @type {Node} + * @default null + */ + this._currentNode = null; + /** * This flag can be used for type testing. * @@ -101,9 +110,10 @@ class StackNode extends Node { * Adds a node to this stack. * * @param {Node} node - The node to add. + * @param {number} [index=this.nodes.length] - The index where the node should be added. * @return {StackNode} A reference to this stack node. */ - addToStack( node ) { + addToStack( node, index = this.nodes.length ) { if ( node.isNode !== true ) { @@ -112,12 +122,26 @@ class StackNode extends Node { } - this.nodes.push( node ); + this.nodes.splice( index, 0, node ); return this; } + /** + * Adds a node to the stack before the current node. + * + * @param {Node} node - The node to add. + * @return {StackNode} A reference to this stack node. + */ + addToStackBefore( node ) { + + const index = this._currentNode ? this.nodes.indexOf( this._currentNode ) : 0; + + return this.addToStack( node, index ); + + } + /** * Represent an `if` statement in TSL. * @@ -267,7 +291,7 @@ class StackNode extends Node { for ( const childNode of this.getChildren() ) { - if ( childNode.isVarNode && childNode.intent === true ) { + if ( childNode.isVarNode && childNode.isIntent( builder ) ) { if ( childNode.isAssign( builder ) !== true ) { @@ -297,19 +321,23 @@ class StackNode extends Node { const previousStack = getCurrentStack(); + const buildStage = builder.buildStage; + setCurrentStack( this ); builder.setActiveStack( this ); - const buildStage = builder.buildStage; + // - for ( const node of this.nodes ) { + const buildNode = ( node ) => { - if ( node.isVarNode && node.intent === true ) { + this._currentNode = node; + + if ( node.isVarNode && node.isIntent( builder ) ) { if ( node.isAssign( builder ) !== true ) { - continue; + return; } @@ -330,7 +358,7 @@ class StackNode extends Node { if ( node.isVarNode && parents && parents.length === 1 && parents[ 0 ] && parents[ 0 ].isStackNode ) { - continue; // skip var nodes that are only used in .toVarying() + return; // skip var nodes that are only used in .toVarying() } @@ -338,6 +366,26 @@ class StackNode extends Node { } + }; + + // + + const nodes = [ ...this.nodes ]; + + for ( const node of nodes ) { + + buildNode( node ); + + } + + this._currentNode = null; + + const newNodes = this.nodes.filter( ( node ) => nodes.indexOf( node ) === - 1 ); + + for ( const node of newNodes ) { + + buildNode( node ); + } // diff --git a/src/nodes/core/VarNode.js b/src/nodes/core/VarNode.js index 3727a0234d0a5e..679e7b8463db3b 100644 --- a/src/nodes/core/VarNode.js +++ b/src/nodes/core/VarNode.js @@ -112,6 +112,22 @@ class VarNode extends Node { } + /** + * Checks if this node is used for intent. + * + * @param {NodeBuilder} builder - The node builder. + * @returns {boolean} Whether this node is used for intent. + */ + isIntent( builder ) { + + const data = builder.getDataFromNode( this ); + + if ( data.forceDeclaration === true ) return false; + + return this.intent; + + } + /** * Returns the intent flag of this node. * @@ -149,49 +165,58 @@ class VarNode extends Node { isAssign( builder ) { - const properties = builder.getNodeProperties( this ); + const data = builder.getDataFromNode( this ); - let assign = properties.assign; + return data.assign; - if ( assign !== true ) { + } - if ( this.node.isShaderCallNodeInternal && this.node.shaderNode.getLayout() === null ) { + build( ...params ) { - if ( builder.fnCall && builder.fnCall.shaderNode ) { + const builder = params[ 0 ]; - const shaderNodeData = builder.getDataFromNode( this.node.shaderNode ); + if ( this._hasStack( builder ) === false && builder.buildStage === 'setup' ) { - if ( shaderNodeData.hasLoop ) { + if ( builder.context.nodeLoop || builder.context.nodeBlock ) { - assign = true; + let addBefore = false; - } + if ( this.node.isShaderCallNodeInternal && this.node.shaderNode.getLayout() === null ) { - } + if ( builder.fnCall && builder.fnCall.shaderNode ) { - } + const shaderNodeData = builder.getDataFromNode( this.node.shaderNode ); - } + if ( shaderNodeData.hasLoop ) { - return assign; + const data = builder.getDataFromNode( this ); + data.forceDeclaration = true; - } + addBefore = true; - build( ...params ) { + } - const builder = params[ 0 ]; + } - if ( this._hasStack( builder ) === false && builder.buildStage === 'setup' ) { + } - if ( builder.context.nodeLoop || builder.context.nodeBlock ) { + const baseStack = builder.getBaseStack(); + + if ( addBefore ) { + + baseStack.addToStackBefore( this ); - builder.getBaseStack().addToStack( this ); + } else { + + baseStack.addToStack( this ); + + } } } - if ( this.intent === true ) { + if ( this.isIntent( builder ) ) { if ( this.isAssign( builder ) !== true ) { @@ -227,7 +252,7 @@ class VarNode extends Node { if ( nodeType == 'void' ) { - if ( this.intent !== true ) { + if ( this.isIntent( builder ) !== true ) { error( 'TSL: ".toVar()" can not be used with void type.' );