DDX DDY support, not very accurate
authorZou Nan hai <nanhai.zou@intel.com>
Tue, 24 Jul 2007 03:09:34 +0000 (11:09 +0800)
committerZou Nan hai <nanhai.zou@intel.com>
Tue, 24 Jul 2007 03:09:34 +0000 (11:09 +0800)
src/mesa/drivers/dri/i965/brw_wm.h
src/mesa/drivers/dri/i965/brw_wm_fp.c
src/mesa/drivers/dri/i965/brw_wm_glsl.c

index 931c0038d4108d9b0f72ce9a451598771753b87e..22e77287f45168cc8436bfdc4f30a16bf63f504f 100644 (file)
@@ -194,6 +194,7 @@ struct brw_wm_compile {
    GLuint nr_fp_insns;
    GLuint fp_temp;
    GLuint fp_interp_emitted;
+   GLuint fp_deriv_emitted;
 
    struct prog_src_register pixel_xy;
    struct prog_src_register delta_xy;
index 403160c49497889c4f927054a3777b146e52d5d6..0a6e516b93305800c2799b61484f70bf68661793 100644 (file)
@@ -361,6 +361,37 @@ static void emit_interp( struct brw_wm_compile *c,
    c->fp_interp_emitted |= 1<<idx;
 }
 
+static void emit_ddx( struct brw_wm_compile *c,
+        const struct prog_instruction *inst )
+{
+    GLuint idx = inst->SrcReg[0].Index;
+    struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
+
+    c->fp_deriv_emitted |= 1<<idx;
+    emit_op(c,
+            OPCODE_DDX,
+            inst->DstReg,
+            0, 0, 0,
+            interp,
+            get_pixel_w(c),
+            src_undef());
+}
+
+static void emit_ddy( struct brw_wm_compile *c,
+        const struct prog_instruction *inst )
+{
+    GLuint idx = inst->SrcReg[0].Index;
+    struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
+
+    c->fp_deriv_emitted |= 1<<idx;
+    emit_op(c,
+            OPCODE_DDY,
+            inst->DstReg,
+            0, 0, 0,
+            interp,
+            get_pixel_w(c),
+            src_undef());
+}
 
 /***********************************************************************
  * Hacks to extend the program parameter and constant lists.
@@ -907,6 +938,12 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
          */
         out->DstReg.WriteMask = 0;
         break;
+      case OPCODE_DDX:
+        emit_ddx(c, inst);
+        break;
+      case OPCODE_DDY:
+         emit_ddy(c, inst);
+       break;
       case OPCODE_END:
         emit_fog(c);
         emit_fb_write(c);
index 09e7590367688d33cb24b69ea744f7707bb555b9..f47f139282d4e5046f8333c99d1a68cddc612107 100644 (file)
@@ -16,6 +16,8 @@ GLboolean brw_wm_is_glsl(struct gl_fragment_program *fp)
            case OPCODE_CAL:
            case OPCODE_BRK:
            case OPCODE_RET:
+           case OPCODE_DDX:
+           case OPCODE_DDY:
            case OPCODE_BGNLOOP:
                return GL_TRUE; 
            default:
@@ -92,7 +94,7 @@ static void prealloc_reg(struct brw_wm_compile *c)
     int i, j;
     struct brw_reg reg;
     int nr_interp_regs = 0;
-    GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted;
+    GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted | c->fp_deriv_emitted;
 
     for (i = 0; i < 4; i++) {
        reg = (i < c->key.nr_depth_regs) 
@@ -862,6 +864,62 @@ static void emit_sne(struct brw_wm_compile *c,
 {
     emit_sop(c, inst, BRW_CONDITIONAL_NEQ);
 }
+
+static void emit_ddx(struct brw_wm_compile *c,
+                struct prog_instruction *inst)
+{
+    struct brw_compile *p = &c->func;
+    GLuint mask = inst->DstReg.WriteMask;
+    struct brw_reg interp[4];
+    struct brw_reg dst;
+    struct brw_reg src0, w;
+    GLuint nr, i;
+    src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
+    w = get_src_reg(c, &inst->SrcReg[1], 3, 1);
+    nr = src0.nr;
+    interp[0] = brw_vec1_grf(nr, 0);
+    interp[1] = brw_vec1_grf(nr, 4);
+    interp[2] = brw_vec1_grf(nr+1, 0);
+    interp[3] = brw_vec1_grf(nr+1, 4);
+    brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
+    for(i = 0; i < 4; i++ ) {
+        if (mask & (1<<i)) {
+            dst = get_dst_reg(c, inst, i, 1);
+            brw_MOV(p, dst, interp[i]);
+            brw_MUL(p, dst, dst, w);
+        }
+    }
+    brw_set_saturate(p, 0);
+}
+
+static void emit_ddy(struct brw_wm_compile *c,
+                struct prog_instruction *inst)
+{
+    struct brw_compile *p = &c->func;
+    GLuint mask = inst->DstReg.WriteMask;
+    struct brw_reg interp[4];
+    struct brw_reg dst;
+    struct brw_reg src0, w;
+    GLuint nr, i;
+
+    src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1);
+    nr = src0.nr;
+    w = get_src_reg(c, &inst->SrcReg[1], 3, 1);
+    interp[0] = brw_vec1_grf(nr, 0);
+    interp[1] = brw_vec1_grf(nr, 4);
+    interp[2] = brw_vec1_grf(nr+1, 0);
+    interp[3] = brw_vec1_grf(nr+1, 4);
+    brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
+    for(i = 0; i < 4; i++ ) {
+        if (mask & (1<<i)) {
+            dst = get_dst_reg(c, inst, i, 1);
+            brw_MOV(p, dst, suboffset(interp[i], 1));
+            brw_MUL(p, dst, dst, w);
+        }
+    }
+    brw_set_saturate(p, 0);
+}
+
 /* TODO
    BIAS on SIMD8 not workind yet...
  */    
@@ -1088,6 +1146,12 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
            case OPCODE_MIN:    
                emit_min(c, inst);
                break;
+           case OPCODE_DDX:
+               emit_ddx(c, inst);
+               break;
+           case OPCODE_DDY:
+                emit_ddy(c, inst);
+                break;
            case OPCODE_SLT:
                emit_slt(c, inst);
                break;