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)
{
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 };
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;