Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLSL ES 3.0 uint on Adreno 5xx/6xx #2989

Closed
lexaknyazev opened this issue Dec 14, 2019 · 3 comments · Fixed by #3190
Closed

GLSL ES 3.0 uint on Adreno 5xx/6xx #2989

lexaknyazev opened this issue Dec 14, 2019 · 3 comments · Fixed by #3190

Comments

@lexaknyazev
Copy link
Member

lexaknyazev commented Dec 14, 2019

From the spec:

Shift operators (<<) and (>>)

For both operators, the operands must be signed or unsigned integers or integer vectors. One operand can be signed while the other is unsigned. In all cases, the resulting type will be the same type as the left operand. If the first operand is a scalar, the second operand has to be a scalar as well. If the first operand is a vector, the second operand must be a scalar or a vector with the same size as the first operand, and the result is computed component-wise. The result is undefined if the right operand is negative, or greater than or equal to the number of bits in the left expression's base type. The value of E1 >> E2 is E1 right-shifted by E2 bit positions. If E1 is a signed integer, the right-shift will extend the sign bit. If E1 is an unsigned integer, the right-shift will zero-extend.

And (&)

The operands must be of type signed or unsigned integers or integer vectors. The operands cannot be vectors of differing size. If one operand is a scalar and the other a vector, the scalar is applied component-wise to the vector, resulting in the same type as the vector. The fundamental types of the operands (signed or unsigned) must match, and will be the resulting fundamental type. For and (&), the result is the bitwise-and function of the operands.

Conversion and Scalar Constructors

The constructor int(uint) preserves the bit pattern in the argument, which will change the argument's value if its sign bit is set. The constructor uint(int) preserves the bit pattern in the argument, which will change its value if it is negative.

Following the definitions above, these two expressions must produce the same value.

precision highp int;
ivec3 d; // must not be compile-time constant
int v1 = (d.x >> 25) & 0x7F;
int v2 = int(uint(d.x & 0xFE000000) >> 25U);

On Adreno 5xx (checked 508 and 540) devices, uint(...) cast is apparently ignored, so the right shift always operates on a signed value.

@lexaknyazev
Copy link
Member Author

lexaknyazev commented Dec 15, 2019

Casting value twice fixes the computation:

int v2 = int(uint(uint(d.x & 0xFE000000)) >> 25U);

The issue doesn't seem to be present on Intel, NVIDIA, or ARM Mali chips.

@lexaknyazev
Copy link
Member Author

lexaknyazev commented Dec 16, 2019

Same bug on Adreno 630 and Adreno 512.

@lexaknyazev lexaknyazev changed the title GLSL ES 3.0 uint on Adreno 5xx GLSL ES 3.0 uint on Adreno 5xx/6xx Dec 16, 2019
@kenrussell
Copy link
Member

Thanks for the report. Could you please provide a reduced conformance test covering this under https://github.com/KhronosGroup/WebGL/tree/master/sdk/tests/conformance2/glsl3 ?

Bonus points if you can see whether this is already covered under the drawElements tests, which are the OpenGL ES test suite on Android:
https://android.googlesource.com/platform/external/deqp/

kenrussell pushed a commit that referenced this issue Dec 4, 2020
Exposes bug on Adreno GPUs with shifting of uint values in shaders.
Casting the value twice (uint(uint(int))) produces correct result. Vector types are not affected.

Fixes #2989.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants