ir3: Support min_lod tex source

Use the .clp modifier. In order to fix
dEQP-VK.glsl.texture_functions.textureoffsetclamp.* we need to add a
workaround for an empirically-discovered problem.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32671>
This commit is contained in:
Connor Abbott 2024-12-03 18:02:59 -05:00 committed by Marge Bot
parent 63959bb716
commit e72fed3faa
3 changed files with 57 additions and 5 deletions

View file

@ -3599,12 +3599,12 @@ static void
emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
{
struct ir3_builder *b = &ctx->build;
struct ir3_instruction **dst, *sam, *src0[12], *src1[4];
struct ir3_instruction **dst, *sam, *src0[12], *src1[5];
struct ir3_instruction *const *coord, *const *off, *const *ddx, *const *ddy;
struct ir3_instruction *lod, *compare, *proj, *sample_index;
struct ir3_instruction *lod, *compare, *proj, *sample_index, *min_lod;
struct tex_src_info info = {0};
bool has_bias = false, has_lod = false, has_proj = false, has_off = false;
bool lod_zero = false;
bool lod_zero = false, has_min_lod = false;
unsigned i, coords, flags, ncomp;
unsigned nsrc0 = 0, nsrc1 = 0;
type_t type;
@ -3613,7 +3613,7 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
ncomp = tex->def.num_components;
coord = off = ddx = ddy = NULL;
lod = proj = compare = sample_index = NULL;
lod = proj = compare = sample_index = min_lod = NULL;
dst = ir3_get_def(ctx, &tex->def, ncomp);
@ -3658,6 +3658,10 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
case nir_tex_src_ms_index:
sample_index = ir3_get_src(ctx, &tex->src[i].src)[0];
break;
case nir_tex_src_min_lod:
min_lod = ir3_get_src(ctx, &tex->src[i].src)[0];
has_min_lod = true;
break;
case nir_tex_src_texture_offset:
case nir_tex_src_sampler_offset:
case nir_tex_src_texture_handle:
@ -3831,7 +3835,7 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
* - lod
* - bias
*/
if (has_off | has_lod | has_bias) {
if (has_off | has_lod | has_bias | has_min_lod) {
if (has_off) {
unsigned off_coords = coords;
if (tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE)
@ -3845,6 +3849,11 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
if (has_lod | has_bias)
src1[nsrc1++] = lod;
if (has_min_lod) {
src1[nsrc1++] = min_lod;
flags |= IR3_INSTR_CLP;
}
}
type = get_tex_dest_type(tex);

View file

@ -13,6 +13,8 @@
#include "ir3_nir.h"
#include "ir3_shader.h"
#include "nir_builtin_builder.h"
/* For use by binning_pass shaders, where const_state is const, but expected
* to be already set up when we compiled the corresponding non-binning variant
*/
@ -626,6 +628,44 @@ ir3_nir_lower_sparse_residency(nir_shader *shader)
nir_metadata_control_flow, NULL);
}
/* The hardware implementiation of min LOD clamp is broken when the given LOD
* clamp value (min_lod) is greater than levelCount - 1 (that is, when it would
* be clamped by the hardware to avoid accessing an out-of-bounds level).
* Instead of clamping the clamped LOD afterwards, it just returns zero. Because
* the LOD would always be clamped to levelCount - 1 in this case, we can just
* clamp min_lod to levelCount - 1 and get the same result while avoiding the
* hardware bug.
*/
static bool
ir3_nir_min_lod_workaround_cb(struct nir_builder *b, nir_tex_instr *tex, void *_data)
{
int src_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod);
if (src_idx < 0)
return false;
b->cursor = nir_before_instr(&tex->instr);
nir_def *level_count = nir_build_texture_query(b, tex,
nir_texop_query_levels, 1,
nir_type_uint32,
false, false);
nir_def *src = tex->src[src_idx].src.ssa;
src = nir_fmin(b, src, nir_i2fN(b, nir_iadd_imm(b, level_count, -1),
src->bit_size));
nir_src_rewrite(&tex->src[src_idx].src, src);
return true;
}
static bool
ir3_nir_min_lod_workaround(nir_shader *shader)
{
return nir_shader_tex_pass(
shader, ir3_nir_min_lod_workaround_cb,
nir_metadata_control_flow, NULL);
}
void
ir3_finalize_nir(struct ir3_compiler *compiler,
const struct ir3_shader_nir_options *options,
@ -666,6 +706,7 @@ ir3_finalize_nir(struct ir3_compiler *compiler,
OPT(s, nir_lower_load_const_to_scalar);
NIR_PASS(_, s, ir3_nir_lower_sparse_residency);
NIR_PASS(_, s, ir3_nir_min_lod_workaround);
if (compiler->array_index_add_half)
OPT(s, ir3_nir_lower_array_sampler);

View file

@ -194,6 +194,8 @@ print_instr_name(struct log_stream *stream, struct ir3_instruction *instr,
mesa_log_stream_printf(stream, ".u");
if (instr->flags & IR3_INSTR_RCK)
mesa_log_stream_printf(stream, ".rck");
if (instr->flags & IR3_INSTR_CLP)
mesa_log_stream_printf(stream, ".clp");
if (instr->opc == OPC_LDC)
mesa_log_stream_printf(stream, ".offset%d", instr->cat6.d);
if (instr->opc == OPC_LDC_K)