[Mesa-dev] [PATCH 09/25] i965/gen7: Fix the untyped surface messages to deal with indirect surface access.

Francisco Jerez currojerez at riseup.net
Mon Dec 2 11:39:17 PST 2013


Change brw_untyped_atomic() and brw_untyped_surface_read() to take the
surface index as a register instead of a constant, construct the
message descriptor dynamically by OR'ing the surface index and other
descriptor bits together and use the non-immediate variant of SEND to
submit the surface message.
---
 src/mesa/drivers/dri/i965/brw_eu.h               |  18 +-
 src/mesa/drivers/dri/i965/brw_eu_emit.c          | 200 +++++++++++++++--------
 src/mesa/drivers/dri/i965/brw_fs_generator.cpp   |   7 +-
 src/mesa/drivers/dri/i965/brw_vec4_generator.cpp |   7 +-
 4 files changed, 147 insertions(+), 85 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h
index a6a65ca..45b421b 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.h
+++ b/src/mesa/drivers/dri/i965/brw_eu.h
@@ -360,20 +360,20 @@ void brw_CMP(struct brw_compile *p,
 
 void
 brw_untyped_atomic(struct brw_compile *p,
-                   struct brw_reg dest,
+                   struct brw_reg dst,
                    struct brw_reg mrf,
-                   GLuint atomic_op,
-                   GLuint bind_table_index,
-                   GLuint msg_length,
-                   GLuint response_length);
+                   struct brw_reg surface,
+                   unsigned atomic_op,
+                   unsigned msg_length,
+                   bool response_expected);
 
 void
 brw_untyped_surface_read(struct brw_compile *p,
-                         struct brw_reg dest,
+                         struct brw_reg dst,
                          struct brw_reg mrf,
-                         GLuint bind_table_index,
-                         GLuint msg_length,
-                         GLuint response_length);
+                         struct brw_reg surface,
+                         unsigned msg_length,
+                         unsigned num_channels);
 
 /*********************************************************************** 
  * brw_eu_util.c:
diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c
index cc093e0..b94a6d1 100644
--- a/src/mesa/drivers/dri/i965/brw_eu_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c
@@ -2527,23 +2527,87 @@ brw_svb_write(struct brw_compile *p,
                             send_commit_msg); /* send_commit_msg */
 }
 
