Mesa (main): nir/serialize: Pack deref modes better

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Oct 16 04:22:06 UTC 2021


Module: Mesa
Branch: main
Commit: d343aef94233d0064fada98ae93bec0a420a0baa
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d343aef94233d0064fada98ae93bec0a420a0baa

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Fri Oct 15 13:25:50 2021 -0500

nir/serialize: Pack deref modes better

With nir_var_image, we've now run out of bits in our packed blob for
deref instructions.  We could revert to an unpacked blob or we could be
a bit more clever about how we encode deref modes and pack them into 5
bits.

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13386>

---

 src/compiler/nir/nir.h           |  4 +++-
 src/compiler/nir/nir_serialize.c | 49 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 939b07e7eaa..e8bb7606665 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -136,7 +136,9 @@ typedef enum {
    nir_var_mem_ssbo        = (1 << 9),
    nir_var_mem_constant    = (1 << 10),
 
-   /* Generic modes intentionally come last. */
+   /* Generic modes intentionally come last. See encode_dref_modes() in
+    * nir_serialize.c for more details.
+    */
    nir_var_shader_temp     = (1 << 11),
    nir_var_function_temp   = (1 << 12),
    nir_var_mem_shared      = (1 << 13),
diff --git a/src/compiler/nir/nir_serialize.c b/src/compiler/nir/nir_serialize.c
index b6108ef9e7f..d13d18f78e6 100644
--- a/src/compiler/nir/nir_serialize.c
+++ b/src/compiler/nir/nir_serialize.c
@@ -627,7 +627,8 @@ union packed_instr {
       unsigned instr_type:4;
       unsigned deref_type:3;
       unsigned cast_type_same_as_last:1;
-      unsigned modes:15; /* deref_var redefines this */
+      unsigned modes:5; /* See (de|en)code_deref_modes() */
+      unsigned _pad:10;
       unsigned packed_src_ssa_16bit:1; /* deref_var redefines this */
       unsigned dest:8;
    } deref;
@@ -965,11 +966,51 @@ read_alu(read_ctx *ctx, union packed_instr header)
    return alu;
 }
 
+#define MODE_ENC_GENERIC_BIT (1 << 4)
+
+static nir_variable_mode
+decode_deref_modes(unsigned modes)
+{
+   if (modes & MODE_ENC_GENERIC_BIT) {
+      modes &= ~MODE_ENC_GENERIC_BIT;
+      return modes << (ffs(nir_var_mem_generic) - 1);
+   } else {
+      return 1 << modes;
+   }
+}
+
+static unsigned
+encode_deref_modes(nir_variable_mode modes)
+{
+   /* Mode sets on derefs generally come in two forms.  For certain OpenCL
+    * cases, we can have more than one of the generic modes set.  In this
+    * case, we need the full bitfield.  Fortunately, there are only 4 of
+    * these.  For all other modes, we can only have one mode at a time so we
+    * can compress them by only storing the bit position.  This, plus one bit
+    * to select encoding, lets us pack the entire bitfield in 5 bits.
+    */
+   STATIC_ASSERT((nir_var_all & ~nir_var_mem_generic) <
+                 (1 << MODE_ENC_GENERIC_BIT));
+
+   unsigned enc;
+   if (modes == 0 || (modes & nir_var_mem_generic)) {
+      assert(!(modes & ~nir_var_mem_generic));
+      enc = modes >> (ffs(nir_var_mem_generic) - 1);
+      assert(enc < MODE_ENC_GENERIC_BIT);
+      enc |= MODE_ENC_GENERIC_BIT;
+   } else {
+      assert(util_is_power_of_two_nonzero(modes));
+      enc = ffs(modes) - 1;
+      assert(enc < MODE_ENC_GENERIC_BIT);
+   }
+   assert(modes == decode_deref_modes(enc));
+   return enc;
+}
+
 static void
 write_deref(write_ctx *ctx, const nir_deref_instr *deref)
 {
    assert(deref->deref_type < 8);
-   assert(deref->modes < (1 << 15));
 
    union packed_instr header;
    header.u32 = 0;
@@ -978,7 +1019,7 @@ write_deref(write_ctx *ctx, const nir_deref_instr *deref)
    header.deref.deref_type = deref->deref_type;
 
    if (deref->deref_type == nir_deref_type_cast) {
-      header.deref.modes = deref->modes;
+      header.deref.modes = encode_deref_modes(deref->modes);
       header.deref.cast_type_same_as_last = deref->type == ctx->last_type;
    }
 
@@ -1114,7 +1155,7 @@ read_deref(read_ctx *ctx, union packed_instr header)
    if (deref_type == nir_deref_type_var) {
       deref->modes = deref->var->data.mode;
    } else if (deref->deref_type == nir_deref_type_cast) {
-      deref->modes = header.deref.modes;
+      deref->modes = decode_deref_modes(header.deref.modes);
    } else {
       assert(deref->parent.is_ssa);
       deref->modes = nir_instr_as_deref(deref->parent.ssa->parent_instr)->modes;



More information about the mesa-commit mailing list