summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2020-04-22 15:47:28 -0500
committerMarge Bot <[email protected]>2020-04-24 09:43:21 +0000
commita1a08a58025a6026aae0f73b67451198f5befb42 (patch)
tree6ce1fa364d7a5242d777b823fe16aee43a6ce064 /src/compiler
parentf4addfdde39070879ed8b1f08fe3bd85f2b0e392 (diff)
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: [email protected] Reviewed-by: Dave Airlie <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4684>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/nir/nir_deref.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index aa841223a3b..e06fd07aeb2 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -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;