[Mesa-dev] [PATCH 21/24] i965/gen7: Handle atomic instructions from the FS back-end.

Francisco Jerez currojerez at riseup.net
Sun Sep 15 00:19:45 PDT 2013


This can deal with all the 15 32-bit untyped atomic operations the
hardware supports, but only INC and PREDEC are going to be exposed
through the API for now.
---
 src/mesa/drivers/dri/i965/brw_fs.h           |  7 +++
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 83 ++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index dcd489c..44930f7 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -392,6 +392,13 @@ public:
    void emit_shader_time_write(enum shader_time_shader_type type,
                                fs_reg value);
 
+   void emit_untyped_atomic(unsigned atomic_op, unsigned surf_index,
+                            unsigned offset, fs_reg dst, fs_reg src0,
+                            fs_reg src1);
+
+   void emit_untyped_surface_read(unsigned surf_index, unsigned offset,
+                                  fs_reg dst);
+
    bool try_rewrite_rhs_to_dst(ir_assignment *ir,
 			       fs_reg dst,
 			       fs_reg src,
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 762832a..412d27a 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -2112,8 +2112,91 @@ fs_visitor::visit(ir_end_primitive *)
 }
 
 void
+fs_visitor::emit_untyped_atomic(unsigned atomic_op, unsigned surf_index,
+                                unsigned offset, fs_reg dst, fs_reg src0,
+                                fs_reg src1)
+{
+   const unsigned operand_len = dispatch_width / 8;
+   unsigned mlen = 0;
+
+   /* Initialize the sample mask in the message header. */
+   emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0)))
+      ->force_writemask_all = true;
+   emit(MOV(brw_uvec_mrf(1, mlen, 7),
+            retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UD)))
+      ->force_writemask_all = true;
+   mlen++;
+
+   /* Set the atomic operation offset. */
+   emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), brw_imm_ud(offset)));
+   mlen += operand_len;
+
+   /* Set the atomic operation arguments. */
+   if (src0.file != BAD_FILE) {
+      emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), src0));
+      mlen += operand_len;
+   }
+
+   if (src1.file != BAD_FILE) {
+      emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), src1));
+      mlen += operand_len;
+   }
+
+   /* Emit the instruction. */
+   fs_inst inst(SHADER_OPCODE_UNTYPED_ATOMIC, dst,
+                fs_reg(atomic_op), fs_reg(surf_index));
+   inst.base_mrf = 0;
+   inst.mlen = mlen;
+   emit(inst);
+}
+
+void
+fs_visitor::emit_untyped_surface_read(unsigned surf_index, unsigned offset,
+                                      fs_reg dst)
+{
+   const unsigned operand_len = dispatch_width / 8;
+   unsigned mlen = 0;
+
+   /* Initialize the sample mask in the message header. */
+   emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0)))
+      ->force_writemask_all = true;
+   emit(MOV(brw_uvec_mrf(1, mlen, 7),
+            retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UD)))
+      ->force_writemask_all = true;
+   mlen++;
+
+   /* Set the surface read offset. */
+   emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), brw_imm_ud(offset)));
+   mlen += operand_len;
+
+   /* Emit the instruction. */
+   fs_inst inst(SHADER_OPCODE_UNTYPED_SURFACE_READ, dst, fs_reg(surf_index));
+   inst.base_mrf = 0;
+   inst.mlen = mlen;
+   emit(inst);
+}
+
+void
 fs_visitor::visit(ir_atomic *ir)
 {
+   ir_variable *loc = ir->location->variable_referenced();
+   unsigned surf_index = SURF_INDEX_WM_ABO(loc->atomic.buffer_index);
+
+   result = fs_reg(this, ir->type);
+
+   switch (ir->op) {
+   case ir_atomic_read:
+      emit_untyped_surface_read(surf_index, loc->atomic.offset, result);
+      break;
+   case ir_atomic_inc:
+      emit_untyped_atomic(BRW_AOP_INC, surf_index, loc->atomic.offset,
+                          result, fs_reg(), fs_reg());
+      break;
+   case ir_atomic_dec:
+      emit_untyped_atomic(BRW_AOP_PREDEC, surf_index, loc->atomic.offset,
+                          result, fs_reg(), fs_reg());
+      break;
+   }
 }
 
 fs_inst *
-- 
1.8.3.4



More information about the mesa-dev mailing list