state->wrap_r = sampler->wrap_r;
state->min_img_filter = sampler->min_img_filter;
state->mag_img_filter = sampler->mag_img_filter;
+ state->min_mip_filter = sampler->min_mip_filter;
state->seamless_cube_map = sampler->seamless_cube_map;
if (sampler->max_lod > 0.0f) {
- state->min_mip_filter = sampler->min_mip_filter;
- } else {
- state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ state->max_lod_pos = 1;
+ }
+
+ if (sampler->lod_bias != 0.0f) {
+ state->lod_bias_non_zero = 1;
}
if (state->min_mip_filter != PIPE_TEX_MIPFILTER_NONE ||
state->min_img_filter != state->mag_img_filter) {
- if (sampler->lod_bias != 0.0f) {
- state->lod_bias_non_zero = 1;
- }
/* If min_lod == max_lod we can greatly simplify mipmap selection.
* This is a case that occurs during automatic mipmap generation.
unsigned length = coord_bld->type.length;
unsigned num_quads = length / 4;
boolean rho_per_quad = rho_bld->type.length != length;
- boolean no_rho_opt = (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) && (dims > 1);
+ boolean no_rho_opt = bld->no_rho_approx && (dims > 1);
unsigned i;
LLVMValueRef i32undef = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
LLVMValueRef rho_xvec, rho_yvec;
*/
void
lp_build_lod_selector(struct lp_build_sample_context *bld,
+ boolean is_lodq,
unsigned texture_unit,
unsigned sampler_unit,
LLVMValueRef s,
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
unsigned mip_filter,
+ LLVMValueRef *out_lod,
LLVMValueRef *out_lod_ipart,
LLVMValueRef *out_lod_fpart,
LLVMValueRef *out_lod_positive)
* I have no clue about the (undocumented) wishes of d3d9/d3d10 here!
*/
- if (bld->static_sampler_state->min_max_lod_equal) {
+ if (bld->static_sampler_state->min_max_lod_equal && !is_lodq) {
/* User is forcing sampling from a particular mipmap level.
* This is hit during mipmap generation.
*/
}
else {
LLVMValueRef rho;
- boolean rho_squared = ((gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) &&
+ boolean rho_squared = (bld->no_rho_approx &&
(bld->dims > 1)) || cube_rho;
rho = lp_build_rho(bld, texture_unit, s, t, r, cube_rho, derivs);
* Compute lod = log2(rho)
*/
- if (!lod_bias &&
+ if (!lod_bias && !is_lodq &&
!bld->static_sampler_state->lod_bias_non_zero &&
!bld->static_sampler_state->apply_max_lod &&
!bld->static_sampler_state->apply_min_lod) {
return;
}
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR &&
- !(gallivm_debug & GALLIVM_DEBUG_NO_BRILINEAR) &&
- !rho_squared) {
+ !bld->no_brilinear && !rho_squared) {
/*
* This can't work if rho is squared. Not sure if it could be
* fixed while keeping it worthwile, could also do sqrt here
lod = LLVMBuildFAdd(builder, lod, sampler_lod_bias, "sampler_lod_bias");
}
+ if (is_lodq) {
+ *out_lod = lod;
+ }
+
/* clamp lod */
if (bld->static_sampler_state->apply_max_lod) {
LLVMValueRef max_lod =
lod = lp_build_max(lodf_bld, lod, min_lod);
}
+
+ if (is_lodq) {
+ *out_lod_fpart = lod;
+ return;
+ }
}
*out_lod_positive = lp_build_cmp(lodf_bld, PIPE_FUNC_GREATER,
lod, lodf_bld->zero);
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
- if (!(gallivm_debug & GALLIVM_DEBUG_NO_BRILINEAR)) {
+ if (!bld->no_brilinear) {
lp_build_brilinear_lod(lodf_bld, lod, BRILINEAR_FACTOR,
out_lod_ipart, out_lod_fpart);
}
maxasat = lp_build_max(coord_bld, as, at);
ar_ge_as_at = lp_build_cmp(coord_bld, PIPE_FUNC_GEQUAL, ar, maxasat);
- if (need_derivs && (derivs_in ||
- ((gallivm_debug & GALLIVM_DEBUG_NO_QUAD_LOD) &&
- (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX)))) {
+ if (need_derivs && (derivs_in || (bld->no_quad_lod && bld->no_rho_approx))) {
/*
* XXX: This is really really complex.
* It is a bit overkill to use this for implicit derivatives as well,
*/
static void
lp_build_sample_common(struct lp_build_sample_context *bld,
+ boolean is_lodq,
unsigned texture_index,
unsigned sampler_index,
LLVMValueRef *coords,
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
LLVMValueRef *lod_pos_or_zero,
+ LLVMValueRef *lod,
LLVMValueRef *lod_fpart,
LLVMValueRef *ilevel0,
LLVMValueRef *ilevel1)
* Compute the level of detail (float).
*/
if (min_filter != mag_filter ||
- mip_filter != PIPE_TEX_MIPFILTER_NONE) {
+ mip_filter != PIPE_TEX_MIPFILTER_NONE || is_lodq) {
/* Need to compute lod either to choose mipmap levels or to
* distinguish between minification/magnification with one mipmap level.
*/
- lp_build_lod_selector(bld, texture_index, sampler_index,
+ lp_build_lod_selector(bld, is_lodq, texture_index, sampler_index,
coords[0], coords[1], coords[2], cube_rho,
derivs, lod_bias, explicit_lod,
- mip_filter,
+ mip_filter, lod,
&lod_ipart, lod_fpart, lod_pos_or_zero);
+ if (is_lodq) {
+ LLVMValueRef last_level;
+ last_level = bld->dynamic_state->last_level(bld->dynamic_state,
+ bld->gallivm,
+ bld->context_ptr,
+ texture_index);
+ first_level = bld->dynamic_state->first_level(bld->dynamic_state,
+ bld->gallivm,
+ bld->context_ptr,
+ texture_index);
+ last_level = lp_build_sub(&bld->int_bld, last_level, first_level);
+ last_level = lp_build_int_to_float(&bld->float_bld, last_level);
+ last_level = lp_build_broadcast_scalar(&bld->lodf_bld, last_level);
+
+ switch (mip_filter) {
+ case PIPE_TEX_MIPFILTER_NONE:
+ *lod_fpart = bld->lodf_bld.zero;
+ break;
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ *lod_fpart = lp_build_round(&bld->lodf_bld, *lod_fpart);
+ /* fallthrough */
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ *lod_fpart = lp_build_clamp(&bld->lodf_bld, *lod_fpart,
+ bld->lodf_bld.zero, last_level);
+ break;
+ }
+ return;
+ }
+
} else {
lod_ipart = bld->lodi_bld.zero;
*lod_pos_or_zero = bld->lodi_bld.zero;
enum lp_sampler_op_type op_type;
LLVMValueRef lod_bias = NULL;
LLVMValueRef explicit_lod = NULL;
- boolean op_is_tex;
+ boolean op_is_tex, op_is_lodq, op_is_gather;
if (0) {
enum pipe_format fmt = static_texture_state->format;
LP_SAMPLER_OP_TYPE_SHIFT;
op_is_tex = op_type == LP_SAMPLER_OP_TEXTURE;
+ op_is_lodq = op_type == LP_SAMPLER_OP_LODQ;
+ op_is_gather = op_type == LP_SAMPLER_OP_GATHER;
if (lod_control == LP_SAMPLER_LOD_BIAS) {
lod_bias = lod;
bld.format_desc = util_format_description(static_texture_state->format);
bld.dims = dims;
+ if (gallivm_debug & GALLIVM_DEBUG_NO_QUAD_LOD || op_is_lodq) {
+ bld.no_quad_lod = TRUE;
+ }
+ if (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX || op_is_lodq) {
+ bld.no_rho_approx = TRUE;
+ }
+ if (gallivm_debug & GALLIVM_DEBUG_NO_BRILINEAR || op_is_lodq) {
+ bld.no_brilinear = TRUE;
+ }
+
bld.vector_width = lp_type_width(type);
bld.float_type = lp_type_float(32);
bld.texel_type = lp_type_int_vec(type.width, type.width * type.length);
}
- if (!static_texture_state->level_zero_only) {
+ if (!static_texture_state->level_zero_only ||
+ !static_sampler_state->max_lod_pos || op_is_lodq) {
derived_sampler_state.min_mip_filter = static_sampler_state->min_mip_filter;
} else {
derived_sampler_state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
}
- if (op_type == LP_SAMPLER_OP_GATHER) {
+ if (op_is_gather) {
/*
* gather4 is exactly like GL_LINEAR filtering but in the end skipping
* the actual filtering. Using mostly the same paths, so cube face
*/
bld.num_mips = bld.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_ARRAY) &&
- (op_is_tex && mip_filter != PIPE_TEX_MIPFILTER_NONE)) {
+ if (bld.no_quad_lod && bld.no_rho_approx &&
+ ((mip_filter != PIPE_TEX_MIPFILTER_NONE && op_is_tex &&
+ (static_texture_state->target == PIPE_TEXTURE_CUBE ||
+ static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY)) ||
+ op_is_lodq)) {
/*
* special case for using per-pixel lod even for implicit lod,
* which is generally never required (ok by APIs) except to please
* can cause derivatives to be different for pixels outside the primitive
* due to the major axis division even if pre-project derivatives are
* looking normal).
+ * For lodq, we do it to simply avoid scalar pack / unpack (albeit for
+ * cube maps we do indeed get per-pixel lod values).
*/
bld.num_mips = type.length;
bld.num_lods = type.length;
newcoords[i] = coords[i];
}
+ if (util_format_is_pure_integer(static_texture_state->format) &&
+ !util_format_has_depth(bld.format_desc) && op_is_tex &&
+ (static_sampler_state->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR ||
+ static_sampler_state->min_img_filter == PIPE_TEX_FILTER_LINEAR ||
+ static_sampler_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR)) {
+ /*
+ * Bail if impossible filtering is specified (the awkard additional
+ * depth check is because it is legal in gallium to have things like S8Z24
+ * here which would say it's pure int despite such formats should sample
+ * the depth component).
+ * In GL such filters make the texture incomplete, this makes it robust
+ * against state trackers which set this up regardless (we'd crash in the
+ * lerp later otherwise).
+ * At least in some apis it may be legal to use such filters with lod
+ * queries and/or gather (at least for gather d3d10 says only the wrap
+ * bits are really used hence filter bits are likely simply ignored).
+ * For fetch, we don't get valid samplers either way here.
+ */
+ unsigned chan;
+ LLVMValueRef zero = lp_build_zero(gallivm, type);
+ for (chan = 0; chan < 4; chan++) {
+ texel_out[chan] = zero;
+ }
+ return;
+ }
+
if (0) {
/* For debug: no-op texture sampling */
lp_build_sample_nop(gallivm,
else {
LLVMValueRef lod_fpart = NULL, lod_positive = NULL;
- LLVMValueRef ilevel0 = NULL, ilevel1 = NULL;
+ LLVMValueRef ilevel0 = NULL, ilevel1 = NULL, lod = NULL;
boolean use_aos;
- if (util_format_is_pure_integer(static_texture_state->format) &&
- !util_format_has_depth(bld.format_desc) &&
- (static_sampler_state->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR ||
- static_sampler_state->min_img_filter == PIPE_TEX_FILTER_LINEAR ||
- static_sampler_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR)) {
- /*
- * Bail if impossible filtering is specified (the awkard additional
- * depth check is because it is legal in gallium to have things like S8Z24
- * here which would say it's pure int despite such formats should sample
- * the depth component).
- * In GL such filters make the texture incomplete, this makes it robust
- * against state trackers which set this up regardless (we'd crash in the
- * lerp later (except for gather)).
- * Must do this after fetch_texel code since with GL state tracker we'll
- * get some junk sampler for buffer textures.
- */
- unsigned chan;
- LLVMValueRef zero = lp_build_zero(gallivm, type);
- for (chan = 0; chan < 4; chan++) {
- texel_out[chan] = zero;
- }
- return;
- }
-
use_aos = util_format_fits_8unorm(bld.format_desc) &&
op_is_tex &&
/* not sure this is strictly needed or simply impossible */
derived_sampler_state.wrap_r);
}
- lp_build_sample_common(&bld, texture_index, sampler_index,
+ lp_build_sample_common(&bld, op_is_lodq, texture_index, sampler_index,
newcoords,
derivs, lod_bias, explicit_lod,
- &lod_positive, &lod_fpart,
+ &lod_positive, &lod, &lod_fpart,
&ilevel0, &ilevel1);
+ if (op_is_lodq) {
+ texel_out[0] = lod_fpart;
+ texel_out[1] = lod;
+ texel_out[2] = texel_out[3] = bld.coord_bld.zero;
+ return;
+ }
+
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.
/* Setup our build context */
memset(&bld4, 0, sizeof bld4);
+ bld4.no_quad_lod = bld.no_quad_lod;
+ bld4.no_rho_approx = bld.no_rho_approx;
+ bld4.no_brilinear = bld.no_brilinear;
bld4.gallivm = bld.gallivm;
bld4.context_ptr = bld.context_ptr;
bld4.static_texture_state = bld.static_texture_state;
bld4.texel_type.length = 4;
bld4.num_mips = bld4.num_lods = 1;
- if ((gallivm_debug & GALLIVM_DEBUG_NO_QUAD_LOD) &&
- (gallivm_debug & GALLIVM_DEBUG_NO_RHO_APPROX) &&
+ if (bld4.no_quad_lod && bld4.no_rho_approx &&
(static_texture_state->target == PIPE_TEXTURE_CUBE ||
static_texture_state->target == PIPE_TEXTURE_CUBE_ARRAY) &&
(op_is_tex && mip_filter != PIPE_TEX_MIPFILTER_NONE)) {