[Mesa-dev] [PATCH 09/24] glsl: Add IR node for atomic operations.
Francisco Jerez
currojerez at riseup.net
Sun Sep 15 00:10:35 PDT 2013
Add a subclass of ir_rvalue that represents an atomic operation on
some ir_variable. Also define a new IR visitor method, and implement
IR builder, printer and reader support for it.
---
src/glsl/ir.cpp | 2 +-
src/glsl/ir.h | 42 ++++++++++++++++++++++++++
src/glsl/ir_builder.cpp | 7 +++++
src/glsl/ir_builder.h | 2 ++
src/glsl/ir_clone.cpp | 11 +++++++
src/glsl/ir_constant_expression.cpp | 7 +++++
src/glsl/ir_hierarchical_visitor.cpp | 16 ++++++++++
src/glsl/ir_hierarchical_visitor.h | 2 ++
src/glsl/ir_hv_accept.cpp | 14 +++++++++
src/glsl/ir_print_visitor.cpp | 20 ++++++++++++
src/glsl/ir_print_visitor.h | 1 +
src/glsl/ir_reader.cpp | 38 +++++++++++++++++++++++
src/glsl/ir_rvalue_visitor.cpp | 18 +++++++++++
src/glsl/ir_rvalue_visitor.h | 3 ++
src/glsl/ir_visitor.h | 2 ++
src/mesa/drivers/dri/i965/brw_fs.h | 1 +
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 5 +++
src/mesa/drivers/dri/i965/brw_vec4.h | 1 +
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 5 +++
src/mesa/program/ir_to_mesa.cpp | 7 +++++
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 7 +++++
21 files changed, 210 insertions(+), 1 deletion(-)
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 1b17999..83bcda2 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1565,7 +1565,7 @@ ir_swizzle::variable_referenced() const
ir_variable::ir_variable(const struct glsl_type *type, const char *name,
ir_variable_mode mode)
: max_array_access(0), read_only(false), centroid(false), invariant(false),
- mode(mode), interpolation(INTERP_QUALIFIER_NONE)
+ mode(mode), interpolation(INTERP_QUALIFIER_NONE), atomic()
{
this->ir_type = ir_type_variable;
this->type = type;
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 2637b40..c4b4677 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -83,6 +83,7 @@ enum ir_node_type {
ir_type_texture,
ir_type_emit_vertex,
ir_type_end_primitive,
+ ir_type_atomic,
ir_type_max /**< maximum ir_type enum number, for validation */
};
@@ -547,6 +548,14 @@ public:
int binding;
/**
+ * Location an atomic counter is stored at.
+ */
+ struct {
+ int buffer_index;
+ int offset;
+ } atomic;
+
+ /**
* Built-in state that backs this uniform
*
* Once set at variable creation, \c state_slots must remain invariant.
@@ -2085,6 +2094,39 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
};
+enum ir_atomic_opcode {
+ ir_atomic_read,
+ ir_atomic_inc,
+ ir_atomic_dec
+};
+
+class ir_atomic : public ir_rvalue {
+public:
+ ir_atomic(enum ir_atomic_opcode op, ir_dereference *location = NULL)
+ : op(op), location(location)
+ {
+ this->type = glsl_type::get_instance(GLSL_TYPE_UINT, 1, 1);
+ this->ir_type = ir_type_atomic;
+ }
+
+ virtual ir_atomic *clone(void *mem_ctx, struct hash_table *) const;
+
+ virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ /** Kind of atomic instruction. */
+ enum ir_atomic_opcode op;
+
+ /** Variable this atomic instruction operates on. */
+ ir_dereference *location;
+};
+
/**
* Apply a visitor to each IR node in a list
*/
diff --git a/src/glsl/ir_builder.cpp b/src/glsl/ir_builder.cpp
index 98b4322..35f075a 100644
--- a/src/glsl/ir_builder.cpp
+++ b/src/glsl/ir_builder.cpp
@@ -535,4 +535,11 @@ if_tree(operand condition,
return result;
}
+ir_atomic *
+atomic(ir_atomic_opcode op, deref counter)
+{
+ void *mem_ctx = ralloc_parent(counter.val);
+ return new(mem_ctx) ir_atomic(op, counter.val);
+}
+
} /* namespace ir_builder */
diff --git a/src/glsl/ir_builder.h b/src/glsl/ir_builder.h
index 6a5f771..4a214fa 100644
--- a/src/glsl/ir_builder.h
+++ b/src/glsl/ir_builder.h
@@ -210,4 +210,6 @@ ir_if *if_tree(operand condition,
ir_instruction *then_branch,
ir_instruction *else_branch);
+ir_atomic *atomic(ir_atomic_opcode op, deref counter);
+
} /* namespace ir_builder */
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index b70b7db..9475809 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -51,6 +51,8 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
var->location = this->location;
var->index = this->index;
var->binding = this->binding;
+ var->atomic.buffer_index = this->atomic.buffer_index;
+ var->atomic.offset = this->atomic.offset;
var->warn_extension = this->warn_extension;
var->origin_upper_left = this->origin_upper_left;
var->pixel_center_integer = this->pixel_center_integer;
@@ -396,6 +398,15 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
return NULL;
}
+ir_atomic *
+ir_atomic::clone(void *mem_ctx, struct hash_table *ht) const
+{
+ ir_atomic *atom = new(mem_ctx) ir_atomic(op);
+
+ atom->location = location->clone(mem_ctx, ht);
+
+ return atom;
+}
class fixup_ir_call_visitor : public ir_hierarchical_visitor {
public:
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
index a67470b..faed0fe 100644
--- a/src/glsl/ir_constant_expression.cpp
+++ b/src/glsl/ir_constant_expression.cpp
@@ -1728,6 +1728,13 @@ ir_call::constant_expression_value(struct hash_table *variable_context)
}
+ir_constant *
+ir_atomic::constant_expression_value(struct hash_table *variable_context)
+{
+ return NULL;
+}
+
+
bool ir_function_signature::constant_expression_evaluate_expression_list(const struct exec_list &body,
struct hash_table *variable_context,
ir_constant **result)
diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp
index 2e606dd..49af569 100644
--- a/src/glsl/ir_hierarchical_visitor.cpp
+++ b/src/glsl/ir_hierarchical_visitor.cpp
@@ -303,6 +303,22 @@ ir_hierarchical_visitor::visit_leave(ir_if *ir)
return visit_continue;
}
+ir_visitor_status
+ir_hierarchical_visitor::visit_enter(ir_atomic *ir)
+{
+ if (this->callback != NULL)
+ this->callback(ir, this->data);
+
+ return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit_leave(ir_atomic *ir)
+{
+ (void) ir;
+ return visit_continue;
+}
+
void
ir_hierarchical_visitor::run(exec_list *instructions)
{
diff --git a/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h
index 647d2e0..ba515f8 100644
--- a/src/glsl/ir_hierarchical_visitor.h
+++ b/src/glsl/ir_hierarchical_visitor.h
@@ -137,6 +137,8 @@ public:
virtual ir_visitor_status visit_leave(class ir_discard *);
virtual ir_visitor_status visit_enter(class ir_if *);
virtual ir_visitor_status visit_leave(class ir_if *);
+ virtual ir_visitor_status visit_enter(class ir_atomic *);
+ virtual ir_visitor_status visit_leave(class ir_atomic *);
/*@}*/
diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp
index 76a607d..5c9c010 100644
--- a/src/glsl/ir_hv_accept.cpp
+++ b/src/glsl/ir_hv_accept.cpp
@@ -428,3 +428,17 @@ ir_end_primitive::accept(ir_hierarchical_visitor *v)
{
return v->visit(this);
}
+
+ir_visitor_status
+ir_atomic::accept(ir_hierarchical_visitor *v)
+{
+ ir_visitor_status s = v->visit_enter(this);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ s = location->accept(v);
+ if (s != visit_continue)
+ return (s == visit_continue_with_parent) ? visit_continue : s;
+
+ return (s == visit_stop) ? s : v->visit_leave(this);
+}
diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
index b518310..fc1dbab 100644
--- a/src/glsl/ir_print_visitor.cpp
+++ b/src/glsl/ir_print_visitor.cpp
@@ -561,3 +561,23 @@ ir_print_visitor::visit(ir_end_primitive *ir)
{
printf("(end-primitive)");
}
+
+void ir_print_visitor::visit(ir_atomic *ir)
+{
+ printf("(atomic ");
+
+ switch (ir->op) {
+ case ir_atomic_read:
+ printf("read ");
+ break;
+ case ir_atomic_inc:
+ printf("inc ");
+ break;
+ case ir_atomic_dec:
+ printf("dec ");
+ break;
+ }
+
+ ir->location->accept(this);
+ printf(")");
+}
diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h
index 865376f..e10c480 100644
--- a/src/glsl/ir_print_visitor.h
+++ b/src/glsl/ir_print_visitor.h
@@ -71,6 +71,7 @@ public:
virtual void visit(ir_loop_jump *);
virtual void visit(ir_emit_vertex *);
virtual void visit(ir_end_primitive *);
+ virtual void visit(ir_atomic *);
/*@}*/
private:
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
index ec35b68..91a2847 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -61,6 +61,7 @@ private:
ir_texture *read_texture(s_expression *);
ir_emit_vertex *read_emit_vertex(s_expression *);
ir_end_primitive *read_end_primitive(s_expression *);
+ ir_atomic *read_atomic(s_expression *);
ir_dereference *read_dereference(s_expression *);
ir_dereference_variable *read_var_ref(s_expression *);
@@ -548,6 +549,8 @@ ir_reader::read_rvalue(s_expression *expr)
rvalue = read_expression(list);
} else if (strcmp(tag->value(), "constant") == 0) {
rvalue = read_constant(list);
+ } else if (strcmp(tag->value(), "atomic") == 0) {
+ rvalue = read_atomic(list);
} else {
rvalue = read_texture(list);
if (rvalue == NULL && !state->error)
@@ -1105,3 +1108,38 @@ ir_reader::read_end_primitive(s_expression *expr)
ir_read_error(NULL, "when reading end-primitive");
return NULL;
}
+
+ir_atomic *
+ir_reader::read_atomic(s_expression *expr)
+{
+ s_symbol *s_tag = NULL;
+ s_expression *s_location = NULL;
+ ir_atomic_opcode op;
+
+ s_pattern pat[] =
+ { "atomic", s_tag, s_location };
+
+ if (!MATCH(expr, pat)) {
+ ir_read_error(NULL, "when reading atomic");
+ return NULL;
+ }
+
+ if (!strcmp("read", s_tag->value())) {
+ op = ir_atomic_read;
+ } else if (!strcmp("inc", s_tag->value())) {
+ op = ir_atomic_inc;
+ } else if (!strcmp("dec", s_tag->value())) {
+ op = ir_atomic_dec;
+ } else {
+ ir_read_error(NULL, "unexpected atomic op %s", s_tag->value());
+ return NULL;
+ }
+
+ ir_dereference *location = read_dereference(s_location);
+ if (!location) {
+ ir_read_error(NULL, "when reading location in (atomic ...)");
+ return NULL;
+ }
+
+ return new(mem_ctx) ir_atomic(op, location);
+}
diff --git a/src/glsl/ir_rvalue_visitor.cpp b/src/glsl/ir_rvalue_visitor.cpp
index 8eb1c62..f918959 100644
--- a/src/glsl/ir_rvalue_visitor.cpp
+++ b/src/glsl/ir_rvalue_visitor.cpp
@@ -145,6 +145,12 @@ ir_rvalue_base_visitor::rvalue_visit(ir_if *ir)
return visit_continue;
}
+ir_visitor_status
+ir_rvalue_base_visitor::rvalue_visit(ir_atomic *ir)
+{
+ return visit_continue;
+}
+
ir_visitor_status
ir_rvalue_visitor::visit_leave(ir_expression *ir)
@@ -201,6 +207,12 @@ ir_rvalue_visitor::visit_leave(ir_if *ir)
}
ir_visitor_status
+ir_rvalue_visitor::visit_leave(ir_atomic *ir)
+{
+ return rvalue_visit(ir);
+}
+
+ir_visitor_status
ir_rvalue_enter_visitor::visit_enter(ir_expression *ir)
{
return rvalue_visit(ir);
@@ -253,3 +265,9 @@ ir_rvalue_enter_visitor::visit_enter(ir_if *ir)
{
return rvalue_visit(ir);
}
+
+ir_visitor_status
+ir_rvalue_enter_visitor::visit_enter(ir_atomic *ir)
+{
+ return rvalue_visit(ir);
+}
diff --git a/src/glsl/ir_rvalue_visitor.h b/src/glsl/ir_rvalue_visitor.h
index 2179fa5..31b3d78 100644
--- a/src/glsl/ir_rvalue_visitor.h
+++ b/src/glsl/ir_rvalue_visitor.h
@@ -41,6 +41,7 @@ public:
ir_visitor_status rvalue_visit(ir_return *);
ir_visitor_status rvalue_visit(ir_swizzle *);
ir_visitor_status rvalue_visit(ir_texture *);
+ ir_visitor_status rvalue_visit(ir_atomic *);
virtual void handle_rvalue(ir_rvalue **rvalue) = 0;
};
@@ -57,6 +58,7 @@ public:
virtual ir_visitor_status visit_leave(ir_return *);
virtual ir_visitor_status visit_leave(ir_swizzle *);
virtual ir_visitor_status visit_leave(ir_texture *);
+ virtual ir_visitor_status visit_leave(ir_atomic *);
};
class ir_rvalue_enter_visitor : public ir_rvalue_base_visitor {
@@ -71,4 +73,5 @@ public:
virtual ir_visitor_status visit_enter(ir_return *);
virtual ir_visitor_status visit_enter(ir_swizzle *);
virtual ir_visitor_status visit_enter(ir_texture *);
+ virtual ir_visitor_status visit_enter(ir_atomic *);
};
diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h
index 40f96ff..5cb21a2 100644
--- a/src/glsl/ir_visitor.h
+++ b/src/glsl/ir_visitor.h
@@ -65,6 +65,7 @@ public:
virtual void visit(class ir_loop_jump *) = 0;
virtual void visit(class ir_emit_vertex *) = 0;
virtual void visit(class ir_end_primitive *) = 0;
+ virtual void visit(class ir_atomic *) = 0;
/*@}*/
};
@@ -85,6 +86,7 @@ public:
virtual void visit(class ir_call *) {}
virtual void visit(class ir_emit_vertex *) {}
virtual void visit(class ir_end_primitive *) {}
+ virtual void visit(class ir_atomic *) {}
};
#endif /* __cplusplus */
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 7cd9fd8..e78267e 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -225,6 +225,7 @@ public:
void visit(ir_function_signature *ir);
void visit(ir_emit_vertex *);
void visit(ir_end_primitive *);
+ void visit(ir_atomic *);
void swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler);
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 0345329..aaadb1d 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -2110,6 +2110,11 @@ fs_visitor::visit(ir_end_primitive *)
assert(!"not reached");
}
+void
+fs_visitor::visit(ir_atomic *ir)
+{
+}
+
fs_inst *
fs_visitor::emit(fs_inst inst)
{
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index c177d05..13c9166 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -328,6 +328,7 @@ public:
virtual void visit(ir_if *);
virtual void visit(ir_emit_vertex *);
virtual void visit(ir_end_primitive *);
+ virtual void visit(ir_atomic *);
/*@}*/
src_reg result;
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 9770f13..a13ce1b 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -2462,6 +2462,11 @@ vec4_visitor::visit(ir_end_primitive *)
}
void
+vec4_visitor::visit(ir_atomic *ir)
+{
+}
+
+void
vec4_visitor::emit_ndc_computation()
{
/* Get the position */
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 44f6d08..5c77267 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -262,6 +262,7 @@ public:
virtual void visit(ir_if *);
virtual void visit(ir_emit_vertex *);
virtual void visit(ir_end_primitive *);
+ virtual void visit(ir_atomic *);
/*@}*/
src_reg result;
@@ -2264,6 +2265,12 @@ ir_to_mesa_visitor::visit(ir_end_primitive *ir)
assert(!"Geometry shaders not supported.");
}
+void
+ir_to_mesa_visitor::visit(ir_atomic *ir)
+{
+ assert(!"Atomics not supported.");
+}
+
ir_to_mesa_visitor::ir_to_mesa_visitor()
{
result.file = PROGRAM_UNDEFINED;
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 67a8ed6..822e0d7 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -366,6 +366,7 @@ public:
virtual void visit(ir_if *);
virtual void visit(ir_emit_vertex *);
virtual void visit(ir_end_primitive *);
+ virtual void visit(ir_atomic *);
/*@}*/
st_src_reg result;
@@ -3019,6 +3020,12 @@ glsl_to_tgsi_visitor::visit(ir_end_primitive *ir)
assert(!"Geometry shaders not supported.");
}
+void
+glsl_to_tgsi_visitor::visit(ir_atomic *ir)
+{
+ assert(!"Atomics not supported.");
+}
+
glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
{
result.file = PROGRAM_UNDEFINED;
--
1.8.3.4
More information about the mesa-dev
mailing list