Mesa (master): gallivm: support array textures

Roland Scheidegger sroland at kemper.freedesktop.org
Thu Nov 29 14:32:36 UTC 2012


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

Author: Roland Scheidegger <sroland at vmware.com>
Date:   Thu Nov 29 04:06:48 2012 +0100

gallivm: support array textures

Support 1d and 2d array textures (including shadow samplers),
and (as a side effect mostly) also shadow cube samplers.
Seems to pass the relevant piglit tests both for sampling and rendering
to (though some require version overrides).
Since we don't support render target indices rendering to array textures
is still restricted to a single layer at a time.
Also, the min/max layer in the sampler view (which is unnecessary for GL)
is ignored (always use all layers).

Reviewed-by: José Fonseca <jfonseca at vmware.com>

---

 src/gallium/auxiliary/gallivm/lp_bld_sample.c     |   13 ++--
 src/gallium/auxiliary/gallivm/lp_bld_sample.h     |    7 ++-
 src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c |   66 ++++++++++---------
 src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c |   76 +++++++++++++--------
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_info.c  |    1 +
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c   |    5 ++
 6 files changed, 103 insertions(+), 65 deletions(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
index 8ea5f5e..04f4135 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
@@ -986,11 +986,14 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld,
       *row_stride_vec = lp_build_get_level_stride_vec(bld,
                                                       bld->row_stride_array,
                                                       ilevel);
-      if (dims == 3 || bld->static_state->target == PIPE_TEXTURE_CUBE) {
-         *img_stride_vec = lp_build_get_level_stride_vec(bld,
-                                                         bld->img_stride_array,
-                                                         ilevel);
-      }
+   }
+   if (dims == 3 ||
+       bld->static_state->target == PIPE_TEXTURE_CUBE ||
+       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+      *img_stride_vec = lp_build_get_level_stride_vec(bld,
+                                                      bld->img_stride_array,
+                                                      ilevel);
    }
 }
 
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
index 7fc432c..ddd450b 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h
@@ -303,15 +303,20 @@ apply_sampler_swizzle(struct lp_build_sample_context *bld,
    lp_build_swizzle_soa_inplace(&bld->texel_bld, texel, swizzles);
 }
 
-
+/*
+ * not really dimension as such, this indicates the amount of
+ * "normal" texture coords subject to minification, wrapping etc.
+ */
 static INLINE unsigned
 texture_dims(enum pipe_texture_target tex)
 {
    switch (tex) {
    case PIPE_TEXTURE_1D:
+   case PIPE_TEXTURE_1D_ARRAY:
    case PIPE_BUFFER:
       return 1;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_2D_ARRAY:
    case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
       return 2;
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
index 1f3a98a..7d7e351 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
@@ -619,12 +619,14 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
                                           &z_offset, &z_subcoord);
          offset = lp_build_add(&bld->int_coord_bld, offset, z_offset);
       }
-      else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
-         LLVMValueRef z_offset;
-         /* The r coord is the cube face in [0,5] */
-         z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
-         offset = lp_build_add(&bld->int_coord_bld, offset, z_offset);
-      }
+   }
+   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
+       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+      LLVMValueRef z_offset;
+      /* The r coord is the cube face in [0,5] or array layer */
+      z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
+      offset = lp_build_add(&bld->int_coord_bld, offset, z_offset);
    }
    if (mipoffsets) {
       offset = lp_build_add(&bld->int_coord_bld, offset, mipoffsets);
@@ -694,9 +696,11 @@ lp_build_sample_image_nearest_afloat(struct lp_build_sample_context *bld,
                                             bld->static_state->wrap_r,
                                             &z_icoord);
       }
-      else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
-         z_icoord = r;
-      }
+   }
+   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
+       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+      z_icoord = r;
    }
 
    /*
@@ -1082,6 +1086,17 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
                                    bld->static_state->wrap_s,
                                    &x_offset0, &x_offset1,
                                    &x_subcoord[0], &x_subcoord[1]);
+
+   /* add potential cube/array/mip offsets now as they are constant per pixel */
+   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
+       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+      LLVMValueRef z_offset;
+      z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
+      /* The r coord is the cube face in [0,5] or array layer */
+      x_offset0 = lp_build_add(&bld->int_coord_bld, x_offset0, z_offset);
+      x_offset1 = lp_build_add(&bld->int_coord_bld, x_offset1, z_offset);
+   }
    if (mipoffsets) {
       x_offset0 = lp_build_add(&bld->int_coord_bld, x_offset0, mipoffsets);
       x_offset1 = lp_build_add(&bld->int_coord_bld, x_offset1, mipoffsets);
@@ -1132,17 +1147,6 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
          }
       }
    }
