summaryrefslogtreecommitdiff
path: root/src/glsl/ast_to_hir.cpp
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2013-10-20 12:38:07 -0700
committerIan Romanick <ian.d.romanick@intel.com>2013-11-07 15:56:57 -0800
commite63bb298531918c3a17e77a9ad96670e724c9c37 (patch)
tree9181aa991c227472ebb5d4a225e2c6dd7c811369 /src/glsl/ast_to_hir.cpp
parent30f61c471de5a9637e5d830e2b5b9dc4145f94d2 (diff)
glsl: Implement parser support for atomic counters.
v2: Mark atomic counters as read-only variables. Move offset overlap code to the linker. Use the contains_atomic() convenience method. v3: Use pointer to integer instead of non-const reference. Add comment so we remember to add a spec quotation from the next GLSL release once the issue of atomic counter aggregation within structures is clarified. v4 (idr): Don't use std::map because it's overkill. Add an assertion that ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS. Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Paul Berry <stereotype441@gmail.com> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Diffstat (limited to 'src/glsl/ast_to_hir.cpp')
-rw-r--r--src/glsl/ast_to_hir.cpp63
1 files changed, 62 insertions, 1 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index f75e68ce192..76b256c731a 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1997,10 +1997,20 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
return false;
}
+ } else if (var->type->contains_atomic()) {
+ assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS);
+ 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;
}
@@ -2300,6 +2310,29 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
var->binding = qual->binding;
}
+ if (var->type->contains_atomic()) {
+ if (var->mode == ir_var_uniform) {
+ if (var->explicit_binding) {
+ unsigned *offset = &state->atomic_counter_offsets[var->binding];
+
+ if (*offset % ATOMIC_COUNTER_SIZE)
+ _mesa_glsl_error(loc, state,
+ "misaligned atomic counter offset");
+
+ var->atomic.offset = *offset;
+ *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?
*/
@@ -2835,6 +2868,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->contains_atomic()) {
+ if (type->qualifier.flags.q.explicit_binding &&
+ type->qualifier.flags.q.explicit_offset)
+ state->atomic_counter_offsets[type->qualifier.binding] =
+ type->qualifier.offset;
+ }
+
if (this->declarations.is_empty()) {
/* If there is no structure involved in the program text, there are two
* possible scenarios:
@@ -2864,6 +2909,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,
@@ -4565,6 +4615,17 @@ ast_process_structure_or_interface_block(exec_list *instructions,
"uniform in non-default uniform block contains sampler");
}
+ if (field_type->contains_atomic()) {
+ /* FINISHME: Add a spec quotation here once updated spec
+ * FINISHME: language is available. See Khronos bug #10903
+ * FINISHME: on whether atomic counters are allowed in
+ * FINISHME: structures.
+ */
+ 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 ||