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

Use getShaderPrecisionFormat to check if highp precision is available in shader #122

Closed
dmnsgn opened this issue Jan 2, 2019 · 16 comments
Closed
Assignees
Labels

Comments

@dmnsgn
Copy link
Member

dmnsgn commented Jan 2, 2019

API could default to highp and be overrided manually, but check getShaderPrecisionFormat in every case:

renderer = createRenderer(opts)
const renderer = createRendererer({
  ...,
 precision: 'highp' // 'lowp' || 'mediump'
})
@dmnsgn dmnsgn added bug labels Jan 2, 2019
@vorg
Copy link
Member

vorg commented Jan 2, 2019

I think in the context of pex-renderer it’s safe to assume such device would not be able to run it anyway.

@vorg vorg closed this as completed Jan 2, 2019
@vorg vorg reopened this Jan 3, 2019
@vorg
Copy link
Member

vorg commented Jan 3, 2019

@dmnsgn I'm re-opening this issue due to iPhoneX problems with normal mapping #123

@dmnsgn
Copy link
Member Author

dmnsgn commented Jan 14, 2019

PR in progress: #125

@vorg
Copy link
Member

vorg commented Jan 14, 2019

From Unity docs: Precision, Hardware Support and Performance

One complication of float/half/fixed data type usage is that PC GPUs are always high precision. That is, for all the PC (Windows/Mac/Linux) GPUs, it does not matter whether you write float, half or fixed data types in your shaders. They always compute everything in full 32-bit floating point precision.

That explains no performance gains when i tested "half-float pipeline" (and all mediump qulifiers you removed in #125)

The half and fixed types only become relevant when targeting mobile GPUs, where these types primarily exist for power (and sometimes performance) constraints. Keep in mind that you need to test your shaders on mobile to see whether or not you are running into precision/numerical issues.

I did run into issues many times that's why i tried to avoid it.

Using lower precision can often be faster, either due to improved GPU register allocation, or due to special “fast path” execution units for certain lower-precision math operations. Even when there’s no raw performance advantage, using lower precision often uses less power on the GPU, leading to better battery life.

Now that's interesting.

A general rule of thumb is to start with half precision for everything except positions and texture coordinates. Only increase precision if half precision is not enough for some parts of the computation.

@vorg
Copy link
Member

vorg commented Jan 14, 2019

In that context this comment from Filament docs makes more sense

This solution solves the storage problem but requires intermediate computations to be performed with single precision floats. We would instead prefer to perform all (or at least most) of the lighting work using half precision floats instead. Doing so can greatly improve performance and power usage, particularly on mobile devices. Half precision floats are however ill-suited for this kind of work as common illuminance and luminance values (for the sun for instance) can exceed their range. The solution is to simply pre-expose the lights themselves instead of the result of the lighting pass. This can be done efficiently on the CPU if updating a light's constant buffer is cheap. This can also be done on the GPU, as shown in listing 25.

@vorg
Copy link
Member

vorg commented Jan 14, 2019

From Apple's [OpenGL ES Programming Guide] (now deprecated of course):

When in doubt, default to high precision.
Colors in the 0.0 to 1.0 range can usually be represented using low precision variables.
Position data should usually be stored as high precision.
Normals and vectors used in lighting calculations can usually be stored as medium precision.
After reducing precision, retest your app to ensure that the results are what you expect.

@vorg
Copy link
Member

vorg commented Jan 14, 2019

ThreeJS work "towards mediump"

I kind of proves my earlier comment that just supporting mediump won't magically fix the devices not having highp and would require setting mobile support as a serious goal with serious mobile testing.

@vorg vorg mentioned this issue Jan 14, 2019
@dmnsgn
Copy link
Member Author

dmnsgn commented Jan 15, 2019

It probably won't fixes all bugs magically but at least provide support for other precisions which could be a good start before planning anything else.

@dmnsgn dmnsgn added this to the 3.0.0 milestone Jan 15, 2019
@vorg
Copy link
Member

vorg commented Jan 15, 2019

I'm not sure about this approach

const renderer = createRendererer({
  ...,
 precision: 'highp' // 'lowp' || 'mediump'
})

After reading all the references above it seems that correct way is to have everything as low as possible because without bugs a) save energy on mobile, b) on desktop it doesn't matter (i.e. it's always "highest quality"). Maybe i need to learn more about ThreeJS approach but the "everything is mediump" way implemented in #125 might be hard to manage as individual uniforms might need to be tweaked (e.g. positions hi/med, colors low etc). Investigating...

@vorg
Copy link
Member

vorg commented Jan 16, 2019

BabylonJS does string replacement on all shaders if highp is not supported. Hmm. So is anybody doing per variable precision optimisations beside some autogenerated/cross-compiled shaders in AAA engines like unity?

@dmnsgn
Copy link
Member Author

dmnsgn commented Jan 16, 2019

I have never seen any WebGL shader in the wild making use of per variable precision setting (eg. no uniform highp mat4 uModelMatrix;)

@vorg
Copy link
Member

vorg commented Jan 18, 2019

If we are not interested in per-variable precision tweaking why not automate the whole thing in pex-context (e.g inside pipeline()) and get rid of getMaxPrecision in favour of capabilities.fragmentPrecisionHigh boolean or GL_FRAGMENT_PRECISION_HIGH glsl define for simpler shaders switches or troubleshooting if necessary (pex-gl/pex-context#60 (comment))

@dmnsgn
Copy link
Member Author

dmnsgn commented Jan 18, 2019

Would it still be possible to have per material precision with this approach?

@vorg
Copy link
Member

vorg commented Mar 20, 2019

I have never seen any WebGL shader in the wild making use of per variable precision setting (eg. no

@dmnsgn

#version 300 es
precision mediump float;
precision mediump int;
layout(std140) uniform FrameUniforms
{
highp mat4 viewFromWorldMatrix;
highp mat4 worldFromViewMatrix;
highp mat4 clipFromViewMatrix;
highp mat4 viewFromClipMatrix;
highp mat4 clipFromWorldMatrix;
highp mat4 worldFromClipMatrix;
highp mat4 lightFromWorldMatrix;
highp vec4 resolution;
highp vec3 cameraPosition;
highp float time;

or

precision mediump float;
precision mediump int;
layout(std140) uniform PostProcessUniforms
{
vec2 uvScale;
float time;
float yOffset;
} postProcessUniforms;
uniform mediump sampler2D postProcess_colorBuffer;
in highp vec2 vertex_uv;

@vorg
Copy link
Member

vorg commented Mar 20, 2019

I think we should test it our pex-renderer materials with mediump devices and use GL_FRAGMENT_PRECISION_HIGH for portability.

@dmnsgn dmnsgn added type/fix A bug fix type/feat A new feature and removed bug labels Jul 5, 2022
@dmnsgn dmnsgn removed the enhancement label Jul 5, 2022
@dmnsgn dmnsgn removed this from the 3.0.0 milestone Oct 19, 2022
@vorg
Copy link
Member

vorg commented Sep 12, 2023

Not sure how much is that relevant in 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

No branches or pull requests

2 participants