I have a shader that ideally needs 28 bits of mantissa, though I can use less and degrade performance. How can I determine what the precision of 'highp' is in OpenGL ES? It's probably an FP24, with 16bits mantissa, but I cannot figure out for sure or how to ask OpenGL. Any ideas?
3 Answers
From the OpenGL ES Shading Language reference:
highp
- 16-bit, floating point range: −262 to 262, integer range: −216 to 216mediump
- 10 bit, floating point range: −214 to 214, integer range: −210 to 210lowp
- 8 bit, floating point range: −2 to 2, integer range: −28 to 28
In OpenGL ES 3 these guarantees have been upgraded, see the GLSL ES 3.00 spec:
highp
- 24-bit, floating point range: −2126 to 2127, signed integer range: −231 to 231−1, unsigned integer range: 0 to 232−1mediump
- 10 bit, floating point range: −214 to 214, signed integer range: −215 to 215−1, unsigned integer range 0 to 216−1lowp
- 8/9 bit (signed/unsigned), floating point range: −2 to 2, signed integer range: −28 to 28−1, unsigned integer range 0 to 29−1

- 18,162
- 8
- 67
- 136

- 170,088
- 45
- 397
- 571
-
1That's the minimum precision required by the standard. Is it also the actual precision used by the PVR SGX GPUs? – Minthos Dec 11 '12 at 10:19
-
It isn't. On my device the numbers appear to be 31 bits, 15 bits and 8 bits. Probably 32, 16 and 8. I don't know where the last bit went. – Minthos Dec 11 '12 at 10:52
-
Integers appear to be 24 bit regardless of type. – Minthos Dec 11 '12 at 10:56
-
5I don't want to nitpick, but GLSL does not mandate anything with respect to the number of bits required to represent `lowp`, `mediump` or `highp`, only the minimum range of values and precision. So for `lowp` floating-point values, we have a guaranteed range of [**-2.0**,**2.0**] and precision of **2.0^-8** but that says nothing of how many bits the system uses to represent it. – Andon M. Coleman Mar 05 '15 at 13:21
-
If the specification for `highp` is +/- 2^16 integers, then doesn't that mean it has 16 bits of mantissa, and it has more bits than that total? – Aaron Franke May 20 '19 at 10:46
In my testing on my line of expensive toys:
For both ints and floats, the precisions and ranges across fragment and vertex shaders are the same.
So I will not list all combinations exhaustively.
Also note that precision of ints is defined to be always 0.
PowerVR SGX543MP3 (iPhone 5):
- Floats
- Low: precision = 8, range = 0 to 0 (Not sure, but I think this means that we cannot expect a
lowp
to actually be able to represent a value reaching exactly2
or-2
, I don't really know of a great way to test this, nor should we over-concern ourselves with these limitations, just usemediump
when this could ever be an issue) - Medium: precision = 10, range = 15 to 15 (meets spec)
- High: precision = 23, range = 127 to 127 (exceeds spec)
- Low: precision = 8, range = 0 to 0 (Not sure, but I think this means that we cannot expect a
- Ints
- Low: range = 23 to 23 (exceeds spec)
- Medium: range = 23 to 23 (exceeds spec)
- High: range = 23 to 23 (exceeds spec)
A7 & PowerVR G6430 (iPad Air):
- Floats
- Low: precision = 10, range = 15 to 15 (exceeds spec)
- Medium: precision = 10, range = 15 to 15 (meets spec)
- High: precision = 23, range = 127 to 127 (exceeds ES 2.0 spec, meets 3.0 spec)
- Ints
- Low: range = 15 to 14 (exceeds spec)
- Medium: range = 15 to 14 (exceeds ES 2.0 spec, meets ES 3.0 spec)
- High: range = 31 to 30 (exceeds ES 2.0 spec, meets ES 3.0 spec)
A8 & PowerVR GX6450 (iPhone 6 Plus):
- Floats
- Low: precision = 10, range = 15 to 15 (exceeds spec)
- Medium: precision = 10, range = 15 to 15 (meets spec)
- High: precision = 23, range = 127 to 127 (exceeds ES 2.0 spec, meets 3.0 spec)
- Ints
- Low: range = 15 to 14 (exceeds spec)
- Medium: range = 15 to 14 (exceeds ES 2.0 spec, meets ES 3.0 spec)
- High: range = 31 to 30 (exceeds ES 2.0 spec, meets ES 3.0 spec)
Here is an example of how you might query the values.
int range[2], precision;
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
NSLog(@"Fragment shader high precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, range, &precision);
NSLog(@"Fragment shader medium precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_FLOAT, range, &precision);
NSLog(@"Fragment shader low precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_INT, range, &precision);
NSLog(@"Fragment shader high precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_INT, range, &precision);
NSLog(@"Fragment shader medium precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_INT, range, &precision);
NSLog(@"Fragment shader low precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_HIGH_FLOAT, range, &precision);
NSLog(@"Vertex shader high precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_MEDIUM_FLOAT, range, &precision);
NSLog(@"Vertex shader medium precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_LOW_FLOAT, range, &precision);
NSLog(@"Vertex shader low precision float range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_HIGH_INT, range, &precision);
NSLog(@"Vertex shader high precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_MEDIUM_INT, range, &precision);
NSLog(@"Vertex shader medium precision int range: %d %d precision: %d", range[0], range[1], precision);
glGetShaderPrecisionFormat(GL_VERTEX_SHADER, GL_LOW_INT, range, &precision);
NSLog(@"Vertex shader low precision int range: %d %d precision: %d", range[0], range[1], precision);
It is not clear to me yet whether you can expect tangible performance improvements by choosing a lower-precision type (Even on some phones that are now 3 years old).
It's clear that the trend is towards convergence with desktop hardware as it can be seen that the recent GPU's have completely eliminated the 8 bit types and are recycling the mediump
ones for lowp
.

- 41,389
- 58
- 210
- 364
You want GetShaderPrecisionFormat to query the range and precision of of shader types
int range[2], precision;
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
will give you the range and precision of highp float.

- 119,907
- 13
- 134
- 226
-
Do you mean `glGetShaderPrecisionFormat`? `glGetShaderPrecisionType` seems to be a typo. – gonzojive Dec 13 '10 at 05:14
-
`glGetShaderPrecisionFormat` sure works, so maybe you should edit your response to fix the typo and I can mark it correct. Just to make it easier on the next guy. Thanks for the answer! – gonzojive Dec 13 '10 at 18:23
-
whoops -- yes, more of a brain-o than a typo -- just misremembering the name and not looking closely enough when checking the spec... – Chris Dodd Dec 13 '10 at 18:52
-
Another minor error in the code: range should be an int array of length 2. The result is the same though. – Minthos Dec 11 '12 at 10:36
-
What determines the precision types? Is it OS dependent? GPU dependent? Does it vary by programming language or OpenGL version? – Aaron Franke May 20 '19 at 10:44
-
@AaronFranke: generally GPU dependent, though it is possible different driver versions will also differ, particularly if they do more or less on the the CPU instead of the GPU. – Chris Dodd May 21 '19 at 14:30