<div dir="ltr">On 29 October 2013 16:37, 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">This can deal with all the 15 32-bit untyped atomic operations the<br>
hardware supports, but only INC and PREDEC are going to be exposed<br>
through the API for now.<br>
<br>
v2: Represent atomics as GLSL intrinsics.  Add support for variably<br>
    indexed atomic counter arrays.  Fix interaction with fragment<br>
    discard.<br>
---<br>
 src/mesa/drivers/dri/i965/brw_fs.h           |   9 ++<br>
</div> src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 131 ++++++++++++++++++++++++++-<br>
 2 files changed, 138 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h<br>
index 5b78313..081f8a3 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs.h<br>
@@ -391,6 +391,13 @@ public:<br>
<div class="im">    void emit_shader_time_write(enum shader_time_shader_type type,<br>
                                fs_reg value);<br>
<br>
+   void emit_untyped_atomic(unsigned atomic_op, unsigned surf_index,<br>
+                            fs_reg dst, fs_reg offset, fs_reg src0,<br>
+                            fs_reg src1);<br>
+<br>
+   void emit_untyped_surface_read(unsigned surf_index, fs_reg dst,<br>
+                                  fs_reg offset);<br>
+<br>
    bool try_rewrite_rhs_to_dst(ir_assignment *ir,<br>
                               fs_reg dst,<br>
                               fs_reg src,<br>
</div>@@ -410,6 +417,8 @@ public:<br>
<div class="im"><br>
    void dump_instruction(backend_instruction *inst);<br>
<br>
+   void visit_atomic_counter_intrinsic(ir_call *ir);<br>
+<br>
    struct gl_fragment_program *fp;<br>
    struct brw_wm_compile *c;<br>
    unsigned int sanity_param_count;<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
</div>index 71b4bf9..b6361d5 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
@@ -106,7 +106,7 @@ fs_visitor::visit(ir_variable *ir)<br>
        * ir_binop_ubo_load expressions and not ir_dereference_variable for UBO<br>
        * variables, so no need for them to be in variable_ht.<br>
        */<br>
-      if (ir->is_in_uniform_block())<br>
+      if (ir->is_in_uniform_block() || ir->type->contains_atomic())<br></blockquote><div><br></div><div>The comment above this "if" statement should be updated to explain why it's ok to return when we encounter a type that contains an atomic.<br>
<br></div><div>With that change, the patch is:<br><br>Reviewed-by: Paul Berry <<a href="mailto:stereotype441@gmail.com">stereotype441@gmail.com</a>><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

          return;<br>
<br>
       if (dispatch_width == 16) {<br>
@@ -2187,9 +2187,58 @@ fs_visitor::visit(ir_loop_jump *ir)<br>
<div class="im"> }<br>
<br>
 void<br>
+fs_visitor::visit_atomic_counter_intrinsic(ir_call *ir)<br>
+{<br>
+   ir_dereference *deref = static_cast<ir_dereference *>(<br>
+      ir->actual_parameters.get_head());<br>
+   ir_variable *location = deref->variable_referenced();<br>
</div>+   unsigned surf_index = (c->prog_data.base.binding_table.abo_start +<br>
+                          location->atomic.buffer_index);<br>
<div><div class="h5">+<br>
+   /* Calculate the surface offset */<br>
+   fs_reg offset(this, glsl_type::uint_type);<br>
+   ir_dereference_array *deref_array = deref->as_dereference_array();<br>
+<br>
+   if (deref_array) {<br>
+      deref_array->array_index->accept(this);<br>
+<br>
+      fs_reg tmp(this, glsl_type::uint_type);<br>
+      emit(MUL(tmp, this->result, ATOMIC_COUNTER_SIZE));<br>
+      emit(ADD(offset, tmp, location->atomic.offset));<br>
+   } else {<br>
+      offset = location->atomic.offset;<br>
+   }<br>
+<br>
+   /* Emit the appropriate machine instruction */<br>
+   const char *callee = ir->callee->function_name();<br>
+   ir->return_deref->accept(this);<br>
+   fs_reg dst = this->result;<br>
+<br>
+   if (!strcmp("__intrinsic_atomic_read", callee)) {<br>
+      emit_untyped_surface_read(surf_index, dst, offset);<br>
+<br>
+   } else if (!strcmp("__intrinsic_atomic_increment", callee)) {<br>
+      emit_untyped_atomic(BRW_AOP_INC, surf_index, dst, offset,<br>
+                          fs_reg(), fs_reg());<br>
+<br>
+   } else if (!strcmp("__intrinsic_atomic_predecrement", callee)) {<br>
+      emit_untyped_atomic(BRW_AOP_PREDEC, surf_index, dst, offset,<br>
+                          fs_reg(), fs_reg());<br>
+   }<br>
+}<br>
+<br>
+void<br>
 fs_visitor::visit(ir_call *ir)<br>
 {<br>
-   assert(!"FINISHME");<br>
+   const char *callee = ir->callee->function_name();<br>
+<br>
+   if (!strcmp("__intrinsic_atomic_read", callee) ||<br>
+       !strcmp("__intrinsic_atomic_increment", callee) ||<br>
+       !strcmp("__intrinsic_atomic_predecrement", callee)) {<br>
+      visit_atomic_counter_intrinsic(ir);<br>
+   } else {<br>
+      assert(!"Unsupported intrinsic.");<br>
+   }<br>
 }<br>
<br>
 void<br>
</div></div>@@ -2240,6 +2289,84 @@ fs_visitor::visit(ir_end_primitive *)<br>
<div class="HOEnZb"><div class="h5">    assert(!"not reached");<br>
 }<br>
