Search Unity

Resolved How does a Branch node operate (behind the scenes)?

Discussion in 'Shader Graph' started by adamgolden, Sep 8, 2020.

  1. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    I have shaders that use Branch to determine flow. I'd like to confirm that the nodes connecting to the Branch are skipped entirely when not in use.

    For example, this graph allows toggle between using either a main texture plus normals texture, or using vertex color plus a value for normals. The shader itself and toggling work as expected, but I find myself wondering.. are the textures still processed and Branch just decides what to use based on the predicate? Or are things structured in a way that nodes connecting to the Branch node effectively don't exist at all when not in use?

    LitVertexLOD.jpg
     
  2. Oxeren

    Oxeren

    Joined:
    Aug 14, 2013
    Posts:
    121
    I remember it being just a lerp before, but i've chekced the manual and it seems they have replaced lerp with a ternary operator. But anyway, it is a function that takes both true and false values as inputs, so they are both evaluated. The manual says the same: "Both sides of the branch will be evaluated in the shader, and the branch not used will be discarded.
    I also needed real conditionals in Shader Graph and had to use custom functions for that.
     
    adamgolden likes this.
  3. StaggartCreations

    StaggartCreations

    Joined:
    Feb 18, 2015
    Posts:
    2,258
    Generally if the branching condition is not a constant value (say, a mask texture, or vertex colors), both branches are executed, and one of the two is discarded. If the condition is a constant, like a shader property there's a good chance a modern GPU driver will not execute the other branch. I think this is more of an issue regarding (older) mobile hardware. Eventually the only way to know for sure is to hookup a graphics debugger on the hardware you're running it on.

    An absolute certain way to avoid branching is to use shader variants, which will end up compiling two versions of the same shader. One evaluating to branch A, and the other to branch B. Shader Graph does support this through the Keyword node.

    Though if you're sampling a normal map in one branch, and look at the shader code. Not everything related to it is going to be wrapped in the keyword scope (passing the normal, tangent and bitangent from the vertex to the pixel shader for one). But the shader compiler is going to throw away everything that ends up being unused away.
     
    Lex4art and adamgolden like this.
  4. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    @Oxeren - thank you for the answer. I was hoping to avoid a material swap this way, but it's fine.. now I won't need to flip a bool and won't have branch nodes or texture nodes so it'll all be the same shared material. Probably for the best in this case at least, but it sure would be great if Branch nodes could be used to optimize in this way. Anyway, thanks again.