-   else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
-      LLVMValueRef z_offset;
-      z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
-      for (y = 0; y < 2; y++) {
-         for (x = 0; x < 2; x++) {
-            /* The r coord is the cube face in [0,5] */
-            offset[0][y][x] = lp_build_add(&bld->int_coord_bld,
-                                           offset[0][y][x], z_offset);
-         }
-      }
-   }
 
    lp_build_sample_fetch_image_linear(bld, data_ptr, offset,
                                       x_subcoord, y_subcoord,
@@ -1253,6 +1257,17 @@ lp_build_sample_image_linear_afloat(struct lp_build_sample_context *bld,
                                   bld->format_desc->block.width,
                                   x_icoord1, x_stride,
                                   &x_offset1, &x_subcoord[1]);
+
+   /* add potential cube/array/mip offsets now as they are constant per pixel */
+   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
+       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+      LLVMValueRef z_offset;
+      z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
+      /* The r coord is the cube face in [0,5] or array layer */
+      x_offset0 = lp_build_add(&bld->int_coord_bld, x_offset0, z_offset);
+      x_offset1 = lp_build_add(&bld->int_coord_bld, x_offset1, z_offset);
+   }
    if (mipoffsets) {
       x_offset0 = lp_build_add(&bld->int_coord_bld, x_offset0, mipoffsets);
       x_offset1 = lp_build_add(&bld->int_coord_bld, x_offset1, mipoffsets);
@@ -1303,17 +1318,6 @@ lp_build_sample_image_linear_afloat(struct lp_build_sample_context *bld,
          }
       }
    }
-   else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
-      LLVMValueRef z_offset;
-      z_offset = lp_build_mul(&bld->int_coord_bld, r, img_stride_vec);
-      for (y = 0; y < 2; y++) {
-         for (x = 0; x < 2; x++) {
-            /* The r coord is the cube face in [0,5] */
-            offset[0][y][x] = lp_build_add(&bld->int_coord_bld,
-                                           offset[0][y][x], z_offset);
-         }
-      }
-   }
 
    lp_build_sample_fetch_image_linear(bld, data_ptr, offset,
                                       x_subcoord, y_subcoord,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index 35eb9cd..659de9b 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -612,7 +612,7 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
    LLVMValueRef flt_width_vec;
    LLVMValueRef flt_height_vec;
    LLVMValueRef flt_depth_vec;
-   LLVMValueRef x, y, z;
+   LLVMValueRef x, y = NULL, z = NULL;
 
    lp_build_extract_image_sizes(bld,
                                 &bld->int_size_bld,
@@ -648,15 +648,12 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
                                           bld->static_state->wrap_r);
          lp_build_name(z, "tex.z.wrapped");
       }
-      else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
-         z = r;
-      }
-      else {
-         z = NULL;
-      }
    }
-   else {
-      y = z = NULL;
+   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
+       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+      z = r;
+      lp_build_name(z, "tex.z.layer");
    }
 
    /*
@@ -695,8 +692,8 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
    LLVMValueRef flt_width_vec;
    LLVMValueRef flt_height_vec;
    LLVMValueRef flt_depth_vec;
-   LLVMValueRef x0, y0, z0, x1, y1, z1;
-   LLVMValueRef s_fpart, t_fpart, r_fpart;
+   LLVMValueRef x0, y0 = NULL, z0 = NULL, x1, y1 = NULL, z1 = NULL;
+   LLVMValueRef s_fpart, t_fpart = NULL, r_fpart = NULL;
    LLVMValueRef neighbors[2][2][4];
    int chan;
 
@@ -740,20 +737,16 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
          lp_build_name(z0, "tex.z0.wrapped");
          lp_build_name(z1, "tex.z1.wrapped");
       }
-      else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
-         z0 = z1 = r;  /* cube face */
-         r_fpart = NULL;
-      }
-      else {
-         z0 = z1 = NULL;
-         r_fpart = NULL;
-      }
    }
