nir/opt_deref: Remove certain sampler type casts

The SPIR-V parser sometimes generates casts from specific sampler types
like sampler2D to the bare sampler type.  This results in a cast which
causes heartburn for drivers but is harmless to remove.

cc: mesa-stable@lists.freedesktop.org

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4684>
This commit is contained in:
Jason Ekstrand
2020-04-22 15:47:28 -05:00
committed by Marge Bot
parent f4addfdde3
commit a1a08a5802

View File

@@ -753,6 +753,42 @@ nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl)
return state.progress;
}
static void
nir_deref_instr_fixup_child_types(nir_deref_instr *parent)
{
nir_foreach_use(use, &parent->dest.ssa) {
if (use->parent_instr->type != nir_instr_type_deref)
continue;
nir_deref_instr *child = nir_instr_as_deref(use->parent_instr);
switch (child->deref_type) {
case nir_deref_type_var:
unreachable("nir_deref_type_var cannot be a child");
case nir_deref_type_array:
case nir_deref_type_array_wildcard:
child->type = glsl_get_array_element(parent->type);
break;
case nir_deref_type_ptr_as_array:
child->type = parent->type;
break;
case nir_deref_type_struct:
child->type = glsl_get_struct_field(parent->type,
child->strct.index);
break;
case nir_deref_type_cast:
/* We stop the recursion here */
continue;
}
/* Recurse into children */
nir_deref_instr_fixup_child_types(child);
}
}
static bool
is_trivial_array_deref_cast(nir_deref_instr *cast)
{
@@ -800,6 +836,44 @@ opt_remove_cast_cast(nir_deref_instr *cast)
return true;
}
static bool
opt_remove_sampler_cast(nir_deref_instr *cast)
{
assert(cast->deref_type == nir_deref_type_cast);
nir_deref_instr *parent = nir_src_as_deref(cast->parent);
if (parent == NULL)
return false;
/* Strip both types down to their non-array type and bail if there are any
* discrepancies in array lengths.
*/
const struct glsl_type *parent_type = parent->type;
const struct glsl_type *cast_type = cast->type;
while (glsl_type_is_array(parent_type) && glsl_type_is_array(cast_type)) {
if (glsl_get_length(parent_type) != glsl_get_length(cast_type))
return false;
parent_type = glsl_get_array_element(parent_type);
cast_type = glsl_get_array_element(cast_type);
}
if (glsl_type_is_array(parent_type) || glsl_type_is_array(cast_type))
return false;
if (!glsl_type_is_sampler(parent_type) ||
cast_type != glsl_bare_sampler_type())
return false;
/* We're a cast from a more detailed sampler type to a bare sampler */
nir_ssa_def_rewrite_uses(&cast->dest.ssa,
nir_src_for_ssa(&parent->dest.ssa));
nir_instr_remove(&cast->instr);
/* Recursively crawl the deref tree and clean up types */
nir_deref_instr_fixup_child_types(parent);
return true;
}
/**
* Is this casting a struct to a contained struct.
* struct a { struct b field0 };
@@ -839,6 +913,9 @@ opt_deref_cast(nir_builder *b, nir_deref_instr *cast)
if (opt_replace_struct_wrapper_cast(b, cast))
return true;
if (opt_remove_sampler_cast(cast))
return true;
progress = opt_remove_cast_cast(cast);
if (!is_trivial_deref_cast(cast))
return progress;