nir: add sampler LOD bias lowering

this is a cleaned up version of the lowering originally written for asahi, moved
to common code so it can be shared with an upcoming Vulkan implementation (not
honeykrisp).

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34507>
This commit is contained in:
Alyssa Rosenzweig 2025-04-14 13:03:31 -04:00 committed by Marge Bot
parent 9de7ea875d
commit 63eb27d166
2 changed files with 48 additions and 0 deletions

View file

@ -5580,6 +5580,12 @@ typedef struct nir_lower_tex_options {
*/
bool lower_lod_zero_width;
/**
* If true, emulates sampler descriptor LOD bias by adding the sampler
* LOD bias to every texture instruction's LOD.
*/
bool lower_sampler_lod_bias;
/* Turns nir_op_tex and other ops with an implicit derivative, in stages
* without implicit derivatives (like the vertex shader) to have an explicit
* LOD with a value of 0.

View file

@ -1471,6 +1471,41 @@ nir_lower_lod_zero_width(nir_builder *b, nir_tex_instr *tex)
nir_def_rewrite_uses_after(&tex->def, def, def->parent_instr);
}
static void
lower_sampler_lod_bias(nir_builder *b, nir_tex_instr *tex)
{
nir_def *bias = nir_build_texture_query(b, tex, nir_texop_lod_bias, 1,
nir_type_float16, false, false);
if (tex->op == nir_texop_txd) {
/* For txd, the computed level-of-detail is log2(rho) where rho should
* scale proportionally to all derivatives. Scale derivatives by
* exp2(bias) to get LOD = log2(exp2(bias) * rho) = bias + log2(rho).
*/
nir_def *ddx = nir_f2f32(b, nir_steal_tex_src(tex, nir_tex_src_ddx));
nir_def *ddy = nir_f2f32(b, nir_steal_tex_src(tex, nir_tex_src_ddy));
nir_def *scale = nir_fexp2(b, nir_f2f32(b, bias));
nir_tex_instr_add_src(tex, nir_tex_src_ddx, nir_fmul(b, ddx, scale));
nir_tex_instr_add_src(tex, nir_tex_src_ddy, nir_fmul(b, ddy, scale));
} else if (tex->op == nir_texop_tex) {
/* Unbiased textures need their opcode fixed up */
tex->op = nir_texop_txb;
nir_tex_instr_add_src(tex, nir_tex_src_bias, bias);
} else {
/* Otherwise, add to the appropriate source (if one exists) */
nir_tex_src_type src =
tex->op == nir_texop_txl ? nir_tex_src_lod : nir_tex_src_bias;
nir_def *orig = nir_steal_tex_src(tex, src);
if (orig) {
bias = nir_fadd(b, bias, nir_f2f16(b, orig));
}
nir_tex_instr_add_src(tex, src, bias);
}
}
static bool
lower_index_to_offset(nir_builder *b, nir_tex_instr *tex)
{
@ -1685,6 +1720,13 @@ nir_lower_tex_block(nir_block *block, nir_builder *b,
progress |= lower_tex_packing(b, tex, options);
}
/* Although tg4 takes a sampler, it ignores the LOD bias. */
if (options->lower_sampler_lod_bias &&
nir_tex_instr_need_sampler(tex) && tex->op != nir_texop_tg4) {
lower_sampler_lod_bias(b, tex);
progress = true;
}
if (tex->op == nir_texop_txd &&
(options->lower_txd ||
(options->lower_txd_clamp && has_min_lod) ||