i965: Add support for attribute interpolation on Sandybridge.
authorEric Anholt <eric@anholt.net>
Sun, 26 Sep 2010 05:28:51 +0000 (13:28 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Tue, 28 Sep 2010 07:58:19 +0000 (15:58 +0800)
Things are simpler these days thanks to barycentric interpolation
parameters being handed in in the payload.

src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm.h
src/mesa/drivers/dri/i965/brw_wm_emit.c
src/mesa/drivers/dri/i965/brw_wm_fp.c
src/mesa/drivers/dri/i965/brw_wm_glsl.c
src/mesa/drivers/dri/i965/gen6_wm_state.c

index 17ff3e2b2b34fa0c91e3d0e8e4b12244233e8564..9ca8e709f558920e41d4d6b8419f80967440287d 100644 (file)
@@ -279,13 +279,52 @@ static void brw_wm_populate_key( struct brw_context *brw,
         }
       }
    }
-        
-   brw_wm_lookup_iz(intel,
-                   line_aa,
-                   lookup,
-                   uses_depth,
-                   key);
 
+   if (intel->gen >= 6) {
+      /* R0-1: masks, pixel X/Y coordinates. */
+      key->nr_payload_regs = 2;
+      /* R2: only for 32-pixel dispatch.*/
+      /* R3-4: perspective pixel location barycentric */
+      key->nr_payload_regs += 2;
+      /* R5-6: perspective pixel location bary for dispatch width != 8 */
+      if (!fp->isGLSL) { /* dispatch_width != 8 */
+        key->nr_payload_regs += 2;
+      }
+      /* R7-10: perspective centroid barycentric */
+      /* R11-14: perspective sample barycentric */
+      /* R15-18: linear pixel location barycentric */
+      /* R19-22: linear centroid barycentric */
+      /* R23-26: linear sample barycentric */
+
+      /* R27: interpolated depth if uses source depth */
+      if (uses_depth) {
+        key->source_depth_reg = key->nr_payload_regs;
+        key->nr_payload_regs++;
+        if (!fp->isGLSL) { /* dispatch_width != 8 */
+           /* R28: interpolated depth if not 8-wide. */
+           key->nr_payload_regs++;
+        }
+      }
+      /* R29: interpolated W set if GEN6_WM_USES_SOURCE_W.
+       */
+      if (uses_depth) {
+        key->source_w_reg = key->nr_payload_regs;
+        key->nr_payload_regs++;
+        if (!fp->isGLSL) { /* dispatch_width != 8 */
+           /* R30: interpolated W if not 8-wide. */
+           key->nr_payload_regs++;
+        }
+      }
+      /* R31: MSAA position offsets. */
+      /* R32-: bary for 32-pixel. */
+      /* R58-59: interp W for 32-pixel. */
+   } else {
+      brw_wm_lookup_iz(intel,
+                      line_aa,
+                      lookup,
+                      uses_depth,
+                      key);
+   }
 
    /* BRW_NEW_WM_INPUT_DIMENSIONS */
    key->proj_attrib_mask = brw->wm.input_size_masks[4-1];
