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