Forums - Adreno 320 GL3 precision bug

7 posts / 0 new
Last post
Adreno 320 GL3 precision bug
kturkowski
Join Date: 3 Aug 12
Posts: 5
Posted: Thu, 2014-08-07 17:58
It appears that the Adreno 320 GL 3.0 uses fixed point instead of floating point for mediump float.
My blur shader works fine on the 225 and is attenuated (truncated) on the 320,
when using mediump both on the coefficient generator (GPU Gems 3, p. 877) and the accumulator.
However, when I change them to highp, the shader passes my tests.
My coefficients range between 0.002 and 0.97.
 
Querying glGetShaderPrecisionFormat() on the 320 and 225 yield the same specs for both devices:
<high_fragment_flt precision="23" range0="127" range1="127"/>
<med_fragment_flt precision="10" range0="15" range1="15"/>
<low_fragment_flt precision="10" range0="15" range1="15"/>
<high_fragment_int precision="0" range0="31" range1="30"/>
<med_fragment_int precision="0" range0="15" range1="14"/>
<low_fragment_int precision="0" range0="15" range1="14"/>
 
Half float should be able to have full 11 bit precision for numbers as small as 6.1e-5.
This is obviously a bug, either in glGetShaderPrecisionFormat(), or in your GLSL compiler, or in the driver.
I just updated my US Samsung Galaxy S4 SGH-M919 a few days ago, and it hasn't fixed the bug.
 
The working 225 is
<system manufacturer="samsung" model="SAMSUNG-SGH-I747" name="d2uc" brand="samsung" language="en" region="US" abi="armeabi-v7a" version="4.4.2"/>
<opengl vendor="Qualcomm" renderer="Adreno (TM) 225" version="OpenGL ES 2.0 [email protected] [email protected] (CL@3869936)" GLSL_version="OpenGL ES GLSL ES 1.00"/>
 
and the broken devices are:
 
<system manufacturer="samsung" model="SM-N900P" name="hltespr" brand="samsung" language="en" region="US" abi="armeabi-v7a" version="4.4.2"/>
<opengl vendor="Qualcomm" renderer="Adreno (TM) 330" version="OpenGL ES 3.0 [email protected] AU@  (CL@)" GLSL_version="OpenGL ES GLSL ES 3.00"/>
 
<system manufacturer="samsung" model="SGH-M919" name="jfltetmo" brand="samsung" language="en" region="US" abi="armeabi-v7a" version="4.4.2"/>
<opengl vendor="Qualcomm" renderer="Adreno (TM) 320" version="OpenGL ES 3.0 [email protected] AU@  (CL@3869936)" GLSL_version="OpenGL ES GLSL ES 3.00"/>
 
<system manufacturer="HTC" model="HTC6435LVW" name="dlx" brand="verizon_wwe" language="xxhdpi" region="" abi="armeabi-v7a" version="4.1.1"/>
<opengl vendor="Qualcomm" renderer="Adreno (TM) 320" version="OpenGL ES 2.0 [email protected] AU@ (CL@2814726)" GLSL_version="OpenGL ES GLSL ES 1.00"/>
 
The bug does not seem to be limited to the 320, as the 330 exhibits this bug as well. Also, it does not seem to be limited to GLSL 3.0, as a device running GLSL 1.0 also exhibits this bug. It appears to be associated with the 300 series GPUs.
 
Has anyone else experienced this bug?
  • Up0
  • Down0
mhfeldma Moderator
Join Date: 29 Nov 12
Posts: 310
Posted: Thu, 2014-08-28 07:37

Thanks for reporting this issue.  Can we get a bit more information?

1) Regarding "half float should be able to have full 11 bit precision for numbers as small as 6.1e-5.  Curious where that value comes from? - note that as per the IEEE-754 standard, the precision is 11 bits though 10 bits are explicity stored (and thus the value returned by glGetShaderPrecisionFormat

2) Would you be able to share your shader code and perhaps a sample apk that demonstates the difference between Adreno 225 and Adreno 320/330?

  • Up0
  • Down0
kturkowski
Join Date: 3 Aug 12
Posts: 5
Posted: Thu, 2014-08-28 17:58

Thank you for your response.

The 6.104e-5 comes from setting the exponent to 1 and the mantissa to 0. This is the smallest normalized number in the half float representation. The smallest denorm is 5.960e-8, obtained by setting the exponent to 0 and the significand to 1. Similarly, the largest representable number is 65504.

