1

I've narrowed my case down to this simple GLSL code:

uniform int zeroUniform; // Always set to zero, it is there so that the code is not optimized out
out int c;

int a = 8660165;
int b = 6;
c = (a + zeroUniform) / b;

When I put this in a shader and inspect the shader with RenderDoc, it says that c is 1443361! But it should be 1443360. What the hell is happening? In hex, 8660165 is 0x8424C5, so there's a whole one byte free before the sign bit could alter the calculations. Am I missing something or is this a GPU bug?

OpenGL 4.6 core, Tested on AMD RX 5700 XT. I've also tried using uint instead of int, which works correctly.

Danol
  • 368
  • 1
  • 15
  • Interesting question. Another possibility, although quite unlikely, is that your driver implements float to integer truncation with a rounding function other than the expected floor function? – jackw11111 Jul 20 '20 at 09:20
  • @jackw11111: There shouldn't be an float -> int conversion in this code. – BDL Jul 20 '20 at 09:25
  • @BDL My mistake, I meant truncation from assigning a float to an int could be ceil() instead of floor(). – jackw11111 Jul 20 '20 at 09:36
  • The current calculation is `int = (int + int) / int;`. There is no floating point number involved. When implemented correctly, there should never be a float -> int assignment. – BDL Jul 20 '20 at 09:44
  • It would be a driver bug, AMD Navi doesn't have a built-in integer division, so it's emulated in software. You could check what actually happens – harold Jul 20 '20 at 10:41
  • How does renderdoc get the result of this calculation? YOu still need to get the data out from there, and depedning on how this is done, there is still a chance that there is some floating-point conversion involved. – derhass Jul 20 '20 at 11:10
  • @derhass In RenderDoc, there's the "Mesh viewer" function where I can view all input and output data of the shader (even for each vertex in vertex shader). So it is as direct as it could be. – Danol Jul 20 '20 at 11:14
  • No, that is not "direct". It involves [transform feedback for renderdoc to get this data, or to modify the shader behind your back](https://github.com/baldurk/renderdoc/blob/v1.x/renderdoc/driver/gl/gl_postvs.cpp) to write the outputs to some buffer. This means that a) there could be a bug in renderdoc, or b) the suspected driver bug could as well be in that areas, so te data is not yet conclusive to me. – derhass Jul 20 '20 at 11:20
  • @derhass Okay, for increasing certainty I've hooked the code to the fragment shader and set the color output to ```vec4(c == 1443361 ? 1 : 0, zeroUniform == 0 ? 1 : 0, c > 0 ? 1 : 0, 1);``` It outputs the white color as expected. Is that good enough? – Danol Jul 20 '20 at 11:35
  • Yes, that appears a lot more conclusive to me. My suspicion now would be the shader compiler. – derhass Jul 20 '20 at 11:41

1 Answers1

1

The result of your division is 1443360.833333333

This spec https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf

On page 144 in the section "12.33 Rounding of Integer Division" it asks if integer division should round and the answer is "RESOLUTION: The rounding mode is undefined for this version of the specification."

So the results you are seeing certainly seems valid given that spec even if not the most useful.

That spec is for GLSL ES 3.00 which likely isn't what you are using but I can't find another spec right now that mentions this, but it seems an indication at least that your results are valid given the spec, even if not what you'd hope for

jcoder
  • 29,554
  • 19
  • 87
  • 130
  • 2
    [Non-ES spec](https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf) doesn't say that, but it doesn't say anything else either, it skips the whole subject – harold Jul 20 '20 at 10:51
  • Yes I couldn't find it anywhere else either, which seems to imply to me that this _might_ be expected behaviour rather than a bug as such. Although I'm not sure what practical difference that makes to you sadly. Perhaps my reply should have been a comment as it's more evidence than answer. – jcoder Jul 20 '20 at 13:19
  • Well I am using the integer division to find out quad ID and quad-local vertex ID from gl_VertexID (in GL_TRIANGLES draw mode). – Danol Jul 20 '20 at 16:17
  • Well if this is true, that is very unfortunate. That basically means you can't rely on GLSL integer division and modulo operations... – Danol Jul 21 '20 at 10:08