Mesa (master): i965: Enable loops in the VS.

Eric Anholt anholt at kemper.freedesktop.org
Fri Sep 11 03:43:56 UTC 2009


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

Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 10 09:44:30 2009 -0700

i965: Enable loops in the VS.

Passes piglit glsl-vs-loop testcase.

Bug #20171

---

 src/mesa/drivers/dri/i965/brw_vs_emit.c |   53 ++++++++++++++++++++++---------
 1 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c
index 584fdbd..1638ef8 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c
@@ -1270,9 +1270,27 @@ post_vs_emit( struct brw_vs_compile *c,
 }
 
 static uint32_t
-get_predicate(uint32_t swizzle)
+get_predicate(const struct prog_instruction *inst)
 {
-   switch (swizzle) {
+   if (inst->DstReg.CondMask == COND_TR)
+      return BRW_PREDICATE_NONE;
+
+   /* All of GLSL only produces predicates for COND_NE and one channel per
+    * vector.  Fail badly if someone starts doing something else, as it might
+    * mean infinite looping or something.
+    *
+    * We'd like to support all the condition codes, but our hardware doesn't
+    * quite match the Mesa IR, which is modeled after the NV extensions.  For
+    * those, the instruction may update the condition codes or not, then any
+    * later instruction may use one of those condition codes.  For gen4, the
+    * instruction may update the flags register based on one of the condition
+    * codes output by the instruction, and then further instructions may
+    * predicate on that.  We can probably support this, but it won't
+    * necessarily be easy.
+    */
+   assert(inst->DstReg.CondMask == COND_NE);
+
+   switch (inst->DstReg.CondSwizzle) {
    case SWIZZLE_XXXX:
       return BRW_PREDICATE_ALIGN16_REPLICATE_X;
    case SWIZZLE_YYYY:
@@ -1282,7 +1300,8 @@ get_predicate(uint32_t swizzle)
    case SWIZZLE_WWWW:
       return BRW_PREDICATE_ALIGN16_REPLICATE_W;
    default:
-      _mesa_problem(NULL, "Unexpected predicate: 0x%08x\n", swizzle);
+      _mesa_problem(NULL, "Unexpected predicate: 0x%08x\n",
+		    inst->DstReg.CondMask);
       return BRW_PREDICATE_NORMAL;
    }
 }
@@ -1294,6 +1313,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
 #define MAX_IF_DEPTH 32
 #define MAX_LOOP_DEPTH 32
    struct brw_compile *p = &c->func;
+   struct brw_context *brw = p->brw;
    const GLuint nr_insns = c->vp->program.Base.NumInstructions;
    GLuint insn, if_depth = 0, loop_depth = 0;
    GLuint end_offset = 0;
@@ -1492,8 +1512,8 @@ void brw_vs_emit(struct brw_vs_compile *c )
       case OPCODE_IF:
 	 assert(if_depth < MAX_IF_DEPTH);
 	 if_inst[if_depth] = brw_IF(p, BRW_EXECUTE_8);
-	 if_inst[if_depth]->header.predicate_control =
-	    get_predicate(inst->DstReg.CondSwizzle);
+	 /* Note that brw_IF smashes the predicate_control field. */
+	 if_inst[if_depth]->header.predicate_control = get_predicate(inst);
 	 if_depth++;
 	 break;
       case OPCODE_ELSE:
@@ -1503,45 +1523,48 @@ void brw_vs_emit(struct brw_vs_compile *c )
          assert(if_depth > 0);
 	 brw_ENDIF(p, if_inst[--if_depth]);
 	 break;			
-#if 0
       case OPCODE_BGNLOOP:
          loop_inst[loop_depth++] = brw_DO(p, BRW_EXECUTE_8);
          break;
       case OPCODE_BRK:
+	 brw_set_predicate_control(p, get_predicate(inst));
          brw_BREAK(p);
-         brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+	 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
          break;
       case OPCODE_CONT:
+	 brw_set_predicate_control(p, get_predicate(inst));
          brw_CONT(p);
          brw_set_predicate_control(p, BRW_PREDICATE_NONE);
          break;
       case OPCODE_ENDLOOP: 
          {
             struct brw_instruction *inst0, *inst1;
+	    GLuint br = 1;
+
             loop_depth--;
+
+	    if (BRW_IS_IGDNG(brw))
+	       br = 2;
+
             inst0 = inst1 = brw_WHILE(p, loop_inst[loop_depth]);
             /* patch all the BREAK/CONT instructions from last BEGINLOOP */
             while (inst0 > loop_inst[loop_depth]) {
                inst0--;
                if (inst0->header.opcode == BRW_OPCODE_BREAK) {
-                  inst0->bits3.if_else.jump_count = inst1 - inst0 + 1;
+                  inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
                   inst0->bits3.if_else.pop_count = 0;
                }
                else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) {
-                  inst0->bits3.if_else.jump_count = inst1 - inst0;
+                  inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
                   inst0->bits3.if_else.pop_count = 0;
                }
             }
          }
          break;
-#else
-         (void) loop_inst;
-         (void) loop_depth;
-#endif
       case OPCODE_BRA:
-         brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+	 brw_set_predicate_control(p, get_predicate(inst));
          brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16));
-         brw_set_predicate_control_flag_value(p, 0xff);
+	 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
          break;
       case OPCODE_CAL:
 	 brw_set_access_mode(p, BRW_ALIGN_1);




More information about the mesa-commit mailing list