diff options
-rw-r--r-- | src/gallium/auxiliary/draw/draw_llvm_sample.c | 3 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample.c | 110 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample.h | 13 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c | 26 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c | 144 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi.h | 1 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 18 | ||||
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_scan.c | 1 | ||||
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_scan.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_tex_sample.c | 3 |
10 files changed, 195 insertions, 126 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm_sample.c b/src/gallium/auxiliary/draw/draw_llvm_sample.c index e51e01101f6..0cb5c210351 100644 --- a/src/gallium/auxiliary/draw/draw_llvm_sample.c +++ b/src/gallium/auxiliary/draw/draw_llvm_sample.c @@ -238,6 +238,7 @@ draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, const struct lp_derivatives *derivs, LLVMValueRef lod_bias, /* optional */ LLVMValueRef explicit_lod, /* optional */ + boolean scalar_lod, LLVMValueRef *texel) { struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base; @@ -256,7 +257,7 @@ draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, coords, offsets, derivs, - lod_bias, explicit_lod, + lod_bias, explicit_lod, scalar_lod, texel); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index d689c7b3858..c2efec9f4cd 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -215,7 +215,7 @@ lp_build_rho(struct lp_build_sample_context *bld, struct lp_build_context *float_size_bld = &bld->float_size_in_bld; struct lp_build_context *float_bld = &bld->float_bld; struct lp_build_context *coord_bld = &bld->coord_bld; - struct lp_build_context *perquadf_bld = &bld->perquadf_bld; + struct lp_build_context *levelf_bld = &bld->levelf_bld; const unsigned dims = bld->dims; LLVMValueRef ddx_ddy[2]; LLVMBuilderRef builder = bld->gallivm->builder; @@ -235,6 +235,8 @@ lp_build_rho(struct lp_build_sample_context *bld, /* Note that all simplified calculations will only work for isotropic filtering */ + assert(bld->num_lods != length); + first_level = bld->dynamic_state->first_level(bld->dynamic_state, bld->gallivm, texture_unit); first_level_vec = lp_build_broadcast_scalar(int_size_bld, first_level); @@ -248,14 +250,14 @@ lp_build_rho(struct lp_build_sample_context *bld, * Cube map code did already everything except size mul and per-quad extraction. */ rho = lp_build_pack_aos_scalars(bld->gallivm, coord_bld->type, - perquadf_bld->type, cube_rho, 0); + levelf_bld->type, cube_rho, 0); if (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) { - rho = lp_build_sqrt(perquadf_bld, rho); + rho = lp_build_sqrt(levelf_bld, rho); } /* Could optimize this for single quad just skip the broadcast */ cubesize = lp_build_extract_broadcast(gallivm, bld->float_size_in_type, - perquadf_bld->type, float_size, index0); - rho = lp_build_mul(perquadf_bld, cubesize, rho); + levelf_bld->type, float_size, index0); + rho = lp_build_mul(levelf_bld, cubesize, rho); } else if (derivs && !(bld->static_texture_state->target == PIPE_TEXTURE_CUBE)) { LLVMValueRef ddmax[3], ddx[3], ddy[3]; @@ -289,12 +291,12 @@ lp_build_rho(struct lp_build_sample_context *bld, } rho_vec = lp_build_max(coord_bld, rho_xvec, rho_yvec); rho = lp_build_pack_aos_scalars(bld->gallivm, coord_bld->type, - perquadf_bld->type, rho_vec, 0); + levelf_bld->type, rho_vec, 0); /* * note that as long as we don't care about per-pixel lod could reduce math * more (at some shuffle cost), but for now only do sqrt after packing. */ - rho = lp_build_sqrt(perquadf_bld, rho); + rho = lp_build_sqrt(levelf_bld, rho); } else { rho_vec = ddmax[0]; @@ -309,7 +311,7 @@ lp_build_rho(struct lp_build_sample_context *bld, * since we can't handle per-pixel rho/lod from now on (TODO). */ rho = lp_build_pack_aos_scalars(bld->gallivm, coord_bld->type, - perquadf_bld->type, rho_vec, 0); + levelf_bld->type, rho_vec, 0); } } else { @@ -381,8 +383,8 @@ lp_build_rho(struct lp_build_sample_context *bld, rho_vec = lp_build_max(coord_bld, rho_xvec, rho_yvec); rho = lp_build_pack_aos_scalars(bld->gallivm, coord_bld->type, - perquadf_bld->type, rho_vec, 0); - rho = lp_build_sqrt(perquadf_bld, rho); + levelf_bld->type, rho_vec, 0); + rho = lp_build_sqrt(levelf_bld, rho); } else { ddx_ddy[0] = lp_build_abs(coord_bld, ddx_ddy[0]); @@ -462,7 +464,7 @@ lp_build_rho(struct lp_build_sample_context *bld, } } rho = lp_build_pack_aos_scalars(bld->gallivm, coord_bld->type, - perquadf_bld->type, rho, 0); + levelf_bld->type, rho, 0); } else { if (dims <= 1) { @@ -652,11 +654,11 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, { LLVMBuilderRef builder = bld->gallivm->builder; - struct lp_build_context *perquadf_bld = &bld->perquadf_bld; + struct lp_build_context *levelf_bld = &bld->levelf_bld; LLVMValueRef lod; - *out_lod_ipart = bld->perquadi_bld.zero; - *out_lod_fpart = perquadf_bld->zero; + *out_lod_ipart = bld->leveli_bld.zero; + *out_lod_fpart = levelf_bld->zero; if (bld->static_sampler_state->min_max_lod_equal) { /* User is forcing sampling from a particular mipmap level. @@ -666,12 +668,15 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, bld->dynamic_state->min_lod(bld->dynamic_state, bld->gallivm, sampler_unit); - lod = lp_build_broadcast_scalar(perquadf_bld, min_lod); + lod = lp_build_broadcast_scalar(levelf_bld, min_lod); } else { if (explicit_lod) { - lod = lp_build_pack_aos_scalars(bld->gallivm, bld->coord_bld.type, - perquadf_bld->type, explicit_lod, 0); + if (bld->num_lods != bld->coord_type.length) + lod = lp_build_pack_aos_scalars(bld->gallivm, bld->coord_bld.type, + levelf_bld->type, explicit_lod, 0); + else + lod = explicit_lod; } else { LLVMValueRef rho; @@ -694,29 +699,29 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, if (mip_filter == PIPE_TEX_MIPFILTER_NONE || mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { - *out_lod_ipart = lp_build_ilog2(perquadf_bld, rho); - *out_lod_fpart = perquadf_bld->zero; + *out_lod_ipart = lp_build_ilog2(levelf_bld, rho); + *out_lod_fpart = levelf_bld->zero; return; } if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR && !(gallivm_debug & GALLIVM_DEBUG_NO_BRILINEAR)) { - lp_build_brilinear_rho(perquadf_bld, rho, BRILINEAR_FACTOR, + lp_build_brilinear_rho(levelf_bld, rho, BRILINEAR_FACTOR, out_lod_ipart, out_lod_fpart); return; } } if (0) { - lod = lp_build_log2(perquadf_bld, rho); + lod = lp_build_log2(levelf_bld, rho); } else { - lod = lp_build_fast_log2(perquadf_bld, rho); + lod = lp_build_fast_log2(levelf_bld, rho); } /* add shader lod bias */ if (lod_bias) { lod_bias = lp_build_pack_aos_scalars(bld->gallivm, bld->coord_bld.type, - perquadf_bld->type, lod_bias, 0); + levelf_bld->type, lod_bias, 0); lod = LLVMBuildFAdd(builder, lod, lod_bias, "shader_lod_bias"); } } @@ -726,7 +731,7 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, LLVMValueRef sampler_lod_bias = bld->dynamic_state->lod_bias(bld->dynamic_state, bld->gallivm, sampler_unit); - sampler_lod_bias = lp_build_broadcast_scalar(perquadf_bld, + sampler_lod_bias = lp_build_broadcast_scalar(levelf_bld, sampler_lod_bias); lod = LLVMBuildFAdd(builder, lod, sampler_lod_bias, "sampler_lod_bias"); } @@ -736,33 +741,33 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, LLVMValueRef max_lod = bld->dynamic_state->max_lod(bld->dynamic_state, bld->gallivm, sampler_unit); - max_lod = lp_build_broadcast_scalar(perquadf_bld, max_lod); + max_lod = lp_build_broadcast_scalar(levelf_bld, max_lod); - lod = lp_build_min(perquadf_bld, lod, max_lod); + lod = lp_build_min(levelf_bld, lod, max_lod); } if (bld->static_sampler_state->apply_min_lod) { LLVMValueRef min_lod = bld->dynamic_state->min_lod(bld->dynamic_state, bld->gallivm, sampler_unit); - min_lod = lp_build_broadcast_scalar(perquadf_bld, min_lod); + min_lod = lp_build_broadcast_scalar(levelf_bld, min_lod); - lod = lp_build_max(perquadf_bld, lod, min_lod); + lod = lp_build_max(levelf_bld, lod, min_lod); } } if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { if (!(gallivm_debug & GALLIVM_DEBUG_NO_BRILINEAR)) { - lp_build_brilinear_lod(perquadf_bld, lod, BRILINEAR_FACTOR, + lp_build_brilinear_lod(levelf_bld, lod, BRILINEAR_FACTOR, out_lod_ipart, out_lod_fpart); } else { - lp_build_ifloor_fract(perquadf_bld, lod, out_lod_ipart, out_lod_fpart); + lp_build_ifloor_fract(levelf_bld, lod, out_lod_ipart, out_lod_fpart); } lp_build_name(*out_lod_fpart, "lod_fpart"); } else { - *out_lod_ipart = lp_build_iround(perquadf_bld, lod); + *out_lod_ipart = lp_build_iround(levelf_bld, lod); } lp_build_name(*out_lod_ipart, "lod_ipart"); @@ -784,20 +789,20 @@ lp_build_nearest_mip_level(struct lp_build_sample_context *bld, LLVMValueRef lod_ipart, LLVMValueRef *level_out) { - struct lp_build_context *perquadi_bld = &bld->perquadi_bld; + struct lp_build_context *leveli_bld = &bld->leveli_bld; LLVMValueRef first_level, last_level, level; first_level = bld->dynamic_state->first_level(bld->dynamic_state, bld->gallivm, texture_unit); last_level = bld->dynamic_state->last_level(bld->dynamic_state, bld->gallivm, texture_unit); - first_level = lp_build_broadcast_scalar(perquadi_bld, first_level); - last_level = lp_build_broadcast_scalar(perquadi_bld, last_level); + first_level = lp_build_broadcast_scalar(leveli_bld, first_level); + last_level = lp_build_broadcast_scalar(leveli_bld, last_level); - level = lp_build_add(perquadi_bld, lod_ipart, first_level); + level = lp_build_add(leveli_bld, lod_ipart, first_level); /* clamp level to legal range of levels */ - *level_out = lp_build_clamp(perquadi_bld, level, first_level, last_level); + *level_out = lp_build_clamp(leveli_bld, level, first_level, last_level); } @@ -815,8 +820,8 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld, LLVMValueRef *level1_out) { LLVMBuilderRef builder = bld->gallivm->builder; - struct lp_build_context *perquadi_bld = &bld->perquadi_bld; - struct lp_build_context *perquadf_bld = &bld->perquadf_bld; + struct lp_build_context *leveli_bld = &bld->leveli_bld; + struct lp_build_context *levelf_bld = &bld->levelf_bld; LLVMValueRef first_level, last_level; LLVMValueRef clamp_min; LLVMValueRef clamp_max; @@ -825,11 +830,11 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld, bld->gallivm, texture_unit); last_level = bld->dynamic_state->last_level(bld->dynamic_state, bld->gallivm, texture_unit); - first_level = lp_build_broadcast_scalar(perquadi_bld, first_level); - last_level = lp_build_broadcast_scalar(perquadi_bld, last_level); + first_level = lp_build_broadcast_scalar(leveli_bld, first_level); + last_level = lp_build_broadcast_scalar(leveli_bld, last_level); - *level0_out = lp_build_add(perquadi_bld, lod_ipart, first_level); - *level1_out = lp_build_add(perquadi_bld, *level0_out, perquadi_bld->one); + *level0_out = lp_build_add(leveli_bld, lod_ipart, first_level); + *level1_out = lp_build_add(leveli_bld, *level0_out, leveli_bld->one); /* * Clamp both *level0_out and *level1_out to [first_level, last_level], with @@ -843,7 +848,7 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld, * converting to our lp_bld_logic helpers. */ #if HAVE_LLVM < 0x0301 - assert(perquadi_bld->type.length == 1); + assert(leveli_bld->type.length == 1); #endif /* *level0_out < first_level */ @@ -858,7 +863,7 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld, first_level, *level1_out, ""); *lod_fpart_inout = LLVMBuildSelect(builder, clamp_min, - perquadf_bld->zero, *lod_fpart_inout, ""); + levelf_bld->zero, *lod_fpart_inout, ""); /* *level0_out >= last_level */ clamp_max = LLVMBuildICmp(builder, LLVMIntSGE, @@ -872,7 +877,7 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld, last_level, *level1_out, ""); *lod_fpart_inout = LLVMBuildSelect(builder, clamp_max, - perquadf_bld->zero, *lod_fpart_inout, ""); + levelf_bld->zero, *lod_fpart_inout, ""); lp_build_name(*level0_out, "texture%u_miplevel0", texture_unit); lp_build_name(*level1_out, "texture%u_miplevel1", texture_unit); @@ -1087,7 +1092,7 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld, LLVMValueRef indexi = lp_build_const_int32(bld->gallivm, i); ileveli = lp_build_extract_broadcast(bld->gallivm, - bld->perquadi_bld.type, + bld->leveli_bld.type, bld4.type, ilevel, indexi); @@ -1131,10 +1136,9 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld, tmp[i] = bld->int_size; tmp[i] = lp_build_minify(&bld->int_size_in_bld, tmp[i], ilevel1); } - int_size_vec = lp_build_concat(bld->gallivm, - tmp, - bld->int_size_in_bld.type, - bld->num_lods); + *out_size = lp_build_concat(bld->gallivm, tmp, + bld->int_size_in_bld.type, + bld->num_lods); } } } @@ -1218,10 +1222,10 @@ lp_build_extract_image_sizes(struct lp_build_sample_context *bld, *out_width = lp_build_pack_aos_scalars(bld->gallivm, size_type, coord_type, size, 0); if (dims >= 2) { - *out_width = lp_build_pack_aos_scalars(bld->gallivm, size_type, - coord_type, size, 1); + *out_height = lp_build_pack_aos_scalars(bld->gallivm, size_type, + coord_type, size, 1); if (dims == 3) { - *out_width = lp_build_pack_aos_scalars(bld->gallivm, size_type, + *out_depth = lp_build_pack_aos_scalars(bld->gallivm, size_type, coord_type, size, 2); } } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index cde8ce96180..a3ecc05877c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -268,13 +268,13 @@ struct lp_build_sample_context struct lp_type texel_type; struct lp_build_context texel_bld; - /** Float per-quad type */ - struct lp_type perquadf_type; - struct lp_build_context perquadf_bld; + /** Float level type */ + struct lp_type levelf_type; + struct lp_build_context levelf_bld; - /** Int per-quad type */ - struct lp_type perquadi_type; - struct lp_build_context perquadi_bld; + /** Int level type */ + struct lp_type leveli_type; + struct lp_build_context leveli_bld; /* Common dynamic state values */ LLVMValueRef row_stride_array; @@ -477,6 +477,7 @@ lp_build_sample_soa(struct gallivm_state *gallivm, const struct lp_derivatives *derivs, LLVMValueRef lod_bias, LLVMValueRef explicit_lod, + boolean scalar_lod, LLVMValueRef texel_out[4]); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c index 104c24d83b9..da416aab87e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c @@ -1422,8 +1422,8 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { LLVMValueRef h16vec_scale = lp_build_const_vec(bld->gallivm, - bld->perquadf_bld.type, 256.0); - LLVMTypeRef i32vec_type = lp_build_vec_type(bld->gallivm, bld->perquadi_bld.type); + bld->levelf_bld.type, 256.0); + LLVMTypeRef i32vec_type = bld->leveli_bld.vec_type; struct lp_build_if_state if_ctx; LLVMValueRef need_lerp; unsigned num_quads = bld->coord_bld.type.length / 4; @@ -1433,9 +1433,9 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, lod_fpart = LLVMBuildFPToSI(builder, lod_fpart, i32vec_type, "lod_fpart.fixed16"); /* need_lerp = lod_fpart > 0 */ - if (num_quads == 1) { + if (bld->num_lods == 1) { need_lerp = LLVMBuildICmp(builder, LLVMIntSGT, - lod_fpart, bld->perquadi_bld.zero, + lod_fpart, bld->leveli_bld.zero, "need_lerp"); } else { @@ -1450,9 +1450,9 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, * lod_fpart values have same sign. * We can however then skip the greater than comparison. */ - lod_fpart = lp_build_max(&bld->perquadi_bld, lod_fpart, - bld->perquadi_bld.zero); - need_lerp = lp_build_any_true_range(&bld->perquadi_bld, num_quads, lod_fpart); + lod_fpart = lp_build_max(&bld->leveli_bld, lod_fpart, + bld->leveli_bld.zero); + need_lerp = lp_build_any_true_range(&bld->leveli_bld, bld->num_lods, lod_fpart); } lp_build_if(&if_ctx, bld->gallivm, need_lerp); @@ -1465,9 +1465,6 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, lp_build_mipmap_level_sizes(bld, ilevel1, &size1, &row_stride1_vec, &img_stride1_vec); - lp_build_mipmap_level_sizes(bld, ilevel1, - &size1, - &row_stride1_vec, &img_stride1_vec); if (bld->num_lods == 1) { data_ptr1 = lp_build_get_mipmap_level(bld, ilevel1); } @@ -1511,7 +1508,7 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, /* interpolate samples from the two mipmap levels */ - if (num_quads == 1) { + if (num_quads == 1 && bld->num_lods == 1) { lod_fpart = LLVMBuildTrunc(builder, lod_fpart, u8n_bld.elem_type, ""); lod_fpart = lp_build_broadcast_scalar(&u8n_bld, lod_fpart); @@ -1526,17 +1523,16 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, #endif } else { - const unsigned num_chans_per_quad = 4 * 4; - LLVMTypeRef tmp_vec_type = LLVMVectorType(u8n_bld.elem_type, bld->perquadi_bld.type.length); + unsigned num_chans_per_lod = 4 * bld->coord_type.length / bld->num_lods; + LLVMTypeRef tmp_vec_type = LLVMVectorType(u8n_bld.elem_type, bld->leveli_bld.type.length); LLVMValueRef shuffle[LP_MAX_VECTOR_LENGTH]; /* Take the LSB of lod_fpart */ lod_fpart = LLVMBuildTrunc(builder, lod_fpart, tmp_vec_type, ""); /* Broadcast each lod weight into their respective channels */ - assert(u8n_bld.type.length == num_quads * num_chans_per_quad); for (i = 0; i < u8n_bld.type.length; ++i) { - shuffle[i] = lp_build_const_int32(bld->gallivm, i / num_chans_per_quad); + shuffle[i] = lp_build_const_int32(bld->gallivm, i / num_chans_per_lod); } lod_fpart = LLVMBuildShuffleVector(builder, lod_fpart, LLVMGetUndef(tmp_vec_type), LLVMConstVector(shuffle, u8n_bld.type.length), ""); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index e0a59d06795..53e3628f56e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -979,17 +979,17 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { struct lp_build_if_state if_ctx; LLVMValueRef need_lerp; - unsigned num_quads = bld->coord_bld.type.length / 4; /* need_lerp = lod_fpart > 0 */ - if (num_quads == 1) { + if (bld->num_lods == 1) { need_lerp = LLVMBuildFCmp(builder, LLVMRealUGT, - lod_fpart, bld->perquadf_bld.zero, + lod_fpart, bld->levelf_bld.zero, "need_lerp"); } else { /* - * We'll do mip filtering if any of the quads need it. + * We'll do mip filtering if any of the quads (or individual + * pixel in case of per-pixel lod) need it. * It might be better to split the vectors here and only fetch/filter * quads which need it. */ @@ -998,13 +998,13 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, * negative values which would screw up filtering if not all * lod_fpart values have same sign. */ - lod_fpart = lp_build_max(&bld->perquadf_bld, lod_fpart, - bld->perquadf_bld.zero); - need_lerp = lp_build_compare(bld->gallivm, bld->perquadf_bld.type, + lod_fpart = lp_build_max(&bld->levelf_bld, lod_fpart, + bld->levelf_bld.zero); + need_lerp = lp_build_compare(bld->gallivm, bld->levelf_bld.type, PIPE_FUNC_GREATER, - lod_fpart, bld->perquadf_bld.zero); - need_lerp = lp_build_any_true_range(&bld->perquadi_bld, num_quads, need_lerp); - } + lod_fpart, bld->levelf_bld.zero); + need_lerp = lp_build_any_true_range(&bld->leveli_bld, bld->num_lods, need_lerp); + } lp_build_if(&if_ctx, bld->gallivm, need_lerp); { @@ -1036,10 +1036,11 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld, /* interpolate samples from the two mipmap levels */ - lod_fpart = lp_build_unpack_broadcast_aos_scalars(bld->gallivm, - bld->perquadf_bld.type, - bld->texel_bld.type, - lod_fpart); + if (bld->num_lods != bld->coord_type.length) + lod_fpart = lp_build_unpack_broadcast_aos_scalars(bld->gallivm, + bld->levelf_bld.type, + bld->texel_bld.type, + lod_fpart); for (chan = 0; chan < 4; chan++) { colors0[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart, @@ -1143,7 +1144,7 @@ lp_build_sample_common(struct lp_build_sample_context *bld, mip_filter, lod_ipart, lod_fpart); } else { - *lod_ipart = bld->perquadi_bld.zero; + *lod_ipart = bld->leveli_bld.zero; } /* @@ -1166,7 +1167,7 @@ lp_build_sample_common(struct lp_build_sample_context *bld, else { first_level = bld->dynamic_state->first_level(bld->dynamic_state, bld->gallivm, texture_index); - first_level = lp_build_broadcast_scalar(&bld->perquadi_bld, first_level); + first_level = lp_build_broadcast_scalar(&bld->leveli_bld, first_level); *ilevel0 = first_level; } break; @@ -1295,7 +1296,7 @@ lp_build_fetch_texel(struct lp_build_sample_context *bld, const LLVMValueRef *offsets, LLVMValueRef *colors_out) { - struct lp_build_context *perquadi_bld = &bld->perquadi_bld; + struct lp_build_context *perquadi_bld = &bld->leveli_bld; struct lp_build_context *int_coord_bld = &bld->int_coord_bld; unsigned dims = bld->dims, chan; unsigned target = bld->static_texture_state->target; @@ -1307,8 +1308,13 @@ lp_build_fetch_texel(struct lp_build_sample_context *bld, /* XXX just like ordinary sampling, we don't handle per-pixel lod (yet). */ if (explicit_lod && bld->static_texture_state->target != PIPE_BUFFER) { - ilevel = lp_build_pack_aos_scalars(bld->gallivm, int_coord_bld->type, - perquadi_bld->type, explicit_lod, 0); + if (bld->num_lods != int_coord_bld->type.length) { + ilevel = lp_build_pack_aos_scalars(bld->gallivm, int_coord_bld->type, + perquadi_bld->type, explicit_lod, 0); + } + else { + ilevel = explicit_lod; + } lp_build_nearest_mip_level(bld, texture_unit, ilevel, &ilevel); } else { @@ -1489,6 +1495,7 @@ lp_build_sample_soa(struct gallivm_state *gallivm, const struct lp_derivatives *derivs, /* optional */ LLVMValueRef lod_bias, /* optional */ LLVMValueRef explicit_lod, /* optional */ + boolean scalar_lod, LLVMValueRef texel_out[4]) { unsigned dims = texture_dims(static_texture_state->target); @@ -1529,10 +1536,6 @@ lp_build_sample_soa(struct gallivm_state *gallivm, bld.float_size_in_type.length = dims > 1 ? 4 : 1; bld.int_size_in_type = lp_int_type(bld.float_size_in_type); bld.texel_type = type; - bld.perquadf_type = type; - /* we want native vector size to be able to use our intrinsics */ - bld.perquadf_type.length = type.length > 4 ? ((type.length + 15) / 16) * 4 : 1; - bld.perquadi_type = lp_int_type(bld.perquadf_type); /* always using the first channel hopefully should be safe, * if not things WILL break in other places anyway. @@ -1564,20 +1567,49 @@ lp_build_sample_soa(struct gallivm_state *gallivm, } /* + * This is all a bit complicated different paths are chosen for performance + * reasons. + * Essentially, there can be 1 lod per element, 1 lod per quad or 1 lod for + * everything (the last two options are equivalent for 4-wide case). + * If there's per-quad lod but we split to 4-wide so we can use AoS, per-quad + * lod is calculated then the lod value extracted afterwards so making this + * case basically the same as far as lod handling is concerned for the + * further sample/filter code as the 1 lod for everything case. + * Different lod handling mostly shows up when building mipmap sizes + * (lp_build_mipmap_level_sizes() and friends) and also in filtering + * (getting the fractional part of the lod to the right texels). + */ + + /* * There are other situations where at least the multiple int lods could be * avoided like min and max lod being equal. */ - if ((is_fetch && explicit_lod && bld.static_texture_state->target != PIPE_BUFFER) || - (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) { + if (explicit_lod && !scalar_lod && + ((is_fetch && bld.static_texture_state->target != PIPE_BUFFER) || + (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE))) + bld.num_lods = type.length; + /* TODO: for true scalar_lod should only use 1 lod value */ + else if (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE) { bld.num_lods = num_quads; } else { bld.num_lods = 1; } + bld.levelf_type = type; + /* we want native vector size to be able to use our intrinsics */ + if (bld.num_lods != type.length) { + bld.levelf_type.length = type.length > 4 ? ((type.length + 15) / 16) * 4 : 1; + } + bld.leveli_type = lp_int_type(bld.levelf_type); bld.float_size_type = bld.float_size_in_type; - bld.float_size_type.length = bld.num_lods > 1 ? type.length : - bld.float_size_in_type.length; + /* Note: size vectors may not be native. They contain minified w/h/d/_ values, + * with per-element lod that is w0/h0/d0/_/w1/h1/d1_/... so up to 8x4f32 */ + if (bld.num_lods > 1) { + bld.float_size_type.length = bld.num_lods == type.length ? + bld.num_lods * bld.float_size_in_type.length : + type.length; + } bld.int_size_type = lp_int_type(bld.float_size_type); lp_build_context_init(&bld.float_bld, gallivm, bld.float_type); @@ -1590,8 +1622,8 @@ lp_build_sample_soa(struct gallivm_state *gallivm, lp_build_context_init(&bld.int_size_bld, gallivm, bld.int_size_type); lp_build_context_init(&bld.float_size_bld, gallivm, bld.float_size_type); lp_build_context_init(&bld.texel_bld, gallivm, bld.texel_type); - lp_build_context_init(&bld.perquadf_bld, gallivm, bld.perquadf_type); - lp_build_context_init(&bld.perquadi_bld, gallivm, bld.perquadi_type); + lp_build_context_init(&bld.levelf_bld, gallivm, bld.levelf_type); + lp_build_context_init(&bld.leveli_bld, gallivm, bld.leveli_type); /* Get the dynamic state */ tex_width = dynamic_state->width(dynamic_state, gallivm, texture_index); @@ -1735,14 +1767,31 @@ lp_build_sample_soa(struct gallivm_state *gallivm, bld4.int_size_in_type = lp_int_type(bld4.float_size_in_type); bld4.texel_type = bld.texel_type; bld4.texel_type.length = 4; - bld4.perquadf_type = type4; + bld4.levelf_type = type4; /* we want native vector size to be able to use our intrinsics */ - bld4.perquadf_type.length = 1; - bld4.perquadi_type = lp_int_type(bld4.perquadf_type); + bld4.levelf_type.length = 1; + bld4.leveli_type = lp_int_type(bld4.levelf_type); + + if (explicit_lod && !scalar_lod && + ((is_fetch && bld.static_texture_state->target != PIPE_BUFFER) || + (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE))) + bld4.num_lods = type4.length; + else + bld4.num_lods = 1; - bld4.num_lods = 1; - bld4.int_size_type = bld4.int_size_in_type; + bld4.levelf_type = type4; + /* we want native vector size to be able to use our intrinsics */ + if (bld4.num_lods != type4.length) { + bld4.levelf_type.length = 1; + } + bld4.leveli_type = lp_int_type(bld4.levelf_type); bld4.float_size_type = bld4.float_size_in_type; + if (bld4.num_lods > 1) { + bld4.float_size_type.length = bld4.num_lods == type4.length ? + bld4.num_lods * bld4.float_size_in_type.length : + type4.length; + } + bld4.int_size_type = lp_int_type(bld4.float_size_type); lp_build_context_init(&bld4.float_bld, gallivm, bld4.float_type); lp_build_context_init(&bld4.float_vec_bld, gallivm, type4); @@ -1754,15 +1803,15 @@ lp_build_sample_soa(struct gallivm_state *gallivm, lp_build_context_init(&bld4.int_size_bld, gallivm, bld4.int_size_type); lp_build_context_init(&bld4.float_size_bld, gallivm, bld4.float_size_type); lp_build_context_init(&bld4.texel_bld, gallivm, bld4.texel_type); - lp_build_context_init(&bld4.perquadf_bld, gallivm, bld4.perquadf_type); - lp_build_context_init(&bld4.perquadi_bld, gallivm, bld4.perquadi_type); + lp_build_context_init(&bld4.levelf_bld, gallivm, bld4.levelf_type); + lp_build_context_init(&bld4.leveli_bld, gallivm, bld4.leveli_type); for (i = 0; i < num_quads; i++) { LLVMValueRef s4, t4, r4; - LLVMValueRef lod_iparts, lod_fparts = NULL; - LLVMValueRef ilevel0s, ilevel1s = NULL; - LLVMValueRef indexi = lp_build_const_int32(gallivm, i); + LLVMValueRef lod_ipart4, lod_fpart4 = NULL; + LLVMValueRef ilevel04, ilevel14 = NULL; LLVMValueRef offsets4[4] = { NULL }; + unsigned num_lods = bld4.num_lods; s4 = lp_build_extract_range(gallivm, s, 4*i, 4); t4 = lp_build_extract_range(gallivm, t, 4*i, 4); @@ -1777,27 +1826,27 @@ lp_build_sample_soa(struct gallivm_state *gallivm, } } } - lod_iparts = LLVMBuildExtractElement(builder, lod_ipart, indexi, ""); - ilevel0s = LLVMBuildExtractElement(builder, ilevel0, indexi, ""); + lod_ipart4 = lp_build_extract_range(gallivm, lod_ipart, num_lods * i, num_lods); + ilevel04 = lp_build_extract_range(gallivm, ilevel0, num_lods * i, num_lods); if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { - ilevel1s = LLVMBuildExtractElement(builder, ilevel1, indexi, ""); - lod_fparts = LLVMBuildExtractElement(builder, lod_fpart, indexi, ""); + ilevel14 = lp_build_extract_range(gallivm, ilevel1, num_lods * i, num_lods); + lod_fpart4 = lp_build_extract_range(gallivm, lod_fpart, num_lods * i, num_lods); } if (use_aos) { /* do sampling/filtering with fixed pt arithmetic */ lp_build_sample_aos(&bld4, sampler_index, s4, t4, r4, offsets4, - lod_iparts, lod_fparts, - ilevel0s, ilevel1s, + lod_ipart4, lod_fpart4, + ilevel04, ilevel14, texelout4); } else { lp_build_sample_general(&bld4, sampler_index, s4, t4, r4, offsets4, - lod_iparts, lod_fparts, - ilevel0s, ilevel1s, + lod_ipart4, lod_fpart4, + ilevel04, ilevel14, texelout4); } for (j = 0; j < 4; j++) { @@ -1864,6 +1913,7 @@ lp_build_size_query_soa(struct gallivm_state *gallivm, lp_build_context_init(&bld_int_vec, gallivm, lp_type_int_vec(32, 128)); if (explicit_lod) { + /* FIXME: this needs to honor per-element lod */ lod = LLVMBuildExtractElement(gallivm->builder, explicit_lod, lp_build_const_int32(gallivm, 0), ""); first_level = dynamic_state->first_level(dynamic_state, gallivm, texture_unit); lod = lp_build_broadcast_scalar(&bld_int_vec, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h index fd566b1ff67..0b4845064a0 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h @@ -184,6 +184,7 @@ struct lp_build_sampler_soa const struct lp_derivatives *derivs, LLVMValueRef lod_bias, /* optional */ LLVMValueRef explicit_lod, /* optional */ + boolean scalar_lod, LLVMValueRef *texel); void diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index f6418591036..43724e77a13 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -1576,6 +1576,7 @@ emit_tex( struct lp_build_tgsi_soa_context *bld, LLVMValueRef offsets[3] = { NULL }; struct lp_derivatives derivs; struct lp_derivatives *deriv_ptr = NULL; + boolean scalar_lod; unsigned num_coords, num_derivs, num_offsets; unsigned i; @@ -1693,6 +1694,9 @@ emit_tex( struct lp_build_tgsi_soa_context *bld, } } + /* TODO: use scalar lod if explicit_lod, lod_bias or derivs are broadcasted scalars */ + scalar_lod = bld->bld_base.info->processor == TGSI_PROCESSOR_FRAGMENT; + bld->sampler->emit_fetch_texel(bld->sampler, bld->bld_base.base.gallivm, bld->bld_base.base.type, @@ -1701,7 +1705,7 @@ emit_tex( struct lp_build_tgsi_soa_context *bld, coords, offsets, deriv_ptr, - lod_bias, explicit_lod, + lod_bias, explicit_lod, scalar_lod, texel); } @@ -1719,6 +1723,7 @@ emit_sample(struct lp_build_tgsi_soa_context *bld, LLVMValueRef offsets[3] = { NULL }; struct lp_derivatives derivs; struct lp_derivatives *deriv_ptr = NULL; + boolean scalar_lod; unsigned num_coords, num_offsets, num_derivs; unsigned i; @@ -1836,6 +1841,9 @@ emit_sample(struct lp_build_tgsi_soa_context *bld, } } + /* TODO: use scalar lod if explicit_lod, lod_bias or derivs are broadcasted scalars */ + scalar_lod = bld->bld_base.info->processor == TGSI_PROCESSOR_FRAGMENT; + bld->sampler->emit_fetch_texel(bld->sampler, bld->bld_base.base.gallivm, bld->bld_base.base.type, @@ -1844,7 +1852,7 @@ emit_sample(struct lp_build_tgsi_soa_context *bld, coords, offsets, deriv_ptr, - lod_bias, explicit_lod, + lod_bias, explicit_lod, scalar_lod, texel); } @@ -1859,6 +1867,7 @@ emit_fetch_texels( struct lp_build_tgsi_soa_context *bld, LLVMValueRef explicit_lod = NULL; LLVMValueRef coords[3]; LLVMValueRef offsets[3] = { NULL }; + boolean scalar_lod; unsigned num_coords; unsigned dims; unsigned i; @@ -1927,6 +1936,9 @@ emit_fetch_texels( struct lp_build_tgsi_soa_context *bld, } } + /* TODO: use scalar lod if explicit_lod is broadcasted scalar */ + scalar_lod = bld->bld_base.info->processor == TGSI_PROCESSOR_FRAGMENT; + bld->sampler->emit_fetch_texel(bld->sampler, bld->bld_base.base.gallivm, bld->bld_base.base.type, @@ -1935,7 +1947,7 @@ emit_fetch_texels( struct lp_build_tgsi_soa_context *bld, coords, offsets, NULL, - NULL, explicit_lod, + NULL, explicit_lod, scalar_lod, texel); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c index 2a37b38d3c7..a4737822566 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.c +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c @@ -72,6 +72,7 @@ tgsi_scan_shader(const struct tgsi_token *tokens, procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY || procType == TGSI_PROCESSOR_COMPUTE); + info->processor = procType; /** diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h index 91eef67ca0b..b62c462356a 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_scan.h +++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h @@ -54,6 +54,8 @@ struct tgsi_shader_info ubyte num_system_values; ubyte system_value_semantic_name[PIPE_MAX_SHADER_INPUTS]; + ubyte processor; + uint file_mask[TGSI_FILE_COUNT]; /**< bitmask of declared registers */ uint file_count[TGSI_FILE_COUNT]; /**< number of declared registers */ int file_max[TGSI_FILE_COUNT]; /**< highest index of declared registers */ diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.c b/src/gallium/drivers/llvmpipe/lp_tex_sample.c index df2a610027c..2fb6f5b3c27 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.c @@ -244,6 +244,7 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, const struct lp_derivatives *derivs, LLVMValueRef lod_bias, /* optional */ LLVMValueRef explicit_lod, /* optional */ + boolean scalar_lod, LLVMValueRef *texel) { struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base; @@ -267,7 +268,7 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base, coords, offsets, derivs, - lod_bias, explicit_lod, + lod_bias, explicit_lod, scalar_lod, texel); } |