Mesa (staging/20.0): nir/opt_deref: Remove certain sampler type casts

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Apr 27 18:08:04 UTC 2020


Module: Mesa
Branch: staging/20.0
Commit: f1ccead5b8b5b67b221ccabe27f8f627cb3822e8
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f1ccead5b8b5b67b221ccabe27f8f627cb3822e8

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Wed Apr 22 15:47:28 2020 -0500

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 at lists.freedesktop.org

Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4684>
(cherry picked from commit a1a08a58025a6026aae0f73b67451198f5befb42)

---

 .pick_status.json            |  2 +-
 src/compiler/nir/nir_deref.c | 77 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/.pick_status.json b/.pick_status.json
index b48abd117b2..450d3df5ef7 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -1210,7 +1210,7 @@
         "description": "nir/opt_deref: Remove certain sampler type casts",
         "nominated": true,
         "nomination_type": 0,
-        "resolution": 0,
+        "resolution": 1,
         "master_sha": null,
         "because_sha": null
     },
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;



More information about the mesa-commit mailing list