<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>