tgsi: add texel offsets and derivatives to sampler interface
authorRoland Scheidegger <sroland@vmware.com>
Fri, 1 Mar 2013 22:27:41 +0000 (23:27 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Sat, 2 Mar 2013 01:54:31 +0000 (02:54 +0100)
Something I never got around to implement, but this is the tgsi execution
side for implementing texel offsets (for ordinary texturing) and explicit
derivatives for sampling (though I guess the ordering of the components
for the derivs parameters is debatable).
There is certainly a runtime cost associated with this.
Unless there are different interfaces used depending on the "complexity"
of the texture instructions, this is impossible to avoid.
Offsets are always active (I think checking if they are active or not is
probably not worth it since it should mostly be an add), whereas the
sampler_control is extended for explicit derivatives.
For now softpipe (the only user of this) just drops all those new values
on the floor (which is the part I never implemented...).

Additionally this also fixes (discovered by accident) inconsistent
projective divide for the comparison coord - the code did do the
projection for shadow2d targets, but not shadow1d ones. This also
drops checking for projection modifier on array targets, since they
aren't possible in any extension I know of (hence we don't actually
know if the array layer should also be divided or not).

Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_exec.h
src/gallium/drivers/softpipe/sp_tex_sample.c

index 6277c3ed95e64b6c12a850442b2cff420535ee8f..da5594b6259503e7cc9f371dfdc1de9837010774 100644 (file)
@@ -1720,6 +1720,8 @@ fetch_texel( struct tgsi_sampler *sampler,
              const union tgsi_exec_channel *p,
              const union tgsi_exec_channel *c0,
              const union tgsi_exec_channel *c1,
+             float derivs[3][2][TGSI_QUAD_SIZE],
+             const int8_t offset[3],
              enum tgsi_sampler_control control,
              union tgsi_exec_channel *r,
              union tgsi_exec_channel *g,
@@ -1731,7 +1733,7 @@ fetch_texel( struct tgsi_sampler *sampler,
 
    /* FIXME: handle explicit derivs, offsets */
    sampler->get_samples(sampler, sview_idx, sampler_idx,
-                        s->f, t->f, p->f, c0->f, c1->f, control, rgba);
+                        s->f, t->f, p->f, c0->f, c1->f, derivs, offset, control, rgba);
 
    for (j = 0; j < 4; j++) {
       r->f[j] = rgba[0][j];
@@ -1748,6 +1750,60 @@ fetch_texel( struct tgsi_sampler *sampler,
 #define TEX_MODIFIER_EXPLICIT_LOD   3
 #define TEX_MODIFIER_LEVEL_ZERO     4
 
+
+/*
+ * Fetch all 3 (for s,t,r coords) texel offsets, put them into int array.
+ */
+static void
+fetch_texel_offsets(struct tgsi_exec_machine *mach,
+                    const struct tgsi_full_instruction *inst,
+                    int8_t offsets[3])
+{
+   if (inst->Texture.NumOffsets == 1) {
+      union tgsi_exec_channel index;
+      union tgsi_exec_channel offset[3];
+      index.i[0] = index.i[1] = index.i[2] = index.i[3] = inst->TexOffsets[0].Index;
+      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
+                             inst->TexOffsets[0].SwizzleX, &index, &ZeroVec, &offset[0]);
+      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
+                             inst->TexOffsets[0].SwizzleY, &index, &ZeroVec, &offset[1]);
+      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
+                             inst->TexOffsets[0].SwizzleZ, &index, &ZeroVec, &offset[2]);
+     offsets[0] = offset[0].i[0];
+     offsets[1] = offset[1].i[0];
+     offsets[2] = offset[2].i[0];
+   } else {
+     assert(inst->Texture.NumOffsets == 0);
+     offsets[0] = offsets[1] = offsets[2] = 0;
+   }
+}
+
+
+/*
+ * Fetch dx and dy values for one channel (s, t or r).
+ * Put dx values into one float array, dy values into another.
+ */
+static void
+fetch_assign_deriv_channel(struct tgsi_exec_machine *mach,
+                           const struct tgsi_full_instruction *inst,
+                           unsigned regdsrcx,
+                           unsigned chan,
+                           float derivs[2][TGSI_QUAD_SIZE])
+{
+   union tgsi_exec_channel d;
+   FETCH(&d, regdsrcx, chan);
+   derivs[0][0] = d.f[0];
+   derivs[0][1] = d.f[1];
+   derivs[0][2] = d.f[2];
+   derivs[0][3] = d.f[3];
+   FETCH(&d, regdsrcx + 1, chan);
+   derivs[1][0] = d.f[0];
+   derivs[1][1] = d.f[1];
+   derivs[1][2] = d.f[2];
+   derivs[1][3] = d.f[3];
+}
+
+
 /*
  * execute a texture instruction.
  *
@@ -1765,6 +1821,10 @@ exec_tex(struct tgsi_exec_machine *mach,
    const union tgsi_exec_channel *lod = &ZeroVec;
    enum tgsi_sampler_control control =  tgsi_sampler_lod_none;
    uint chan;
+   int8_t offsets[3];
+
+   /* always fetch all 3 offsets, overkill but keeps code simple */
+   fetch_texel_offsets(mach, inst, offsets);
 
    assert(modifier != TEX_MODIFIER_LEVEL_ZERO);
 
