Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question Benefits to taking if-else maths out of fragment shader!

Discussion in 'Shaders' started by andyz, Jun 30, 2022.

  1. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    1,939
    Sometimes it seems normal & simple to add a load of maths in the (frag) shader, but it isn't optimal. Not if you can pre-calculate it in the vertex shader or even for the whole material - property level.

    So take a bit of if-else maths as an example, where b is a shader property: a = b < .5 ? b*.8 : .4 + ((b-.5)*2.0);
    I imagine the cost is as follows:
    1. (fastest, ugly) Pre-calculate a new property for the material (in C#) - pass an extra property to shader
    2. (next fastest, but more vertex data) Pre-calculate in vertex shader - pass to fragment
    3. (slowest) Just do the maths in fragment

    At a guess, is it worth removing (from frag) small if-else maths like this if you are supporting more basic desktop GPUs and/or mobile devices?
    And is there only minor penalty for doing in vertex shader (assuming not ultra-high poly counts!)?
    Are if-else statements still a note-worthy penalty on mobile and older GPUs?
     
  2. _Franz

    _Franz

    Joined:
    Apr 29, 2016
    Posts:
    3
    I'm not sure if that is true for every platform but as far as I understand, in Shaders both cases (if and else) will get executed anyway because of the GPU it parallel nature.

    As long you are not bottlenecked by memory or you work on some other edge cases like point clouds or volumetric calculations. I guess its better to move the math from fragment to vertex.

    For calculate values passing via property. It depends. Do you calculate it in every frame? Is it a shared global property? And where is your bottlenecked?
    I had cases where on IOS and Android it was fine to waste circles in the GPU since the CPU was at its limit.
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    11,701
    Doing it in c# before hand is indeed the fastest.

    Doing it in the fragment shader is likely the next fastest.

    This is counter intuitive, and may not be true on all GPUs and in all cases, but there's a cost to transferring data between the vertex and the fragment that most people do not take into account. For simple calculations like the above example, it's almost guaranteed to be more expensive to do it in the vertex shader. But the only way to know it's to try both options.

    And yes, there's a difference between mobile and desktop GPUs here. Mobile the vertex based method may win out slightly more often than on desktop. Both GPUs have gotten insanely fast at doing math, and not increased how fast it is to move things around in memory at the same pace.
     
    andyz likes this.
unityunity