[Mesa-dev] [PATCH 04/14] glsl: Handle most qualifier ordering in C code rather than the grammar.

Matt Turner mattst88 at gmail.com
Thu Jul 18 13:38:27 PDT 2013


On Mon, Jul 15, 2013 at 7:32 PM, Kenneth Graunke <kenneth at whitecape.org> wrote:
> The GL_ARB_shading_language_420pack extension/GLSL 4.20 allow qualifiers
> to be specified in (basically) any order.  In order to support this, we
> can't hardcode the ordering restrictions in the grammar.
>
> This patch alters the grammar to accept invariant, storage, layout, and
> interpolation qualifiers in any order, but adds C code to enforce the
> ordering requirements.  In the 420pack case, we should be able to simply
> skip the error checks.
>
> As a bonus, this also lets us generate decent error messages, rather
> than Bison's awful "unexpected TOKEN" errors.
>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/glsl/glsl_parser.yy | 110 ++++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 92 insertions(+), 18 deletions(-)
>
> diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
> index b8f3df9..72bf560 100644
> --- a/src/glsl/glsl_parser.yy
> +++ b/src/glsl/glsl_parser.yy
> @@ -1314,34 +1314,108 @@ parameter_type_qualifier:
>     ;
>
>  type_qualifier:
> -   storage_qualifier
> -   | layout_qualifier
> -   | layout_qualifier storage_qualifier
> +   /* Single qualifiers */
> +   INVARIANT
>     {
> -      $$ = $1;
> -      $$.flags.i |= $2.flags.i;
> +      memset(& $$, 0, sizeof($$));
> +      $$.flags.q.invariant = 1;
>     }
> +   | storage_qualifier
>     | interpolation_qualifier
> -   | interpolation_qualifier storage_qualifier
> -   {
> -      $$ = $1;
> -      $$.flags.i |= $2.flags.i;
> -   }
> -   | INVARIANT storage_qualifier
> +   | layout_qualifier
> +
> +   /* Multiple qualifiers:
> +    * In GLSL 4.20, these can be specified in any order.  In earlier versions,
> +    * they appear in this order (see GLSL 1.50 section 4.7 & comments below):
> +    *
> +    *    invariant interpolation storage precision  ...or...
> +    *    layout storage precision
> +    *
> +    * Each qualifier's rule ensures that the accumulated qualifiers on the right
> +    * side don't contain any that must appear on the left hand side.
> +    * For example, when processing a storage qualifier, we check that there are
> +    * no interpolation, layout, or invariant qualifiers to the right.
> +    */
> +   | INVARIANT type_qualifier
>     {
> +      if ($2.flags.q.invariant)
> +         _mesa_glsl_error(&@1, state, "Duplicate \"invariant\" qualifier.\n");
> +
> +      if ($2.has_layout()) {
> +         _mesa_glsl_error(&@1, state,
> +                          "\"invariant\" cannot be used with layout(...).\n");
> +      }
> +
>        $$ = $2;
>        $$.flags.q.invariant = 1;
>     }
> -   | INVARIANT interpolation_qualifier storage_qualifier
> +   | interpolation_qualifier type_qualifier
> +   {
> +      /* Section 4.3 of the GLSL 1.40 specification states:
> +       * "...qualified with one of these interpolation qualifiers"
> +       *
> +       * GLSL 1.30 claims to allow "one or more", but insists that:
> +       * "These interpolation qualifiers may only precede the qualifiers in,
> +       *  centroid in, out, or centroid out in a declaration."
> +       *
> +       * ...which means that e.g. smooth can't precede smooth, so there can be
> +       * only one after all, and the 1.40 text is a clarification, not a change.
> +       */
> +      if ($2.has_interpolation())
> +         _mesa_glsl_error(&@1, state, "Duplicate interpolation qualifier.\n");
> +
> +      if ($2.has_layout()) {
> +         _mesa_glsl_error(&@1, state, "Interpolation qualifiers cannot be used "
> +                          "with layout(...).\n");
> +      }
> +
> +      if ($2.flags.q.invariant) {
> +         _mesa_glsl_error(&@1, state, "Interpolation qualifiers must come "
> +                          "after \"invariant\".\n");
> +      }
> +
> +      $$ = $1;
> +      $$.flags.i |= $2.flags.i;
> +   }
> +   | layout_qualifier type_qualifier
>     {
> -      $$ = $2;
> -      $$.flags.i |= $3.flags.i;
> -      $$.flags.q.invariant = 1;
> +      /* The GLSL 1.50 grammar indicates that a layout(...) declaration can be
> +       * used standalone or immediately before a storage qualifier.  It cannot
> +       * be used with interpolation qualifiers or invariant.  There does not
> +       * appear to be any text indicating that it must come before the storage
> +       * qualifier, but always seems to in examples.
> +       */
> +      if ($2.has_layout())

Should be

if (!state->ARB_shading_language_420pack_enable && $2.has_layout())

Since duplicate layout qualifiers are explicitly allowed.


More information about the mesa-dev mailing list