I have written a half float simulator in software, and have determined that the problem is with the 225, not the 320&330. The software simulation of the half float blur shader has consistent results with the 320&330.

The problem is that the 225 is returning the wrong information in the glGetShaderPrecisionFormat() query. It says that it has 10 bits of medium precision whereas in fact it has 23, as determined by the shaders given at the end of this post. I have at least 4 different shaders that are chosen based upon various extension and other queries. I would really rather not have to compile and run a shader to determine which other shaders to configure at launch time. Luckily, for the 225, I can just query GL_OES_fragment_precision_high and deploy a high precision shader. However, for other functions, there may be performance differences between medium and high precision, and I would like to choose the fastest shader that produces the correct results.

 <opengl vendor="Qualcomm" renderer="Adreno (TM) 225" version="OpenGL ES 2.0 [email protected] [email protected] (CL@3869936)" GLSL_version="OpenGL ES GLSL ES 1.00"/>
  <high_fragment_flt precision="23" range0="127" range1="127"/>
   <med_fragment_flt precision="10" range0="15" range1="15"/>
   <low_fragment_flt precision="10" range0="15" range1="15"/>
   Screen Phase = (-1.5, -1.5)
   GPU H precision: 23 truncated
   GPU M precision: 23 truncated
   CPU H precision: 23 rounded
 
 
<opengl vendor="Qualcomm" renderer="Adreno (TM) 320" version="OpenGL ES 3.0 [email protected] AU@  (CL@3869936)" GLSL_version="OpenGL ES GLSL ES 3.00"/>
   <high_fragment_flt precision="23" range0="127" range1="127"/>
   <med_fragment_flt precision="10" range0="15" range1="15"/>
   <low_fragment_flt precision="10" range0="15" range1="15"/>
   Screen Phase = (0, 0)
   GPU H precision: 23 truncated
   GPU M precision: 10 truncated
   CPU H precision: 23 rounded
 
The shaders used to determine the precision were derived from those of Stuart Russell and Tom Olson from the following article:
 
#define HIGHP highp
#define MEDIUMP mediump
static const char gHighPrecisionShader[] = {
"uniform "HIGHP" vec3 resolution;\n"
"void main(void) {\n"
" "HIGHP" float y = floor(gl_FragCoord.y - resolution.z) * 26.0 / float(resolution.y);\n" /* y in the domain [0, 26], starting at 0 at the bottom */
" "HIGHP" float x = 1.0 - (floor(gl_FragCoord.x - resolution.z) / float(resolution.x));\n" /* x in the domain [0, 1], starting at 1 and decreasing to 0 toward the right */
" "HIGHP" float b = fract(pow(2.0, floor(y)) + x);\n" /* Fractional part of 2^y + x */
" gl_FragColor = vec4(b, b, b, 1.0);\n"
"}\n"
};
static const char gMediumPrecisionShader[] = {
"uniform "HIGHP" vec3 resolution;\n"
"void main(void) {\n"
" "MEDIUMP" float y = floor(gl_FragCoord.y - resolution.z) * 26.0 / float(resolution.y);\n" /* y in the domain [0, 26], starting at 0 at the bottom */
" "MEDIUMP" float x = 1.0 - (floor(gl_FragCoord.x - resolution.z) / float(resolution.x));\n" /* x in the domain [0, 1], starting at 1 and decreasing to 0 toward the right */
" "MEDIUMP" float b = fract(pow(2.0, floor(y)) + x);\n" /* Fractional part of 2^y + x */
" gl_FragColor = vec4(b, b, b, 1.0);\n"
"}\n"
};
 

 

  • Up0
  • Down0
kturkowski
Join Date: 3 Aug 12
Posts: 5
Posted: Thu, 2014-08-28 18:06

Thank you for your response.

The 6.104e-5 comes from setting the exponent to 1 and the significand to 0. This is the smallest normalized number in the half float representation. The smallest denorm is 5.960e-8, obtained by setting the exponent to 0 and the significand to 1, but I doubt that many GPUs would implement denorms. Similarly, the largest representable half float number is 65504.

I have written a half float simulator in software, and have since determined that the problem is with the 225, not the 320&330. The software simulation of the half float blur shader has consistent results with the 320&330.

