nir/glsl: set deref cast mode during function inlining

See code comment for details.

Issue: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11535
Fixes: c6c150b4cd ("glsl_to_nir: support conversion of opaque function params")

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30338>
This commit is contained in:
Timothy Arceri 2024-07-24 13:57:53 +10:00 committed by Marge Bot
parent aad503ecfa
commit d681cf96fb
2 changed files with 36 additions and 6 deletions

View file

@ -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;
}

View file

@ -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;