Search Unity

Force to use highp local variables in fragment shader on Android

Discussion in 'Shaders' started by ZhivaevDmitriy, Aug 1, 2020.

  1. ZhivaevDmitriy

    ZhivaevDmitriy

    Joined:
    May 15, 2018
    Posts:
    7
    Hello, I am using Unity 2020.1.0f1 and I need to get precise height data in fragment shader on Android.
    This is necessary in order to draw beautiful elevation lines.

    My shader (I've just simply modify and copy URP graph shader):

    Code (CSharp):
    1. Shader "Unlit Master"
    2. {
    3.     Properties
    4.     {
    5.         [NoScaleOffset]SurfaceHeightfield("SurfaceHeightfield", 2D) = "black" {}
    6.     }
    7.     SubShader
    8.     {
    9.         Tags
    10.         {
    11.             "RenderPipeline"="UniversalPipeline"
    12.             "RenderType"="Opaque"
    13.             "Queue"="Geometry+0"
    14.         }
    15.        
    16.         Pass
    17.         {
    18.             Name "Pass"
    19.             Tags
    20.             {
    21.                 // LightMode: <None>
    22.             }
    23.          
    24.             // Render State
    25.             Blend One Zero, One Zero
    26.             Cull Back
    27.             ZTest LEqual
    28.             ZWrite On
    29.             // ColorMask: <None>
    30.            
    31.        
    32.             HLSLPROGRAM
    33.             #pragma vertex vert
    34.             #pragma fragment frag
    35.        
    36.             // Pragmas
    37.             #pragma prefer_hlslcc gles
    38.             #pragma exclude_renderers d3d11_9x
    39.             #pragma target 3.5
    40.             #pragma multi_compile_fog
    41.             #pragma multi_compile_instancing
    42.          
    43.             // Keywords
    44.             #pragma multi_compile _ LIGHTMAP_ON
    45.             #pragma multi_compile _ DIRLIGHTMAP_COMBINED
    46.             #pragma shader_feature _ _SAMPLE_GI
    47.             // GraphKeywords: <None>
    48.            
    49.             // Defines
    50.             #define ATTRIBUTES_NEED_NORMAL
    51.             #define ATTRIBUTES_NEED_TANGENT
    52.             #define ATTRIBUTES_NEED_TEXCOORD0
    53.             #define VARYINGS_NEED_TEXCOORD0
    54.             #pragma multi_compile_instancing
    55.             #define SHADERPASS_UNLIT
    56.            
    57.             #define PREFER_HALF 0
    58.             #define SHADER_HINT_NICE_QUALITY 1
    59.        
    60.             // Includes
    61.            
    62.             ...
    63.        
    64.             // --------------------------------------------------
    65.             // Graph
    66.        
    67.             // Graph Properties
    68.             CBUFFER_START(UnityPerMaterial)
    69.             CBUFFER_END
    70.             TEXTURE2D_FLOAT(SurfaceHeightfield);
    71.             SAMPLER(samplerSurfaceHeightfield);
    72.             float4 SurfaceHeightfield_TexelSize;
    73.             SAMPLER(SamplerState_Linear_Clamp);
    74.        
    75.             // Graph Vertex
    76.             // GraphVertex: <None>
    77.            
    78.             // Graph Pixel
    79.             struct SurfaceDescriptionInputs
    80.             {
    81.                 float4 uv0;
    82.             };
    83.            
    84.             struct SurfaceDescription
    85.             {
    86.                 float3 Color;
    87.                 float Alpha;
    88.                 float AlphaClipThreshold;
    89.             };
    90.            
    91.             SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN)
    92.             {
    93.                 SurfaceDescription surface = (SurfaceDescription)0;
    94.  
    95.                 surface.Color =
    96.                     SurfaceHeightfield.Sample(SamplerState_Linear_Clamp, IN.uv0);
    97.  
    98.                 surface.Alpha = 1;
    99.                 surface.AlphaClipThreshold = 0;
    100.  
    101.                 return surface;
    102.             }
    103.        
    104.            ...
    105.  
    106.             ENDHLSL
    107.         }
    108.  
    109.         ...
    110.  
    111.     }
    112. }
    113.  
    I have added line 57 and 58 by myself:

    #define PREFER_HALF 0
    #define SHADER_HINT_NICE_QUALITY 1


    After I press "compile and show code" and see this in glsl:
    Code (CSharp):
    1.  
    2.  
    3. ...
    4.  
    5. #ifdef VERTEX
    6. #version 300 es
    7.  
    8. ...
    9.  
    10. in highp vec3 in_POSITION0;
    11. in highp vec4 in_TEXCOORD0;
    12. out highp vec4 vs_TEXCOORD0;
    13. vec4 u_xlat0;
    14. vec4 u_xlat1;
    15. void main()
    16. {
    17.     u_xlat0.xyz = in_POSITION0.yyy * hlslcc_mtx4x4unity_ObjectToWorld[1].xyz;
    18.     u_xlat0.xyz = hlslcc_mtx4x4unity_ObjectToWorld[0].xyz * in_POSITION0.xxx + u_xlat0.xyz;
    19.     u_xlat0.xyz = hlslcc_mtx4x4unity_ObjectToWorld[2].xyz * in_POSITION0.zzz + u_xlat0.xyz;
    20.     u_xlat0.xyz = u_xlat0.xyz + hlslcc_mtx4x4unity_ObjectToWorld[3].xyz;
    21.     u_xlat1 = u_xlat0.yyyy * hlslcc_mtx4x4unity_MatrixVP[1];
    22.     u_xlat1 = hlslcc_mtx4x4unity_MatrixVP[0] * u_xlat0.xxxx + u_xlat1;
    23.     u_xlat0 = hlslcc_mtx4x4unity_MatrixVP[2] * u_xlat0.zzzz + u_xlat1;
    24.     gl_Position = u_xlat0 + hlslcc_mtx4x4unity_MatrixVP[3];
    25.     vs_TEXCOORD0 = in_TEXCOORD0;
    26.     return;
    27. }
    28.  
    29. #endif
    30. #ifdef FRAGMENT
    31. #version 300 es
    32.  
    33. precision highp float;
    34. precision highp int;
    35.  
    36. ...
    37.  
    38. UNITY_LOCATION(0) uniform highp sampler2D SurfaceHeightfield;
    39. in highp vec4 vs_TEXCOORD0;
    40. layout(location = 0) out highp vec4 SV_TARGET0;
    41. mediump vec3 u_xlat10_0;
    42. void main()
    43. {
    44.     u_xlat10_0.xyz = texture(SurfaceHeightfield, vs_TEXCOORD0.xy).xyz;
    45.     SV_TARGET0.xyz = u_xlat10_0.xyz;
    46.     SV_TARGET0.w = 1.0;
    47.     return;
    48. }
    49.  
    50. #endif
    51.  

    The problem is in line 41 :

    mediump vec3 u_xlat10_0;

    I need highp here. How can i archive that?
     
  2. StaggartCreations

    StaggartCreations

    Joined:
    Feb 18, 2015
    Posts:
    2,266
    Perhaps #pragma fragmentoption ARB_precision_hint_nicest might do the trick!
     
  3. ZhivaevDmitriy

    ZhivaevDmitriy

    Joined:
    May 15, 2018
    Posts:
    7
    Nope, does not work(

    Unfortunately, as described here:
    https://docs.unity3d.com/Manual/SL-ShaderPrograms.html

    Directive "#pragma fragmentoption" deprecated and don't do anything.
     
  4. ZhivaevDmitriy

    ZhivaevDmitriy

    Joined:
    May 15, 2018
    Posts:
    7
    That's very strange and interesting.

    I have replaced line 95, 96 in shader by this:

    surface.Color = SAMPLE_TEXTURE2D(SurfaceHeightfield, samplerSurfaceHeightfield, IN.uv0).xyz;

    and then, success:

    Code (CSharp):
    1. #ifdef FRAGMENT
    2. #version 300 es
    3.  
    4. ...
    5.  
    6. UNITY_LOCATION(0) uniform highp sampler2D SurfaceHeightfield;
    7. in highp vec4 vs_TEXCOORD0;
    8. layout(location = 0) out highp vec4 SV_TARGET0;
    9. vec3 u_xlat0;
    10. void main()
    11. {
    12.     u_xlat0.xyz = texture(SurfaceHeightfield, vs_TEXCOORD0.xy).xyz;
    13.     SV_TARGET0.xyz = u_xlat0.xyz;
    14.     SV_TARGET0.w = 1.0;
    15.     return;
    16. }
    17.  
    18. #endif
    But if I change this line with (different SamplerState):

    surface.Color = SAMPLE_TEXTURE2D(SurfaceHeightfield, SamplerState_Linear_Clamp, IN.uv0).xyz;

    Again get precision reduction:

    Code (CSharp):
    1. #ifdef FRAGMENT
    2. #version 300 es
    3.  
    4. ...
    5.  
    6. UNITY_LOCATION(0) uniform highp sampler2D SurfaceHeightfield;
    7. in highp vec4 vs_TEXCOORD0;
    8. layout(location = 0) out highp vec4 SV_TARGET0;
    9. mediump vec3 u_xlat10_0;
    10. void main()
    11. {
    12.     u_xlat10_0.xyz = texture(SurfaceHeightfield, vs_TEXCOORD0.xy).xyz;
    13.     SV_TARGET0.xyz = u_xlat10_0.xyz;
    14.     SV_TARGET0.w = 1.0;
    15.     return;
    16. }
    17.  
    18. #endif
    Why this is happening?
     
  5. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,025
    This pragma doesn't do anything.

    Can you please submit a bug report?
     
  6. ZhivaevDmitriy

    ZhivaevDmitriy

    Joined:
    May 15, 2018
    Posts:
    7
    aleksandrk likes this.
  7. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,025
    Hi!
    I finally had time to take a look into this.
    There's two things here: one is that using SamplerState (which has no native counterpart in GLSL) effectively overrides the texture properties with what the SamplerState provides. This includes precision information, so the compiler thinks "no highp needed here". Another issue is that SamplerState has currently no way to override the precision.
    Can you set the texture filtering and clamping behaviour on the texture settings?
     
  8. ZhivaevDmitriy

    ZhivaevDmitriy

    Joined:
    May 15, 2018
    Posts:
    7

    Hello! Yes, I already did that.
    But this is part of a much larger problem.
    Our artists work with Shader Graph, and now I have to convert each of their shaders into code format and make patches. I am a little sad about this situation. (
     
  9. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,025
    Why is that?
    Is ShaderGraph generating SamplerState stuff?
     
  10. ZhivaevDmitriy

    ZhivaevDmitriy

    Joined:
    May 15, 2018
    Posts:
    7
    Yes, ShaderGraph always creates custom SamplerState even if I do not use custom SamplerState ShaderGraph Node.
    Plus there is no way to replace TEXTURE2D with TEXTURE2D_FLOAT only manual in code.
    Plus there is no way to enable "#define PREFER_HALF 0" using ShaderGraph.
     
    Last edited: Aug 24, 2020
  11. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,025
    Got it.
    I flagged your initial bug report as an improvement to the possible SamplerState overrides.

    Do you mind submitting another bug report with these issues for the ShaderGraph area? :)
     
  12. ZhivaevDmitriy

    ZhivaevDmitriy

    Joined:
    May 15, 2018
    Posts:
    7
    Yeah, of course. I will do it today)
     
    aleksandrk likes this.
  13. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,025
    Thank you!