gallivm: support array textures
authorRoland Scheidegger <sroland@vmware.com>
Thu, 29 Nov 2012 03:06:48 +0000 (04:06 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Thu, 29 Nov 2012 14:28:25 +0000 (15:28 +0100)
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@vmware.com>
src/gallium/auxiliary/gallivm/lp_bld_sample.c
src/gallium/auxiliary/gallivm/lp_bld_sample.h
src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_info.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c

index 8ea5f5e01dc41fb4e80f0f6727a29390395a0620..04f41355e7bd491544c27e1ab64740b26582be79 100644 (file)
@@ -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);
    }
 }
 
index 7fc432cb4c2efaf237258d9d0645461d452c1a5f..ddd450b7be93dadbfbb3aec15147cf4e05732522 100644 (file)
@@ -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;
index 1f3a98a689607d1c05fdc41df425079ec19c0985..7d7e351d21de22fe2bdb43676873def09fc5a6d3 100644 (file)
@@ -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,
index 35eb9cd8d08ed55a75c781771302e65112e82102..659de9b5626eb975eea2cb3c96fa3464ea37ca80 100644 (file)
@@ -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);
 }
index ab393ed942a022c9025b49d2a6bc5e7bf2c107a1..c62e117b89f94f6d92336a9065718f3b70d0f2cb 100644 (file)
@@ -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:
index 2afdd3027e03d638d86fa7500a51a9a529660f51..b94e12cb77f83de197a03561ea87739cabc18e95 100644 (file)
@@ -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);
    }