1 Reply Latest reply on Oct 30, 2012 10:01 PM by cccccc

    double-precision constant problem in GLSL

    cccccc

      I was porting a GLSL shader from single-precision to double-precision, and found that nothing would render on the AMD cards I tested on (using Catalyst 12.8). I reduced the buggy program down to the following simple test case:

       

      // Vertex shader -- draw a full-screen triangle with glDrawArrays(GL_TRIANGLES,0,3)

      #version 150

      out vec2 outVS_TexCoord0;

      void main(void)

      {

          const vec4 verts[3] = vec4[](

              vec4(-1, 1, 0, 0),

              vec4(-1,-3, 0, 2),

              vec4( 3, 1, 2, 0)

          );

           vec4 vert = verts[clamp(gl_VertexID,0,2)];

          gl_Position = vec4(vert.x, vert.y, 0, 1);

          outVS_TexCoord0 = vert.zw;

      }

       

      // Fragment shader -- draws a red circle on a green background

      #version 330 core

      #extension GL_ARB_gpu_shader_fp64 : enable

      #extension GL_ARB_gpu_shader5 : enable

      in vec2 outVS_TexCoord0;

      out vec4 outFS_FragColor0;

      void main()

      {

          // Convert incoming texture coordinates [0..1] to the range [-1..1]

          double x = -1.0 + outVS_TexCoord0.x*2.0;

          double y = -1.0 + outVS_TexCoord0.y*2.0;

          //double radius = 1.0; // WORKS

          //const double radius = double(1.0); // WORKS

          //const double radius = 1.0LF; // WORKS

          const double radius = 1.0; // FAILS -- draws green to the whole screen.

          if (x*x+y*y < radius)

          {

              outFS_FragColor0 = vec4(1,0,0,1); // output red

          }

          else

          {

              outFS_FragColor0 = vec4(0,1,0,1); // output green

          }

      }

       

      So, declaring the circle radius as a "double" works correctly, but making it a "const double" causes the if() condition to always fail (unless I cast the 1.0 to a double, either using an explicit double() or by adding the "LF" suffix to the initial value).

       

      So, I have three different ways I can fix my original code, but I still don't understand why the original "const double radius = 1.0" version doesn't work. Even if there was a precision mismatch somewhere, I'd expect the final comparison to behave correctly. Also, why would "const double" fail but "double" work correctly? I would at least expect a compiler error/warning, but the info log mentions nothing out of the ordinary.

       

      Thanks!

      -c