glslang
glslang copied to clipboard
Implement fixes for built-in block member ambiguities across multiple specifications
It was not always clear which built-in variables are supposed to be in which built-in block (or not at all). There were both specification issues and glslang issues related to this.
Much work was already done in glslang to address the progress in this space, and this issue is meant to help finish it all off.
On the glslang side:
- [x] semantic checking infrastructure that extension-based member inclusion in a block is only allowed if the extension is enabled
- [ ] all the built-in variables from extensions make use the previous line
- [ ] there is a SPIR-V generation problem with the numbering of optional members: We get almost to spitting out SPIR-V with things like gl_SecondaryViewportMaskNV and gl_ViewportMaskPerViewNV, then at the last minute, don't include them. Because gl_ViewportIndex and gl_Layer are at the end, they get confused some member numbering code.
- [ ] there might be another place where member numbering is not working correctly, needs some analysis
The following is the earlier analysis I had done (in https://gitlab.khronos.org/opengl/API/issues/44#note_171908) updated for the changes/clarifications we made in ARB_shader_viewport_layer_array revision 2.
The following is the "maximal" set of shader inputs/outputs across all extensions. Includes
- GLSL 4.60
- ESSL 3.20
- GL_EXT_clip_cull_distance (adds missing stuff to ES)
- GL_OES_viewport_array (add missing stuff to ES)
- GL_NV_viewport_array2
- GL_NV_stereo_view_rendering
- GL_ARB_shader_viewport_layer_array
- GL_OES/EXT_tessellation_shader_point_size (adds missing stuff to ES)
- GL_OES/EXT_geometry_shader_point_size (adds missing stuff to ES)
- GL_ARB_ES3_2_compatibility (adds missing stuff to GL)
- GL_NV_fragment_shader_barycentric
- GL_NV_shading_rate_image
Vertex shader inputs/outputs
in int gl_VertexID; // GL + ES
in int gl_InstanceID; // GL + ES
in int gl_DrawID; // GL only
in int gl_BaseVertex; // GL only
in int gl_BaseInstance; // GL only
out gl_PerVertex {
vec4 gl_Position; // GL + ES
float gl_PointSize; // GL + ES
float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
highp int gl_ViewportIndex; // GL_ARB_shader_viewport_layer_array in GL, GL_NV_viewport_array2 in GL & ES
highp int gl_Layer; // GL_ARB_shader_viewport_layer_array in GL, GL_NV_viewport_array2 in GL & ES
highp int gl_ViewportMask[]; // GL_NV_viewport_array2 in GL & ES
highp vec4 gl_SecondaryPositionNV; // GL_NV_stereo_view_rendering in GL & ES
highp int gl_SecondaryViewportMaskNV[]; // GL_NV_stereo_view_rendering in GL & ES
};
Tessellation control shader inputs/outputs
in gl_PerVertex {
vec4 gl_Position; // GL + ES
float gl_PointSize; // GL + GL_OES/EXT_tessellation_shader_point_size in ES
float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
highp vec4 gl_SecondaryPositionNV; // GL_NV_stereo_view_rendering in GL & ES
} gl_in[gl_MaxPatchVertices];
in int gl_PatchVerticesIn; // GL + ES
in int gl_PrimitiveID; // GL + ES
in int gl_InvocationID; // GL + ES
out gl_PerVertex {
vec4 gl_Position; // GL + ES
float gl_PointSize; // GL + GL_OES/EXT_tessellation_shader_point_size in ES
float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
highp int gl_ViewportIndex; // GL_NV_viewport_array2 in GL & ES
highp int gl_Layer; // GL_NV_viewport_array2 in GL & ES
highp int gl_ViewportMask[]; // GL_NV_viewport_array2 in GL & ES
highp vec4 gl_SecondaryPositionNV; // GL_NV_stereo_view_rendering in GL & ES
highp int gl_SecondaryViewportMaskNV[]; // GL_NV_stereo_view_rendering in GL & ES
} gl_out[];
patch out float gl_TessLevelOuter[4]; // GL + ES
patch out float gl_TessLevelInner[2]; // GL + ES
patch out highp vec4 gl_BoundingBox[2]; // ES + GL_ARB_ES3_2_compatibility in GL
Tessellation evaluation shader inputs/outputs
in gl_PerVertex {
vec4 gl_Position; // GL + ES
float gl_PointSize; // GL + GL_OES/EXT_tessellation_shader_point_size in ES
float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
highp vec4 gl_SecondaryPositionNV; // GL_NV_stereo_view_rendering in GL & ES
} gl_in[gl_MaxPatchVertices];
in int gl_PatchVerticesIn; // GL + ES
in int gl_PrimitiveID; // GL + ES
in vec3 gl_TessCoord; // GL + ES
patch in float gl_TessLevelOuter[4]; // GL + ES
patch in float gl_TessLevelInner[2]; // GL + ES
out gl_PerVertex {
vec4 gl_Position; // GL + ES
float gl_PointSize; // GL + GL_OES/EXT_tessellation_shader_point_size in ES
float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
highp int gl_ViewportIndex; // GL_ARB_shader_viewport_layer_array in GL, GL_NV_viewport_array2 in GL & ES
highp int gl_Layer; // GL_ARB_shader_viewport_layer_array in GL, GL_NV_viewport_array2 in GL & ES
highp int gl_ViewportMask[]; // GL_NV_viewport_array2 in GL & ES
highp vec4 gl_SecondaryPositionNV; // GL_NV_stereo_view_rendering in GL & ES
highp int gl_SecondaryViewportMaskNV[]; // GL_NV_stereo_view_rendering in GL & ES
};
Geometry Shader inputs/outputs
in gl_PerVertex {
vec4 gl_Position; // GL + ES
float gl_PointSize; // GL + GL_OES/EXT_geometry_shader_point_size in ES
float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
highp vec4 gl_SecondaryPositionNV; // GL_NV_stereo_view_rendering in GL & ES
} gl_in[];
in int gl_PrimitiveIDIn; // GL + ES
in int gl_InvocationID; // GL + ES
out gl_PerVertex {
vec4 gl_Position; // GL + ES
float gl_PointSize; // GL + GL_OES/EXT_geometry_shader_point_size in ES
float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
highp vec4 gl_SecondaryPositionNV; // GL_NV_stereo_view_rendering in GL & ES
highp int gl_SecondaryViewportMaskNV[]; // GL_NV_stereo_view_rendering in GL & ES
};
out int gl_PrimitiveID; // GL + ES
out int gl_Layer; // GL + ES
out int gl_ViewportIndex; // GL + GL_OES_viewport_array in ES
out highp int gl_ViewportMask[]; // GL_NV_viewport_array2 in GL & ES
Fragment shader inputs/outputs
in vec4 gl_FragCoord; // GL + ES
in bool gl_FrontFacing; // GL + ES
in float gl_ClipDistance[]; // GL + GL_EXT_clip_cull_distance in ES
in float gl_CullDistance[]; // GL + GL_EXT_clip_cull_distance in ES
in vec2 gl_PointCoord; // GL + ES
in int gl_PrimitiveID; // GL + ES
in int gl_SampleID; // GL + ES
in vec2 gl_SamplePosition; // GL + ES
in int gl_SampleMaskIn[]; // GL + ES
in int gl_Layer; // GL + ES
in int gl_ViewportIndex; // GL + GL_OES_viewport_array in ES
in bool gl_HelperInvocation; // GL + ES
out float gl_FragDepth; // GL + ES
out int gl_SampleMask[]; // GL + ES
in vec3 gl_BaryCoordNV; // GL_NV_fragment_shader_barycentric in GL & ES
in vec3 gl_BaryCoordNoPerspNV; // GL_NV_fragment_shader_barycentric in GL & ES
in ivec2 gl_FragmentSizeNV; // GL_NV_shading_rate_image in GL & ES
in int gl_InvocationsPerPixelNV; // GL_NV_shading_rate_image in GL & ES
One thing to note:
- gl_Layer, gl_ViewportIndex, gl_ViewportMask[], and gl_SecondaryViewportMaskNV[] only ever appear as outputs, and never as inputs and thus they can really only be written in the last VTG stage that is present (as they wouldn't be able to form a matching interface with a subsequent VTG stage, at least in non-SSO mode).
This was discussed in the Vulkan working group in the context of which Builtin
s are allowed to appear as a block in the SPIR-V. In Vulkan we do not think there's any reason to include these variables in a block, so we prefer the style in which all the inputs and outputs are emitted outside a block. For that reason we intend to clarify the Vulkan spec that only a restricted set of these builtins are valid in a block. glslang should not change to place more members in the block when generating SPIR-V for Vulkan, although this issue may still be relevant for GL.