-   else {
-      y0 = y1 = t_fpart = NULL;
-      z0 = z1 = r_fpart = NULL;
+   if (bld->static_state->target == PIPE_TEXTURE_CUBE ||
+       bld->static_state->target == PIPE_TEXTURE_1D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_2D_ARRAY) {
+      z0 = z1 = r;  /* cube face or array layer */
+      lp_build_name(z0, "tex.z0.layer");
+      lp_build_name(z1, "tex.z1.layer");
    }
 
+
    /*
     * Get texture colors.
     */
@@ -1017,6 +1010,7 @@ lp_build_sample_common(struct lp_build_sample_context *bld,
    const unsigned mip_filter = bld->static_state->min_mip_filter;
    const unsigned min_filter = bld->static_state->min_img_filter;
    const unsigned mag_filter = bld->static_state->mag_img_filter;
+   const unsigned target = bld->static_state->target;
    LLVMValueRef first_level;
    struct lp_derivatives face_derivs;
 
@@ -1028,7 +1022,7 @@ lp_build_sample_common(struct lp_build_sample_context *bld,
    /*
     * Choose cube face, recompute texcoords and derivatives for the chosen face.
     */
-   if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
+   if (target == PIPE_TEXTURE_CUBE) {
       LLVMValueRef face, face_s, face_t;
       lp_build_cube_lookup(bld, *s, *t, *r, &face, &face_s, &face_t);
       *s = face_s; /* vec */
@@ -1041,6 +1035,24 @@ lp_build_sample_common(struct lp_build_sample_context *bld,
       face_derivs.ddx_ddy[1] = NULL;
       derivs = &face_derivs;
    }
+   else if (target == PIPE_TEXTURE_1D_ARRAY ||
+            target == PIPE_TEXTURE_2D_ARRAY) {
+      LLVMValueRef layer, maxlayer;
+
+      if (target == PIPE_TEXTURE_1D_ARRAY) {
+         layer = *t;
+      }
+      else {
+         layer = *r;
+      }
+      layer = lp_build_iround(&bld->coord_bld, layer);
+      maxlayer = bld->dynamic_state->depth(bld->dynamic_state,
+                                           bld->gallivm, unit);
+      maxlayer = lp_build_sub(&bld->int_bld, maxlayer, bld->int_bld.one);
+      maxlayer = lp_build_broadcast_scalar(&bld->int_coord_bld, maxlayer);
+      *r = lp_build_clamp(&bld->int_coord_bld, layer,
+                          bld->int_coord_bld.zero, maxlayer);
+   }
 
    /*
     * Compute the level of detail (float).
@@ -1067,7 +1079,7 @@ lp_build_sample_common(struct lp_build_sample_context *bld,
       /* fall-through */
    case PIPE_TEX_MIPFILTER_NONE:
       /* always use mip level 0 */
-      if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
+      if (target == PIPE_TEXTURE_CUBE) {
          /* XXX this is a work-around for an apparent bug in LLVM 2.7.
           * We should be able to set ilevel0 = const(0) but that causes
           * bad x86 code to be emitted.
@@ -1297,23 +1309,31 @@ lp_build_fetch_texel(struct lp_build_sample_context *bld,
 
 /**
  * Do shadow test/comparison.
- * \param p  the texcoord Z (aka R, aka P) component
+ * \param coords  incoming texcoords
  * \param texel  the texel to compare against (use the X channel)
  * Ideally this should really be done per-sample.
  */
 static void
 lp_build_sample_compare(struct lp_build_sample_context *bld,
-                        LLVMValueRef p,
+                        const LLVMValueRef *coords,
                         LLVMValueRef texel[4])
 {
    struct lp_build_context *texel_bld = &bld->texel_bld;
    LLVMBuilderRef builder = bld->gallivm->builder;
-   LLVMValueRef res;
+   LLVMValueRef res, p;
    const unsigned chan = 0;
 
    if (bld->static_state->compare_mode == PIPE_TEX_COMPARE_NONE)
       return;
 
+   if (bld->static_state->target == PIPE_TEXTURE_2D_ARRAY ||
+       bld->static_state->target == PIPE_TEXTURE_CUBE) {
+      p = coords[3];
+   }
+   else {
+      p = coords[2];
+   }
+
    /* debug code */
    if (0) {
       LLVMValueRef indx = lp_build_const_int32(bld->gallivm, 0);
@@ -1661,7 +1681,7 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
       }
    }
 
-   lp_build_sample_compare(&bld, r, texel_out);
+   lp_build_sample_compare(&bld, coords, texel_out);
 
    apply_sampler_swizzle(&bld, texel_out);
 }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_info.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_info.c
index ab393ed..c62e117 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_info.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_info.c
@@ -129,6 +129,7 @@ analyse_tex(struct analysis_context *ctx,
          readmask = TGSI_WRITEMASK_XYZ;
          break;
       case TGSI_TEXTURE_SHADOW2D_ARRAY:
+      case TGSI_TEXTURE_SHADOWCUBE:
          readmask = TGSI_WRITEMASK_XYZW;
          break;
       default:
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index 2afdd30..b94e12c 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -1195,6 +1195,7 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
       dims = 3;
       break;
    case TGSI_TEXTURE_SHADOW2D_ARRAY:
+   case TGSI_TEXTURE_SHADOWCUBE:
       num_coords = 4;
       dims = 2;
       break;
@@ -1203,11 +1204,14 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
       return;
    }
 
+   /* Note lod and especially projected are illegal in a LOT of cases */
    if (modifier == LP_BLD_TEX_MODIFIER_LOD_BIAS) {
+      assert(num_coords < 4);
       lod_bias = lp_build_emit_fetch( &bld->bld_base, inst, 0, 3 );
       explicit_lod = NULL;
    }
    else if (modifier == LP_BLD_TEX_MODIFIER_EXPLICIT_LOD) {
+      assert(num_coords < 4);
       lod_bias = NULL;
       explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 3 );
    }
@@ -1217,6 +1221,7 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
    }
 
    if (modifier == LP_BLD_TEX_MODIFIER_PROJECTED) {
+      assert(num_coords < 4);
       oow = lp_build_emit_fetch( &bld->bld_base, inst, 0, 3 );
       oow = lp_build_rcp(&bld->bld_base.base, oow);
    }




More information about the mesa-commit mailing list