title: Differing floating point behaviour between uniform and constants in GLSL
body: <p>I am trying to implement emulated double-precision in GLSL, and I observe a strange behaviour difference leading to subtle floating point errors in GLSL. </p>
  
  <p>Consider the following fragment shader, writing to a 4-float texture to print the output.</p>
  
  <pre><code>layout (location = 0) out vec4 Output
  uniform float s;
  void main()
  {
    float a = 0.1f;
    float b = s;
  
    const float split = 8193.0; // = 2^13 + 1
  
    float ca = split * a;
    float cb = split * b;
  
    float v1a = ca - (ca - a);
    float v1b = cb - (cb - b);
  
    Output = vec4(a,b,v1a,v1b);
  }
  </code></pre>
  
  <p>This is the output I observe</p>
  
  <p><strong>GLSL output with uniform :</strong> </p>
  
  <pre><code>a = 0.1            0x3dcccccd
  b = 2.86129e-06    0x36400497
  v1a = 0.0999756    0x3dccc000
  v1b = 2.86129e-06  0x36400497
  </code></pre>
  
  <p>Now, with the given values of <code>b1</code> and  <code>b2</code> as inputs, the value of <code>v2b</code> does not have the expected result. Or at least it does not have the same result as on CPU (as seen <a href="https://ideone.com/y4OTKR" rel="noreferrer">here</a>):</p>
  
  <p><strong>C++ output :</strong> </p>
  
  <pre><code>a = 0.100000     0x3dcccccd
  b = 0.000003     0x36400497
  v1a = 0.099976   0x3dccc000
  v1b = 0.000003   0x36400000
  </code></pre>
  
  <p>Note the discrepancy for the value of <code>v1b</code> (<code>0x36400497</code> vs <code>0x36400000</code>). </p>
  
  <p>So in an effort to figure out what was happening (and who was right) I attempted to redo the computation in GLSL, replacing the uniform value by a constant, using a slightly modified shader, where I replaced the uniform by it value.</p>
  
  <pre><code>layout (location = 0) out vec4 Output
  void main()
  {
    float a = 0.1f;
    float b = uintBitsToFloat(0x36400497u);
  
    const float split = 8193.0; // = 2^13 + 1
  
    float ca = split * a;
    float cb = split * b;
  
    float v1a = ca - (ca - a);
    float v1b = cb - (cb - b);
  
    Output = vec4(a,b,v1a,v1b);
  }
  </code></pre>
  
  <p>This time, I get the same output as the C++ version of the same computation.</p>
  
  <p><strong>GLSL output with constants :</strong></p>
  
  <pre><code>a = 0.1            0x3dcccccd
  b = 2.86129e-06    0x36400497
  v1a = 0.0999756    0x3dccc000
  v1b = 2.86102e-06  0x36400000
  </code></pre>
  
  <p>My question is, what makes the floating point computation behave differently between a uniform variable and a constant ? Is this some kind of behind-the-scenes compiler optimization ?</p>
  
  <p>Here are my OpenGL vendor strings from my laptop's intel GPU, but I also observed the same behaviour on a nVidia card as well.</p>
  
  <pre><code>Renderer : Intel(R) HD Graphics 520
  Vendor   : Intel
  OpenGL   : 4.5.0 - Build 23.20.16.4973
  GLSL     : 4.50 - Build 23.20.16.4973
  </code></pre>