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

Roland Scheidegger sroland at vmware.com
Fri Mar 1 12:40:49 PST 2013


Am 01.03.2013 19:54, schrieb Brian Paul:
> Looks good, just minor things below.
> 
> Reviewed-by: Brian Paul <brianp at vmware.com>
> 
> On 03/01/2013 11:41 AM, sroland at vmware.com wrote:
>> 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
> 
> assert(inst->Texture.NumOffsets == 0) here just to be safe?
Yes sounds good. After all we could get more if someone tries some
advanced gather at some point.

> 
> 
>> +     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,
>>      }
>>   }
>>
>> +
> 
> Maybe put a comment on this function to explain it:
Yes.

> 
>> +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;
> 
> This block of code seems to be repeated several times.  Can it be put
> into a helper function like get_texel_offsets()?
I blame lazy copy&paste :-). But you are certainly right it was repeated
5 times.
(FWIW it isn't really optimized as it always fetches all 3 offsets
regardless the texture dimension. Could be improved but that way needs
less code for this probably not often used feature.)

> 
>>
>>      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])
>>   {

Roland


More information about the mesa-dev mailing list