<div dir="ltr">On 15 September 2013 00:10, Francisco Jerez <span dir="ltr"><<a href="mailto:currojerez@riseup.net" target="_blank">currojerez@riseup.net</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">---<br>
 src/glsl/ast.h                | 15 ++++++++++<br>
 src/glsl/ast_to_hir.cpp       | 68 +++++++++++++++++++++++++++++++++++++++++--<br>
 src/glsl/ast_type.cpp         | 13 +++++++--<br>
 src/glsl/glsl_lexer.ll        |  2 +-<br>
 src/glsl/glsl_parser.yy       | 13 +++++++--<br>
 src/glsl/glsl_parser_extras.h | 10 +++++++<br>
 6 files changed, 114 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/src/glsl/ast.h b/src/glsl/ast.h<br>
index 26c4701..8a5d3fc 100644<br>
--- a/src/glsl/ast.h<br>
+++ b/src/glsl/ast.h<br>
@@ -405,6 +405,12 @@ struct ast_type_qualifier {<br>
           */<br>
          unsigned explicit_binding:1;<br>
<br>
+         /**<br>
+          * Flag set if GL_ARB_shader_atomic counter "offset" layout<br>
+          * qualifier is used.<br>
+          */<br>
+         unsigned explicit_offset:1;<br>
+<br>
          /** \name Layout qualifiers for GL_AMD_conservative_depth */<br>
          /** \{ */<br>
          unsigned depth_any:1;<br>
@@ -468,6 +474,15 @@ struct ast_type_qualifier {<br>
    int binding;<br>
<br>
    /**<br>
+    * Offset specified via GL_ARB_shader_atomic_counter's "offset"<br>
+    * keyword.<br>
+    *<br>
+    * \note<br>
+    * This field is only valid if \c explicit_offset is set.<br>
+    */<br>
+   int offset;<br>
+<br>
+   /**<br>
     * Return true if and only if an interpolation qualifier is present.<br>
     */<br>
    bool has_interpolation() const;<br>
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp<br>
index fcca5df..7edbee4 100644<br>
--- a/src/glsl/ast_to_hir.cpp<br>
+++ b/src/glsl/ast_to_hir.cpp<br>
@@ -1197,6 +1197,9 @@ ast_expression::hir(exec_list *instructions,<br>
                  !state->check_version(120, 300, &loc,<br>
                                        "array comparisons forbidden")) {<br>
         error_emitted = true;<br>
+      } else if ((op[0]->type->atomic_size() || op[1]->type->atomic_size())) {<br>
+        _mesa_glsl_error(&loc, state, "atomic counter comparisons forbidden");<br>
+        error_emitted = true;<br></blockquote><div><br></div><div>Do we have spec text to back this up?  I looked around and couldn't find anything.  It seems like doing equality comparisons on atomic counters is ill-defined, though (do two counters compare equal if they have equal values, or if they point to the same counter?  Both possibilities seem dodgy).  Maybe we should file a spec bug so we can get clarification from khronos about what's intended.<br>

<br>Note that we currently permit other comparisons that are similarly dodgy (e.g. comparing samplers).  It would be nice to get clarification from khronos about this too.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">


       }<br>
<br>
       if (error_emitted) {<br>
@@ -1952,10 +1955,19 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,<br>
<br>
          return false;<br>
       }<br>
+   } else if (var->type->atomic_size()) {<br>
+      if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) {<br>
+         _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the "<br>
+                          " maximum number of atomic counter buffer bindings"<br>
+                          "(%d)", qual->binding,<br>
+                          ctx->Const.MaxAtomicBufferBindings);<br>
+<br>
+         return false;<br>
+      }<br>
    } else {<br>
       _mesa_glsl_error(loc, state,<br>
                        "the \"binding\" qualifier only applies to uniform "<br>
-                       "blocks, samplers, or arrays of samplers");<br>
+                       "blocks, samplers, atomic counters, or arrays thereof");<br>
       return false;<br>
    }<br>
<br>
@@ -1983,7 +1995,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,<br>
    }<br>
<br>
    if (qual->flags.q.constant || qual->flags.q.attribute<br>
-       || qual->flags.q.uniform<br>
+       || (qual->flags.q.uniform && var->type != glsl_type::atomic_uint_type)<br>
        || (qual->flags.q.varying && (state->target == fragment_shader)))<br>
       var->read_only = 1;<br></blockquote><div><br></div><div>I'm not entirely convinced this is right.  An atomic counter, like a sampler, is a handle to an underlying object, not the underlying object itself.  The handle should be considered read-only even if the object it refers to is mutable.  That way we still prohibit<br>
<br></div><div>uniform atomic_uint foo;<br></div><div>uniform atomic_uint bar;<br>void main() {<br></div><div>   foo = bar;<br>}<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<br>
@@ -2225,6 +2237,35 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,<br>
       var->binding = qual->binding;<br>
    }<br>
<br>
+   if (var->type->atomic_size()) {<br>
+      if (var->mode == ir_var_uniform) {<br>
+         if (var->explicit_binding) {<br>
+            _mesa_glsl_parse_state::atomic_counter_binding &binding =<br>
+               state->atomic_counter_bindings[var->binding];<br>
+<br>
+            if (binding.next_offset % ATOMIC_COUNTER_SIZE)<br>
+               _mesa_glsl_error(loc, state,<br>
+                                "misaligned atomic counter offset");<br>
+<br>
+            if (binding.offsets.count(binding.next_offset))<br>
+               _mesa_glsl_error(loc, state,<br>
+                                "atomic counter offsets must be unique");<br></blockquote><div><br></div><div>GLSL 4.20 clarifies that atomic counter offsets must be unique and non-overlapping (see GLSL 4.20 4.4.4.1 "Atomic Counter Layout Qualifiers").  So I tihnk we need a stronger check than this.  Specifically, declarations like the following should be disallowed:<br>
<br></div><div>layout(binding=0, offset=16) atomic_uint foo[4]; // Uses offsets 16, 20, 24, 28<br></div><div>layout(binding=0, offset=20) atomic_uint bar; // Error: overlaps foo.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+<br>
+            var->atomic.offset = binding.next_offset;<br>
+            binding.offsets.insert(binding.next_offset);<br>
+            binding.next_offset += var->type->atomic_size();<br>
+<br>
+         } else {<br>
+            _mesa_glsl_error(loc, state,<br>
+                             "atomic counters require explicit binding point");<br>
+         }<br>
+      } else if (var->mode != ir_var_function_in) {<br>
+         _mesa_glsl_error(loc, state, "atomic counters may only be declared as "<br>
+                          "function parameters or uniform-qualified "<br>
+                          "global variables");<br>
+      }<br>
+   }<br>
+<br>
    /* Does the declaration use the deprecated 'attribute' or 'varying'<br>
     * keywords?<br>
     */<br>
