Mesa (master): softpipe: support for 1D/2D texture arrays

Brian Paul brianp at kemper.freedesktop.org
Wed Jan 26 03:27:37 UTC 2011


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

Author: Brian Paul <brianp at vmware.com>
Date:   Tue Jan 25 20:27:10 2011 -0700

softpipe: support for 1D/2D texture arrays

---

 src/gallium/drivers/softpipe/sp_screen.c     |    4 +
 src/gallium/drivers/softpipe/sp_tex_sample.c |  201 ++++++++++++++++++++++++++
 src/gallium/drivers/softpipe/sp_texture.c    |    6 +-
 3 files changed, 210 insertions(+), 1 deletions(-)

diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index e19f2e6..6d47fb9 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -125,6 +125,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_INSTANCED_DRAWING:
       return 1;
+   case PIPE_CAP_ARRAY_TEXTURES:
+      return 1;
    default:
       return 0;
    }
@@ -185,7 +187,9 @@ softpipe_is_format_supported( struct pipe_screen *screen,
 
    assert(target == PIPE_BUFFER ||
           target == PIPE_TEXTURE_1D ||
+          target == PIPE_TEXTURE_1D_ARRAY ||
           target == PIPE_TEXTURE_2D ||
+          target == PIPE_TEXTURE_2D_ARRAY ||
           target == PIPE_TEXTURE_RECT ||
           target == PIPE_TEXTURE_3D ||
           target == PIPE_TEXTURE_CUBE);
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index 242c27c..15f7eb2 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -539,6 +539,19 @@ wrap_linear_unorm_clamp_to_edge(const float s[4], unsigned size,
 }
 
 
+/**
+ * Do coordinate to array index conversion.  For array textures.
+ */
+static INLINE void
+wrap_array_layer(const float coord[4], unsigned size, int layer[4])
+{
+   uint ch;
+   for (ch = 0; ch < 4; ch++) {
+      int c = util_ifloor(coord[ch] + 0.5F);
+      layer[ch] = CLAMP(c, 0, size - 1);
+   }
+}
+
 
 /**
  * Examine the quad's texture coordinates to compute the partial
@@ -990,6 +1003,47 @@ img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler,
 
 
 static void
+img_filter_1d_array_nearest(struct tgsi_sampler *tgsi_sampler,
+                            const float s[QUAD_SIZE],
+                            const float t[QUAD_SIZE],
+                            const float p[QUAD_SIZE],
+                            const float c0[QUAD_SIZE],
+                            enum tgsi_sampler_control control,
+                            float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width;
+   int x[4], layer[4];
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+
+   assert(width > 0);
+
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->nearest_texcoord_s(s, width, x);
+   wrap_array_layer(t, texture->height0, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *out = get_texel_2d(samp, addr, x[j], layer[j]);
+      int c;
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = out[c];
+      }
+   }
+
+   if (DEBUG_TEX) {
+      print_sample(__FUNCTION__, rgba);
+   }
+}
+
+
+static void
 img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
                       const float s[QUAD_SIZE],
                       const float t[QUAD_SIZE],
@@ -1033,6 +1087,50 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler,
 }
 
 
+static void
+img_filter_2d_array_nearest(struct tgsi_sampler *tgsi_sampler,
+                            const float s[QUAD_SIZE],
+                            const float t[QUAD_SIZE],
+                            const float p[QUAD_SIZE],
+                            const float c0[QUAD_SIZE],
+                            enum tgsi_sampler_control control,
+                            float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width, height;
+   int x[4], y[4], layer[4];
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+   height = u_minify(texture->height0, level0);
+
+   assert(width > 0);
+   assert(height > 0);
+ 
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->nearest_texcoord_s(s, width, x);
+   samp->nearest_texcoord_t(t, height, y);
+   wrap_array_layer(p, texture->depth0, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *out = get_texel_3d(samp, addr, x[j], y[j], layer[j]);
+      int c;
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = out[c];
+      }
+   }
+
+   if (DEBUG_TEX) {
+      print_sample(__FUNCTION__, rgba);
+   }
+}
+
+
 static INLINE union tex_tile_address
 face(union tex_tile_address addr, unsigned face )
 {
@@ -1168,6 +1266,47 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler,
 
 
 static void
+img_filter_1d_array_linear(struct tgsi_sampler *tgsi_sampler,
+                           const float s[QUAD_SIZE],
+                           const float t[QUAD_SIZE],
+                           const float p[QUAD_SIZE],
+                           const float c0[QUAD_SIZE],
+                           enum tgsi_sampler_control control,
+                           float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width;
+   int x0[4], x1[4], layer[4];
+   float xw[4]; /* weights */
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+
+   assert(width > 0);
+
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->linear_texcoord_s(s, width, x0, x1, xw);
+   wrap_array_layer(t, texture->height0, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *tx0 = get_texel_2d(samp, addr, x0[j], layer[j]);
+      const float *tx1 = get_texel_2d(samp, addr, x1[j], layer[j]);
+      int c;
+
+      /* interpolate R, G, B, A */
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = lerp(xw[j], tx0[c], tx1[c]);
+      }
+   }
+}
+
+
+static void
 img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
                      const float s[QUAD_SIZE],
                      const float t[QUAD_SIZE],
