Clarify `invariant gl_FragCoord` for WebGL2
grovesNL opened this issue · 2 comments
Is invariant gl_FragCoord
allowed under a fragment shader for both WebGL1 and WebGL2? WebGL1 and WebGL2 seem to disagree currently.
Under
WebGL/sdk/tests/conformance/glsl/misc/shaders-with-invariance.html
Lines 247 to 252 in bd18b05
invariant gl_Position
in the vertex shader and invariant gl_FragCoord
in the fragment shader under WebGL1 succeeds.
If we port the same test case to WebGL2 it will currently fail under Chrome and Firefox on Windows, e.g. adding a test case with
<script id="vertexShaderInvariantGlPosition" type="text/something-not-javascript">#version 300 es
precision mediump float;
invariant gl_Position;
void main()
{
gl_Position = vec4(0, 0, 0, 0);
}
</script>
<script id="fragmentShaderInvariantGlFragCoord" type="text/something-not-javascript">#version 300 es
precision mediump float;
invariant gl_FragCoord;
out vec4 my_color;
void main()
{
my_color = gl_FragCoord;
}
</script>
..results in the following error:
Error compiling FRAGMENT_SHADER '[object WebGLShader]':ERROR: 0:3: 'invariant' : Cannot be qualified as invariant.
(full test case at grovesNL@afe0a53 for convenience)
The ESSL specs both seem to say (under "Invariance" header, ESSL 1.00 10.18 or ESSL 3.00 12.13):
RESOLUTION: Add an invariance qualifier to variables but permit its use only for outputs from the
vertex and fragment shaders. Add a global invariance option for use when complete invariance is
required.
ESSL 3.00 restricts this a little further, which is probably where the shader compiler error originates from:
RESOLUTION: Only allow invariant declarations on outputs.
..but both ESSL 1.00 and ESSL 3.00 also mention gl_FragCoord
invariance as a special variable:
How does this rule apply to the built-in special variables.
Option 1: It should be the same as for varyings. But gl_Position is used internally by the rasterizer as
well as for gl_FragCoord so there may be cases where rasterization is required to be invariant but
gl_FragCoord is not.
Option 2: gl_FragCoord and gl_PointCoord can be qualified as invariance if and only if gl_Position and
gl_PointSize are qualified invariant, respectively.
(there's no resolution for these options unfortunately)
gl_FragCoord
is an input so it's restricted based on Only allow invariant declarations on outputs.
However the line about gl_FragCoord and gl_PointCoord can be qualified as invariance
implies that it should be allowed - just restricted so that it can only be specified when gl_Position
is also invariant.
The essl300 spec is missing the text, but the essl310 spec has it:
How does this rule apply to the built-in special variables?
Option 1: It should be the same as for varyings. But gl_Position is used internally by the rasterizer as
well as for gl_FragCoord so there may be cases where rasterization is required to be invariant but
gl_FragCoord is not.Option 2: gl_FragCoord and gl_PointCoord can be qualified as invariance if and only if gl_Position and
gl_PointSize are qualified invariant, respectively.RESOLUTION: Option 1.
I believe that the intent is actually:
How does this rule apply to the built-in special variables?
Option 1: It should be the same as for varyings.
But [because] gl_Position is used internally by the rasterizer as
well as for gl_FragCoord so there may be cases where rasterization is required to be invariant but
gl_FragCoord is not [, consider:]Option 2: gl_FragCoord and gl_PointCoord can be qualified as invariance if and only if gl_Position and
gl_PointSize are qualified invariant, respectively.RESOLUTION: Option 1. [but we acknowledge here the gap in flexibility that this leaves]
That's how I'm going to rule this.
Thanks for bringing this to our attention!
Sounds great, thank you!