Search Unity

bug multi_compile_local (LOCAL!)

Discussion in 'Shaders' started by AlexHell, May 30, 2019.

  1. AlexHell

    AlexHell

    Joined:
    Oct 2, 2014
    Posts:
    167
    When I write shader with variants via multi_compile_local (not multi_compile)
    Code (CSharp):
    1. #pragma multi_compile_local MASK_A MASK_R MASK_G MASK_B
    Complete shader code

    Code (CSharp):
    1. Shader "Custom/MyMaskTest"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Texture", 2D) = "white" {}
    6.         _MaskTex ("Mask Texture", 2D) = "white" {}
    7.     }
    8.  
    9.     SubShader
    10.     {
    11.         Tags
    12.         {
    13.             "RenderType" = "Opaque"
    14.             "Queue" = "Transparent"
    15.         }
    16.  
    17.         Lighting Off
    18.         ZWrite Off
    19.         Cull Off
    20.  
    21.         Pass
    22.         {
    23.             CGPROGRAM
    24.  
    25.             #pragma multi_compile_local MASK_A MASK_R MASK_G MASK_B
    26.  
    27.             #include "UnityCG.cginc"
    28.  
    29.             #pragma vertex ComputeVertex
    30.             #pragma fragment ComputeFragment
    31.  
    32.             sampler2D _MainTex;
    33.             sampler2D _MaskTex;
    34.  
    35.             struct VertexInput
    36.             {
    37.                 float4 vertex : POSITION;
    38.                 float2 texcoord : TEXCOORD0;
    39.             };
    40.  
    41.             struct VertexOutput
    42.             {
    43.                 float4 vertex : SV_POSITION;
    44.                 half2 texcoord : TEXCOORD0;
    45.             };
    46.  
    47.             VertexOutput ComputeVertex (VertexInput vertexInput)
    48.             {
    49.                 VertexOutput vertexOutput;
    50.  
    51.                 vertexOutput.vertex = UnityObjectToClipPos(vertexInput.vertex);
    52.                 vertexOutput.texcoord = vertexInput.texcoord;
    53.              
    54.                 return vertexOutput;
    55.             }
    56.  
    57.             fixed4 ComputeFragment (VertexOutput vertexOutput) : SV_Target
    58.             {
    59.                 half4 colorFromMask = tex2D(_MaskTex, vertexOutput.texcoord);
    60.  
    61.                 half testComponent;
    62. #if defined(MASK_A)
    63.                 testComponent = colorFromMask.a;
    64.                 //return half4(0,0,0,1); // todo TEST
    65. #endif
    66. #if defined(MASK_R)
    67.                 testComponent = colorFromMask.r;
    68.                 //return half4(1,0,0,1); // todo TEST
    69. #endif
    70. #if defined(MASK_G)
    71.                 testComponent = colorFromMask.g;
    72.                 //return half4(0,1,0,1); // todo TEST
    73. #endif
    74. #if defined(MASK_B)
    75.                 testComponent = colorFromMask.b;
    76.                 //return half4(0,0,1,1); // todo TEST
    77. #endif
    78.  
    79.                 if (testComponent < 1)
    80.                 {
    81.                     discard;
    82.                 }
    83.  
    84.                 return tex2D(_MainTex, vertexOutput.texcoord);
    85.             }
    86.  
    87.             ENDCG
    88.         }
    89.     }
    90. }
    Then select shader variant via C# code
    Code (CSharp):
    1.  
    2.               _materialMyMaskTest.DisableKeyword("MASK_A");
    3.                 _materialMyMaskTest.DisableKeyword("MASK_R");
    4.                 _materialMyMaskTest.DisableKeyword("MASK_G");
    5.                 _materialMyMaskTest.DisableKeyword("MASK_B");
    6.                 //
    7.                 if (partType == ..G)
    8.                 {
    9.                     _materialMyMaskTest.EnableKeyword("MASK_G");
    10.                 }
    11.                 else if (partType == ..B)
    12.                 {
    13.                     _materialMyMaskTest.EnableKeyword("MASK_B");
    14.                 }
    15.                 else if (partType == ..A)
    16.                 {
    17.                     _materialMyMaskTest.EnableKeyword("MASK_A");
    18.                 }
    19.                 else
    20.                 {
    21.                     _materialMyMaskTest.EnableKeyword("MASK_R");
    22.                 }
    23.  
    24.                 _materialMyMaskTest.SetTexture("_MaskTex", _combinedMask);
    25.                 Graphics.Blit(textureOrigin, textureResult, _materialMyMaskTest);
    In runtime I get error
    Code (CSharp):
    1. Shader error in 'Custom/MyMaskTest': variable 'testComponent' used without having been completely initialized at line 81 (on d3d11)
    2.  
    3. Compiling Fragment program
    4. Platform defines: UNITY_ENABLE_REFLECTION_BUFFERS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA
    ______
    Note: I don't have "__ " (in first place of multi_compile_local or multi_compile) in allowed variants, i.e. only 4 - R | G | B | A, but not have "disabled"
    ______

    Questions:

    * Why shader variants is not selected if - multi_compile_local
    (without block of 4s DisableKeyword it is NOT work too)

    * What is the semantic of multi_compile_local when I change it on material
    Code (CSharp):
    1. _materialMyMaskTest.EnableKeyword("MASK_G");
    does it changes on concrete instance of material? In that case I can have 2 materials with different variant (A and G mask for example)

    * If I change to
    Code (CSharp):
    1. #pragma multi_compile MASK_A MASK_R MASK_G MASK_B
    (instead of multi_compile_local)
    the error is gone and all works as expected
    (but I thought multi_compile_local is better due to not expose keywords to global scope, as doc says)
    Why it work in that case?

    * If I change to "multi_compile" without "local" - does keywords can be assigned from any material or shader? or shader of type "Custom/MyMaskTest" only? Does keywords have any other problems? Possibility of collisions?

    (unity 5.6.5p4 if it's a bug of unity)
     
    Last edited: May 30, 2019
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    5.6.5p4 was released in 2017. It does not have the multi_compile_local pragma parameter, that was introduced in Unity 2019.1. Is there a specific reason you're still on such an old Unity version?
     
    bgolus likes this.
  3. AlexHell

    AlexHell

    Joined:
    Oct 2, 2014
    Posts:
    167
    Thanks for info! We have tested unity 2017 - 2018 - 2019, and all the time we have encountered many unity bugs.. because of this we stay in the stable version, in which we develop our project in last years
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    What kind of bugs? Bugs should be reported so they can be fixed. If you are seeing red errors, that's not really a "bug", it just means some of your code is using deprecated/removed methods, but there are always better replacements for those methods, usually suggested to you in the error message so you can alter your code to use them.

    But if you're using some third-party addons that haven't been updated in years for newer Unity versions and you can't modify them yourself then yeah that can be an issue. 2018.4 is very stable though as it's the long-term-support release (though it doesn't have this multi_compile_local feature you want).
     
  5. AlexHell

    AlexHell

    Joined:
    Oct 2, 2014
    Posts:
    167
    Thank you for info. We will migrate to 2018-2019 version in future. In past we have encountered bugs with webgl in runtime or build, which is not simple to reproduce or report.

    multi_compile_local is not must-have to us, if it will take many time to regressions tests and waiting for fixes of new unity versions