[Mesa-dev] [PATCH] tgsi: add texel offsets and derivatives to sampler interface

sroland at vmware.com sroland at vmware.com
Fri Mar 1 10:41:36 PST 2013


From: Roland Scheidegger <sroland at vmware.com>

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).
---
 src/gallium/auxiliary/tgsi/tgsi_exec.c       |  255 ++++++++++++++++++++------
 src/gallium/auxiliary/tgsi/tgsi_exec.h       |   10 +-
 src/gallium/drivers/softpipe/sp_tex_sample.c |   10 +-
 3 files changed, 210 insertions(+), 65 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 6277c3e..feb5928 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -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];
@@ -1765,6 +1767,23 @@ 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];
+
+   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
+     offsets[0] = offsets[1] = offsets[2] = 0;
 
    assert(modifier != TEX_MODIFIER_LEVEL_ZERO);
 
@@ -1791,25 +1810,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 +1859,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 +1867,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 +1879,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 +1892,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 +1908,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 +1925,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 +1942,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 +1956,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 +1981,132 @@ exec_tex(struct tgsi_exec_machine *mach,
    }
 }
 
+
+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];
+}
+
 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.
-    */
+   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
+     offsets[0] = offsets[1] = offsets[2] = 0;
 
    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:
@@ -2142,6 +2230,23 @@ 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];
+
+   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
+     offsets[0] = offsets[1] = offsets[2] = 0;
 
    assert(modifier != TEX_MODIFIER_PROJECTED);
 
@@ -2170,13 +2275,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 +2294,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 +2314,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 +2333,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 +2363,35 @@ 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];
+
+   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
+     offsets[0] = offsets[1] = offsets[2] = 0;
 
    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 +2400,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 +2415,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 +2431,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;
 
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index c009a97c..ef1fa82 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -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,
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index 30ecc6f..8e16ff9 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -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])
 {
-- 
1.7.9.5



More information about the mesa-dev mailing list