nir: Handle out of bounds access in nir_vectorize_tess_levels.
Replace out of bounds loads with undef.
Then, delete instructions with out of bounds access.
Fixes: f5adf27fb9 "nir,radv: add and use nir_vectorize_tess_levels()"
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6264
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Rhys Perry <pendingchaos02@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15775>
This commit is contained in:
@@ -613,7 +613,7 @@ nir_vectorize_tess_levels_impl(nir_function_impl *impl)
|
||||
nir_builder_init(&b, impl);
|
||||
|
||||
nir_foreach_block(block, impl) {
|
||||
nir_foreach_instr(instr, block) {
|
||||
nir_foreach_instr_safe(instr, block) {
|
||||
if (instr->type != nir_instr_type_intrinsic)
|
||||
continue;
|
||||
|
||||
@@ -633,7 +633,8 @@ nir_vectorize_tess_levels_impl(nir_function_impl *impl)
|
||||
|
||||
assert(deref->deref_type == nir_deref_type_array);
|
||||
assert(nir_src_is_const(deref->arr.index));
|
||||
unsigned index = nir_src_as_uint(deref->arr.index);;
|
||||
unsigned index = nir_src_as_uint(deref->arr.index);
|
||||
unsigned vec_size = glsl_get_vector_elements(var->type);
|
||||
|
||||
b.cursor = nir_before_instr(instr);
|
||||
nir_ssa_def *new_deref = &nir_build_deref_var(&b, var)->dest.ssa;
|
||||
@@ -641,7 +642,23 @@ nir_vectorize_tess_levels_impl(nir_function_impl *impl)
|
||||
|
||||
nir_deref_instr_remove_if_unused(deref);
|
||||
|
||||
intrin->num_components = glsl_get_vector_elements(var->type);
|
||||
intrin->num_components = vec_size;
|
||||
|
||||
/* Handle out of bounds access. */
|
||||
if (index >= vec_size) {
|
||||
if (intrin->intrinsic == nir_intrinsic_load_deref) {
|
||||
/* Return undef from out of bounds loads. */
|
||||
b.cursor = nir_after_instr(instr);
|
||||
nir_ssa_def *val = &intrin->dest.ssa;
|
||||
nir_ssa_def *u = nir_ssa_undef(&b, val->num_components, val->bit_size);
|
||||
nir_ssa_def_rewrite_uses(val, u);
|
||||
}
|
||||
|
||||
/* Finally, remove the out of bounds access. */
|
||||
nir_instr_remove(instr);
|
||||
progress = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (intrin->intrinsic == nir_intrinsic_store_deref) {
|
||||
nir_intrinsic_set_write_mask(intrin, 1 << index);
|
||||
|
||||
Reference in New Issue
Block a user