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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev