From d681cf96fbf962b67d98ecab1968ed0bb7a04eb0 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Wed, 24 Jul 2024 13:57:53 +1000 Subject: [PATCH] nir/glsl: set deref cast mode during function inlining MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See code comment for details. Issue: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11535 Fixes: c6c150b4cd87 ("glsl_to_nir: support conversion of opaque function params") Reviewed-by: Marek Olšák Part-of: --- src/compiler/glsl/glsl_to_nir.cpp | 7 +------ src/compiler/nir/nir_functions.c | 35 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 6c7395aad8f..7ad246990b8 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -2528,13 +2528,8 @@ nir_visitor::visit(ir_dereference_variable *ir) i++; } - nir_variable_mode mode = - glsl_contains_opaque(ir->variable_referenced()->type) && - ir->variable_referenced()->data.mode == ir_var_function_in ? - nir_var_uniform : nir_var_function_temp; - this->deref = nir_build_deref_cast(&b, nir_load_param(&b, i), - mode, ir->type, 0); + nir_var_function_temp, ir->type, 0); return; } diff --git a/src/compiler/nir/nir_functions.c b/src/compiler/nir/nir_functions.c index cb5af9592c0..9f3cc5eea68 100644 --- a/src/compiler/nir/nir_functions.c +++ b/src/compiler/nir/nir_functions.c @@ -53,6 +53,30 @@ function_ends_in_jump(nir_function_impl *impl) return nir_block_ends_in_jump(last_block); } +/* A cast is used to deref function in/out params. However the bindless + * textures spec allows both uniforms and functions temps to be passed to a + * function param defined the same way. To deal with this we need to update + * this when we inline and know what variable mode we are dealing with. + */ +static void +fixup_cast_deref_mode(nir_deref_instr *deref) +{ + nir_deref_instr *parent = nir_src_as_deref(deref->parent); + if (parent && parent->modes & nir_var_uniform && + deref->modes & nir_var_function_temp) { + deref->modes |= nir_var_uniform; + deref->modes ^= nir_var_function_temp; + + nir_foreach_use(use, &deref->def) { + if (nir_src_parent_instr(use)->type != nir_instr_type_deref) + continue; + + /* Recurse into children */ + fixup_cast_deref_mode(nir_instr_as_deref(nir_src_parent_instr(use))); + } + } +} + void nir_inline_function_impl(struct nir_builder *b, const nir_function_impl *impl, @@ -68,6 +92,17 @@ nir_inline_function_impl(struct nir_builder *b, switch (instr->type) { case nir_instr_type_deref: { nir_deref_instr *deref = nir_instr_as_deref(instr); + + /* Note: This shouldn't change the mode of anything but the + * replaced nir_intrinsic_load_param intrinsics handled later in + * this switch table. Any incorrect modes should have already been + * detected by previous nir_vaidate calls. + */ + if (deref->deref_type == nir_deref_type_cast) { + fixup_cast_deref_mode(deref); + break; + } + if (deref->deref_type != nir_deref_type_var) break;