Search Unity

Question Getting invalid subscript shader error from a function disabled by keyword

Discussion in 'Shaders' started by Beauque, May 19, 2022.

  1. Beauque

    Beauque

    Joined:
    Mar 7, 2017
    Posts:
    61
    Hi, I am writing a PBR shader for URP with togglable shader features such as normal map and planar/triplanar mapping. I am currently facing a curious situation I hope to get some clarification about:

    When I don't use normal map I make sure not to declare world space tangents and bitangents in the fragment input:
    Code (CSharp):
    1. #ifdef _NORMALMAP
    2.    half4 normalWS                    : TEXCOORD2;
    3.    half4 tangentWS                    : TEXCOORD3;
    4.    half4 bitangentWS                  : TEXCOORD4;
    5. #else
    6.    half3 normalWS                    : TEXCOORD2;
    7. #endif
    In an include used by the fragment shader, I call the function "TriplanarSampleNormal" only when _NORMALMAP and _MAPPINGMODE_TRIPLANAR keywords are ON:
    Code (CSharp):
    1. half3 SampleNormalMultiMapping(Varyings IN, TEXTURE2D_PARAM(bumpMap, sampler_bumpMap), half scale = half(1.0))
    2. {
    3.     #ifdef _NORMALMAP
    4.         #ifdef _MAPPINGMODE_TRIPLANAR
    5.             //this -----------------------------------------------------
    6.             return TriplanarSampleNormal(TEXTURE2D_ARGS(bumpMap, sampler_bumpMap), IN);
    7.             //this function is called only here -------------------------
    8.  
    9.         #elif _MAPPINGMODE_PLANAR
    10.             //Same
    11.             return PlanarSampleNormal(TEXTURE2D_ARGS(bumpMap, sampler_bumpMap), IN);
    12.      
    13.         #else
    14.             half4 n = SAMPLE_TEXTURE2D(bumpMap, sampler_bumpMap, IN.uv);
    15.             #if BUMP_SCALE_NOT_SUPPORTED
    16.                 return UnpackNormal(n);
    17.             #else
    18.                 return UnpackNormalScale(n, scale);
    19.             #endif
    20.         #endif
    21.  
    22.     #else
    23.         return half3(0.0h, 0.0h, 1.0h);
    24.     #endif
    25. }
    In that setup the shader works fine.

    But when I turn off _NORMALMAP on the material, it turns pink and I get the following message: "Shader error in 'Lit 2022': invalid subscript 'tangentWS' at /.../IFSurface.hlsl(51) (on d3d11)", from the TriplanarSampleNormal function:
    Code (CSharp):
    1. half4 TriplanarSampleNormal(TEXTURE2D_PARAM(textureMap, sampler_textureMap), Varyings IN)
    2. {
    3.     float blend = 20;
    4.     float3 Node_UV = (IN.positionWS + _Offset.xyz) * _TilingPlanar;
    5.     float3 Node_Blend = max(pow(abs(IN.normalWS.xyz), blend), 0);
    6.     Node_Blend /= (Node_Blend.x + Node_Blend.y + Node_Blend.z ).xxx;
    7.     float3 Node_X = UnpackNormal(SAMPLE_TEXTURE2D(textureMap, sampler_textureMap, Node_UV.zy));
    8.     float3 Node_Y = UnpackNormal(SAMPLE_TEXTURE2D(textureMap, sampler_textureMap, Node_UV.xz));
    9.     float3 Node_Z = UnpackNormal(SAMPLE_TEXTURE2D(textureMap, sampler_textureMap, Node_UV.xy));
    10.     Node_X = float3(Node_X.xy + IN.normalWS.zy, abs(Node_X.z) * IN.normalWS.x);
    11.     Node_Y = float3(Node_Y.xy + IN.normalWS.xz, abs(Node_Y.z) * IN.normalWS.y);
    12.     Node_Z = float3(Node_Z.xy + IN.normalWS.xy, abs(Node_Z.z) * IN.normalWS.z);
    13.     float4 Out = float4(normalize(Node_X.zyx * Node_Blend.x + Node_Y.xzy * Node_Blend.y + Node_Z.xyz * Node_Blend.z), 1);
    14.     //this line ---------------------------------------------------------------
    15.     float3x3 Node_Transform = float3x3(IN.tangentWS.xyz, IN.bitangentWS.xyz, IN.normalWS.xyz);
    16.     //-------------------------------------------------------------------
    17.     Out.rgb = TransformWorldToTangent(Out.rgb, Node_Transform);
    18.     return Out;
    19. }
    When _NORMALMAP is OFF it is obvious that it can't get the tangentWS or bitengentWS since I don't initialize them, but the TriplanarSampleNormal function shouldn't be included in the shader variant anyway. So why the compiler is throwing me this error, why does it care about this code?

    Note: If I insert #ifdef _NORMALMAP directly in the function, the error is gone. But from my understanding I shouldn't have to do that, since I do it already before calling the function.

    I don't want unused code to be compiled in the variants this is why I use keywords, but given the error I am not sure if my keywords work as I expect. Is this a normal behavior? What would be the proper way to place #ifdef conditions in the code?

    Any help / clarification on this would be appreciated, thanks
     
    Last edited: May 19, 2022
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,014
    Hi!
    It doesn't matter that you don't call the function in your code, it's enough that it's present there.
     
    Beauque likes this.
  3. Beauque

    Beauque

    Joined:
    Mar 7, 2017
    Posts:
    61
    Ok, thanks. So getting an error doesn't necessarily mean the code is included in the final shader variant ?
    In that case all I have to do I guess is adding one more #ifdef _NORMALMAP in the function just to keep the compiler quiet.
     
  4. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,014
    Exactly.
     
    Beauque likes this.