6 Replies Latest reply on Jun 17, 2016 6:06 AM by ionutcava

    GLSL textureOffset using sampler2DArrayShadow compilation error

    anothercoder

      Greetings -

       

      Debugging an issue here with one of the shaders which works fine on other hardware, but fails to compile on my Radeon 7950. Using Catalyst 14.1 Beta driver here (since I wanted to try out Mantle on BF4 ) on this machine, haven't tried other AMD GPUs yet, on different drivers. but this might be a known issue.

       

      The shader fetches texels from a sampler2DArrayShadow, averages them via PCF and that works fine using texture(...)

       

      [Snippet]

      uniform sampler2DArrayShadow    m_shadowSampler[kMaxShadowSamplers];

      ... // Compute other stuff, set index by comparing with cascade bounds

      vec4 shadowPos = m_entityparameters.m_biasedShadowMvp[lightIndex*kMaxShadowCascades+index] * vec4(shaderInput.m_position, 1.f);

      ... // Add layer to vec4, bias z etc.

      float sum = texture(m_shadowSampler[lightIndex], shadowPos);  

       

      Now using a gaussian kernel to smooth the borders, the shader does this:

       

        // Gaussian 3x3 kernel

          float sum = texture(m_shadowSampler[lightIndex], shadowPos) * 0.25f;   

          vec4 samples;

          samples.x = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2(-1,-1));

          samples.y = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2(-1,+1));

          samples.z = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2(+1,-1));

          samples.w = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2(+1,+1));

          sum += dot(vec4(0.0625f), samples);   

          samples.x = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2(-1, 0));

          samples.y = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2( 0,-1));

          samples.z = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2( 0,+1));

          samples.w = textureOffset(m_shadowSampler[lightIndex], shadowPos, ivec2(+1, 0));

          sum += dot(vec4(0.125f), samples);

       

      Compiles fine on Nvidia hardware for example, but shader compiler on 14.1 reports:

       

      Source:Shader Compiler  Type:Error      ID:2000

      Severity:High   Message:glCompileShader failed to compile a GLSL shader with the

      following shader info log: 'Fragment shader failed to compile with the followin

      g errors:

      ERROR: 1:110: error(#202) No matching overloaded function found: textureOffset

      ERROR: 1:111: error(#202) No matching overloaded function found: textureOffset

      ERROR: 1:112: error(#202) No matching overloaded function found: textureOffset

      ERROR: 1:113: error(#202) No matching overloaded function found: textureOffset

      ERROR: 1:116: error(#202) No matching overloaded function found: textureOffset

      ERROR: 1:117: error(#202) No matching overloaded function found: textureOffset

      ERROR: 1:118: error(#202) No matching overloaded function found: textureOffset

      ERROR: 1:119: error(#202) No matching overloaded function found: textureOffset

      ERROR: error(#273) 8 compilation errors.  No code generated

       

      The specs says:

      textureOffset - OpenGL 4 Shading Language Reference Pages

      float textureOffset(sampler2DArrayShadow sampler,
      vec4 P,
      vec2 offset);

       

      Noticed the vec2 instead of ivec2 that I'm using, not sure if this is a typo in the spec. Nonetheless, I've tried using vec2 with the same effect.

       

      Any clues?

       

      Thanks

        • Re: GLSL textureOffset using sampler2DArrayShadow compilation error
          tomus

          I Think your problem don't come from the offset format but from the texture coordinate format.

           

          OpenGL documentation :

           gvec textureOffset(gsampler sampler, vec texCoord, ivec offset[, float bias]); 

          The texCoord will have its value offset by offset texels before performing the lookup. Cubemap, multisample, and buffer samplers are not allowed as types for gsampler.

          The type ivec has the same type, but in integers, as vec. So when accessing a 2D sampler, vec is "vec2" and ivec is "ivec2". When accessing a 1D sampler, vec is "float" and ivec is "int".

           

           

          You are using a sampler2D texture so there is just 2 dimension for your texture coordinate. Your variable shadowPos must be a vec2

            • Re: GLSL textureOffset using sampler2DArrayShadow compilation error
              ionutcava

              Recently ran into the same issue.

              But also wanted to say, that in this case, tomus, you are wrong because he (and me) isn't using a regular sampler2D, but a sampler2DArrayShadow.

              A sampler2DArrayShadow requires 4 coordinates: U, V, Layer and Ref value. The layer selects the proper array slice and the ref value does the depth comparison.

              nVidia and Intel's implementations handle this just fine.

              This is a bug on AMD's side.

                • Re: GLSL textureOffset using sampler2DArrayShadow compilation error
                  dwitczak

                  So the prototype for textureOffset() for this case is:

                   

                  float textureOffset (sampler2DShadow sampler, vec3 P, ivec2 offset [, float bias] )

                   

                  Note that this a non-LOD version of the function, meaning you can't use it in vertex shader stage. I'm assuming this is not the case, right?

                   

                  Anyway, I would appreciate if you could copy-paste shader code which fails to compile. I'll be happy to have a look and see if I can help.

                    • Re: GLSL textureOffset using sampler2DArrayShadow compilation error
                      ionutcava

                      textureOffset (sampler2DShadow ...

                      Nope: sampler2DArrayShadow. ARRAY samplers need an extra member in P that specifies the layer.

                      sampler2DShadow requires U,V,Ref

                      sampler2DArrayShadow requires U,V,Layer,Ref

                       

                      If you look at the man pages for 'textureOffset', you'll notice that P is the same exact P used by the regular texture function (as it should). At the man page for 'texture', P is defined as following:

                       

                      For shadow forms, when compare is present, it is used as Dsub and the array layer is specified in P.w. When compare is not present, the last component of P is used as Dsub and the array layer is specified in the second to last component of P. (The second component of P is unused for 1D shadow lookups.)
                      L.E. : usage code

                        • Re: GLSL textureOffset using sampler2DArrayShadow compilation error
                          dwitczak

                          I wouldn't really pay that much attention to reference pages. Official specification should always be the reference.

                           

                          From https://www.opengl.org/registry/doc/GLSLangSpec.4.50.pdf, we have:

                           

                          gvec4 textureOffset (gsampler2DArray sampler, vec3 P, ivec2 offset [, float bias] )

                           

                          So yeah, on the surface that shader should work. For reproduction purposes, can I ask you to copy-paste the whole GLSL body of the fragment shader which fails to compile, please? The shader you linked to seems to only hold function implementations. Thanks.

                            • Re: GLSL textureOffset using sampler2DArrayShadow compilation error
                              ionutcava

                              On this (rare) occasion, the man pages actually match up with the official spec.

                              From the PDF: float textureOffset(sampler2DArrayShadow sampler, vec4 P, ivec2 offset );  (p. 165)

                              So it should indeed compile. However, with the latest Crimson driver (16.6.1) I get the exact same "ERROR: 1:110: error(#202) No matching overloaded function found: textureOffset" message.

                               

                              Don't know if a complete GLSL body would help much as I create shaders on the fly from various small files such as the linked one and offline compilation tools usually fall over when analyzing it.

                              The final fragment shader is about 1000 lines of code with odd spacing for the most basic case (no textures, no skinning, etc). The vertex shader isn't all that short, either.
                              I linked my nVidia generated code which should use the problematic code (everything else vendor specific is commented out).

                               

                              I'll see if I can generate something smaller and portable, maybe using some online GLSL tool or something.