Skip to content

TSL - SetLayout Function Being Constructed Multiple Times in WGSL Output #31827

@cmhhelgeson

Description

@cmhhelgeson

Description

Encountered this error when trying to encapsulate bitonic sort.

The function:

export const getBitonicFlipIndices = /*@__PURE__*/ Fn( ( [ index, swapSpan ] ) => {

	const blockOffset = ( index.mul( 2 ).div( swapSpan ) ).mul( swapSpan );
	const halfHeight = swapSpan.div( 2 );
	const idx = uvec2(
		index.mod( halfHeight ),
		swapSpan.sub( index.mod( halfHeight ) ).sub( 1 )
	);
	idx.x.addAssign( blockOffset );
	idx.y.addAssign( blockOffset );

	return idx;

}, { index: 'uint', swapSpan: 'uint', return: 'uvec2' } );

And it's invocation in the ComputeNodes:

class BitonicSort {
...

_globalCompareAndSwapTSL( idxBefore, idxAfter, dataBuffer, tempBuffer ) {
	// If the later element is less than the current element
	If( dataBuffer.element( idxAfter ).lessThan( dataBuffer.element( idxBefore ) ), () => {
		tempBuffer.element( idxBefore ).assign( dataBuffer.element( idxAfter ) );
		tempBuffer.element( idxAfter ).assign( dataBuffer.element( idxBefore ) );
	} ).Else( () => {
		// Otherwise apply the existing values to temporary storage.
		tempBuffer.element( idxBefore ).assign( dataBuffer.element( idxBefore ) );
		tempBuffer.element( idxAfter ).assign( dataBuffer.element( idxAfter ) );
	} );
}

_getFlipGlobal() {
	const { infoStorage, tempBuffer, dataBuffer } = this;
	const currentSwapSpan = infoStorage.element( 1 );
	const fnDef = Fn( () => {
		const idx = getBitonicFlipIndices( instanceIndex, currentSwapSpan );
		this._globalCompareAndSwapTSL( idx.x, idx.y, dataBuffer, tempBuffer );
	} )().compute( this.dispatchSize, [ this.workgroupSize ] );
	return fnDef;
}

}

Generates this WGSL output, where the function fn2 is being called two more times than necessary ( the relevant line to search for is "fn2( instanceIndex, BitonicSortInfo.value[ 1u ] );" )

// Three.js r180dev - Node System

// codes
fn fn2 ( index : u32, swapSpan : u32 ) -> vec2<u32> {

	var nodeVar0 : u32;
	var nodeVar1 : vec2<u32>;
	var nodeVar2 : u32;

	nodeVar0 = ( swapSpan / 2u );
	nodeVar1 = vec2<u32>( ( index % nodeVar0 ), ( ( swapSpan - ( index % nodeVar0 ) ) - 1u ) );
	nodeVar2 = ( ( ( index * 2u ) / swapSpan ) * swapSpan );
	nodeVar1.x = ( nodeVar1.x + nodeVar2 );
	nodeVar1.y = ( nodeVar1.y + nodeVar2 );

	return nodeVar1;

}

@compute @workgroup_size( 64, 1, 1 )
fn main( @builtin( global_invocation_id ) globalId : vec3<u32>,
	@builtin( workgroup_id ) workgroupId : vec3<u32>,
	@builtin( local_invocation_id ) localId : vec3<u32>,
	@builtin( num_workgroups ) numWorkgroups : vec3<u32>,
	@builtin( subgroup_size ) subgroupSize : u32 ) {

	// system
	instanceIndex = globalId.x
		+ globalId.y * ( 64 * numWorkgroups.x )
		+ globalId.z * ( 64 * numWorkgroups.x ) * ( 1 * numWorkgroups.y );
	
	var nodeVar0 : vec2<u32>;
	var nodeVar1 : vec2<u32>;
	var nodeVar2 : vec2<u32>;

        // fn2 being called 2 extra times

	nodeVar0 = fn2( instanceIndex, BitonicSortInfo.value[ 1u ] );
	if ( ( Elements.value[ nodeVar0.y ] < Elements.value[ nodeVar0.x ] ) ) {
		nodeVar1 = fn2( instanceIndex, BitonicSortInfo.value[ 1u ] );
		TempStorage.value[ nodeVar1.x ] = Elements.value[ nodeVar1.y ];
		TempStorage.value[ nodeVar1.y ] = Elements.value[ nodeVar1.x ];
	} else {
		nodeVar2 = fn2( instanceIndex, BitonicSortInfo.value[ 1u ] );
		TempStorage.value[ nodeVar2.x ] = Elements.value[ nodeVar2.x ];
		TempStorage.value[ nodeVar2.y ] = Elements.value[ nodeVar2.y ];
	}
}

Reproduction steps

  1. Currently this is occurring on a non-functional version of an encapsulated bitonic sort that I am working on for both webgpu_compute_sort_bitonic and eventually birds, but the most up to date version of the branch is here. I've included a console.log of this.computeShader in the githack. The shader generating the display on the left is obviously non-functional.

  2. Search for the relevant line of text 'fn2( instanceIndex, BitonicSortInfo.value[ 1u ] );' in the Chrome devTools. The global flip shader should at most be compiled around three seconds after the example begins.

Code

Seen above...can post full class (albeit incomplete) if requested.

Live example

https://raw.githack.com/cmhhelgeson/three.js/cmh/birds_hash/examples/webgpu_compute_sort_bitonic.html

...

Screenshots

No response

Version

r180

Device

Desktop

Browser

Chrome

OS

Windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    TSLThree.js Shading Language

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions