Search Unity

Replace all multi_compile by static branching if(), good idea or not?

Discussion in 'Shaders' started by colin299, Mar 5, 2020.

  1. colin299

    colin299

    Joined:
    Sep 2, 2013
    Posts:
    181
    I am writing an uber shader for URP, I am wondering which or the following option is better.
    -multi_compile
    -static branching if()

    multi_compile's disadvantage:
    • spike when each shader variant was seen by the camera first time (trigger create GPU program)
    • build time very long (2^n) where n is the number of features
    • shader size becomes very large easily
    • will break SRP batcher's batching because it is batch by each shader variant
    • quite annoying if you need to update shader variant collection for a better shader warmup
    static branching if() 's disadvantage:
    • GPU performance is slower (but by how much? is it neglectable ? I am targeting mobile)
    • higher chance to reach shader's limitation like registry/instruction count

    Question: I wonder if multi_compile is still always a better option than static branching if() in URP?
    -----------------------------------------
    The following are links that I found which support the following statement
    "if() itself is not a problem, only dynamic branching inside a wavefront is."

    tweet
    https://twitter.com/bgolus/status/1235351597816795136
    https://twitter.com/bgolus/status/1235254923819802626?s=20

    shadertoy
    https://www.shadertoy.com/view/wlsG...0AMPS5XpbtBPSzSN9Mh8clW4itRgDIpy5ROcXW1Iyf86g

    stackoverflow
    https://stackoverflow.com/questions...aVj4YGZwBwgcYXvVkpRAo7MXbWxK5CN02pTPRG2uB8bCU
     
    Last edited: Mar 6, 2020
  2. Dragnipurake97

    Dragnipurake97

    Joined:
    Sep 28, 2019
    Posts:
    40
    Will depend on what you are branching for I reckon. There are some tricks you can do to avoid branching in some cases though: http://theorangeduck.com/page/avoiding-shader-conditionals

    Not all branching is bad though, for instance I am using an if statement to do some logic for each eye and that causes no divergence because each eye is rendered separately.
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Oh no... don't do any of those.
    https://twitter.com/bgolus/status/1235349901518630912?s=20

    As per the original tweet @colin299 linked to, https://twitter.com/bgolus/status/1235254923819802626 , conditionals aren't bad and lots of stuff people do to avoid conditionals don't avoid them because the intrinsic functions they are using are also conditionals.

    Plus that is from 2013. GPUs are much different today than they were 7 years ago (though that article was probably wrong then too).



    If you're targeting recent-ish OpenGL ES 3.0 or Metal devices and plan on having features be toggled by material properties, it'll be relative fast. Yes it'll be slower than using variants in terms of the cost of a single draw, but it may be overall faster due to avoiding render state switching costs (changing the shader).

    If you're targeting OpenGL ES 2.0 ... those don't do branching at all so it'll be doing all features all the time.

    Best thing you can do is try both and see if one ends up being obviously faster than the other. Start with variants so the keywords get set, then remove the multi_compile / shader_feature lines and #if blocks and use if statements.
     
    Last edited: Mar 6, 2020
    craig_cerceo and colin299 like this.