glsl/nir: fix function cloning at link time

As per the code comment added in this commit the nir produced from
glsl to nir doesn't always keep function declarations before the
code that calls them e.g. calls from within other function
implementations. The change in this commit works around this problem by
first cloning all function declarations in a first pass, then cloning
the implementations in a second pass once we have filled the remap
table.

Fixes: cbfc225e2b ("glsl: switch to a full nir based linker")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12115

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Acked-by: Marek Olšák <marek.olsak@amd.com>
(cherry picked from commit 59b2549279)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32261>
This commit is contained in:
Timothy Arceri
2024-11-13 10:12:35 +11:00
committed by Dylan Baker
parent c11a931703
commit 439879abd3
2 changed files with 16 additions and 2 deletions

View File

@@ -294,7 +294,7 @@
"description": "glsl/nir: fix function cloning at link time",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "cbfc225e2bda2c8627a4580fa3a9b63bfb7133e0",
"notes": null

View File

@@ -465,13 +465,27 @@ gl_nir_link_function_calls(struct gl_shader_program *prog,
list_add(&func_sig->node, func_list);
_mesa_hash_table_insert(func_lookup, func->name, func_list);
}
}
/* Now that all functions are cloned we can clone any function
* implementations. We can't do this in the previous loop above because
* glsl to nir places function declarations next to implementations i.e.
* we have lost any predeclared function signatures so we won't always
* find them in the remap table until they have all been processed.
*/
nir_foreach_function(func, shader_list[i]->nir) {
if (func->impl) {
assert(!f->impl);
nir_function_impl *f_impl =
nir_function_impl_clone_remap_globals(linked_sh->Program->nir,
func->impl, remap_table);
struct hash_entry *e =
_mesa_hash_table_search(remap_table, func);
assert(e);
nir_function *f = (nir_function *) e->data;
assert(!f->impl);
nir_function_set_impl(f, f_impl);
}
}