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

Author: Faith Ekstrand <[email protected]>
Date:   Tue Feb 21 07:37:28 2023 -0600

nir/lower_io: Handle buffer_array_length for more address modes

Reviewed-by: Caio Oliveira <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21446>

---

 src/compiler/nir/nir.h          |  8 ++++----
 src/compiler/nir/nir_lower_io.c | 30 ++++++++++++++++++++++++------
 2 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 12ff307db18..8181f472a1a 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -4814,10 +4814,10 @@ typedef enum {
     * An address format which is a 64-bit global base address and a 32-bit
     * offset.
     *
-    * The address is comprised as a 32-bit vec4 where .xy are a uint64_t base
-    * address stored with the low bits in .x and high bits in .y, .z is
-    * undefined, and .w is an offset.  This is intended to match
-    * 64bit_bounded_global but without the bounds checking.
+    * This is identical to 64bit_bounded_global except that bounds checking
+    * is not applied when lowering to global access.  Even though the size is
+    * never used for an actual bounds check, it needs to be valid so we can
+    * lower deref_buffer_array_length properly.
     */
    nir_address_format_64bit_global_32bit_offset,
 
diff --git a/src/compiler/nir/nir_lower_io.c b/src/compiler/nir/nir_lower_io.c
index bfedfc48a66..a65242e1e9c 100644
--- a/src/compiler/nir/nir_lower_io.c
+++ b/src/compiler/nir/nir_lower_io.c
@@ -2175,13 +2175,31 @@ lower_explicit_io_array_length(nir_builder *b, 
nir_intrinsic_instr *intrin,
    assert(stride > 0);
 
    nir_ssa_def *addr = &deref->dest.ssa;
-   nir_ssa_def *index = addr_to_index(b, addr, addr_format);
-   nir_ssa_def *offset = addr_to_offset(b, addr, addr_format);
-   unsigned access = nir_intrinsic_access(intrin);
 
-   nir_ssa_def *arr_size = nir_get_ssbo_size(b, index, .access=access);
-   arr_size = nir_usub_sat(b, arr_size, offset);
-   arr_size = nir_udiv_imm(b, arr_size, stride);
+   nir_ssa_def *offset, *size;
+   switch (addr_format) {
+   case nir_address_format_64bit_global_32bit_offset:
+   case nir_address_format_64bit_bounded_global:
+      offset = nir_channel(b, addr, 3);
+      size = nir_channel(b, addr, 2);
+      break;
+
+   case nir_address_format_32bit_index_offset:
+   case nir_address_format_32bit_index_offset_pack64:
+   case nir_address_format_vec2_index_32bit_offset: {
+      offset = addr_to_offset(b, addr, addr_format);
+      nir_ssa_def *index = addr_to_index(b, addr, addr_format);
+      unsigned access = nir_intrinsic_access(intrin);
+      size = nir_get_ssbo_size(b, index, .access=access);
+      break;
+   }
+
+   default:
+      unreachable("Cannot determine SSBO size");
+   }
+
+   nir_ssa_def *remaining = nir_usub_sat(b, size, offset);
+   nir_ssa_def *arr_size = nir_udiv_imm(b, remaining, stride);
 
    nir_ssa_def_rewrite_uses(&intrin->dest.ssa, arr_size);
    nir_instr_remove(&intrin->instr);

Reply via email to