The problem is that the 225 is returning the wrong information in the glGetShaderPrecisionFormat() query. It says that it has 10 bits of medium precision whereas in fact it has 23, as determined by the shaders given at the end of this post. I have at least 4 different shaders that are chosen based upon various extension and other queries. I would really rather not have to compile and run a shader to determine which other shaders to configure at launch time. Luckily, for the 225, I can just query GL_OES_fragment_precision_high and deploy a high precision shader. However, for other functions, there may be performance differences between medium and high precision, and I would like to choose the fastest shader that produces the correct results.

 <opengl vendor="Qualcomm" renderer="Adreno (TM) 225" version="OpenGL ES 2.0 [email protected] [email protected] (CL@3869936)" GLSL_version="OpenGL ES GLSL ES 1.00"/>
  <high_fragment_flt precision="23" range0="127" range1="127"/>
   <med_fragment_flt precision="10" range0="15" range1="15"/>
   <low_fragment_flt precision="10" range0="15" range1="15"/>
   Screen Phase = (-1.5, -1.5)
   GPU H precision: 23 truncated
   GPU M precision: 23 truncated
   CPU H precision: 23 rounded
 
 
<opengl vendor="Qualcomm" renderer="Adreno (TM) 320" version="OpenGL ES 3.0 [email protected] AU@  (CL@3869936)" GLSL_version="OpenGL ES GLSL ES 3.00"/>
   <high_fragment_flt precision="23" range0="127" range1="127"/>
   <med_fragment_flt precision="10" range0="15" range1="15"/>
   <low_fragment_flt precision="10" range0="15" range1="15"/>
   Screen Phase = (0, 0)
   GPU H precision: 23 truncated
   GPU M precision: 10 truncated
   CPU H precision: 23 rounded
 
The shaders used to determine the precision were derived from those of Stuart Russell and Tom Olson from the following article:
 
#define HIGHP highp
#define MEDIUMP mediump
static const char gHighPrecisionShader[] = {
"uniform "HIGHP" vec3 resolution;\n"
"void main(void) {\n"
" "HIGHP" float y = floor(gl_FragCoord.y - resolution.z) * 26.0 / float(resolution.y);\n" /* y in the domain [0, 26], starting at 0 at the bottom */
" "HIGHP" float x = 1.0 - (floor(gl_FragCoord.x - resolution.z) / float(resolution.x));\n" /* x in the domain [0, 1], starting at 1 and decreasing to 0 toward the right */
" "HIGHP" float b = fract(pow(2.0, floor(y)) + x);\n" /* Fractional part of 2^y + x */
" gl_FragColor = vec4(b, b, b, 1.0);\n"
"}\n"
};
static const char gMediumPrecisionShader[] = {
"uniform "HIGHP" vec3 resolution;\n"
"void main(void) {\n"
" "MEDIUMP" float y = floor(gl_FragCoord.y - resolution.z) * 26.0 / float(resolution.y);\n" /* y in the domain [0, 26], starting at 0 at the bottom */
" "MEDIUMP" float x = 1.0 - (floor(gl_FragCoord.x - resolution.z) / float(resolution.x));\n" /* x in the domain [0, 1], starting at 1 and decreasing to 0 toward the right */
" "MEDIUMP" float b = fract(pow(2.0, floor(y)) + x);\n" /* Fractional part of 2^y + x */
" gl_FragColor = vec4(b, b, b, 1.0);\n"
"}\n"
};
 

So, the title of this thread should really be "glGetShaderPrecisionFormat() bug in Adreno 225".

  • Up0
  • Down0
mhfeldma Moderator
Join Date: 29 Nov 12
Posts: 310
Posted: Mon, 2014-09-22 10:16

We'll reach out directly to you to better understand your findings.

  • Up0
  • Down0
Maddius
Join Date: 2 Aug 15
Posts: 1
Posted: Sun, 2015-08-02 15:12

Hey,

I'd be really interested in hearing the outcome of this discussion as I have a very similar situation, I have a pixel shader which gets truncated values for one of its calculations when using precision mediump float; but with precision highp float; everything is fine.

It only happens on Samsung Galaxy S4, the same code runs fine on a Google Nexus 7 (2012).

I can give more information if required but it sounds like whatever the answer was here is probably the answer for me.

Thanks

  • Up0
  • Down0
mhfeldma Moderator
Join Date: 29 Nov 12
Posts: 310
Posted: Mon, 2015-08-03 07:37

This issue turned out to be a mismatch of the build that was installed on the specific Samsung Galaxy S3 device being used. The problem was fixed shortly thereafter with a software updated from Samsung.

If you have more details, feel free to share...

 

  • Up0
  • Down0
or Register

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.