Mesa (master): i915: fix broken indirect constant buffer reads

Brian Paul brianp at kemper.freedesktop.org
Fri Apr 17 22:13:53 UTC 2009


Module: Mesa
Branch: master
Commit: 0bc214a834bbb12b9338837dd9fca9bc389b4bc2
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=0bc214a834bbb12b9338837dd9fca9bc389b4bc2

Author: Brian Paul <brianp at vmware.com>
Date:   Fri Apr 17 16:01:20 2009 -0600

i915: fix broken indirect constant buffer reads

The READ message's msg_control value can be 0 or 1 to indicate that the
Oword should be read into the lower or upper half of the target register.
It seems that the other half of the register gets clobbered though.  So
we read into two dest registers then use a MOV to combine the upper/lower
halves.

---

 src/mesa/drivers/dri/i965/brw_eu.h      |    1 +
 src/mesa/drivers/dri/i965/brw_eu_emit.c |   47 ++-----------------------------
 src/mesa/drivers/dri/i965/brw_vs_emit.c |   43 +++++++++++++++++++++++----
 3 files changed, 40 insertions(+), 51 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h
index 896e67d..62c98bd 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.h
+++ b/src/mesa/drivers/dri/i965/brw_eu.h
@@ -867,6 +867,7 @@ void brw_dp_READ_4( struct brw_compile *p,
 
 void brw_dp_READ_4_vs( struct brw_compile *p,
                        struct brw_reg dest,
+                       GLuint oword,
                        GLboolean relAddr,
                        struct brw_reg addrReg,
                        GLuint location,
diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c
index df21416..60ea44f 100644
--- a/src/mesa/drivers/dri/i965/brw_eu_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c
@@ -1009,6 +1009,7 @@ void brw_dp_READ_4( struct brw_compile *p,
  */
 void brw_dp_READ_4_vs(struct brw_compile *p,
                       struct brw_reg dest,
+                      GLuint oword,
                       GLboolean relAddr,
                       struct brw_reg addrReg,
                       GLuint location,
@@ -1016,6 +1017,7 @@ void brw_dp_READ_4_vs(struct brw_compile *p,
 {
    GLuint msg_reg_nr = 1;
 
+   assert(oword < 2);
    /*
    printf("vs const read msg, location %u, msg_reg_nr %d\n",
           location, msg_reg_nr);
@@ -1061,56 +1063,13 @@ void brw_dp_READ_4_vs(struct brw_compile *p,
 
       brw_set_dp_read_message(insn,
 			      bind_table_index,
-			      0,  /* msg_control (0 means 1 Oword, lower half) */
+			      oword,  /* 0 = lower Oword, 1 = upper Oword */
 			      BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */
 			      0, /* source cache = data cache */
 			      1, /* msg_length */
 			      1, /* response_length (1 Oword) */
 			      0); /* eot */
    }
-
-   if (relAddr) {
-      /* second read to get second constant */
-      msg_reg_nr++;
-      {
-         /* Setup MRF[1] with location/offset into const buffer */
-         struct brw_reg b;
-
-         brw_push_insn_state(p);
-         brw_set_compression_control(p, BRW_COMPRESSION_NONE);
-         brw_set_mask_control(p, BRW_MASK_DISABLE);
-         brw_set_predicate_control(p, BRW_PREDICATE_NONE);
-
-         b = brw_message_reg(msg_reg_nr);
-         b = retype(b, BRW_REGISTER_TYPE_UD);
-         addrReg = suboffset(addrReg, 1); /* upper half of addrReg */
-         brw_ADD(p, b, addrReg, brw_imm_ud(location));
-
-         brw_pop_insn_state(p);
-      }
-
-      {
-         struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND);
-
-         insn->header.predicate_control = BRW_PREDICATE_NONE;
-         insn->header.compression_control = BRW_COMPRESSION_NONE; 
-         insn->header.destreg__conditonalmod = msg_reg_nr;
-         insn->header.mask_control = BRW_MASK_DISABLE;
-         /*insn->header.access_mode = BRW_ALIGN_16;*/
-
-         brw_set_dest(insn, dest);
-         brw_set_src0(insn, brw_null_reg());
-
-         brw_set_dp_read_message(insn,
-                                 bind_table_index,
-                                 1,  /* msg_control (1 means 1 Oword, upper half) */
-                                 BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */
-                                 0, /* source cache = data cache */
-                                 1, /* msg_length */
-                                 1, /* response_length (1 Oword) */
-                                 0); /* eot */
-      }
-   }
 }
 
 
diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c
index 0c86c23..524f121 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c
@@ -708,10 +708,12 @@ get_constant(struct brw_vs_compile *c,
    const struct prog_src_register *src = &inst->SrcReg[argIndex];
    struct brw_compile *p = &c->func;
    struct brw_reg const_reg;
+   struct brw_reg const2_reg;
 
    assert(argIndex < 3);
 
    if (c->current_const[argIndex].index != src->Index || src->RelAddr) {
+      struct brw_reg addrReg = c->regs[PROGRAM_ADDRESS][0];
 
       c->current_const[argIndex].index = src->Index;
 
@@ -719,19 +721,46 @@ get_constant(struct brw_vs_compile *c,
       printf("  fetch const[%d] for arg %d into reg %d\n",
              src->Index, argIndex, c->current_const[argIndex].reg.nr);
 #endif
-
       /* need to fetch the constant now */
       brw_dp_READ_4_vs(p,
-                       c->current_const[argIndex].reg, /* writeback dest */
-                       src->RelAddr,                   /* relative indexing? */
-                       c->regs[PROGRAM_ADDRESS][0],    /* address register */
-                       16 * src->Index,                /* byte offset */
-                       SURF_INDEX_VERT_CONST_BUFFER    /* binding table index */
+                       c->current_const[argIndex].reg,/* writeback dest */
+                       0,                             /* oword */
+                       src->RelAddr,                  /* relative indexing? */
+                       addrReg,                       /* address register */
+                       16 * src->Index,               /* byte offset */
+                       SURF_INDEX_VERT_CONST_BUFFER   /* binding table index */
                        );
+
+      if (src->RelAddr) {
+         /* second read */
+         const2_reg = get_tmp(c);
+
+         /* use upper half of address reg for second read */
+         addrReg = stride(addrReg, 0, 4, 0);
+         addrReg.subnr = 16;
+
+         brw_dp_READ_4_vs(p,
+                          const2_reg,              /* writeback dest */
+                          1,                       /* oword */
+                          src->RelAddr,            /* relative indexing? */
+                          addrReg,                 /* address register */
+                          16 * src->Index,         /* byte offset */
+                          SURF_INDEX_VERT_CONST_BUFFER
+                          );
+      }
    }
 
    const_reg = c->current_const[argIndex].reg;
-   if (!src->RelAddr) {
+
+   if (src->RelAddr) {
+      /* merge the two Owords into the constant register */
+      /* const_reg[7..4] = const2_reg[7..4] */
+      brw_MOV(p,
+              suboffset(stride(const_reg, 0, 4, 1), 4),
+              suboffset(stride(const2_reg, 0, 4, 1), 4));
+      release_tmp(c, const2_reg);
+   }
+   else {
       /* replicate lower four floats into upper half (to get XYZWXYZW) */
       const_reg = stride(const_reg, 0, 4, 0);
       const_reg.subnr = 0;




More information about the mesa-commit mailing list