From 95e03914d82f4a3722cda00cd6eda54a6f328a73 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 29 Nov 2012 04:06:48 +0100 Subject: [PATCH] gallivm: support array textures MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- src/gallium/auxiliary/gallivm/lp_bld_sample.c | 13 ++-- src/gallium/auxiliary/gallivm/lp_bld_sample.h | 7 +- .../auxiliary/gallivm/lp_bld_sample_aos.c | 66 ++++++++-------- .../auxiliary/gallivm/lp_bld_sample_soa.c | 76 ++++++++++++------- .../auxiliary/gallivm/lp_bld_tgsi_info.c | 1 + .../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 8ea5f5e01dc..04f41355e7b 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 7fc432cb4c2..ddd450b7be9 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 1f3a98a6896..7d7e351d21d 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 35eb9cd8d08..659de9b5626 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 ab393ed942a..c62e117b89f 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 2afdd3027e0..b94e12cb77f 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); } -- 2.30.2