index fed13729698de32b4c7fd163f201a8bdde6ad1fb..a38df1e111eb7cb464e086356464237274d7bd50 100644 (file)
@@ -59,6 +59,7 @@
 
 struct brw_wm_prog_key {
    GLuint source_depth_reg:3;
+   GLuint source_w_reg:3;
    GLuint aa_dest_stencil_reg:3;
    GLuint dest_depth_reg:3;
    GLuint nr_payload_regs:4;
@@ -182,6 +183,8 @@ struct brw_wm_instruction {
 
 #define PROGRAM_PAYLOAD   (PROGRAM_FILE_MAX)
 #define PAYLOAD_DEPTH     (FRAG_ATTRIB_MAX)
+#define PAYLOAD_W         (FRAG_ATTRIB_MAX + 1)
+#define PAYLOAD_FP_REG_MAX (FRAG_ATTRIB_MAX + 2)
 
 struct brw_wm_compile {
    struct brw_compile func;
@@ -224,7 +227,7 @@ struct brw_wm_compile {
    } payload;
 
 
-   const struct brw_wm_ref *pass0_fp_reg[PROGRAM_PAYLOAD+1][256][4];
+   const struct brw_wm_ref *pass0_fp_reg[PAYLOAD_FP_REG_MAX][256][4];
 
    struct brw_wm_ref undef_ref;
    struct brw_wm_value undef_value;
@@ -252,7 +255,7 @@ struct brw_wm_compile {
    struct {
       GLboolean inited;
       struct brw_reg reg;
-   } wm_regs[PROGRAM_PAYLOAD+1][256][4];
+   } wm_regs[PAYLOAD_FP_REG_MAX][256][4];
 
    GLboolean used_grf[BRW_WM_MAX_GRF];
    GLuint first_free_grf;
index a4754ca8cf6f0522eb9638b18907c07ebfd14e72..86ec96368c8ad1e199c96e141418fd800da2284d 100644 (file)
@@ -254,6 +254,8 @@ void emit_pixel_w(struct brw_wm_compile *c,
    struct brw_compile *p = &c->func;
    struct intel_context *intel = &p->brw->intel;
 
+   assert(intel->gen < 6);
+
    /* Don't need this if all you are doing is interpolating color, for
     * instance.
     */
@@ -288,7 +290,6 @@ void emit_pixel_w(struct brw_wm_compile *c,
    }
 }
 
-
 void emit_linterp(struct brw_compile *p,
                  const struct brw_reg *dst,
                  GLuint mask,
@@ -307,7 +308,9 @@ void emit_linterp(struct brw_compile *p,
 
    for (i = 0; i < 4; i++) {
       if (mask & (1<<i)) {
-        if (can_do_pln(intel, deltas)) {
+        if (intel->gen >= 6) {
+           brw_PLN(p, dst[i], interp[i], brw_vec8_grf(2, 0));
+        } else 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]);
@@ -330,6 +333,11 @@ void emit_pinterp(struct brw_compile *p,
    GLuint nr = arg0[0].nr;
    GLuint i;
 
+   if (intel->gen >= 6) {
+      emit_linterp(p, dst, mask, arg0, interp);
+      return;
+   }
+
    interp[0] = brw_vec1_grf(nr, 0);
    interp[1] = brw_vec1_grf(nr, 4);
    interp[2] = brw_vec1_grf(nr+1, 0);
index 3870bf10fcb75fca0abc7247da92645effcf0c1a..a88b7bdea85d9c7c2d937b58e58cfc3e47c2a3d3 100644 (file)
@@ -336,7 +336,13 @@ static struct prog_src_register get_delta_xy( struct brw_wm_compile *c )
 
 static struct prog_src_register get_pixel_w( struct brw_wm_compile *c )
 {
-   if (src_is_undef(c->pixel_w)) {
+   /* This is only called for producing 1/w in pre-gen6 interp.  for
+    * gen6, the interp opcodes don't use this argument.
+    */
+   if (c->func.brw->intel.gen >= 6)
+      return src_undef();
+
+   if (!src_is_undef(c->pixel_w)) {
       struct prog_dst_register pixel_w = get_temp(c);
       struct prog_src_register deltas = get_delta_xy(c);
       struct prog_src_register interp_wpos = src_reg(PROGRAM_PAYLOAD, FRAG_ATTRIB_WPOS);
@@ -363,7 +369,13 @@ static void emit_interp( struct brw_wm_compile *c,
 {
    struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx);
    struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
-   struct prog_src_register deltas = get_delta_xy(c);
+   struct prog_src_register deltas;
+
+   if (c->func.brw->intel.gen < 6) {
+      deltas = get_delta_xy(c);
+   } else {
+      deltas = src_undef();
+   }
 
    /* Need to use PINTERP on attributes which have been
     * multiplied by 1/W in the SF program, and LINTERP on those
@@ -1056,6 +1068,7 @@ static void print_insns( const struct prog_instruction *insn,
  */
 void brw_wm_pass_fp( struct brw_wm_compile *c )
 {
+   struct intel_context *intel = &c->func.brw->intel;
    struct brw_fragment_program *fp = c->fp;
    GLuint insn;
 
@@ -1067,7 +1080,14 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
    }
 
    c->pixel_xy = src_undef();
-   c->delta_xy = src_undef();
+   if (intel->gen >= 6) {
+      /* The interpolation deltas come in as the perspective pixel
+       * location barycentric params.
+       */
+      c->delta_xy = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
+   } else {
+      c->delta_xy = src_undef();
+   }
    c->pixel_w = src_undef();
    c->nr_fp_insns = 0;
    c->fp->tex_units_used = 0x0;
index 7c05e452ddd1d1a70239f7ca7bc2d664f0646270..a0f299195c4b3bddbaa8a27a461e995fec33a294 100644 (file)
@@ -296,6 +296,8 @@ static void prealloc_reg(struct brw_wm_compile *c)
             reg = brw_vec8_grf(0, 0);
        set_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, i, reg);
     }
+    set_reg(c, PROGRAM_PAYLOAD, PAYLOAD_W, 0,
+           brw_vec8_grf(c->key.source_w_reg, 0));
     reg_index += c->key.nr_payload_regs;
 
     /* constants */
index 2cd640de17526e15b2652fc8ab41c9037416e9bc..afce1da666954f9876fa455ec945056caab76ebf 100644 (file)
@@ -151,6 +151,8 @@ upload_wm_state(struct brw_context *brw)
    if (fp->program.UsesKill || ctx->Color.AlphaEnabled)
       dw5 |= GEN6_WM_KILL_ENABLE;
 
+   dw6 |= GEN6_WM_PERSPECTIVE_PIXEL_BARYCENTRIC;
+
    /* This should probably be FS inputs read */
    dw6 |= brw_count_bits(brw->vs.prog_data->outputs_written) <<
       GEN6_WM_NUM_SF_OUTPUTS_SHIFT;