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.
  2. Dismiss Notice

Bug max instruction optimized out after shader code compiling

Discussion in 'Shaders' started by dlphncheng2, Jan 6, 2021.

  1. dlphncheng2

    dlphncheng2

    Joined:
    Jun 12, 2020
    Posts:
    1
    I am puzzled about the intelligence of shader compiling.
    here is my shader snippet, it is used to compute anistropic specular lighting.
    Sorry , there are too many parentheses ,but just Focus on the last 2 lines.
    The line that begins with " half s_den" contains 2 "max" instructions. They have the same parameter (0.001) each.


    half len=max(0.001,length(((L)+(V))));
    half3 H=((((L)+(V)))/(len));
    half NoV=max(0.001,dot(V,N));
    half NoH=dot(H,N);
    half HoT=dot(H,Tangent);
    half HoB=dot(H,Binormal);
    half2 beta=half2(((HoT)/(RoughnessX)),((HoB)/(RoughnessY)));
    (beta)*=(beta);
    half s_den=max(0.001,((((((314.15926)*(RoughnessX)))*(RoughnessY)))*(max(0.001,sqrt(((NoL)*(NoV)))))));
    half aniso=((exp((((-(((beta.x)+(beta.y)))))/(max(0.01,((0.5)+(((0.5)*(NoH+0.3)))))))))/(s_den));


    Click the "compile and show code" button , I find the compiled gles3 code ralated to the "max" line.


    u_xlat16_27 = sqrt(u_xlat16_27);
    u_xlat16_15.x = u_xlat16_27 * u_xlat16_15.x;
    u_xlat16_15.x = max(u_xlat16_15.x, 0.00100000005);
    u_xlat16_3.x = u_xlat16_3.x / u_xlat16_15.x;


    the variable "u_xlat16_27" that computed by "sqrt" funcion, is supposed to excute a "max" instruction, before the subsequent multiply by "u_xlat16_15.x".
    however , it seems that unity compiler omits the second "max" funcion.
    the result on the mobile shows wrong rendering.

    then ,after making some tries, I find out assigning slightly different values to "max" function works fine sometimes.


    half s_den=max(0.001,((((((314.15926)*(RoughnessX)))*(RoughnessY)))*(max(0.0011,sqrt(((NoL)*(NoV)))))));


    the following code is the compiled gles3 snippet.

    u_xlat16_27 = sqrt(u_xlat16_27);
    u_xlat16_27 = max(u_xlat16_27, 0.00109999999);
    u_xlat16_15.x = u_xlat16_27 * u_xlat16_15.x;
    u_xlat16_15.x = max(u_xlat16_15.x, 0.00100000005);
    u_xlat16_3.x = u_xlat16_3.x / u_xlat16_15.x;


    here , we see there are 2 "max" instructions in the gles3 code, and the mobile result is correct.


    How can I avoid the problem alike happening.
    Is there some compiling regulations to follow.
    my unity is 2018.4.5f1.
    thanks ~
     
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,822
    Hi!
    Please submit a bug report, we'll take a look :)
     
  3. rjonaitis

    rjonaitis

    Unity Technologies

    Joined:
    Jan 5, 2017
    Posts:
    115
    I think "sometimes" is the key here, this looks to be more of a precision loss problem depending on the order of operations. Check if your code works with full precision instead of half.