Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 56 additions & 6 deletions src/nodes/code/FunctionCallNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,38 @@ class FunctionCallNode extends TempNode {
const inputs = functionNode.getInputs( builder );
const parameters = this.parameters;

// Track storage pointer bindings for this function
const storageBindingMap = {};

const generateInput = ( node, inputNode ) => {

const type = inputNode.type;
const pointer = type === 'pointer';
const storagePointer = type === 'storagePointer';

let output;

if ( pointer ) output = '&' + node.build( builder );
else output = node.build( builder, type );
if ( storagePointer ) {

// Build the storage buffer node - this registers it as a uniform/binding
// and returns the property name (e.g., "nodeU1")
output = node.build( builder );

// Store the mapping from parameter name to the generated binding name
storageBindingMap[ inputNode.name ] = output;

// Return null to indicate this parameter should not be in the call
return null;

} else if ( pointer ) {

output = '&' + node.build( builder );

} else {

output = node.build( builder, type );

}

return output;

Expand Down Expand Up @@ -140,7 +163,14 @@ class FunctionCallNode extends TempNode {

for ( let i = 0; i < parameters.length; i ++ ) {

params.push( generateInput( parameters[ i ], inputs[ i ] ) );
const result = generateInput( parameters[ i ], inputs[ i ] );

// Only add non-storage pointer parameters to the call
if ( result !== null ) {

params.push( result );

}

}

Expand All @@ -152,20 +182,40 @@ class FunctionCallNode extends TempNode {

if ( node !== undefined ) {

params.push( generateInput( node, inputNode ) );
const result = generateInput( node, inputNode );

// Only add non-storage pointer parameters to the call
if ( result !== null ) {

params.push( result );

}

} else {

error( `TSL: Input '${ inputNode.name }' not found in \'Fn()\'.` );
// Only error for non-storage pointer parameters
if ( inputNode.type !== 'storagePointer' ) {

error( `TSL: Input '${ inputNode.name }' not found in \'Fn()\'.` );

params.push( generateInput( float( 0 ), inputNode ) );
params.push( generateInput( float( 0 ), inputNode ) );

}

}

}

}

// Store storage binding map in builder's node data for FunctionNode to use
if ( Object.keys( storageBindingMap ).length > 0 ) {

const functionNodeData = builder.getDataFromNode( functionNode );
functionNodeData.storageBindingMap = storageBindingMap;

}

const functionName = functionNode.build( builder, 'property' );

return `${ functionName }( ${ params.join( ', ' ) } )`;
Expand Down
41 changes: 40 additions & 1 deletion src/nodes/code/FunctionNode.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CodeNode from './CodeNode.js';
import { nodeObject } from '../tsl/TSLBase.js';

Check warning on line 2 in src/nodes/code/FunctionNode.js

View workflow job for this annotation

GitHub Actions / Lint, Unit, Unit addons, Circular dependencies & Examples testing

'nodeObject' is defined but never used

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import nodeObject.

/**
* This class represents a native shader function. It can be used to implement
Expand Down Expand Up @@ -45,6 +46,15 @@

super( code, includes, language );

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isFunctionNode = true;

}

/**
Expand Down Expand Up @@ -114,6 +124,35 @@

generate( builder, output ) {

// Get storage binding map if set by FunctionCallNode (before building includes)
const nodeData = builder.getDataFromNode( this );
const storageBindingMap = nodeData.storageBindingMap || null;

// Propagate storage binding map to included functions before building them
if ( storageBindingMap !== null ) {

const includes = this.getIncludes( builder );

for ( const include of includes ) {

if ( include.isFunctionNode || ( include.value && include.value.isFunctionNode ) ) {

const includeNode = include.isFunctionNode ? include : include.value;
const includeData = builder.getDataFromNode( includeNode );

// Merge storage binding maps (don't overwrite if already set)
if ( ! includeData.storageBindingMap ) {

includeData.storageBindingMap = storageBindingMap;

}

}

}

}

super.generate( builder );

const nodeFunction = this.getNodeFunction( builder );
Expand All @@ -133,7 +172,7 @@

const propertyName = builder.getPropertyName( nodeCode );

const code = this.getNodeFunction( builder ).getCode( propertyName );
const code = this.getNodeFunction( builder ).getCode( propertyName, storageBindingMap );

nodeCode.code = code + '\n';

Expand Down
Loading
Loading