+static struct brw_instruction *
+brw_load_indirect_message_descriptor(struct brw_compile *p,
+                                     struct brw_reg dst,
+                                     struct brw_reg src,
+                                     unsigned msg_length,
+                                     unsigned response_length,
+                                     bool header_present)
+{
+   struct brw_instruction *insn;
+
+   brw_push_insn_state(p);
+   brw_set_access_mode(p, BRW_ALIGN_1);
+   brw_set_mask_control(p, BRW_MASK_DISABLE);
+   brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+
+   if (src.file == BRW_IMMEDIATE_VALUE) {
+      insn = brw_MOV(p, dst, brw_imm_ud(src.dw1.ud));
+   } else {
+      struct brw_reg tmp = suboffset(vec1(retype(src, BRW_REGISTER_TYPE_UD)),
+                                     BRW_GET_SWZ(src.dw1.bits.swizzle, 0));
+      insn = brw_OR(p, dst, tmp, brw_imm_ud(0));
+   }
+
+   insn->bits3.generic_gen5.msg_length = msg_length;
+   insn->bits3.generic_gen5.response_length = response_length;
+   insn->bits3.generic_gen5.header_present = header_present;
+
+   brw_pop_insn_state(p);
+
+   return insn;
+}
+
+static struct brw_instruction *
+brw_send_indirect_message(struct brw_compile *p,
+                          unsigned sfid,
+                          struct brw_reg dst,
+                          struct brw_reg mrf,
+                          struct brw_reg desc)
+{
+   /* Due to a hardware limitation the message descriptor desc MUST be
+    * stored in a0.0.  That means that there's only room for one
+    * descriptor and the surface indices of different channels in the
+    * same SIMD thread cannot diverge.  That's OK for the moment
+    * because OpenGL requires image (and atomic counter) array
+    * indexing to be dynamically uniform.
+    */
+   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+
+   brw_set_dest(p, insn, retype(dst, BRW_REGISTER_TYPE_UD));
+   brw_set_src0(p, insn, retype(mrf, BRW_REGISTER_TYPE_UD));
+   brw_set_src1(p, insn, retype(desc, BRW_REGISTER_TYPE_UD));
+
+   /* On Gen6+ Message target/SFID goes in bits 27:24 of the header */
+   insn->header.destreg__conditionalmod = sfid;
+
+   return insn;
+}
+
+static unsigned
+brw_surface_payload_size(struct brw_compile *p,
+                         unsigned num_channels,
+                         bool has_simd4x2,
+                         bool has_simd16)
+{
+   if (has_simd4x2 && p->current->header.access_mode == BRW_ALIGN_16)
+      return 1;
+   else if (has_simd16 && p->compressed)
+      return 2 * num_channels;
+   else
+      return num_channels;
+}
+
 static void
 brw_set_dp_untyped_atomic_message(struct brw_compile *p,
                                   struct brw_instruction *insn,
-                                  GLuint atomic_op,
-                                  GLuint bind_table_index,
-                                  GLuint msg_length,
-                                  GLuint response_length,
-                                  bool header_present)
+                                  unsigned atomic_op,
+                                  bool response_expected)
 {
    if (p->brw->is_haswell) {
-      brw_set_message_descriptor(p, insn, HSW_SFID_DATAPORT_DATA_CACHE_1,
-                                 msg_length, response_length,
-                                 header_present, false);
-
-
-      if (insn->header.access_mode == BRW_ALIGN_1) {
-         if (insn->header.execution_size != BRW_EXECUTE_16)
+      if (p->current->header.access_mode == BRW_ALIGN_1) {
+         if (!p->compressed)
             insn->bits3.ud |= 1 << 12; /* SIMD8 mode */
 
          insn->bits3.gen7_dp.msg_type =
@@ -2554,95 +2618,90 @@ brw_set_dp_untyped_atomic_message(struct brw_compile *p,
       }
 
    } else {
-      brw_set_message_descriptor(p, insn, GEN7_SFID_DATAPORT_DATA_CACHE,
-                                 msg_length, response_length,
-                                 header_present, false);
-
       insn->bits3.gen7_dp.msg_type = GEN7_DATAPORT_DC_UNTYPED_ATOMIC_OP;
 
-      if (insn->header.execution_size != BRW_EXECUTE_16)
+      if (!p->compressed)
          insn->bits3.ud |= 1 << 12; /* SIMD8 mode */
    }
 
-   if (response_length)
+   if (response_expected)
       insn->bits3.ud |= 1 << 13; /* Return data expected */
 
-   insn->bits3.gen7_dp.binding_table_index = bind_table_index;
    insn->bits3.ud |= atomic_op << 8;
 }
 
 void
 brw_untyped_atomic(struct brw_compile *p,
-                   struct brw_reg dest,
+                   struct brw_reg dst,
                    struct brw_reg mrf,
-                   GLuint atomic_op,
-                   GLuint bind_table_index,
-                   GLuint msg_length,
-                   GLuint response_length) {
-   struct brw_instruction *insn = brw_next_insn(p, BRW_OPCODE_SEND);
+                   struct brw_reg surface,
+                   unsigned atomic_op,
+                   unsigned msg_length,
+                   bool response_expected)
+{
+   const unsigned sfid = (p->brw->is_haswell ?
+                          HSW_SFID_DATAPORT_DATA_CACHE_1 :
+                          GEN7_SFID_DATAPORT_DATA_CACHE);
+   const bool header_present = p->current->header.access_mode == BRW_ALIGN_1;
+   struct brw_reg desc = retype(brw_address_reg(0), BRW_REGISTER_TYPE_UD);
+   struct brw_instruction *insn;
+
+   insn = brw_load_indirect_message_descriptor(
+      p, desc, surface, msg_length,
+      brw_surface_payload_size(p, response_expected, p->brw->is_haswell, true),
+      header_present);
 
-   brw_set_dest(p, insn, retype(dest, BRW_REGISTER_TYPE_UD));
-   brw_set_src0(p, insn, retype(mrf, BRW_REGISTER_TYPE_UD));
-   brw_set_src1(p, insn, brw_imm_d(0));
    brw_set_dp_untyped_atomic_message(
-      p, insn, atomic_op, bind_table_index, msg_length, response_length,
-      insn->header.access_mode == BRW_ALIGN_1);
+      p, insn, atomic_op, response_expected);
+
+   brw_send_indirect_message(p, sfid, dst, mrf, desc);
 }
 
 static void
 brw_set_dp_untyped_surface_read_message(struct brw_compile *p,
                                         struct brw_instruction *insn,
-                                        GLuint bind_table_index,
-                                        GLuint msg_length,
-                                        GLuint response_length,
-                                        bool header_present)
+                                        unsigned num_channels)
 {
-   const unsigned dispatch_width =
-      (insn->header.execution_size == BRW_EXECUTE_16 ? 16 : 8);
-   const unsigned num_channels = response_length / (dispatch_width / 8);
-
-   if (p->brw->is_haswell) {
-      brw_set_message_descriptor(p, insn, HSW_SFID_DATAPORT_DATA_CACHE_1,
-                                 msg_length, response_length,
-                                 header_present, false);
-
-      insn->bits3.gen7_dp.msg_type = HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ;
-   } else {
-      brw_set_message_descriptor(p, insn, GEN7_SFID_DATAPORT_DATA_CACHE,
-                                 msg_length, response_length,
-                                 header_present, false);
-
-      insn->bits3.gen7_dp.msg_type = GEN7_DATAPORT_DC_UNTYPED_SURFACE_READ;
-   }
+   insn->bits3.gen7_dp.msg_type = (p->brw->is_haswell ?
+                                   HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ :
+                                   GEN7_DATAPORT_DC_UNTYPED_SURFACE_READ);
 
-   if (insn->header.access_mode == BRW_ALIGN_1) {
-      if (dispatch_width == 16)
+   if (p->current->header.access_mode == BRW_ALIGN_1) {
+      if (p->compressed)
          insn->bits3.ud |= 1 << 12; /* SIMD16 mode */
       else
          insn->bits3.ud |= 2 << 12; /* SIMD8 mode */
+   } else {
+      insn->bits3.ud |= 0 << 12; /* SIMD4x2 mode */
    }
 
-   insn->bits3.gen7_dp.binding_table_index = bind_table_index;
-
    /* Set mask of 32-bit channels to drop. */
    insn->bits3.ud |= (0xf & (0xf << num_channels)) << 8;
 }
 
 void
 brw_untyped_surface_read(struct brw_compile *p,
-                         struct brw_reg dest,
+                         struct brw_reg dst,
                          struct brw_reg mrf,
-                         GLuint bind_table_index,
-                         GLuint msg_length,
-                         GLuint response_length)
+                         struct brw_reg surface,
+                         unsigned msg_length,
+                         unsigned num_channels)
 {
-   struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
+   const unsigned sfid = (p->brw->is_haswell ? HSW_SFID_DATAPORT_DATA_CACHE_1 :
+                          GEN7_SFID_DATAPORT_DATA_CACHE);
+   const bool header_present = p->current->header.access_mode == BRW_ALIGN_1;
+   struct brw_reg desc = retype(brw_address_reg(0), BRW_REGISTER_TYPE_UD);
+   struct brw_instruction *insn;
+
+   insn = brw_load_indirect_message_descriptor(
+      p, desc, surface, msg_length,
+      brw_surface_payload_size(p, num_channels, true, true),
+      header_present);
 
-   brw_set_dest(p, insn, retype(dest, BRW_REGISTER_TYPE_UD));
-   brw_set_src0(p, insn, retype(mrf, BRW_REGISTER_TYPE_UD));
    brw_set_dp_untyped_surface_read_message(
-      p, insn, bind_table_index, msg_length, response_length,
-      insn->header.access_mode == BRW_ALIGN_1);
+      p, insn, num_channels);
+
+   brw_send_indirect_message(p, sfid, dst, mrf, desc);
 }
 
 /**
@@ -2681,8 +2740,13 @@ void brw_shader_time_add(struct brw_compile *p,
                                       BRW_ARF_NULL, 0));
    brw_set_src0(p, send, brw_vec1_reg(payload.file,
                                       payload.nr, 0));
-   brw_set_dp_untyped_atomic_message(p, send, BRW_AOP_ADD, surf_index,
-                                     2 /* message length */,
-                                     0 /* response length */,
-                                     false /* header present */);
+   brw_set_src1(p, send, brw_imm_ud(0));
+   brw_set_dp_untyped_atomic_message(p, send, BRW_AOP_ADD, false);
+
+   /* On Gen6+ Message target/SFID goes in bits 27:24 of the header */
+   send->header.destreg__conditionalmod =
+      (p->brw->is_haswell ? HSW_SFID_DATAPORT_DATA_CACHE_1 :
+       GEN7_SFID_DATAPORT_DATA_CACHE);
+   send->bits3.generic_gen5.msg_length = 2;
+   send->bits3.ud |= surf_index;
 }
diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
index 9c2c318..4eb651f 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
@@ -1265,8 +1265,8 @@ fs_generator::generate_untyped_atomic(fs_inst *inst, struct brw_reg dst,
 	  surf_index.type == BRW_REGISTER_TYPE_UD);
 
    brw_untyped_atomic(p, dst, brw_message_reg(inst->base_mrf),
-                      atomic_op.dw1.ud, surf_index.dw1.ud,
-                      inst->mlen, dispatch_width / 8);
+                      surf_index, atomic_op.dw1.ud,
+                      inst->mlen, true);
 
    brw_mark_surface_used(&c->prog_data.base, surf_index.dw1.ud);
 }
@@ -1279,8 +1279,7 @@ fs_generator::generate_untyped_surface_read(fs_inst *inst, struct brw_reg dst,
 	  surf_index.type == BRW_REGISTER_TYPE_UD);
 
    brw_untyped_surface_read(p, dst, brw_message_reg(inst->base_mrf),
-                            surf_index.dw1.ud,
-                            inst->mlen, dispatch_width / 8);
+                            surf_index, inst->mlen, 1);
 
    brw_mark_surface_used(&c->prog_data.base, surf_index.dw1.ud);
 }
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp
index 83a2a27..3ac45a9 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_generator.cpp
@@ -859,8 +859,8 @@ vec4_generator::generate_untyped_atomic(vec4_instruction *inst,
 	  surf_index.type == BRW_REGISTER_TYPE_UD);
 
    brw_untyped_atomic(p, dst, brw_message_reg(inst->base_mrf),
-                      atomic_op.dw1.ud, surf_index.dw1.ud,
-                      inst->mlen, 1);
+                      surf_index, atomic_op.dw1.ud,
+                      inst->mlen, true);
 
    brw_mark_surface_used(&prog_data->base, surf_index.dw1.ud);
 }
@@ -874,8 +874,7 @@ vec4_generator::generate_untyped_surface_read(vec4_instruction *inst,
 	  surf_index.type == BRW_REGISTER_TYPE_UD);
 
    brw_untyped_surface_read(p, dst, brw_message_reg(inst->base_mrf),
-                            surf_index.dw1.ud,
-                            inst->mlen, 1);
+                            surf_index, inst->mlen, 1);
 
    brw_mark_surface_used(&prog_data->base, surf_index.dw1.ud);
 }
-- 
1.8.3.4



More information about the mesa-dev mailing list