diff options
-rw-r--r-- | docs/features.txt | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample.c | 40 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample.h | 10 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c | 137 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c | 13 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_screen.c | 2 |
6 files changed, 145 insertions, 59 deletions
diff --git a/docs/features.txt b/docs/features.txt index fe412f6607a..c186dc70da3 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -131,7 +131,7 @@ GL 4.0, GLSL 4.00 --- all DONE: i965/gen7+, nvc0, r600, radeonsi GL_ARB_texture_buffer_object_rgb32 DONE (i965/gen6+, llvmpipe, softpipe, swr) GL_ARB_texture_cube_map_array DONE (i965/gen6+, nv50, llvmpipe, softpipe) GL_ARB_texture_gather DONE (i965/gen6+, nv50, llvmpipe, softpipe, swr) - GL_ARB_texture_query_lod DONE (i965, nv50, softpipe) + GL_ARB_texture_query_lod DONE (i965, nv50, llvmpipe, softpipe) GL_ARB_transform_feedback2 DONE (i965/gen6+, nv50, llvmpipe, softpipe, swr) GL_ARB_transform_feedback3 DONE (i965/gen7+, llvmpipe, softpipe, swr) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index a1dc61d40f6..db3d9d65c9c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -156,19 +156,19 @@ lp_sampler_static_sampler_state(struct lp_static_sampler_state *state, 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. @@ -234,7 +234,7 @@ lp_build_rho(struct lp_build_sample_context *bld, 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; @@ -694,6 +694,7 @@ lp_build_ilog2_sqrt(struct lp_build_context *bld, */ void lp_build_lod_selector(struct lp_build_sample_context *bld, + boolean is_lodq, unsigned texture_unit, unsigned sampler_unit, LLVMValueRef s, @@ -704,6 +705,7 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, 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) @@ -736,7 +738,7 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, * 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. */ @@ -756,7 +758,7 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, } 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); @@ -765,7 +767,7 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, * 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) { @@ -792,8 +794,7 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, 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 @@ -839,6 +840,10 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, 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 = @@ -856,13 +861,18 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, 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); } @@ -1679,9 +1689,7 @@ lp_build_cube_lookup(struct lp_build_sample_context *bld, 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, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index 9ec051a340b..c00997b8983 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -82,7 +82,8 @@ enum lp_sampler_lod_control { enum lp_sampler_op_type { LP_SAMPLER_OP_TEXTURE, LP_SAMPLER_OP_FETCH, - LP_SAMPLER_OP_GATHER + LP_SAMPLER_OP_GATHER, + LP_SAMPLER_OP_LODQ }; @@ -165,6 +166,7 @@ struct lp_static_sampler_state unsigned normalized_coords:1; unsigned min_max_lod_equal:1; /**< min_lod == max_lod ? */ unsigned lod_bias_non_zero:1; + unsigned max_lod_pos:1; unsigned apply_min_lod:1; /**< min_lod > 0 ? */ unsigned apply_max_lod:1; /**< max_lod < last_level ? */ unsigned seamless_cube_map:1; @@ -321,6 +323,10 @@ struct lp_build_sample_context /** number of lod values (valid are 1, length/4, length) */ unsigned num_lods; + boolean no_quad_lod; + boolean no_brilinear; + boolean no_rho_approx; + /** regular scalar float type */ struct lp_type float_type; struct lp_build_context float_bld; @@ -486,6 +492,7 @@ lp_sampler_static_texture_state(struct lp_static_texture_state *state, void lp_build_lod_selector(struct lp_build_sample_context *bld, + boolean is_lodq, unsigned texture_index, unsigned sampler_index, LLVMValueRef s, @@ -496,6 +503,7 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, 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); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 1539849b2d6..b67a089c47b 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -1829,6 +1829,7 @@ lp_build_layer_coord(struct lp_build_sample_context *bld, */ static void lp_build_sample_common(struct lp_build_sample_context *bld, + boolean is_lodq, unsigned texture_index, unsigned sampler_index, LLVMValueRef *coords, @@ -1836,6 +1837,7 @@ lp_build_sample_common(struct lp_build_sample_context *bld, LLVMValueRef lod_bias, /* optional */ LLVMValueRef explicit_lod, /* optional */ LLVMValueRef *lod_pos_or_zero, + LLVMValueRef *lod, LLVMValueRef *lod_fpart, LLVMValueRef *ilevel0, LLVMValueRef *ilevel1) @@ -1908,15 +1910,44 @@ lp_build_sample_common(struct lp_build_sample_context *bld, * 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; @@ -2522,7 +2553,7 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, 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; @@ -2537,6 +2568,8 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, 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; @@ -2582,6 +2615,16 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, 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); @@ -2611,12 +2654,13 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, 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 @@ -2677,11 +2721,11 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, */ 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 @@ -2689,6 +2733,8 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, * 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; @@ -2802,6 +2848,32 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, 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, @@ -2818,33 +2890,9 @@ lp_build_sample_soa_code(struct gallivm_state *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 */ @@ -2885,12 +2933,19 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, 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. @@ -2937,6 +2992,9 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, /* 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; @@ -2964,8 +3022,7 @@ lp_build_sample_soa_code(struct gallivm_state *gallivm, 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)) { diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index f16c579f38d..3e47372b5cf 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -3146,6 +3146,18 @@ tg4_emit( } static void +lodq_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base); + + emit_tex(bld, emit_data->inst, LP_BLD_TEX_MODIFIER_NONE, + emit_data->output, 1, LP_SAMPLER_OP_LODQ); +} + +static void txq_emit( const struct lp_build_tgsi_action * action, struct lp_build_tgsi_context * bld_base, @@ -3875,6 +3887,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm, bld.bld_base.op_actions[TGSI_OPCODE_TXB2].emit = txb2_emit; bld.bld_base.op_actions[TGSI_OPCODE_TXL2].emit = txl2_emit; bld.bld_base.op_actions[TGSI_OPCODE_TG4].emit = tg4_emit; + bld.bld_base.op_actions[TGSI_OPCODE_LODQ].emit = lodq_emit; /* DX10 sampling ops */ bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE].emit = sample_emit; bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_B].emit = sample_b_emit; diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 482eac3d6c4..53171162a54 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -252,7 +252,6 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: return 4; case PIPE_CAP_TEXTURE_GATHER_SM5: - case PIPE_CAP_TEXTURE_QUERY_LOD: case PIPE_CAP_SAMPLE_SHADING: case PIPE_CAP_TEXTURE_GATHER_OFFSETS: return 0; @@ -265,6 +264,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 1; case PIPE_CAP_FAKE_SW_MSAA: return 1; + case PIPE_CAP_TEXTURE_QUERY_LOD: case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: case PIPE_CAP_TGSI_ARRAY_COMPONENTS: case PIPE_CAP_DOUBLES: |