mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.63k stars 35.37k forks source link

TSL: `If` statement produces WGSL error. #28794

Open Mugen87 opened 4 months ago

Mugen87 commented 4 months ago

Description

I'm currently trying to port the FXAA shader to TSL. The code uses more than one return statement to return a color value computed in its FxaaPixelShader() function.

Using an If() statement in TSL to determine if a return is required produces a WGSL error though.

Error while parsing WGSL: :40:3 error: return statement type must match its function return type, returned 'vec4', expected 'OutputStruct' return vec4( 1.0, 0.0, 0.0, 1.0 ); ^^^^^^

I have reproduce the issue with a live example by writing a simple effect that output just two colors depending on how an if statement evaluates.

Reproduction steps

  1. Go to https://jsfiddle.net/pq2dtag3/
  2. Check browser console.

Code

class CustomEffectNode extends TempNode {

    constructor() {

        super();

    }

    setup() {

        const effect = tslFn( () => {

            If( uv().x.lessThan( 0.5 ), () => {

                    return vec4( 1, 0, 0, 1 );

                } );

            return vec4( 0, 0, 1, 1 );

        } );

        const outputNode = effect();

        return outputNode;

    }

}

Live example

https://jsfiddle.net/pq2dtag3/

Screenshots

No response

Version

r167dev

Device

Desktop

Browser

Chrome

OS

MacOS

sunag commented 4 months ago

Could you use an setLayout() for now, until I create an approach for this problem?

For example:

const DFGApprox = tslFn( ( { roughness, dotNV } ) => {

    const c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );

    const c1 = vec4( 1, 0.0425, 1.04, - 0.04 );

    const r = roughness.mul( c0 ).add( c1 );

    const a004 = r.x.mul( r.x ).min( dotNV.mul( - 9.28 ).exp2() ).mul( r.x ).add( r.y );

    const fab = vec2( - 1.04, 1.04 ).mul( a004 ).add( r.zw );

    return fab;

} ).setLayout( {
    name: 'DFGApprox',
    type: 'vec2',
    inputs: [
        { name: 'roughness', type: 'float' },
        { name: 'dotNV', type: 'vec3' }
    ]
} );
Mugen87 commented 4 months ago

Setting the layout did work when I've implemented NeutralToneMapping support for WebGPURenderer.

But unfortunately, it does not seem to work in this particular case: https://jsfiddle.net/5esvrnuy/

Mugen87 commented 4 months ago

I'll try a workaround by putting the code holding the if statements in another TSL function and call it from the main TSL function that is returned by setup().

If that does not work, I'll reopen the issue.

sunag commented 4 months ago

It's better transfer uniforms/varyings using parameters for now if used layout. texture as parameters is not avaiable for layout yet:

 const effect = tslFn( ( { uv } ) => {

    If( uv.x.lessThan( 0.5 ), () => {

        return vec4( 1, 0, 0, 1 );

    } );

      return vec4( 0, 0, 1, 1 );

} ).setLayout( {
      name: 'effect',
      type: 'vec4',
      inputs: [
        { name: 'uv', type: 'vec2' }
      ]
} );

const outputNode = effect( { uv: uv() } );

It's no problem to keep this issue open, as it requires improvement. It is related to the automatic creation of the layout.

Mugen87 commented 4 months ago

Probably should make a different issue for this but maybe I'm just doing something wrong on my side. I'm making progress with porting FXAA but now I'm stuck again. The TSL port of FXAAShader produces the following WGSL error:

Error while parsing WGSL: :99:15 error: 'textureSampleBias' must only be called from uniform control flow

I've demonstrated the issue with a stripped-down version of FXAANode. Most of the code is commented out:

https://jsfiddle.net/eouc17gv/1/

The following fiddle is almost the same version but the if statement that produces the above error is now commented out. This should demonstrate the the previous parts of the code work:

https://jsfiddle.net/eouc17gv/2/ (this is actually a nice learning resource since it shows how FXAA detects low-frequency image parts where no anti-aliasing will be applied 🤓 ).

FYI: I could fix a the same warning previously with adding toVar() but that does not seem to help in this instance.

sunag commented 4 months ago

Error while parsing WGSL: :99:15 error: 'textureSampleBias' must only be called from uniform control flow

Try sample the texture outside the conditional, TSL does not yet handle this type of situation in WGSL automatically. It would be part of the limitations of WGSL...