mediump vs highp precision on Embedded GPUs

There are a lot of  tests on GPU performance, in terms of how many operations per sec (rendering, float arithmetic, etc..), but not a lot on quality and precision. Most would argue that such a benchmark is not very relevant, well that is true in general cases but not all (actually its like having 5k resolution on a 4 inch device; but that is another story). In this post I am discussing the “special” cases where it does matter, focusing on mediump vs highp in fragment programs as well as vertex programs.

Since OpenGL ES specs loosely define the float precision requirements and leaves to the vendors the freedom of implementing it,  resulting in having no two devices with same precision. To most applications this is not an issue, but dealing with large CAD data-sets and requiring consistent behavior on all devices such inconsistency becomes an issue especially that this relates directly to the performance.

Testing our application with a Nexus 10 device, that includes the new Mali-T604, encountered a weird bad quality of rendering (second image below). Weird since I had very high hopes for this new device, and the same impl is giving very good quality on its predecessor Mali-400 and on Tegra 3.  Searching/experimenting to find hints to this issue, I came across a blog post by Stuart Russell which compares different devices regarding float precision; and a very informative post by Tom Olson describing the float precision on Mali-T604 and why it’s different (which gave the hint/answer to my problem) .

Problem: used to depend on mediump precision on all devices since highp was not available on some of the devices I tested; and since it is not performing well on others even if it says they do.  After reading those posts decided to do a similar benchmark but on mediump with the available devices at hand . The shaders are similar to the ones described in the referenced posts, with one modification: color is passed from vertex shader to get an idea on the precision in vertex shaders as well.

Results:


Turns out that on Mali-400 MP, Tegra-3, and Adreno 320 the mediump precision is higher than what you expect: (which is 210) and is lower using Mali-T604 especially at the vertex shader. Thus getting a new inconsistency in the data passed from vertex to fragment; which is another reason for the variations shown in the benchmarks.

This inconsistency removes the idea that highp is not really needed on embedded device. And brings another problem on the table, why should we force the highp path in a case that is not needed or in a case where the precision diff is not much (based on the user data). But how can we tell, with no way of querying this precision. If an implementation does declare highp but with insignificant diff with mediump, it would be nice to be able to decide what to choose to enhance performance.

Discussion: The snapshots below show that  highp (vertex shader) had no visible effect on Mali-400MP (as well as tegra-2, tegra-3, adreno 320..),  but on Mali-T604 it had a major effect (from corrupted scene to a very accurate rendering) .  But which implementation is better, cant really tell. But based on specs, both are correct!

Solution: not optimal, but gives correct and “consistent” results

Knowing that my input data is variable (so need for highp or mediump is based on the model), moved to using highp in the cases where it is supported in the fragment language; with the consequence of  having un-profitable computations on devices that declare highp but without giving highp.

Finally, since the main variation is found between devices that implement highp in fragment vs those who do not, found the below declaration a compatible way to have “just enough” precision. Thus on mali-400 and tegra-3 we will continue to use mediump as for Mali-T604 it will use highp in the vertex shaders.

//declared in vertex shader

#ifndef GL_FRAGMENT_PRECISION_HIGH
precision mediump float;
precision mediump int;
#else
precision highp float;
precision highp int;
#endif

Results:

mediump on Samsung Galaxy S2 with Mali-400 MP

mediump on Samsung Nexus 10 with Mali-T604

mediump on Samsung Nexus 10 with Mali-T604

highp on Samsung Nexus 10 with Mali-400 MP

highp on Samsung Galaxy S2 with Mali-400 MP

highp on Samsung Nexus 10 with Mali-T604

highp on Samsung Nexus 10 with Mali-T604

, , , , , , ,

2 Comments

  • Nicolas says:

    Nice post. Lately I’ve come across precision issue with a special color space converter shader (for rendering video through texture) on Mali 400 (Odroid U2). When compiling my shader, with the highp precision set, I get a warning from the compiler saying that highp is not supported, that it’s falling back to mediump. That might explain why you don’t see any difference between mediump and highp on Mali 400.

  • Betty says:

    Thanks ffor another magnificent article. Where else may anyon get that type of information in such an ideal manner of
    writing? I have a presentation subsequent week, aand I’m at the look for such
    info.

    My website Internal communications strategy (Betty)

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>