Mesa (master): softpipe: add ARB_texture_cube_map_array support (v1.1)

Dave Airlie airlied at kemper.freedesktop.org
Fri Nov 9 00:46:34 UTC 2012


Module: Mesa
Branch: master
Commit: 309fda2fb28dfe7e8b9be31806346125bef13b21
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=309fda2fb28dfe7e8b9be31806346125bef13b21

Author: Dave Airlie <airlied at gmail.com>
Date:   Sat Nov  3 20:51:45 2012 +1000

softpipe: add ARB_texture_cube_map_array support (v1.1)

This adds support to the softpipe texture sampler and tgsi exec.

In order to handle the extra input to the texture sampling,
I've had to expand the interfaces to take a c1 value for storing
the texture compare value for the TEX2 case.

v1.1: add comments (Brian)

Reviewed-by: Brian Paul <brianp at vmware.com>
Signed-off-by: Dave Airlie <airlied at redhat.com>

---

 src/gallium/auxiliary/tgsi/tgsi_exec.c       |  120 ++++++++++++++-----
 src/gallium/auxiliary/tgsi/tgsi_exec.h       |   13 ++
 src/gallium/drivers/softpipe/sp_screen.c     |    4 +-
 src/gallium/drivers/softpipe/sp_tex_sample.c |  172 ++++++++++++++++++++++++--
 src/gallium/drivers/softpipe/sp_tex_sample.h |    5 +-
 src/gallium/drivers/softpipe/sp_texture.c    |    4 +
 6 files changed, 274 insertions(+), 44 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 0b58f09..428227d 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -1709,6 +1709,7 @@ fetch_texel( struct tgsi_sampler *sampler,
              const union tgsi_exec_channel *t,
              const union tgsi_exec_channel *p,
              const union tgsi_exec_channel *c0,
+             const union tgsi_exec_channel *c1,
              enum tgsi_sampler_control control,
              union tgsi_exec_channel *r,
              union tgsi_exec_channel *g,
@@ -1718,7 +1719,7 @@ fetch_texel( struct tgsi_sampler *sampler,
    uint j;
    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
 
-   sampler->get_samples(sampler, s->f, t->f, p->f, c0->f, control, rgba);
+   sampler->get_samples(sampler, s->f, t->f, p->f, c0->f, c1->f, control, rgba);
 
    for (j = 0; j < 4; j++) {
       r->f[j] = rgba[0][j];
@@ -1734,19 +1735,25 @@ fetch_texel( struct tgsi_sampler *sampler,
 #define TEX_MODIFIER_LOD_BIAS       2
 #define TEX_MODIFIER_EXPLICIT_LOD   3
 
-
+/*
+ * execute a texture instruction.
+ *
+ * modifier is used to control the channel routing for the\
+ * instruction variants like proj, lod, and texture with lod bias.
+ * sampler indicates which src register the sampler is contained in.
+ */
 static void
 exec_tex(struct tgsi_exec_machine *mach,
          const struct tgsi_full_instruction *inst,
-         uint modifier)
+         uint modifier, uint sampler)
 {
-   const uint unit = inst->Src[1].Register.Index;
-   union tgsi_exec_channel r[4];
+   const uint unit = inst->Src[sampler].Register.Index;
+   union tgsi_exec_channel r[4], cubearraycomp, cubelod;
    const union tgsi_exec_channel *lod = &ZeroVec;
    enum tgsi_sampler_control control;
    uint chan;
 
-   if (modifier != TEX_MODIFIER_NONE) {
+   if (modifier != TEX_MODIFIER_NONE && (sampler == 1)) {
       FETCH(&r[3], 0, TGSI_CHAN_W);
       if (modifier != TEX_MODIFIER_PROJECTED) {
          lod = &r[3];
@@ -1768,7 +1775,7 @@ exec_tex(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &ZeroVec, &ZeroVec, lod,  /* S, T, P, LOD */
+                  &r[0], &ZeroVec, &ZeroVec, lod, &ZeroVec, /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
       break;
@@ -1781,7 +1788,7 @@ exec_tex(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &ZeroVec, &r[2], lod,  /* S, T, P, LOD */
+                  &r[0], &ZeroVec, &r[2], lod, &ZeroVec, /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
       break;
@@ -1801,7 +1808,7 @@ exec_tex(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  &r[0], &r[1], &r[2], lod, &ZeroVec,    /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
@@ -1815,7 +1822,7 @@ exec_tex(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &ZeroVec, lod,     /* S, T, P, LOD */
+                  &r[0], &r[1], &ZeroVec, lod, &ZeroVec,    /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
@@ -1829,7 +1836,7 @@ exec_tex(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  &r[0], &r[1], &r[2], lod, &ZeroVec,    /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
@@ -1845,7 +1852,7 @@ exec_tex(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  &r[0], &r[1], &r[2], lod, &ZeroVec,    /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
@@ -1857,7 +1864,24 @@ exec_tex(struct tgsi_exec_machine *mach,
       FETCH(&r[3], 0, TGSI_CHAN_W);
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], &r[3],     /* S, T, P, LOD */
+                  &r[0], &r[1], &r[2], &r[3], &ZeroVec,    /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+   case TGSI_TEXTURE_CUBE_ARRAY:
+      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);
+
+      if (modifier == TEX_MODIFIER_EXPLICIT_LOD ||
+          modifier == TEX_MODIFIER_LOD_BIAS)
+         FETCH(&cubelod, 1, TGSI_CHAN_X);
+      else
+         cubelod = ZeroVec;
+
+      fetch_texel(mach->Samplers[unit],
+                  &r[0], &r[1], &r[2], &r[3], &cubelod,    /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
@@ -1874,11 +1898,24 @@ exec_tex(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], lod,
+                  &r[0], &r[1], &r[2], lod, &ZeroVec,
                   control,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
 
+   case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
+      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(&cubearraycomp, 1, TGSI_CHAN_X);
+
+      fetch_texel(mach->Samplers[unit],
+                  &r[0], &r[1], &r[2], &r[3], &cubearraycomp, /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
    default:
       assert(0);
    }
@@ -1920,7 +1957,7 @@ exec_txd(struct tgsi_exec_machine *mach,
       FETCH(&r[0], 0, TGSI_CHAN_X);
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, BIAS */
+                  &r[0], &ZeroVec, &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, BIAS */
                   tgsi_sampler_lod_bias,
                   &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
       break;
@@ -1937,7 +1974,7 @@ exec_txd(struct tgsi_exec_machine *mach,
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], &ZeroVec,   /* inputs */
+                  &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,   /* inputs */
                   tgsi_sampler_lod_bias,
                   &r[0], &r[1], &r[2], &r[3]);     /* outputs */
       break;
@@ -1945,13 +1982,13 @@ exec_txd(struct tgsi_exec_machine *mach,
    case TGSI_TEXTURE_2D_ARRAY:
    case TGSI_TEXTURE_3D:
    case TGSI_TEXTURE_CUBE:
-
+   case TGSI_TEXTURE_CUBE_ARRAY:
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], &ZeroVec,
+                  &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,
                   tgsi_sampler_lod_bias,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
@@ -1964,7 +2001,7 @@ exec_txd(struct tgsi_exec_machine *mach,
       FETCH(&r[3], 0, TGSI_CHAN_W);
 
       fetch_texel(mach->Samplers[unit],
-                  &r[0], &r[1], &r[2], &r[3],
+                  &r[0], &r[1], &r[2], &r[3], &ZeroVec,
                   tgsi_sampler_lod_bias,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
@@ -2121,7 +2158,7 @@ exec_sample(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[sampler_unit],
-                  &r[0], &ZeroVec, &ZeroVec, lod,  /* S, T, P, LOD */
+                  &r[0], &ZeroVec, &ZeroVec, lod, &ZeroVec,  /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
       break;
@@ -2143,7 +2180,7 @@ exec_sample(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[sampler_unit],
-                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  &r[0], &r[1], &r[2], lod, &ZeroVec,     /* S, T, P, LOD */
                   control,
                   &r[0], &r[1], &r[2], &r[3]);  /* outputs */
       break;
@@ -2151,6 +2188,7 @@ exec_sample(struct tgsi_exec_machine *mach,
    case TGSI_TEXTURE_2D_ARRAY:
    case TGSI_TEXTURE_3D:
    case TGSI_TEXTURE_CUBE:
+   case TGSI_TEXTURE_CUBE_ARRAY:
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
@@ -2162,7 +2200,7 @@ exec_sample(struct tgsi_exec_machine *mach,
       }
 
       fetch_texel(mach->Samplers[sampler_unit],
-                  &r[0], &r[1], &r[2], lod,
+                  &r[0], &r[1], &r[2], lod, &ZeroVec,
                   control,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
@@ -2177,7 +2215,7 @@ exec_sample(struct tgsi_exec_machine *mach,
       assert(modifier != TEX_MODIFIER_PROJECTED);
 
       fetch_texel(mach->Samplers[sampler_unit],
-                  &r[0], &r[1], &r[2], &r[3],
+                  &r[0], &r[1], &r[2], &r[3], &ZeroVec,
                   control,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
@@ -2212,7 +2250,7 @@ exec_sample_d(struct tgsi_exec_machine *mach,
       FETCH(&r[0], 0, TGSI_CHAN_X);
 
       fetch_texel(mach->Samplers[sampler_unit],
-                  &r[0], &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, BIAS */
+                  &r[0], &ZeroVec, &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, BIAS */
                   tgsi_sampler_lod_bias,
                   &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
       break;
@@ -2227,20 +2265,21 @@ exec_sample_d(struct tgsi_exec_machine *mach,
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
       fetch_texel(mach->Samplers[sampler_unit],
-                  &r[0], &r[1], &r[2], &ZeroVec,   /* inputs */
+                  &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,   /* inputs */
                   tgsi_sampler_lod_bias,
                   &r[0], &r[1], &r[2], &r[3]);     /* outputs */
       break;
 
    case TGSI_TEXTURE_3D:
    case TGSI_TEXTURE_CUBE:
+   case TGSI_TEXTURE_CUBE_ARRAY:
 
       FETCH(&r[0], 0, TGSI_CHAN_X);
       FETCH(&r[1], 0, TGSI_CHAN_Y);
       FETCH(&r[2], 0, TGSI_CHAN_Z);
 
       fetch_texel(mach->Samplers[sampler_unit],
-                  &r[0], &r[1], &r[2], &ZeroVec,
+                  &r[0], &r[1], &r[2], &ZeroVec, &ZeroVec,
                   tgsi_sampler_lod_bias,
                   &r[0], &r[1], &r[2], &r[3]);
       break;
@@ -3643,14 +3682,14 @@ exec_instruction(
       /* simple texture lookup */
       /* src[0] = texcoord */
       /* src[1] = sampler unit */
-      exec_tex(mach, inst, TEX_MODIFIER_NONE);
+      exec_tex(mach, inst, TEX_MODIFIER_NONE, 1);
       break;
 
    case TGSI_OPCODE_TXB:
       /* Texture lookup with lod bias */
       /* src[0] = texcoord (src[0].w = LOD bias) */
       /* src[1] = sampler unit */
-      exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS);
+      exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 1);
       break;
 
    case TGSI_OPCODE_TXD:
@@ -3666,14 +3705,14 @@ exec_instruction(
       /* Texture lookup with explit LOD */
       /* src[0] = texcoord (src[0].w = LOD) */
       /* src[1] = sampler unit */
-      exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD);
+      exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 1);
       break;
 
    case TGSI_OPCODE_TXP:
       /* Texture lookup with projection */
       /* src[0] = texcoord (src[0].w = projection) */
       /* src[1] = sampler unit */
-      exec_tex(mach, inst, TEX_MODIFIER_PROJECTED);
+      exec_tex(mach, inst, TEX_MODIFIER_PROJECTED, 1);
       break;
 
    case TGSI_OPCODE_UP2H:
@@ -4208,6 +4247,27 @@ exec_instruction(
       exec_vector_unary(mach, inst, micro_isgn, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
       break;
 
+   case TGSI_OPCODE_TEX2:
+      /* simple texture lookup */
+      /* src[0] = texcoord */
+      /* src[1] = compare */
+      /* src[2] = sampler unit */
+      exec_tex(mach, inst, TEX_MODIFIER_NONE, 2);
+      break;
+   case TGSI_OPCODE_TXB2:
+      /* simple texture lookup */
+      /* src[0] = texcoord */
+      /* src[1] = bias */
+      /* src[2] = sampler unit */
+      exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 2);
+      break;
+   case TGSI_OPCODE_TXL2:
+      /* simple texture lookup */
+      /* src[0] = texcoord */
+      /* src[1] = lod */
+      /* src[2] = sampler unit */
+      exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 2);
+      break;
    default:
       assert( 0 );
    }
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index 0ecb4e9..fc1ee09 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -100,11 +100,24 @@ enum tgsi_sampler_control {
 struct tgsi_sampler
 {
    /** Get samples for four fragments in a quad */
+   /* this interface contains 5 sets of channels that vary
+    * depending on the 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,
+    *     layer for 2D arrays. Compare value for 1D/2D shadows.
+    * c0 - lod value for lod variants, compare value for shadow cube
+    *      and shadow 2d arrays.
+    * c1 - cube array only - lod for cube map arrays
+    *                        compare for shadow cube map arrays.
+    */
    void (*get_samples)(struct tgsi_sampler *sampler,
                        const float s[TGSI_QUAD_SIZE],
                        const float t[TGSI_QUAD_SIZE],
                        const float p[TGSI_QUAD_SIZE],
                        const float c0[TGSI_QUAD_SIZE],
+                       const float c1[TGSI_QUAD_SIZE],
                        enum tgsi_sampler_control control,
                        float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
    void (*get_dims)(struct tgsi_sampler *sampler, int level,
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 5051462..3a38182 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -169,6 +169,7 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
       return 0;
    case PIPE_CAP_QUERY_TIMESTAMP:
+   case PIPE_CAP_CUBE_MAP_ARRAY:
       return 1;
    }
    /* should only get here on unhandled cases */
@@ -279,7 +280,8 @@ softpipe_is_format_supported( struct pipe_screen *screen,
           target == PIPE_TEXTURE_2D_ARRAY ||
           target == PIPE_TEXTURE_RECT ||
           target == PIPE_TEXTURE_3D ||
-          target == PIPE_TEXTURE_CUBE);
+          target == PIPE_TEXTURE_CUBE ||
+          target == PIPE_TEXTURE_CUBE_ARRAY);
 
    format_desc = util_format_description(format);
    if (!format_desc)
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index 992a2f7..5bbf11c 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -739,6 +739,25 @@ get_texel_2d_array(const struct sp_sampler_variant *samp,
 }
 
 
+/* Get texel pointer for cube array texture */
+static INLINE const float *
+get_texel_cube_array(const struct sp_sampler_variant *samp,
+                     union tex_tile_address addr, int x, int y, int layer)
+{
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level = addr.bits.level;
+
+   assert(layer < (int) texture->array_size);
+   assert(layer >= 0);
+
+   if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
+       y < 0 || y >= (int) u_minify(texture->height0, level)) {
+      return samp->sampler->border_color.f;
+   }
+   else {
+      return get_texel_3d_no_border(samp, addr, x, y, layer);
+   }
+}
 /**
  * Given the logbase2 of a mipmap's base level size and a mipmap level,
  * return the size (in texels) of that mipmap level.
@@ -1123,6 +1142,45 @@ img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler,
    }
 }
 
+static void
+img_filter_cube_array_nearest(struct tgsi_sampler *tgsi_sampler,
+                        float s,
+                        float t,
+                        float p,
+                        unsigned level,
+                        unsigned face_id,
+                        enum tgsi_sampler_control control,
+                        float *rgba)
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   int width, height;
+   int x, y, layer;
+   union tex_tile_address addr;
+   const float *out;
+   int c;
+
+   width = u_minify(texture->width0, level);
+   height = u_minify(texture->height0, level);
+
+   assert(width > 0);
+   assert(height > 0);
+ 
+   addr.value = 0;
+   addr.bits.level = level;
+
+   samp->nearest_texcoord_s(s, width, &x);
+   samp->nearest_texcoord_t(t, height, &y);
+   wrap_array_layer(p, texture->array_size, &layer);
+
+   out = get_texel_cube_array(samp, addr, x, y, layer * 6 + face_id);
+   for (c = 0; c < TGSI_QUAD_SIZE; c++)
+      rgba[TGSI_NUM_CHANNELS*c] = out[c];
+
+   if (DEBUG_TEX) {
+      print_sample(__FUNCTION__, rgba);
+   }
+}
 
 static void
 img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler,
@@ -1373,6 +1431,50 @@ img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
 
 
 static void
+img_filter_cube_array_linear(struct tgsi_sampler *tgsi_sampler,
+                             float s,
+                             float t,
+                             float p,
+                             unsigned level,
+                             unsigned face_id,
+                             enum tgsi_sampler_control control,
+                             float *rgba)
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   int width, height;
+   int x0, y0, x1, y1, layer;
+   float xw, yw; /* weights */
+   union tex_tile_address addr, addrj;
+   const float *tx0, *tx1, *tx2, *tx3;
+   int c;
+
+   width = u_minify(texture->width0, level);
+   height = u_minify(texture->height0, level);
+
+   assert(width > 0);
+   assert(height > 0);
+
+   addr.value = 0;
+   addr.bits.level = level;
+
+   samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
+   samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
+   wrap_array_layer(p, texture->array_size, &layer);
+
+   tx0 = get_texel_cube_array(samp, addr, x0, y0, layer * 6 + face_id);
+   tx1 = get_texel_cube_array(samp, addr, x1, y0, layer * 6 + face_id);
+   tx2 = get_texel_cube_array(samp, addr, x0, y1, layer * 6 + face_id);
+   tx3 = get_texel_cube_array(samp, addr, x1, y1, layer * 6 + face_id);
+
+   /* interpolate R, G, B, A */
+   for (c = 0; c < TGSI_QUAD_SIZE; c++)
+      rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
+                                          tx0[c], tx1[c],
+                                          tx2[c], tx3[c]);
+}
+
+static void
 img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler,
                      float s,
                      float t,
@@ -1451,6 +1553,7 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler,
                   const float t[TGSI_QUAD_SIZE],
                   const float p[TGSI_QUAD_SIZE],
                   const float c0[TGSI_QUAD_SIZE],
+                  const float c1[TGSI_QUAD_SIZE],
                   enum tgsi_sampler_control control,
                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -1461,11 +1564,18 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler,
 
    if (control == tgsi_sampler_lod_bias) {
       float lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias;
-      compute_lod(samp->sampler, lambda, c0, lod);
+      if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY)
+         compute_lod(samp->sampler, lambda, c1, lod);
+      else
+         compute_lod(samp->sampler, lambda, c0, lod);
    } else {
       assert(control == tgsi_sampler_lod_explicit);
 
-      memcpy(lod, c0, sizeof(lod));
+      if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY)
+         memcpy(lod, c1, sizeof(lod));
+      else
+         memcpy(lod, c0, sizeof(lod));
+
    }
 
    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
@@ -1508,6 +1618,7 @@ mip_filter_nearest(struct tgsi_sampler *tgsi_sampler,
                    const float t[TGSI_QUAD_SIZE],
                    const float p[TGSI_QUAD_SIZE],
                    const float c0[TGSI_QUAD_SIZE],
+                   const float c1[TGSI_QUAD_SIZE],
                    enum tgsi_sampler_control control,
                    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -1518,11 +1629,17 @@ mip_filter_nearest(struct tgsi_sampler *tgsi_sampler,
 
    if (control == tgsi_sampler_lod_bias) {
       float lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias;
-      compute_lod(samp->sampler, lambda, c0, lod);
+      if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY)
+         compute_lod(samp->sampler, lambda, c1, lod);
+      else
+         compute_lod(samp->sampler, lambda, c0, lod);
    } else {
       assert(control == tgsi_sampler_lod_explicit);
 
-      memcpy(lod, c0, sizeof(lod));
+      if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY)
+         memcpy(lod, c1, sizeof(lod));
+      else
+         memcpy(lod, c0, sizeof(lod));
    }
 
    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
@@ -1547,6 +1664,7 @@ mip_filter_none(struct tgsi_sampler *tgsi_sampler,
                 const float t[TGSI_QUAD_SIZE],
                 const float p[TGSI_QUAD_SIZE],
                 const float c0[TGSI_QUAD_SIZE],
+                const float c1[TGSI_QUAD_SIZE],
                 enum tgsi_sampler_control control,
                 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -1556,11 +1674,17 @@ mip_filter_none(struct tgsi_sampler *tgsi_sampler,
 
    if (control == tgsi_sampler_lod_bias) {
       float lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias;
-      compute_lod(samp->sampler, lambda, c0, lod);
+      if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY)
+         compute_lod(samp->sampler, lambda, c1, lod);
+      else
+         compute_lod(samp->sampler, lambda, c0, lod);
    } else {
       assert(control == tgsi_sampler_lod_explicit);
 
-      memcpy(lod, c0, sizeof(lod));
+      if (samp->key.bits.target == PIPE_TEXTURE_CUBE_ARRAY)
+         memcpy(lod, c1, sizeof(lod));
+      else
+         memcpy(lod, c0, sizeof(lod));
    }
 
    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
@@ -1580,6 +1704,7 @@ mip_filter_none_no_filter_select(struct tgsi_sampler *tgsi_sampler,
                                      const float t[TGSI_QUAD_SIZE],
                                      const float p[TGSI_QUAD_SIZE],
                                      const float c0[TGSI_QUAD_SIZE],
+                                     const float c1[TGSI_QUAD_SIZE],
                                      enum tgsi_sampler_control control,
                                      float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -1814,6 +1939,7 @@ mip_filter_linear_aniso(struct tgsi_sampler *tgsi_sampler,
                         const float t[TGSI_QUAD_SIZE],
                         const float p[TGSI_QUAD_SIZE],
                         const float c0[TGSI_QUAD_SIZE],
+                        const float c1[TGSI_QUAD_SIZE],
                         enum tgsi_sampler_control control,
                         float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -1913,6 +2039,7 @@ mip_filter_linear_2d_linear_repeat_POT(
    const float t[TGSI_QUAD_SIZE],
    const float p[TGSI_QUAD_SIZE],
    const float c0[TGSI_QUAD_SIZE],
+   const float c1[TGSI_QUAD_SIZE],
    enum tgsi_sampler_control control,
    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -1971,6 +2098,7 @@ sample_compare(struct tgsi_sampler *tgsi_sampler,
                const float t[TGSI_QUAD_SIZE],
                const float p[TGSI_QUAD_SIZE],
                const float c0[TGSI_QUAD_SIZE],
+               const float c1[TGSI_QUAD_SIZE],
                enum tgsi_sampler_control control,
                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -1980,7 +2108,7 @@ sample_compare(struct tgsi_sampler *tgsi_sampler,
    float val;
    float pc0, pc1, pc2, pc3;
 
-   samp->mip_filter(tgsi_sampler, s, t, p, c0, control, rgba);
+   samp->mip_filter(tgsi_sampler, s, t, p, c0, c1, control, rgba);
 
    /**
     * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
@@ -1995,6 +2123,11 @@ sample_compare(struct tgsi_sampler *tgsi_sampler,
       pc1 = CLAMP(c0[1], 0.0F, 1.0F);
       pc2 = CLAMP(c0[2], 0.0F, 1.0F);
       pc3 = CLAMP(c0[3], 0.0F, 1.0F);
+   } else if (samp->view->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
+      pc0 = CLAMP(c1[0], 0.0F, 1.0F);
+      pc1 = CLAMP(c1[1], 0.0F, 1.0F);
+      pc2 = CLAMP(c1[2], 0.0F, 1.0F);
+      pc3 = CLAMP(c1[3], 0.0F, 1.0F);
    } else {
       pc0 = CLAMP(p[0], 0.0F, 1.0F);
       pc1 = CLAMP(p[1], 0.0F, 1.0F);
@@ -2081,6 +2214,7 @@ sample_cube(struct tgsi_sampler *tgsi_sampler,
             const float t[TGSI_QUAD_SIZE],
             const float p[TGSI_QUAD_SIZE],
             const float c0[TGSI_QUAD_SIZE],
+            const float c1[TGSI_QUAD_SIZE],
             enum tgsi_sampler_control control,
             float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
@@ -2091,8 +2225,12 @@ sample_cube(struct tgsi_sampler *tgsi_sampler,
    /* Not actually used, but the intermediate steps that do the
     * dereferencing don't know it.
     */
-   static const float pppp[4] = { 0, 0, 0, 0 };
+   static float pppp[4] = { 0, 0, 0, 0 };
 
+   pppp[0] = c0[0];
+   pppp[1] = c0[1];
+   pppp[2] = c0[2];
+   pppp[3] = c0[3];
    /*
      major axis
      direction    target                             sc     tc    ma
@@ -2160,7 +2298,7 @@ sample_cube(struct tgsi_sampler *tgsi_sampler,
     * is not active, this will point somewhere deeper into the
     * pipeline, eg. to mip_filter or even img_filter.
     */
-   samp->compare(tgsi_sampler, ssss, tttt, pppp, c0, control, rgba);
+   samp->compare(tgsi_sampler, ssss, tttt, pppp, c0, c1, control, rgba);
 }
 
 
@@ -2243,13 +2381,14 @@ sample_swizzle(struct tgsi_sampler *tgsi_sampler,
                const float t[TGSI_QUAD_SIZE],
                const float p[TGSI_QUAD_SIZE],
                const float c0[TGSI_QUAD_SIZE],
+               const float c1[TGSI_QUAD_SIZE],
                enum tgsi_sampler_control control,
                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
 {
    struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
    float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
 
-   samp->sample_target(tgsi_sampler, s, t, p, c0, control, rgba_temp);
+   samp->sample_target(tgsi_sampler, s, t, p, c0, c1, control, rgba_temp);
 
    do_swizzling(samp, rgba_temp, rgba);
 }
@@ -2370,6 +2509,7 @@ get_lambda_func(const union sp_sampler_key key)
    case PIPE_TEXTURE_2D_ARRAY:
    case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
+   case PIPE_TEXTURE_CUBE_ARRAY:
       return compute_lambda_2d;
    case PIPE_TEXTURE_3D:
       return compute_lambda_3d;
@@ -2445,6 +2585,12 @@ get_img_filter(const union sp_sampler_key key,
       else
          return img_filter_cube_linear;
       break;
+   case PIPE_TEXTURE_CUBE_ARRAY:
+      if (filter == PIPE_TEX_FILTER_NEAREST) 
+         return img_filter_cube_array_nearest;
+      else
+         return img_filter_cube_array_linear;
+      break;
    case PIPE_TEXTURE_3D:
       if (filter == PIPE_TEX_FILTER_NEAREST) 
          return img_filter_3d_nearest;
@@ -2516,6 +2662,10 @@ sample_get_dims(struct tgsi_sampler *tgsi_sampler, int level,
        dims[1] = u_minify(texture->height0, level);
        dims[2] = u_minify(texture->depth0, level);
        return;
+    case PIPE_TEXTURE_CUBE_ARRAY:
+       dims[1] = u_minify(texture->height0, level);
+       dims[2] = texture->array_size / 6;
+       return;
     default:
        assert(!"unexpected texture target in sample_get_dims()");
        return;
@@ -2722,7 +2872,7 @@ sp_create_sampler_variant( const struct pipe_sampler_state *sampler,
       samp->compare = samp->mip_filter;
    }
    
-   if (key.bits.target == PIPE_TEXTURE_CUBE) {
+   if (key.bits.target == PIPE_TEXTURE_CUBE || key.bits.target == PIPE_TEXTURE_CUBE_ARRAY) {
       samp->sample_target = sample_cube;
    }
    else {
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.h b/src/gallium/drivers/softpipe/sp_tex_sample.h
index dd847af..8415196 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.h
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.h
@@ -63,13 +63,14 @@ typedef void (*filter_func)(struct tgsi_sampler *tgsi_sampler,
                             const float t[TGSI_QUAD_SIZE],
                             const float p[TGSI_QUAD_SIZE],
                             const float c0[TGSI_QUAD_SIZE],
+                            const float c1[TGSI_QUAD_SIZE],
                             enum tgsi_sampler_control control,
                             float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
 
 union sp_sampler_key {
    struct {
-      unsigned target:3;
+      unsigned target:5;
       unsigned is_pot:1;
       unsigned processor:2;
       unsigned unit:4;
@@ -77,7 +78,7 @@ union sp_sampler_key {
       unsigned swizzle_g:3;
       unsigned swizzle_b:3;
       unsigned swizzle_a:3;
-      unsigned pad:10;
+      unsigned pad:8;
    } bits;
    unsigned value;
 };
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
index b4bca07..9c31daa 100644
--- a/src/gallium/drivers/softpipe/sp_texture.c
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -258,6 +258,7 @@ sp_get_tex_image_offset(const struct softpipe_resource *spr,
    unsigned offset = spr->level_offset[level];
 
    if (spr->base.target == PIPE_TEXTURE_CUBE ||
+       spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||
        spr->base.target == PIPE_TEXTURE_3D ||
        spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
       offset += layer * nblocksy * spr->stride[level];
@@ -364,6 +365,9 @@ softpipe_transfer_map(struct pipe_context *pipe,
       else if (resource->target == PIPE_TEXTURE_CUBE) {
          assert(box->z < 6);
       }
+      else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) {
+         assert(box->z <= resource->array_size);
+      }
       else {
          assert(box->z + box->depth <= (u_minify(resource->depth0, level)));
       }




More information about the mesa-commit mailing list