@@ -2725,6 +2766,18 @@ ast_declarator_list::hir(exec_list *instructions,<br>
    (void) this->type->specifier->hir(instructions, state);<br>
<br>
    decl_type = this->type->glsl_type(& type_name, state);<br>
+<br>
+   /* An offset-qualified atomic counter declaration sets the default<br>
+    * offset for the next declaration within the same atomic counter<br>
+    * buffer.<br>
+    */<br>
+   if (decl_type && decl_type->atomic_size()) {<br>
+      if (type->qualifier.flags.q.explicit_binding &&<br>
+          type->qualifier.flags.q.explicit_offset)<br>
+         state->atomic_counter_bindings[type->qualifier.binding]<br>
+            .next_offset = type->qualifier.offset;<br>
+   }<br>
+<br>
    if (this->declarations.is_empty()) {<br>
       /* If there is no structure involved in the program text, there are two<br>
        * possible scenarios:<br>
@@ -2754,6 +2807,11 @@ ast_declarator_list::hir(exec_list *instructions,<br>
          _mesa_glsl_error(&loc, state,<br>
                           "invalid type `%s' in empty declaration",<br>
                           type_name);<br>
+      } else if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) {<br>
+         /* Empty atomic counter declarations are allowed and useful<br>
+          * to set the default offset qualifier.<br>
+          */<br>
+         return NULL;<br>
       } else if (this->type->qualifier.precision != ast_precision_none) {<br>
          if (this->type->specifier->structure != NULL) {<br>
             _mesa_glsl_error(&loc, state,<br>
@@ -4475,6 +4533,12 @@ ast_process_structure_or_interface_block(exec_list *instructions,<br>
                              "uniform in non-default uniform block contains sampler");<br>
          }<br>
<br>
+         if (field_type->atomic_size()) {<br>
+            YYLTYPE loc = decl_list->get_location();<br>
+            _mesa_glsl_error(&loc, state, "atomic counter in structure or "<br>
+                             "uniform block");<br>
+         }<br>
+<br></blockquote><div><br></div><div>Are you sure this is not allowed?  I can't find any spec text to back this up.  All I found was this text from ARB_shader_atomic_counters:<br><br>"Except for array indexing, structure field selection, and parenthesis, counters are not allowed to be operands in expressions."<br>
<br></div><div>Which would seem to imply that atomic counters *are* allowed as structure fields.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

          const struct ast_type_qualifier *const qual =<br>
             & decl_list->type->qualifier;<br>
          if (qual->flags.q.std140 ||<br>
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp<br>
index 8aabd95..2b088bf 100644<br>
--- a/src/glsl/ast_type.cpp<br>
+++ b/src/glsl/ast_type.cpp<br>
@@ -72,7 +72,8 @@ ast_type_qualifier::has_layout() const<br>
           || this->flags.q.packed<br>
           || this->flags.q.explicit_location<br>
           || this->flags.q.explicit_index<br>
-          || this->flags.q.explicit_binding;<br>
+          || this->flags.q.explicit_binding<br>
+          || this->flags.q.explicit_offset;<br>
 }<br>
<br>
 bool<br>
@@ -121,13 +122,18 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,<br>
    ubo_layout_mask.flags.q.packed = 1;<br>
    ubo_layout_mask.flags.q.shared = 1;<br>
<br>
+   ast_type_qualifier ubo_binding_mask;<br>
+   ubo_binding_mask.flags.q.explicit_binding = 1;<br>
+   ubo_binding_mask.flags.q.explicit_offset = 1;<br>
+<br>
    /* Uniform block layout qualifiers get to overwrite each<br>
     * other (rightmost having priority), while all other<br>
     * qualifiers currently don't allow duplicates.<br>
     */<br>
<br>
    if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |<br>
-                                     ubo_layout_mask.flags.i)) != 0) {<br>
+                                     ubo_layout_mask.flags.i |<br>
+                                      ubo_binding_mask.flags.i)) != 0) {<br>
       _mesa_glsl_error(loc, state,<br>
                       "duplicate layout qualifiers used");<br>
       return false;<br>
@@ -168,6 +174,9 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,<br>
    if (q.flags.q.explicit_binding)<br>
       this->binding = q.binding;<br>
<br>
+   if (q.flags.q.explicit_offset)<br>
+      this->offset = q.offset;<br>
+<br>
    if (q.precision != ast_precision_none)<br>
       this->precision = q.precision;<br>
<br>
diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll<br>
index e24df80..822d70d 100644<br>
--- a/src/glsl/glsl_lexer.ll<br>
+++ b/src/glsl/glsl_lexer.ll<br>
@@ -337,6 +337,7 @@ samplerExternalOES          {<br>
                             return IDENTIFIER;<br>
                }<br>
<br>
+atomic_uint     KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT);<br>
<br>
 struct         return STRUCT;<br>
 void           return VOID_TOK;<br>
@@ -518,7 +519,6 @@ restrict    KEYWORD(0, 300, 0, 0, RESTRICT);<br>
 readonly       KEYWORD(0, 300, 0, 0, READONLY);<br>
 writeonly      KEYWORD(0, 300, 0, 0, WRITEONLY);<br>
 resource       KEYWORD(0, 300, 0, 0, RESOURCE);<br>
-atomic_uint    KEYWORD(0, 300, 0, 0, ATOMIC_UINT);<br>
 patch          KEYWORD(0, 300, 0, 0, PATCH);<br>
 sample         KEYWORD(0, 300, 0, 0, SAMPLE);<br>
 subroutine     KEYWORD(0, 300, 0, 0, SUBROUTINE);<br>
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy<br>
index fa6e205..b9498b4 100644<br>
--- a/src/glsl/glsl_parser.yy<br>
+++ b/src/glsl/glsl_parser.yy<br>
@@ -118,6 +118,7 @@ _mesa_glsl_lex(YYSTYPE *val, YYLTYPE *loc, _mesa_glsl_parse_state *state)<br>
 %token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS<br>
 %token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY<br>
 %token SAMPLEREXTERNALOES<br>
+%token ATOMIC_UINT<br>
 %token STRUCT VOID_TOK WHILE<br>
 %token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER<br>
 %type <identifier> any_identifier<br>
@@ -147,7 +148,7 @@ _mesa_glsl_lex(YYSTYPE *val, YYLTYPE *loc, _mesa_glsl_parse_state *state)<br>
 %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4<br>
 %token SAMPLER3DRECT<br>
 %token SIZEOF CAST NAMESPACE USING<br>
-%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE ATOMIC_UINT PATCH SAMPLE<br>
+%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE PATCH SAMPLE<br>
 %token SUBROUTINE<br>
<br>
 %token ERROR_TOK<br>
@@ -1288,12 +1289,19 @@ layout_qualifier_id:<br>
          }<br>
       }<br>
<br>
-      if (state->ARB_shading_language_420pack_enable &&<br>
+      if ((state->ARB_shading_language_420pack_enable ||<br>
+           state->ARB_shader_atomic_counters_enable) &&<br>
           strcmp("binding", $1) == 0) {<br>
          $$.flags.q.explicit_binding = 1;<br>
          $$.binding = $3;<br>
       }<br>
<br>
+      if (state->ARB_shader_atomic_counters_enable &&<br>
+          strcmp("offset", $1) == 0) {<br>
+         $$.flags.q.explicit_offset = 1;<br>
+         $$.offset = $3;<br>
+      }<br>
+<br>
       if (strcmp("max_vertices", $1) == 0) {<br>
          $$.flags.q.max_vertices = 1;<br>
<br>
@@ -1663,6 +1671,7 @@ basic_type_specifier_nonarray:<br>
    | SAMPLER2DMSARRAY       { $$ = "sampler2DMSArray"; }<br>
    | ISAMPLER2DMSARRAY      { $$ = "isampler2DMSArray"; }<br>
    | USAMPLER2DMSARRAY      { $$ = "usampler2DMSArray"; }<br>
+   | ATOMIC_UINT            { $$ = "atomic_uint"; }<br>
    ;<br>
<br>
 precision_qualifier:<br>
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h<br>
index 4ffbf8f..d0e131a 100644<br>
--- a/src/glsl/glsl_parser_extras.h<br>
+++ b/src/glsl/glsl_parser_extras.h<br>
@@ -31,6 +31,8 @@<br>
 #ifdef __cplusplus<br>
<br>
<br>
+#include <map><br>
+#include <set><br>
 #include <stdlib.h><br>
 #include "glsl_symbol_table.h"<br>
<br>
@@ -331,6 +333,14 @@ struct _mesa_glsl_parse_state {<br>
     * Unused for other shader types.<br>
     */<br>
    unsigned gs_input_size;<br>
+<br>
+   struct atomic_counter_binding {<br>
+      atomic_counter_binding() : offsets(), next_offset(0) {}<br>
+      std::set<unsigned> offsets;<br>
+      unsigned next_offset;<br>
+   };<br>
+<br>
+   std::map<unsigned, atomic_counter_binding> atomic_counter_bindings;<br>
 };<br>
<br>
 # define YYLLOC_DEFAULT(Current, Rhs, N)                       \<br>
<span><font color="#888888">--<br>
1.8.3.4<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>