From 9da75f96bce738d5b2c58e6fe0ce8ad436667c58 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Sat, 30 Aug 2014 01:32:59 +0200 Subject: [PATCH] gallivm: handle cube map arrays for texture sampling Pretty easy, just make sure that all paths testing for PIPE_TEXTURE_CUBE also recognize PIPE_TEXTURE_CUBE_ARRAY, and add the layer * 6 calculation to the calculated face. Also handle it for texture size query, looks like OpenGL wants the number of cubes, not layers (so need division by 6). No piglit regressions. v2: fix up adding cube layer to face for seamless filtering (needs to happen after calculating per-sample face). Undetected by piglit unfortunately. Reviewed-by: Jose Fonseca (v1) --- src/gallium/auxiliary/gallivm/lp_bld_sample.c | 5 +- src/gallium/auxiliary/gallivm/lp_bld_sample.h | 17 ++- .../auxiliary/gallivm/lp_bld_sample_aos.c | 16 +-- .../auxiliary/gallivm/lp_bld_sample_soa.c | 108 ++++++++++++++---- .../auxiliary/gallivm/lp_bld_tgsi_soa.c | 5 +- 5 files changed, 107 insertions(+), 44 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index f1bf28519de..85c0d4ed6f8 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -1313,10 +1313,7 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld, bld->row_stride_array, ilevel); } - if (dims == 3 || - bld->static_texture_state->target == PIPE_TEXTURE_CUBE || - bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY || - bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) { + if (dims == 3 || has_layer_coord(bld->static_texture_state->target)) { *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 fd4e0532607..be05b136edb 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -356,9 +356,7 @@ texture_dims(enum pipe_texture_target tex) case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_RECT: case PIPE_TEXTURE_CUBE: - return 2; case PIPE_TEXTURE_CUBE_ARRAY: - assert(0); return 2; case PIPE_TEXTURE_3D: return 3; @@ -368,6 +366,21 @@ texture_dims(enum pipe_texture_target tex) } } +static INLINE boolean +has_layer_coord(enum pipe_texture_target tex) +{ + switch (tex) { + case PIPE_TEXTURE_1D_ARRAY: + case PIPE_TEXTURE_2D_ARRAY: + /* cube is not layered but 3rd coord (after cube mapping) behaves the same */ + case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_CUBE_ARRAY: + return TRUE; + default: + return FALSE; + } +} + boolean lp_sampler_wrap_mode_uses_border_color(unsigned mode, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c index 2f026065766..394521d382a 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c @@ -704,9 +704,7 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld, offset = lp_build_add(&bld->int_coord_bld, offset, z_offset); } } - if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE || - bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY || - bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) { + if (has_layer_coord(bld->static_texture_state->target)) { 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); @@ -781,9 +779,7 @@ lp_build_sample_image_nearest_afloat(struct lp_build_sample_context *bld, &z_icoord); } } - if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE || - bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY || - bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) { + if (has_layer_coord(bld->static_texture_state->target)) { z_icoord = r; } @@ -1130,9 +1126,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld, &x_subcoord[0], &x_subcoord[1]); /* add potential cube/array/mip offsets now as they are constant per pixel */ - if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE || - bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY || - bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) { + if (has_layer_coord(bld->static_texture_state->target)) { 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 */ @@ -1301,9 +1295,7 @@ lp_build_sample_image_linear_afloat(struct lp_build_sample_context *bld, &x_offset1, &x_subcoord[1]); /* add potential cube/array/mip offsets now as they are constant per pixel */ - if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE || - bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY || - bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) { + if (has_layer_coord(bld->static_texture_state->target)) { 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 */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index e29f5034452..99309fe75bd 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -752,10 +752,14 @@ lp_build_sample_image_nearest(struct lp_build_sample_context *bld, lp_build_name(z, "tex.z.wrapped"); } } - if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE || - bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY || - bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) { - z = coords[2]; + if (has_layer_coord(bld->static_texture_state->target)) { + if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) { + /* add cube layer to face */ + z = lp_build_add(&bld->int_coord_bld, coords[2], coords[3]); + } + else { + z = coords[2]; + } lp_build_name(z, "tex.z.layer"); } @@ -868,7 +872,8 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld, int chan, texel_index; boolean seamless_cube_filter, accurate_cube_corners; - seamless_cube_filter = bld->static_texture_state->target == PIPE_TEXTURE_CUBE && + seamless_cube_filter = (bld->static_texture_state->target == PIPE_TEXTURE_CUBE || + bld->static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) && bld->static_sampler_state->seamless_cube_map; accurate_cube_corners = ACCURATE_CUBE_CORNERS && seamless_cube_filter; @@ -923,10 +928,15 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld, lp_build_name(z1, "tex.z1.wrapped"); } } - if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE || - bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY || - bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) { - z00 = z01 = z10 = z11 = z1 = coords[2]; /* cube face or layer */ + if (has_layer_coord(bld->static_texture_state->target)) { + if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) { + /* add cube layer to face */ + z00 = z01 = z10 = z11 = z1 = + lp_build_add(&bld->int_coord_bld, coords[2], coords[3]); + } + else { + z00 = z01 = z10 = z11 = z1 = coords[2]; /* cube face or layer */ + } lp_build_name(z00, "tex.z0.layer"); lp_build_name(z1, "tex.z1.layer"); } @@ -1047,6 +1057,14 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld, z10 = lp_build_select(ivec_bld, fall_off_yp_notxm, new_faces[3], z10); z11 = lp_build_select(ivec_bld, fall_off_yp_notxp, new_faces[3], z11); + if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) { + /* now can add cube layer to face (per sample) */ + z00 = lp_build_add(ivec_bld, z00, coords[3]); + z01 = lp_build_add(ivec_bld, z01, coords[3]); + z10 = lp_build_add(ivec_bld, z10, coords[3]); + z11 = lp_build_add(ivec_bld, z11, coords[3]); + } + LLVMBuildStore(builder, x00, xs[0]); LLVMBuildStore(builder, x01, xs[1]); LLVMBuildStore(builder, x10, xs[2]); @@ -1070,10 +1088,19 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld, LLVMBuildStore(builder, y0, ys[1]); LLVMBuildStore(builder, y1, ys[2]); LLVMBuildStore(builder, y1, ys[3]); - LLVMBuildStore(builder, face, zs[0]); - LLVMBuildStore(builder, face, zs[1]); - LLVMBuildStore(builder, face, zs[2]); - LLVMBuildStore(builder, face, zs[3]); + if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) { + LLVMValueRef cube_layer = lp_build_add(ivec_bld, face, coords[3]); + LLVMBuildStore(builder, cube_layer, zs[0]); + LLVMBuildStore(builder, cube_layer, zs[1]); + LLVMBuildStore(builder, cube_layer, zs[2]); + LLVMBuildStore(builder, cube_layer, zs[3]); + } + else { + LLVMBuildStore(builder, face, zs[0]); + LLVMBuildStore(builder, face, zs[1]); + LLVMBuildStore(builder, face, zs[2]); + LLVMBuildStore(builder, face, zs[3]); + } lp_build_endif(&edge_if); @@ -1644,6 +1671,7 @@ lp_build_sample_mipmap_both(struct lp_build_sample_context *bld, static LLVMValueRef lp_build_layer_coord(struct lp_build_sample_context *bld, unsigned texture_unit, + boolean is_cube_array, LLVMValueRef layer, LLVMValueRef *out_of_bounds) { @@ -1655,6 +1683,7 @@ lp_build_layer_coord(struct lp_build_sample_context *bld, if (out_of_bounds) { LLVMValueRef out1, out; + assert(!is_cube_array); num_layers = lp_build_broadcast_scalar(int_coord_bld, num_layers); out = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, layer, int_coord_bld->zero); out1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, layer, num_layers); @@ -1663,7 +1692,9 @@ lp_build_layer_coord(struct lp_build_sample_context *bld, } else { LLVMValueRef maxlayer; - maxlayer = lp_build_sub(&bld->int_bld, num_layers, bld->int_bld.one); + LLVMValueRef s = is_cube_array ? lp_build_const_int32(bld->gallivm, 6) : + bld->int_bld.one; + maxlayer = lp_build_sub(&bld->int_bld, num_layers, s); maxlayer = lp_build_broadcast_scalar(int_coord_bld, maxlayer); return lp_build_clamp(int_coord_bld, layer, int_coord_bld->zero, maxlayer); } @@ -1703,7 +1734,7 @@ lp_build_sample_common(struct lp_build_sample_context *bld, * Choose cube face, recompute texcoords for the chosen face and * compute rho here too (as it requires transform of derivatives). */ - if (target == PIPE_TEXTURE_CUBE) { + if (target == PIPE_TEXTURE_CUBE || target == PIPE_TEXTURE_CUBE_ARRAY) { boolean need_derivs; need_derivs = ((min_filter != mag_filter || mip_filter != PIPE_TEX_MIPFILTER_NONE) && @@ -1711,11 +1742,19 @@ lp_build_sample_common(struct lp_build_sample_context *bld, !explicit_lod); lp_build_cube_lookup(bld, coords, derivs, &cube_rho, &cube_derivs, need_derivs); derivs = &cube_derivs; + if (target == PIPE_TEXTURE_CUBE_ARRAY) { + /* calculate cube layer coord now */ + LLVMValueRef layer = lp_build_iround(&bld->coord_bld, coords[3]); + LLVMValueRef six = lp_build_const_int_vec(bld->gallivm, bld->int_coord_type, 6); + layer = lp_build_mul(&bld->int_coord_bld, layer, six); + coords[3] = lp_build_layer_coord(bld, texture_index, TRUE, layer, NULL); + /* because of seamless filtering can't add it to face (coords[2]) here. */ + } } else if (target == PIPE_TEXTURE_1D_ARRAY || target == PIPE_TEXTURE_2D_ARRAY) { coords[2] = lp_build_iround(&bld->coord_bld, coords[2]); - coords[2] = lp_build_layer_coord(bld, texture_index, coords[2], NULL); + coords[2] = lp_build_layer_coord(bld, texture_index, FALSE, coords[2], NULL); } if (bld->static_sampler_state->compare_mode != PIPE_TEX_COMPARE_NONE) { @@ -2223,11 +2262,11 @@ lp_build_fetch_texel(struct lp_build_sample_context *bld, if (target == PIPE_TEXTURE_1D_ARRAY || target == PIPE_TEXTURE_2D_ARRAY) { if (out_of_bound_ret_zero) { - z = lp_build_layer_coord(bld, texture_unit, z, &out1); + z = lp_build_layer_coord(bld, texture_unit, FALSE, z, &out1); out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds, out1); } else { - z = lp_build_layer_coord(bld, texture_unit, z, NULL); + z = lp_build_layer_coord(bld, texture_unit, FALSE, z, NULL); } } @@ -2463,7 +2502,8 @@ lp_build_sample_soa(struct gallivm_state *gallivm, if ((gallivm_debug & GALLIVM_DEBUG_NO_QUAD_LOD) && (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) && - (static_texture_state->target == PIPE_TEXTURE_CUBE) && + (static_texture_state->target == PIPE_TEXTURE_CUBE || + static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) && (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) { /* * special case for using per-pixel lod even for implicit lod, @@ -2601,7 +2641,8 @@ lp_build_sample_soa(struct gallivm_state *gallivm, use_aos &= lp_is_simple_wrap_mode(derived_sampler_state.wrap_r); } } - if (static_texture_state->target == PIPE_TEXTURE_CUBE && + if ((static_texture_state->target == PIPE_TEXTURE_CUBE || + static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) && derived_sampler_state.seamless_cube_map && (derived_sampler_state.min_img_filter == PIPE_TEX_FILTER_LINEAR || derived_sampler_state.mag_img_filter == PIPE_TEX_FILTER_LINEAR)) { @@ -2631,6 +2672,13 @@ lp_build_sample_soa(struct gallivm_state *gallivm, &lod_positive, &lod_fpart, &ilevel0, &ilevel1); + if (use_aos && static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) { + /* The aos path doesn't do seamless filtering so simply add cube layer + * to face now. + */ + newcoords[2] = lp_build_add(&bld.int_coord_bld, newcoords[2], newcoords[3]); + } + /* * we only try 8-wide sampling with soa as it appears to * be a loss with aos with AVX (but it should work, except @@ -2695,7 +2743,8 @@ lp_build_sample_soa(struct gallivm_state *gallivm, bld4.num_mips = bld4.num_lods = 1; if ((gallivm_debug & GALLIVM_DEBUG_NO_QUAD_LOD) && (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) && - (static_texture_state->target == PIPE_TEXTURE_CUBE) && + (static_texture_state->target == PIPE_TEXTURE_CUBE || + static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) && (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) { bld4.num_mips = type4.length; bld4.num_lods = type4.length; @@ -2891,6 +2940,7 @@ lp_build_size_query_soa(struct gallivm_state *gallivm, switch (target) { case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_2D_ARRAY: + case PIPE_TEXTURE_CUBE_ARRAY: has_array = TRUE; break; default: @@ -2932,10 +2982,20 @@ lp_build_size_query_soa(struct gallivm_state *gallivm, size = lp_build_minify(&bld_int_vec4, size, lod, TRUE); - if (has_array) - size = LLVMBuildInsertElement(gallivm->builder, size, - dynamic_state->depth(dynamic_state, gallivm, texture_unit), + if (has_array) { + LLVMValueRef layers = dynamic_state->depth(dynamic_state, gallivm, texture_unit); + if (target == PIPE_TEXTURE_CUBE_ARRAY) { + /* + * It looks like GL wants number of cubes, d3d10.1 has it undefined? + * Could avoid this by passing in number of cubes instead of total + * number of layers (might make things easier elsewhere too). + */ + LLVMValueRef six = lp_build_const_int32(gallivm, 6); + layers = LLVMBuildSDiv(gallivm->builder, layers, six, ""); + } + size = LLVMBuildInsertElement(gallivm->builder, size, layers, lp_build_const_int32(gallivm, dims), ""); + } /* * d3d10 requires zero for x/y/z values (but not w, i.e. mip levels) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index 93c926ade94..c0bd7bec193 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -2333,7 +2333,7 @@ emit_fetch_texels( struct lp_build_tgsi_soa_context *bld, unsigned unit, target; LLVMValueRef coord_undef = LLVMGetUndef(bld->bld_base.base.int_vec_type); LLVMValueRef explicit_lod = NULL; - LLVMValueRef coords[3]; + LLVMValueRef coords[5]; LLVMValueRef offsets[3] = { NULL }; enum lp_sampler_lod_property lod_property = LP_SAMPLER_LOD_SCALAR; unsigned dims, i; @@ -2395,7 +2395,8 @@ emit_fetch_texels( struct lp_build_tgsi_soa_context *bld, for (i = 0; i < dims; i++) { coords[i] = lp_build_emit_fetch(&bld->bld_base, inst, 0, i); } - for (i = dims; i < 3; i++) { + /* never use more than 3 coords here but emit_fetch_texel copies all 5 anyway */ + for (i = dims; i < 5; i++) { coords[i] = coord_undef; } if (layer_coord) -- 2.30.2