<br>
+void<br>
+fs_visitor::emit_untyped_atomic(unsigned atomic_op, unsigned surf_index,<br>
+                                fs_reg dst, fs_reg offset, fs_reg src0,<br>
+                                fs_reg src1)<br>
+{<br>
+   const unsigned operand_len = dispatch_width / 8;<br>
+   unsigned mlen = 0;<br>
+<br>
+   /* Initialize the sample mask in the message header. */<br>
+   emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0)))<br>
+      ->force_writemask_all = true;<br>
+<br>
+   if (fp->UsesKill) {<br>
+      emit(MOV(brw_uvec_mrf(1, mlen, 7), brw_flag_reg(0, 1)))<br>
+         ->force_writemask_all = true;<br>
+   } else {<br>
+      emit(MOV(brw_uvec_mrf(1, mlen, 7),<br>
+               retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UD)))<br>
+         ->force_writemask_all = true;<br>
+   }<br>
+<br>
+   mlen++;<br>
+<br>
+   /* Set the atomic operation offset. */<br>
+   emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), offset));<br>
+   mlen += operand_len;<br>
+<br>
+   /* Set the atomic operation arguments. */<br>
+   if (src0.file != BAD_FILE) {<br>
+      emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), src0));<br>
+      mlen += operand_len;<br>
+   }<br>
+<br>
+   if (src1.file != BAD_FILE) {<br>
+      emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), src1));<br>
+      mlen += operand_len;<br>
+   }<br>
+<br>
+   /* Emit the instruction. */<br>
+   fs_inst inst(SHADER_OPCODE_UNTYPED_ATOMIC, dst, atomic_op, surf_index);<br>
+   inst.base_mrf = 0;<br>
+   inst.mlen = mlen;<br>
+   emit(inst);<br>
+}<br>
+<br>
+void<br>
+fs_visitor::emit_untyped_surface_read(unsigned surf_index, fs_reg dst,<br>
+                                      fs_reg offset)<br>
+{<br>
+   const unsigned operand_len = dispatch_width / 8;<br>
+   unsigned mlen = 0;<br>
+<br>
+   /* Initialize the sample mask in the message header. */<br>
+   emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0)))<br>
+      ->force_writemask_all = true;<br>
+<br>
+   if (fp->UsesKill) {<br>
+      emit(MOV(brw_uvec_mrf(1, mlen, 7), brw_flag_reg(0, 1)))<br>
+         ->force_writemask_all = true;<br>
+   } else {<br>
+      emit(MOV(brw_uvec_mrf(1, mlen, 7),<br>
+               retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UD)))<br>
+         ->force_writemask_all = true;<br>
+   }<br>
+<br>
+   mlen++;<br>
+<br>
+   /* Set the surface read offset. */<br>
+   emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), offset));<br>
+   mlen += operand_len;<br>
+<br>
+   /* Emit the instruction. */<br>
+   fs_inst inst(SHADER_OPCODE_UNTYPED_SURFACE_READ, dst, surf_index);<br>
+   inst.base_mrf = 0;<br>
+   inst.mlen = mlen;<br>
+   emit(inst);<br>
+}<br>
+<br>
 fs_inst *<br>
 fs_visitor::emit(fs_inst inst)<br>
 {<br>
--<br>
1.8.3.4<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">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>
</div></div></blockquote></div><br></div></div>