[Mesa-dev] [PATCH 10/24] glsl: Implement parser support for atomic counters.

Ian Romanick idr at freedesktop.org
Wed Sep 18 08:23:19 PDT 2013


On 09/15/2013 02:10 AM, Francisco Jerez wrote:
> ---
>  src/glsl/ast.h                | 15 ++++++++++
>  src/glsl/ast_to_hir.cpp       | 68 +++++++++++++++++++++++++++++++++++++++++--
>  src/glsl/ast_type.cpp         | 13 +++++++--
>  src/glsl/glsl_lexer.ll        |  2 +-
>  src/glsl/glsl_parser.yy       | 13 +++++++--
>  src/glsl/glsl_parser_extras.h | 10 +++++++
>  6 files changed, 114 insertions(+), 7 deletions(-)
> 
> diff --git a/src/glsl/ast.h b/src/glsl/ast.h
> index 26c4701..8a5d3fc 100644
> --- a/src/glsl/ast.h
> +++ b/src/glsl/ast.h
> @@ -405,6 +405,12 @@ struct ast_type_qualifier {
>            */
>           unsigned explicit_binding:1;
>  
> +         /**
> +          * Flag set if GL_ARB_shader_atomic counter "offset" layout
> +          * qualifier is used.
> +          */
> +         unsigned explicit_offset:1;
> +
>           /** \name Layout qualifiers for GL_AMD_conservative_depth */
>           /** \{ */
>           unsigned depth_any:1;
> @@ -468,6 +474,15 @@ struct ast_type_qualifier {
>     int binding;
>  
>     /**
> +    * Offset specified via GL_ARB_shader_atomic_counter's "offset"
> +    * keyword.
> +    *
> +    * \note
> +    * This field is only valid if \c explicit_offset is set.
> +    */
> +   int offset;
> +
> +   /**
>      * Return true if and only if an interpolation qualifier is present.
>      */
>     bool has_interpolation() const;
> diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
> index fcca5df..7edbee4 100644
> --- a/src/glsl/ast_to_hir.cpp
> +++ b/src/glsl/ast_to_hir.cpp
> @@ -1197,6 +1197,9 @@ ast_expression::hir(exec_list *instructions,
>                   !state->check_version(120, 300, &loc,
>                                         "array comparisons forbidden")) {
>  	 error_emitted = true;
> +      } else if ((op[0]->type->atomic_size() || op[1]->type->atomic_size())) {
> +	 _mesa_glsl_error(&loc, state, "atomic counter comparisons forbidden");
> +	 error_emitted = true;
>        }
>  
>        if (error_emitted) {
> @@ -1952,10 +1955,19 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
>  
>           return false;
>        }
> +   } else if (var->type->atomic_size()) {
> +      if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) {
> +         _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the "
> +                          " maximum number of atomic counter buffer bindings"
> +                          "(%d)", qual->binding,
> +                          ctx->Const.MaxAtomicBufferBindings);
> +
> +         return false;
> +      }
>     } else {
>        _mesa_glsl_error(loc, state,
>                         "the \"binding\" qualifier only applies to uniform "
> -                       "blocks, samplers, or arrays of samplers");
> +                       "blocks, samplers, atomic counters, or arrays thereof");
>        return false;
>     }
>  
> @@ -1983,7 +1995,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
>     }
>  
>     if (qual->flags.q.constant || qual->flags.q.attribute
> -       || qual->flags.q.uniform
> +       || (qual->flags.q.uniform && var->type != glsl_type::atomic_uint_type)
>         || (qual->flags.q.varying && (state->target == fragment_shader)))
>        var->read_only = 1;
>  
> @@ -2225,6 +2237,35 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
>        var->binding = qual->binding;
>     }
>  
> +   if (var->type->atomic_size()) {
> +      if (var->mode == ir_var_uniform) {
> +         if (var->explicit_binding) {
> +            _mesa_glsl_parse_state::atomic_counter_binding &binding =
> +               state->atomic_counter_bindings[var->binding];
> +
> +            if (binding.next_offset % ATOMIC_COUNTER_SIZE)
> +               _mesa_glsl_error(loc, state,
> +                                "misaligned atomic counter offset");
> +
> +            if (binding.offsets.count(binding.next_offset))
> +               _mesa_glsl_error(loc, state,
> +                                "atomic counter offsets must be unique");
> +
> +            var->atomic.offset = binding.next_offset;
> +            binding.offsets.insert(binding.next_offset);
> +            binding.next_offset += var->type->atomic_size();
> +
> +         } else {
> +            _mesa_glsl_error(loc, state,
> +                             "atomic counters require explicit binding point");
> +         }
> +      } else if (var->mode != ir_var_function_in) {
> +         _mesa_glsl_error(loc, state, "atomic counters may only be declared as "
> +                          "function parameters or uniform-qualified "
> +                          "global variables");
> +      }
> +   }
> +
>     /* Does the declaration use the deprecated 'attribute' or 'varying'
>      * keywords?
>      */
> @@ -2725,6 +2766,18 @@ ast_declarator_list::hir(exec_list *instructions,
>     (void) this->type->specifier->hir(instructions, state);
>  
>     decl_type = this->type->glsl_type(& type_name, state);
> +
> +   /* An offset-qualified atomic counter declaration sets the default
> +    * offset for the next declaration within the same atomic counter
> +    * buffer.
> +    */
> +   if (decl_type && decl_type->atomic_size()) {
> +      if (type->qualifier.flags.q.explicit_binding &&
> +          type->qualifier.flags.q.explicit_offset)
> +         state->atomic_counter_bindings[type->qualifier.binding]
> +            .next_offset = type->qualifier.offset;
> +   }
> +
>     if (this->declarations.is_empty()) {
>        /* If there is no structure involved in the program text, there are two
>         * possible scenarios:
> @@ -2754,6 +2807,11 @@ ast_declarator_list::hir(exec_list *instructions,
>           _mesa_glsl_error(&loc, state,
>                            "invalid type `%s' in empty declaration",
>                            type_name);
> +      } else if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) {
> +         /* Empty atomic counter declarations are allowed and useful
> +          * to set the default offset qualifier.
> +          */
> +         return NULL;
>        } else if (this->type->qualifier.precision != ast_precision_none) {
>           if (this->type->specifier->structure != NULL) {
>              _mesa_glsl_error(&loc, state,
> @@ -4475,6 +4533,12 @@ ast_process_structure_or_interface_block(exec_list *instructions,
>                               "uniform in non-default uniform block contains sampler");
>           }
>  
> +         if (field_type->atomic_size()) {
> +            YYLTYPE loc = decl_list->get_location();
> +            _mesa_glsl_error(&loc, state, "atomic counter in structure or "
> +                             "uniform block");
> +         }
> +
>           const struct ast_type_qualifier *const qual =
>              & decl_list->type->qualifier;
>           if (qual->flags.q.std140 ||
> diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
> index 8aabd95..2b088bf 100644
> --- a/src/glsl/ast_type.cpp
> +++ b/src/glsl/ast_type.cpp
> @@ -72,7 +72,8 @@ ast_type_qualifier::has_layout() const
>            || this->flags.q.packed
>            || this->flags.q.explicit_location
>            || this->flags.q.explicit_index
> -          || this->flags.q.explicit_binding;
> +          || this->flags.q.explicit_binding
> +          || this->flags.q.explicit_offset;
>  }
>  
>  bool
> @@ -121,13 +122,18 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
>     ubo_layout_mask.flags.q.packed = 1;
>     ubo_layout_mask.flags.q.shared = 1;
>  
> +   ast_type_qualifier ubo_binding_mask;
> +   ubo_binding_mask.flags.q.explicit_binding = 1;
> +   ubo_binding_mask.flags.q.explicit_offset = 1;
> +
>     /* Uniform block layout qualifiers get to overwrite each
>      * other (rightmost having priority), while all other
>      * qualifiers currently don't allow duplicates.
>      */
>  
>     if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
> -				      ubo_layout_mask.flags.i)) != 0) {
> +				      ubo_layout_mask.flags.i |
> +                                      ubo_binding_mask.flags.i)) != 0) {
>        _mesa_glsl_error(loc, state,
>  		       "duplicate layout qualifiers used");
>        return false;
> @@ -168,6 +174,9 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
>     if (q.flags.q.explicit_binding)
>        this->binding = q.binding;
>  
> +   if (q.flags.q.explicit_offset)
> +      this->offset = q.offset;
> +
>     if (q.precision != ast_precision_none)
>        this->precision = q.precision;
>  
> diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
> index e24df80..822d70d 100644
> --- a/src/glsl/glsl_lexer.ll
> +++ b/src/glsl/glsl_lexer.ll
> @@ -337,6 +337,7 @@ samplerExternalOES		{
>  			     return IDENTIFIER;
>  		}
>  
> +atomic_uint     KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT);
>  
>  struct		return STRUCT;
>  void		return VOID_TOK;
> @@ -518,7 +519,6 @@ restrict	KEYWORD(0, 300, 0, 0, RESTRICT);
>  readonly	KEYWORD(0, 300, 0, 0, READONLY);
>  writeonly	KEYWORD(0, 300, 0, 0, WRITEONLY);
>  resource	KEYWORD(0, 300, 0, 0, RESOURCE);
> -atomic_uint	KEYWORD(0, 300, 0, 0, ATOMIC_UINT);
>  patch		KEYWORD(0, 300, 0, 0, PATCH);
>  sample		KEYWORD(0, 300, 0, 0, SAMPLE);
>  subroutine	KEYWORD(0, 300, 0, 0, SUBROUTINE);
> diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
> index fa6e205..b9498b4 100644
> --- a/src/glsl/glsl_parser.yy
> +++ b/src/glsl/glsl_parser.yy
> @@ -118,6 +118,7 @@ _mesa_glsl_lex(YYSTYPE *val, YYLTYPE *loc, _mesa_glsl_parse_state *state)
>  %token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
>  %token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY
>  %token SAMPLEREXTERNALOES
> +%token ATOMIC_UINT
>  %token STRUCT VOID_TOK WHILE
>  %token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
>  %type <identifier> any_identifier
> @@ -147,7 +148,7 @@ _mesa_glsl_lex(YYSTYPE *val, YYLTYPE *loc, _mesa_glsl_parse_state *state)
>  %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4
>  %token SAMPLER3DRECT
>  %token SIZEOF CAST NAMESPACE USING
> -%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE ATOMIC_UINT PATCH SAMPLE
> +%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE PATCH SAMPLE
>  %token SUBROUTINE
>  
>  %token ERROR_TOK
> @@ -1288,12 +1289,19 @@ layout_qualifier_id:
>           }
>        }
>  
> -      if (state->ARB_shading_language_420pack_enable &&
> +      if ((state->ARB_shading_language_420pack_enable ||
> +           state->ARB_shader_atomic_counters_enable) &&
>            strcmp("binding", $1) == 0) {
>           $$.flags.q.explicit_binding = 1;
>           $$.binding = $3;
>        }
>  
> +      if (state->ARB_shader_atomic_counters_enable &&
> +          strcmp("offset", $1) == 0) {
> +         $$.flags.q.explicit_offset = 1;
> +         $$.offset = $3;
> +      }
> +
>        if (strcmp("max_vertices", $1) == 0) {
>           $$.flags.q.max_vertices = 1;
>  
> @@ -1663,6 +1671,7 @@ basic_type_specifier_nonarray:
>     | SAMPLER2DMSARRAY       { $$ = "sampler2DMSArray"; }
>     | ISAMPLER2DMSARRAY      { $$ = "isampler2DMSArray"; }
>     | USAMPLER2DMSARRAY      { $$ = "usampler2DMSArray"; }
> +   | ATOMIC_UINT            { $$ = "atomic_uint"; }
>     ;
>  
>  precision_qualifier:
> diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
> index 4ffbf8f..d0e131a 100644
> --- a/src/glsl/glsl_parser_extras.h
> +++ b/src/glsl/glsl_parser_extras.h
> @@ -31,6 +31,8 @@
>  #ifdef __cplusplus
>  
>  
> +#include <map>
> +#include <set>

No.  We are not using STL or templates.

>  #include <stdlib.h>
>  #include "glsl_symbol_table.h"
>  
> @@ -331,6 +333,14 @@ struct _mesa_glsl_parse_state {
>      * Unused for other shader types.
>      */
>     unsigned gs_input_size;
> +
> +   struct atomic_counter_binding {
> +      atomic_counter_binding() : offsets(), next_offset(0) {}
> +      std::set<unsigned> offsets;
> +      unsigned next_offset;
> +   };
> +
> +   std::map<unsigned, atomic_counter_binding> atomic_counter_bindings;
>  };
>  
>  # define YYLLOC_DEFAULT(Current, Rhs, N)			\
> 



More information about the mesa-dev mailing list