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@vmware.com>
This commit is contained in:
Roland Scheidegger 2012-11-29 04:06:48 +01:00
parent 88e92f5bcd
commit 95e03914d8
6 changed files with 103 additions and 65 deletions

View 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);
}
}

View 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;

View 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,

View 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);
}

View 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:

View 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);
}