Skip to content

Commit 60d8954

Browse files
authored
TSL: Introduce uniformFlow() (#31531)
* init branch * fixes * move to new approach, adjust existing conditional node flow to take advantage of more existing flow code functionality * remove forceWebGL checks * cleanup * revert requested examples * fix typo * try build again * fix spacing in select statement * change
1 parent 13be9fb commit 60d8954

File tree

9 files changed

+79
-6
lines changed

9 files changed

+79
-6
lines changed

examples/webgpu_compute_cloth.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,4 +561,4 @@
561561

562562
</script>
563563
</body>
564-
</html>
564+
</html>

examples/webgpu_compute_points.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import Stats from 'stats-gl';
3131

3232

33-
import { Fn, uniform, instancedArray, float, vec2, vec3, color, instanceIndex } from 'three/tsl';
33+
import { Fn, uniform, instancedArray, float, vec2, color, instanceIndex } from 'three/tsl';
3434

3535
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
3636

@@ -76,7 +76,7 @@
7676
const pointerSize = 0.1;
7777
const distanceFromPointer = pointer.sub( position ).length();
7878

79-
particle.assign( distanceFromPointer.lessThanEqual( pointerSize ).select( vec3(), position ) );
79+
particle.assign( distanceFromPointer.lessThanEqual( pointerSize ).select( vec2(), position ) );
8080

8181
} );
8282

examples/webgpu_compute_sort_bitonic.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@
383383

384384
} else {
385385

386-
nextAlgo.assign( nextBlockHeight.greaterThan( WORKGROUP_SIZE[ 0 ] * 2 ).select( StepType.DISPERSE_GLOBAL, StepType.DISPERSE_LOCAL ) );
386+
nextAlgo.assign( nextBlockHeight.greaterThan( WORKGROUP_SIZE[ 0 ] * 2 ).select( StepType.DISPERSE_GLOBAL, StepType.DISPERSE_LOCAL ).uniformFlow() );
387387

388388
}
389389

src/Three.TSL.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ export const uniform = TSL.uniform;
547547
export const uniformArray = TSL.uniformArray;
548548
export const uniformCubeTexture = TSL.uniformCubeTexture;
549549
export const uniformGroup = TSL.uniformGroup;
550+
export const uniformFlow = TSL.uniformFlow;
550551
export const uniformTexture = TSL.uniformTexture;
551552
export const unpremultiplyAlpha = TSL.unpremultiplyAlpha;
552553
export const userData = TSL.userData;

src/nodes/core/ContextNode.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,16 @@ export default ContextNode;
131131
*/
132132
export const context = /*@__PURE__*/ nodeProxy( ContextNode ).setParameterLength( 1, 2 );
133133

134+
/**
135+
* TSL function for defining a uniformFlow context value for a given node.
136+
*
137+
* @tsl
138+
* @function
139+
* @param {Node} node - The node whose dependencies should all execute within a uniform control-flow path.
140+
* @returns {ContextNode}
141+
*/
142+
export const uniformFlow = ( node ) => context( node, { uniformFlow: true } );
143+
134144
/**
135145
* TSL function for defining a name for the context value for a given node.
136146
*
@@ -162,4 +172,5 @@ export function label( node, name ) {
162172

163173
addMethodChaining( 'context', context );
164174
addMethodChaining( 'label', label );
175+
addMethodChaining( 'uniformFlow', uniformFlow );
165176
addMethodChaining( 'setName', setName );

src/nodes/core/NodeBuilder.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,22 @@ class NodeBuilder {
826826

827827
}
828828

829+
/**
830+
* Returns the native snippet for a ternary operation. E.g. GLSL would output
831+
* a ternary op as `cond ? x : y` whereas WGSL would output it as `select(y, x, cond)`
832+
*
833+
* @abstract
834+
* @param {string} condSnippet - The condition determining which expression gets resolved.
835+
* @param {string} ifSnippet - The expression to resolve to if the condition is true.
836+
* @param {string} elseSnippet - The expression to resolve to if the condition is false.
837+
* @return {string} The resolved method name.
838+
*/
839+
getTernary( /* condSnippet, ifSnippet, elseSnippet*/ ) {
840+
841+
return null;
842+
843+
}
844+
829845
/**
830846
* Returns a node for the given hash, see {@link NodeBuilder#setHashNode}.
831847
*

src/nodes/math/ConditionalNode.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,12 @@ class ConditionalNode extends Node {
112112

113113
//
114114

115+
const isUniformFlow = builder.context.uniformFlow;
116+
115117
const properties = builder.getNodeProperties( this );
116118
properties.condNode = condNode;
117-
properties.ifNode = ifNode.context( { nodeBlock: ifNode } );
118-
properties.elseNode = elseNode ? elseNode.context( { nodeBlock: elseNode } ) : null;
119+
properties.ifNode = isUniformFlow ? ifNode : ifNode.context( { nodeBlock: ifNode } );
120+
properties.elseNode = elseNode ? ( isUniformFlow ? elseNode : elseNode.context( { nodeBlock: elseNode } ) ) : null;
119121

120122
}
121123

@@ -140,6 +142,20 @@ class ConditionalNode extends Node {
140142
nodeData.nodeProperty = nodeProperty;
141143

142144
const nodeSnippet = condNode.build( builder, 'bool' );
145+
const isUniformFlow = builder.context.uniformFlow;
146+
147+
if ( isUniformFlow && elseNode !== null ) {
148+
149+
const ifSnippet = ifNode.build( builder, type );
150+
const elseSnippet = elseNode.build( builder, type );
151+
152+
const mathSnippet = builder.getTernary( nodeSnippet, ifSnippet, elseSnippet );
153+
154+
// TODO: If node property already exists return something else
155+
156+
return builder.format( mathSnippet, type, output );
157+
158+
}
143159

144160
builder.addFlowCode( `\n${ builder.tab }if ( ${ nodeSnippet } ) {\n\n` ).addFlowTab();
145161

src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,20 @@ class GLSLNodeBuilder extends NodeBuilder {
134134

135135
}
136136

137+
/**
138+
* Returns the native snippet for a ternary operation.
139+
*
140+
* @param {string} condSnippet - The condition determining which expression gets resolved.
141+
* @param {string} ifSnippet - The expression to resolve to if the condition is true.
142+
* @param {string} elseSnippet - The expression to resolve to if the condition is false.
143+
* @return {string} The resolved method name.
144+
*/
145+
getTernary( condSnippet, ifSnippet, elseSnippet ) {
146+
147+
return `${condSnippet} ? ${ifSnippet} : ${elseSnippet}`;
148+
149+
}
150+
137151
/**
138152
* Returns the output struct name. Not relevant for GLSL.
139153
*

src/renderers/webgpu/nodes/WGSLNodeBuilder.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,21 @@ ${ flowData.code }
18991899

19001900
}
19011901

1902+
/**
1903+
* Returns the native snippet for a ternary operation.
1904+
*
1905+
* @param {string} condSnippet - The condition determining which expression gets resolved.
1906+
* @param {string} ifSnippet - The expression to resolve to if the condition is true.
1907+
* @param {string} elseSnippet - The expression to resolve to if the condition is false.
1908+
* @return {string} The resolved method name.
1909+
*/
1910+
getTernary( condSnippet, ifSnippet, elseSnippet ) {
1911+
1912+
return `select( ${elseSnippet}, ${ifSnippet}, ${condSnippet} )`;
1913+
1914+
}
1915+
1916+
19021917
/**
19031918
* Returns the WGSL type of the given node data type.
19041919
*

0 commit comments

Comments
 (0)