i965: Use the PLN instruction when possible in interpolation.
authorEric Anholt <eric@anholt.net>
Wed, 10 Mar 2010 22:46:27 +0000 (14:46 -0800)
committerEric Anholt <eric@anholt.net>
Wed, 10 Mar 2010 23:18:19 +0000 (15:18 -0800)
Saves an instruction in PINTERP, LINTERP, and PIXEL_W from
brw_wm_glsl.c For non-GLSL it isn't used yet because the deltas have
to be laid out differently.

src/mesa/drivers/dri/i965/brw_context.c
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_disasm.c
src/mesa/drivers/dri/i965/brw_eu.h
src/mesa/drivers/dri/i965/brw_eu_emit.c
src/mesa/drivers/dri/i965/brw_wm_emit.c
src/mesa/drivers/dri/i965/brw_wm_glsl.c

index a512896f3158289b177e3b3c23cf0fb48eea81c5..241193c3579f5ae4903c66b9b622d8098ca959cd 100644 (file)
@@ -156,6 +156,7 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
       brw->has_surface_tile_offset = GL_TRUE;
       brw->has_compr4 = GL_TRUE;
       brw->has_aa_line_parameters = GL_TRUE;
+      brw->has_pln = GL_TRUE;
   } else {
       brw->CMD_VF_STATISTICS = CMD_VF_STATISTICS_965;
       brw->CMD_PIPELINE_SELECT = CMD_PIPELINE_SELECT_965;
index d6fc37e4d8912f9a43bce50923364c16a144c480..2855c93ea6662f48597884e8776d68e27a376a53 100644 (file)
@@ -446,6 +446,7 @@ struct brw_context
    GLboolean has_compr4;
    GLboolean has_negative_rhw_bug;
    GLboolean has_aa_line_parameters;
+   GLboolean has_pln;
 ;
    struct {
       struct brw_state_flags dirty;
index bb1b5f5ef037038a253ebf38c4bdbd74467845e6..984e56d00c8c0c6eaecb034438fb903e12a408f5 100644 (file)
 #define BRW_OPCODE_DP2        87
 #define BRW_OPCODE_DPA2       88
 #define BRW_OPCODE_LINE       89
+#define BRW_OPCODE_PLN        90
 #define BRW_OPCODE_NOP        126
 
 #define BRW_PREDICATE_NONE             0
index 4d25152efc28d80927a12f9f96bf564ed4f5d09b..ad61770212c631fe8e70bbbdf6fe81a8b5a7c721 100644 (file)
@@ -50,6 +50,7 @@ struct {
     [BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 },
     [BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 },
     [BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 },
+    [BRW_OPCODE_PLN] = { .name = "pln", .nsrc = 2, .ndst = 1 },
     [BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 },
     [BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 },
     [BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 },
index 39eb88d7c2b3baa14a26058589799b1d131d338f..8e9117b6440b8770676968cb71384463097597e2 100644 (file)
@@ -795,6 +795,7 @@ ALU2(DPH)
 ALU2(DP3)
 ALU2(DP2)
 ALU2(LINE)
+ALU2(PLN)
 
 #undef ALU1
 #undef ALU2
index 82f2fdab2fcff5d8b1e2dbb1f4fc15ac19ebd18d..d2395dec288ab53624922fb644f879651a110aec 100644 (file)
@@ -573,7 +573,7 @@ ALU2(DPH)
 ALU2(DP3)
 ALU2(DP2)
 ALU2(LINE)
-
+ALU2(PLN)
 
 
 
index c7d87b9d94cdf9c7af0c3cb73eadb2b69d637bed..412e09b76a1d31f92885677e7fc567afcbc8f289 100644 (file)
 #include "brw_context.h"
 #include "brw_wm.h"
 
+static GLboolean can_do_pln(struct intel_context *intel,
+                           const struct brw_reg *deltas)
+{
+   struct brw_context *brw = brw_context(&intel->ctx);
+
+   if (!brw->has_pln)
+      return GL_FALSE;
+
+   if (deltas[1].nr != deltas[0].nr + 1)
+      return GL_FALSE;
+
+   if (intel->gen < 6 && ((deltas[0].nr & 1) != 0))
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
 /* Not quite sure how correct this is - need to understand horiz
  * vs. vertical strides a little better.
  */
@@ -186,6 +203,7 @@ void emit_pixel_w(struct brw_wm_compile *c,
                  const struct brw_reg *deltas)
 {
    struct brw_compile *p = &c->func;
+   struct intel_context *intel = &p->brw->intel;
 
    /* Don't need this if all you are doing is interpolating color, for
     * instance.
@@ -196,8 +214,12 @@ void emit_pixel_w(struct brw_wm_compile *c,
       /* Calc 1/w - just linterp wpos[3] optimized by putting the
        * result straight into a message reg.
        */
-      brw_LINE(p, brw_null_reg(), interp3, deltas[0]);
-      brw_MAC(p, brw_message_reg(2), suboffset(interp3, 1), deltas[1]);
+      if (can_do_pln(intel, deltas)) {
+        brw_PLN(p, brw_message_reg(2), interp3, deltas[0]);
+      } else {
+        brw_LINE(p, brw_null_reg(), interp3, deltas[0]);
+        brw_MAC(p, brw_message_reg(2), suboffset(interp3, 1), deltas[1]);
+      }
 
       /* Calc w */
       if (c->dispatch_width == 16) {
@@ -224,6 +246,7 @@ void emit_linterp(struct brw_compile *p,
                  const struct brw_reg *arg0,
                  const struct brw_reg *deltas)
 {
+   struct intel_context *intel = &p->brw->intel;
    struct brw_reg interp[4];
    GLuint nr = arg0[0].nr;
    GLuint i;
@@ -235,8 +258,12 @@ void emit_linterp(struct brw_compile *p,
 
    for (i = 0; i < 4; i++) {
       if (mask & (1<<i)) {
-        brw_LINE(p, brw_null_reg(), interp[i], deltas[0]);
-        brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]);
+        if (can_do_pln(intel, deltas)) {
+           brw_PLN(p, dst[i], interp[i], deltas[0]);
+        } else {
+           brw_LINE(p, brw_null_reg(), interp[i], deltas[0]);
+           brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]);
+        }
       }
    }
 }
@@ -249,6 +276,7 @@ void emit_pinterp(struct brw_compile *p,
                  const struct brw_reg *deltas,
                  const struct brw_reg *w)
 {
+   struct intel_context *intel = &p->brw->intel;
    struct brw_reg interp[4];
    GLuint nr = arg0[0].nr;
    GLuint i;
@@ -260,8 +288,12 @@ void emit_pinterp(struct brw_compile *p,
 
    for (i = 0; i < 4; i++) {
       if (mask & (1<<i)) {
-        brw_LINE(p, brw_null_reg(), interp[i], deltas[0]);
-        brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]);
+        if (can_do_pln(intel, deltas)) {
+           brw_PLN(p, dst[i], interp[i], deltas[0]);
+        } else {
+           brw_LINE(p, brw_null_reg(), interp[i], deltas[0]);
+           brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]);
+        }
       }
    }
    for (i = 0; i < 4; i++) {
index af249452b9b75888d3b23894e4db3965b2fe46da..0b66cc6c9f3ea34848563e35d5df1739044bc4ab 100644 (file)
@@ -289,6 +289,7 @@ reclaim_temps(struct brw_wm_compile *c)
  */
 static void prealloc_reg(struct brw_wm_compile *c)
 {
+    struct intel_context *intel = &c->func.brw->intel;
     int i, j;
     struct brw_reg reg;
     int urb_read_length = 0;
@@ -413,6 +414,43 @@ static void prealloc_reg(struct brw_wm_compile *c)
        }
     }
 
+    for (i = 0; i < c->nr_fp_insns; i++) {
+       const struct prog_instruction *inst = &c->prog_instructions[i];
+
+       switch (inst->Opcode) {
+       case WM_DELTAXY:
+           /* Allocate WM_DELTAXY destination on G45/GM45 to an
+            * even-numbered GRF if possible so that we can use the PLN
+            * instruction.
+            */
+           if (inst->DstReg.WriteMask == WRITEMASK_XY &&
+               !c->wm_regs[inst->DstReg.File][inst->DstReg.Index][0].inited &&
+               !c->wm_regs[inst->DstReg.File][inst->DstReg.Index][1].inited &&
+               (IS_G4X(intel->intelScreen->deviceID) || intel->gen == 5)) {
+               int grf;
+
+               for (grf = c->first_free_grf & ~1;
+                    grf < BRW_WM_MAX_GRF;
+                    grf += 2)
+               {
+                   if (!c->used_grf[grf] && !c->used_grf[grf + 1]) {
+                       c->used_grf[grf] = GL_TRUE;
+                       c->used_grf[grf + 1] = GL_TRUE;
+                       c->first_free_grf = grf + 2;  /* a guess */
+
+                       set_reg(c, inst->DstReg.File, inst->DstReg.Index, 0,
+                               brw_vec8_grf(grf, 0));
+                       set_reg(c, inst->DstReg.File, inst->DstReg.Index, 1,
+                               brw_vec8_grf(grf + 1, 0));
+                       break;
+                   }
+               }
+           }
+       default:
+           break;
+       }
+    }
+
     /* An instruction may reference up to three constants.
      * They'll be found in these registers.
      * XXX alloc these on demand!