@@ -1215,6 +1354,54 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler,
 
 
 static void
+img_filter_2d_array_linear(struct tgsi_sampler *tgsi_sampler,
+                           const float s[QUAD_SIZE],
+                           const float t[QUAD_SIZE],
+                           const float p[QUAD_SIZE],
+                           const float c0[QUAD_SIZE],
+                           enum tgsi_sampler_control control,
+                           float rgba[NUM_CHANNELS][QUAD_SIZE])
+{
+   const struct sp_sampler_variant *samp = sp_sampler_variant(tgsi_sampler);
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level0, j;
+   int width, height;
+   int x0[4], y0[4], x1[4], y1[4], layer[4];
+   float xw[4], yw[4]; /* weights */
+   union tex_tile_address addr;
+
+   level0 = samp->level;
+   width = u_minify(texture->width0, level0);
+   height = u_minify(texture->height0, level0);
+
+   assert(width > 0);
+   assert(height > 0);
+
+   addr.value = 0;
+   addr.bits.level = samp->level;
+
+   samp->linear_texcoord_s(s, width,  x0, x1, xw);
+   samp->linear_texcoord_t(t, height, y0, y1, yw);
+   wrap_array_layer(p, texture->depth0, layer);
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const float *tx0 = get_texel_3d(samp, addr, x0[j], y0[j], layer[j]);
+      const float *tx1 = get_texel_3d(samp, addr, x1[j], y0[j], layer[j]);
+      const float *tx2 = get_texel_3d(samp, addr, x0[j], y1[j], layer[j]);
+      const float *tx3 = get_texel_3d(samp, addr, x1[j], y1[j], layer[j]);
+      int c;
+
+      /* interpolate R, G, B, A */
+      for (c = 0; c < 4; c++) {
+         rgba[c][j] = lerp_2d(xw[j], yw[j],
+                              tx0[c], tx1[c],
+                              tx2[c], tx3[c]);
+      }
+   }
+}
+
+
+static void
 img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
                        const float s[QUAD_SIZE],
                        const float t[QUAD_SIZE],
@@ -1906,8 +2093,10 @@ get_lambda_func(const union sp_sampler_key key)
    
    switch (key.bits.target) {
    case PIPE_TEXTURE_1D:
+   case PIPE_TEXTURE_1D_ARRAY:
       return compute_lambda_1d;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_2D_ARRAY:
    case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
       return compute_lambda_2d;
@@ -1932,6 +2121,12 @@ get_img_filter(const union sp_sampler_key key,
       else
          return img_filter_1d_linear;
       break;
+   case PIPE_TEXTURE_1D_ARRAY:
+      if (filter == PIPE_TEX_FILTER_NEAREST) 
+         return img_filter_1d_array_nearest;
+      else
+         return img_filter_1d_array_linear;
+      break;
    case PIPE_TEXTURE_2D:
    case PIPE_TEXTURE_RECT:
       /* Try for fast path:
@@ -1967,6 +2162,12 @@ get_img_filter(const union sp_sampler_key key,
       else
          return img_filter_2d_linear;
       break;
+   case PIPE_TEXTURE_2D_ARRAY:
+      if (filter == PIPE_TEX_FILTER_NEAREST) 
+         return img_filter_2d_array_nearest;
+      else
+         return img_filter_2d_array_linear;
+      break;
    case PIPE_TEXTURE_CUBE:
       if (filter == PIPE_TEX_FILTER_NEAREST) 
          return img_filter_cube_nearest;
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
index 509d998..2daed20 100644
--- a/src/gallium/drivers/softpipe/sp_texture.c
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -227,9 +227,13 @@ 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_3D) {
+       spr->base.target == PIPE_TEXTURE_3D ||
+       spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
       offset += layer * nblocksy * spr->stride[level];
    }
+   else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) {
+      offset += layer * spr->stride[level];
+   }
    else {
       assert(layer == 0);
    }




More information about the mesa-commit mailing list