@@ -1791,25 +1851,41 @@ exec_tex(struct tgsi_exec_machine *mach,
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &ZeroVec, &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
       break;
+
    case TGSI_TEXTURE_SHADOW1D:
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
       if (modifier == TEX_MODIFIER_PROJECTED) {
          micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[2], &r[2], &r[3]);
       }
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &ZeroVec, &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
       break;
 
    case TGSI_TEXTURE_2D:
    case TGSI_TEXTURE_RECT:
+      FETCH(&r[0], 0, TGSI_CHAN_X);
+      FETCH(&r[1], 0, TGSI_CHAN_Y);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+      }
+
+      fetch_texel(mach->Sampler, unit, unit,
+                  &r[0], &r[1], &ZeroVec, &ZeroVec, lod,    /* S, T, P, C, LOD */
+                  NULL, offsets, control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
    case TGSI_TEXTURE_SHADOW2D:
    case TGSI_TEXTURE_SHADOWRECT:
       FETCH(&r[0], 0, TGSI_CHAN_X);
@@ -1824,7 +1900,7 @@ exec_tex(struct tgsi_exec_machine *mach,
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &r[2], &ZeroVec, lod,    /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
 
@@ -1832,13 +1908,11 @@ exec_tex(struct tgsi_exec_machine *mach,
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
 
-      if (modifier == TEX_MODIFIER_PROJECTED) {
-         micro_div(&r[0], &r[0], &r[3]);
-      }
+      assert(modifier != TEX_MODIFIER_PROJECTED);
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &ZeroVec, &ZeroVec, lod,   /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
    case TGSI_TEXTURE_SHADOW1D_ARRAY:
@@ -1846,13 +1920,11 @@ exec_tex(struct tgsi_exec_machine *mach,
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
-      if (modifier == TEX_MODIFIER_PROJECTED) {
-         micro_div(&r[0], &r[0], &r[3]);
-      }
+      assert(modifier != TEX_MODIFIER_PROJECTED);
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &r[2], &ZeroVec, lod,   /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
 
@@ -1861,14 +1933,11 @@ exec_tex(struct tgsi_exec_machine *mach,
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
-      if (modifier == TEX_MODIFIER_PROJECTED) {
-         micro_div(&r[0], &r[0], &r[3]);
-         micro_div(&r[1], &r[1], &r[3]);
-      }
+      assert(modifier != TEX_MODIFIER_PROJECTED);
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &r[2], &ZeroVec, lod,   /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
    case TGSI_TEXTURE_SHADOW2D_ARRAY:
@@ -1880,7 +1949,7 @@ exec_tex(struct tgsi_exec_machine *mach,
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &r[2], &r[3], &ZeroVec,    /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
    case TGSI_TEXTURE_CUBE_ARRAY:
@@ -1897,7 +1966,7 @@ exec_tex(struct tgsi_exec_machine *mach,
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &r[2], &r[3], &cubelod,    /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
    case TGSI_TEXTURE_3D:
@@ -1914,7 +1983,7 @@ exec_tex(struct tgsi_exec_machine *mach,
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &r[2], &ZeroVec, lod,
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
 
@@ -1928,7 +1997,7 @@ exec_tex(struct tgsi_exec_machine *mach,
 
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &r[1], &r[2], &r[3], &cubearraycomp, /* S, T, P, C, LOD */
-                  control,
+                  NULL, offsets, control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
    default:
@@ -1953,72 +2022,99 @@ exec_tex(struct tgsi_exec_machine *mach,
    }
 }
 
+
 static void
 exec_txd(struct tgsi_exec_machine *mach,
          const struct tgsi_full_instruction *inst)
 {
    const uint unit = inst->Src[3].Register.Index;
    union tgsi_exec_channel r[4];
+   float derivs[3][2][TGSI_QUAD_SIZE];
    uint chan;
+   int8_t offsets[3];
 
-   /*
-    * XXX: This is fake TXD -- the derivatives are not taken into account, yet.
-    */
+   /* always fetch all 3 offsets, overkill but keeps code simple */
+   fetch_texel_offsets(mach, inst, offsets);
 
    switch (inst->Texture.Texture) {
    case TGSI_TEXTURE_1D:
-   case TGSI_TEXTURE_SHADOW1D:
-
       FETCH(&r[0], 0, TGSI_CHAN_X);
 
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
+
       fetch_texel(mach->Sampler, unit, unit,
                   &r[0], &ZeroVec, &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, C, LOD */
-                  tgsi_sampler_lod_none,
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
                   &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
       break;
 
+   case TGSI_TEXTURE_SHADOW1D:
    case TGSI_TEXTURE_1D_ARRAY:
-   case TGSI_TEXTURE_2D:
-   case TGSI_TEXTURE_RECT:
    case TGSI_TEXTURE_SHADOW1D_ARRAY:
-   case TGSI_TEXTURE_SHADOW2D:
-   case TGSI_TEXTURE_SHADOWRECT:
-
+      /* SHADOW1D/1D_ARRAY would not need Y/Z respectively, but don't bother */
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
+
       fetch_texel(mach->Sampler, unit, unit,
-                  &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,   /* inputs */
-                  tgsi_sampler_lod_none,
-                  &r[0], &r[1], &r[2], &r[3]);     /* outputs */
+                  &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,   /* S, T, P, C, LOD */
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
+                  &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
       break;
 
-   case TGSI_TEXTURE_2D_ARRAY:
-   case TGSI_TEXTURE_3D:
-   case TGSI_TEXTURE_CUBE:
-   case TGSI_TEXTURE_CUBE_ARRAY:
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
-      FETCH(&r[2], 0, TGSI_CHAN_Z);
+
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
 
       fetch_texel(mach->Sampler, unit, unit,
-                  &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,
-                  tgsi_sampler_lod_none,
-                  &r[0], &r[1], &r[2], &r[3]);
+                  &r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, C, LOD */
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
+                  &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
       break;
 
+
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWRECT:
+   case TGSI_TEXTURE_2D_ARRAY:
    case TGSI_TEXTURE_SHADOW2D_ARRAY:
+      /* only SHADOW2D_ARRAY actually needs W */
+      FETCH(&r[0], 0, TGSI_CHAN_X);
+      FETCH(&r[1], 0, TGSI_CHAN_Y);
+      FETCH(&r[2], 0, TGSI_CHAN_Z);
+      FETCH(&r[3], 0, TGSI_CHAN_W);
+
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
+
+      fetch_texel(mach->Sampler, unit, unit,
+                  &r[0], &r[1], &r[2], &r[3], &ZeroVec,   /* inputs */
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
+                  &r[0], &r[1], &r[2], &r[3]);     /* outputs */
+      break;
 
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+   case TGSI_TEXTURE_CUBE_ARRAY:
+      /* only TEXTURE_CUBE_ARRAY actually needs W */
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
       FETCH(&r[3], 0, TGSI_CHAN_W);
 
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
+      fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Z, derivs[2]);
+
       fetch_texel(mach->Sampler, unit, unit,
-                  &r[0], &r[1], &r[2], &r[3], &ZeroVec,
-                  tgsi_sampler_lod_none,
-                  &r[0], &r[1], &r[2], &r[3]);
+                  &r[0], &r[1], &r[2], &r[3], &ZeroVec,   /* inputs */
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
+                  &r[0], &r[1], &r[2], &r[3]);     /* outputs */
       break;
 
    default:
@@ -2039,26 +2135,13 @@ exec_txf(struct tgsi_exec_machine *mach,
 {
    const uint unit = inst->Src[2].Register.Index;
    union tgsi_exec_channel r[4];
-   union tgsi_exec_channel offset[3];
    uint chan;
    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
    int j;
    int8_t offsets[3];
 
-   if (inst->Texture.NumOffsets == 1) {
-      union tgsi_exec_channel index;
-      index.i[0] = index.i[1] = index.i[2] = index.i[3] = inst->TexOffsets[0].Index;
-      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
-                             inst->TexOffsets[0].SwizzleX, &index, &ZeroVec, &offset[0]);
-      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
-                             inst->TexOffsets[0].SwizzleY, &index, &ZeroVec, &offset[1]);
-      fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
-                             inst->TexOffsets[0].SwizzleZ, &index, &ZeroVec, &offset[2]);
-     offsets[0] = offset[0].i[0];
-     offsets[1] = offset[1].i[0];
-     offsets[2] = offset[2].i[0];
-   } else
-     offsets[0] = offsets[1] = offsets[2] = 0;
+   /* always fetch all 3 offsets, overkill but keeps code simple */
+   fetch_texel_offsets(mach, inst, offsets);
 
    IFETCH(&r[3], 0, TGSI_CHAN_W);
 
@@ -2142,6 +2225,10 @@ exec_sample(struct tgsi_exec_machine *mach,
    const union tgsi_exec_channel *lod = &ZeroVec;
    enum tgsi_sampler_control control = tgsi_sampler_lod_none;
    uint chan;
+   int8_t offsets[3];
+
+   /* always fetch all 3 offsets, overkill but keeps code simple */
+   fetch_texel_offsets(mach, inst, offsets);
 
    assert(modifier != TEX_MODIFIER_PROJECTED);
 
@@ -2170,13 +2257,13 @@ exec_sample(struct tgsi_exec_machine *mach,
          FETCH(&r[2], 3, TGSI_CHAN_X);
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &ZeroVec, &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
       }
       else {
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &ZeroVec, &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
       }
       break;
@@ -2189,13 +2276,13 @@ exec_sample(struct tgsi_exec_machine *mach,
          FETCH(&r[2], 3, TGSI_CHAN_X);
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &r[1], &r[2], &ZeroVec, lod,    /* S, T, P, C, LOD */
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       }
       else {
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &r[1], &ZeroVec, &ZeroVec, lod,    /* S, T, P, C, LOD */
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       }
       break;
@@ -2209,13 +2296,13 @@ exec_sample(struct tgsi_exec_machine *mach,
          FETCH(&r[3], 3, TGSI_CHAN_X);
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &r[1], &r[2], &r[3], lod,
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);
       }
       else {
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &r[1], &r[2], &ZeroVec, lod,
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);
       }
       break;
@@ -2228,13 +2315,13 @@ exec_sample(struct tgsi_exec_machine *mach,
          FETCH(&r[4], 3, TGSI_CHAN_X);
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &r[1], &r[2], &r[3], &r[4],
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);
       }
       else {
          fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                      &r[0], &r[1], &r[2], &r[3], lod,
-                     control,
+                     NULL, offsets, control,
                      &r[0], &r[1], &r[2], &r[3]);
       }
       break;
@@ -2258,18 +2345,22 @@ exec_sample_d(struct tgsi_exec_machine *mach,
    const uint resource_unit = inst->Src[1].Register.Index;
    const uint sampler_unit = inst->Src[2].Register.Index;
    union tgsi_exec_channel r[4];
+   float derivs[3][2][TGSI_QUAD_SIZE];
    uint chan;
-   /*
-    * XXX: This is fake SAMPLE_D -- the derivatives are not taken into account, yet.
-    */
+   int8_t offsets[3];
+
+   /* always fetch all 3 offsets, overkill but keeps code simple */
+   fetch_texel_offsets(mach, inst, offsets);
 
    switch (mach->SamplerViews[resource_unit].Resource) {
    case TGSI_TEXTURE_1D:
       FETCH(&r[0], 0, TGSI_CHAN_X);
 
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
+
       fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                   &r[0], &ZeroVec, &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, C, LOD */
-                  tgsi_sampler_lod_none,
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
                   &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
       break;
 
@@ -2278,9 +2369,12 @@ exec_sample_d(struct tgsi_exec_machine *mach,
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
 
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]);
+
       fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                   &r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec,   /* inputs */
-                  tgsi_sampler_lod_none,
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
                   &r[0], &r[1], &r[2], &r[3]);     /* outputs */
       break;
 
@@ -2290,9 +2384,13 @@ exec_sample_d(struct tgsi_exec_machine *mach,
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]);
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Z, derivs[2]);
+
       fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                   &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,
-                  tgsi_sampler_lod_none,
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
 
@@ -2302,9 +2400,13 @@ exec_sample_d(struct tgsi_exec_machine *mach,
       FETCH(&r[2], 0, TGSI_CHAN_Z);
       FETCH(&r[3], 0, TGSI_CHAN_W);
 
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]);
+      fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Z, derivs[2]);
+
       fetch_texel(mach->Sampler, resource_unit, sampler_unit,
                   &r[0], &r[1], &r[2], &r[3], &ZeroVec,
-                  tgsi_sampler_lod_none,
+                  derivs, offsets, tgsi_sampler_derivs_explicit,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
 
index c009a97c5743b00f2d55b2789219932084d226ad..ef1fa8247f1e7e24a996f8da68a114b6361a312b 100644 (file)
@@ -92,8 +92,8 @@ enum tgsi_sampler_control {
    tgsi_sampler_lod_none,
    tgsi_sampler_lod_bias,
    tgsi_sampler_lod_explicit,
-   tgsi_sampler_lod_zero
-   /* FIXME: tgsi_sampler_derivs_explicit */
+   tgsi_sampler_lod_zero,
+   tgsi_sampler_derivs_explicit
 };
 
 /**
@@ -108,10 +108,12 @@ struct tgsi_sampler
     * s - the first texture coordinate for sampling.
     * t - the second texture coordinate for sampling - unused for 1D,
           layer for 1D arrays.
-    * p - the third coordinate for sampling for 3D, cube, cube arrays,
+    * r - the third coordinate for sampling for 3D, cube, cube arrays,
     *     layer for 2D arrays. Compare value for 1D/2D shadows.
     * c0 - Compare value for shadow cube and shadow 2d arrays,
     *      layer for cube arrays.
+    * derivs - explicit derivatives.
+    * offset - texel offsets
     * lod - lod value, except for shadow cube arrays (compare value there).
     */
    void (*get_samples)(struct tgsi_sampler *sampler,
@@ -122,6 +124,8 @@ struct tgsi_sampler
                        const float r[TGSI_QUAD_SIZE],
                        const float c0[TGSI_QUAD_SIZE],
                        const float c1[TGSI_QUAD_SIZE],
+                       float derivs[3][2][TGSI_QUAD_SIZE],
+                       const int8_t offset[3],
                        enum tgsi_sampler_control control,
                        float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
    void (*get_dims)(struct tgsi_sampler *sampler,
index 30ecc6f379b20e46b1ce7e37e7f43195b6bccf34..8e16ff9e0f03ce60be076625e503c2449bd59340 100644 (file)
@@ -1645,6 +1645,8 @@ compute_lod(const struct pipe_sampler_state *sampler,
    switch (control) {
    case tgsi_sampler_lod_none:
    case tgsi_sampler_lod_zero:
+   /* XXX FIXME */
+   case tgsi_sampler_derivs_explicit:
       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
       break;
    case tgsi_sampler_lod_bias:
@@ -1687,6 +1689,8 @@ compute_lambda_lod(struct sp_sampler_variant *samp,
 
    switch (control) {
    case tgsi_sampler_lod_none:
+      /* XXX FIXME */
+   case tgsi_sampler_derivs_explicit:
       lambda = samp->compute_lambda(samp, s, t, p) + lod_bias;
       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lambda, min_lod, max_lod);
       break;
@@ -2085,7 +2089,9 @@ mip_filter_linear_aniso(struct sp_sampler_variant *samp,
    float dvdy = (t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]) * t_to_v;
    
    if (control == tgsi_sampler_lod_bias ||
-       control == tgsi_sampler_lod_none) {
+       control == tgsi_sampler_lod_none ||
+       /* XXX FIXME */
+       control == tgsi_sampler_derivs_explicit) {
       /* note: instead of working with Px and Py, we will use the 
        * squared length instead, to avoid sqrt.
        */
@@ -3051,6 +3057,8 @@ sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
                     const float p[TGSI_QUAD_SIZE],
                     const float c0[TGSI_QUAD_SIZE],
                     const float lod[TGSI_QUAD_SIZE],
+                    float derivs[3][2][TGSI_QUAD_SIZE],
+                    const int8_t offset[3],
                     enum tgsi_sampler_control control,
                     float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {