From 2fee7ac87f6a83712513d8cb0ec82c05c820113b Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Wed, 10 Jun 2026 08:16:12 +0200 Subject: [PATCH] nir/lower_ssbo: add option to insert bounds checks This is mostly useful in combination with `min_ssbo_size` when the native SSBO access instructions do the bounds check in HW so we don't want to add bounds checks for all SSBO accesses. Signed-off-by: Job Noorman Reviewed-by: Emma Anholt Part-of: --- src/compiler/nir/nir.h | 7 +++++++ src/compiler/nir/nir_lower_ssbo.c | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 8a894878bbc..d53c2f81703 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -6720,6 +6720,13 @@ typedef struct nir_lower_ssbo_options { * larger buffers. */ uint32_t min_ssbo_size; + + /* Add manual bounds checks for the generated global memory accesses. This + * is mostly useful in combination with `min_ssbo_size` when the native + * SSBO access instructions do the bounds check in HW so we don't want to + * add bounds checks for all SSBO accesses. + */ + bool bounds_check; } nir_lower_ssbo_options; bool nir_lower_ssbo(nir_shader *shader, const nir_lower_ssbo_options *opts); diff --git a/src/compiler/nir/nir_lower_ssbo.c b/src/compiler/nir/nir_lower_ssbo.c index 10378faf7e0..cf786af9afa 100644 --- a/src/compiler/nir/nir_lower_ssbo.c +++ b/src/compiler/nir/nir_lower_ssbo.c @@ -54,6 +54,7 @@ pass(nir_builder *b, nir_intrinsic_instr *intr, void *data) const nir_lower_ssbo_options *opts = data; uint32_t min_ssbo_size = opts ? opts->min_ssbo_size : 0; + bool bounds_check = opts && opts->bounds_check; b->cursor = nir_before_instr(&intr->instr); @@ -63,6 +64,18 @@ pass(nir_builder *b, nir_intrinsic_instr *intr, void *data) nir_push_if(b, nir_uge_imm(b, ssbo_size, min_ssbo_size)); } + if (bounds_check) { + nir_def *ssbo_size = + nir_get_ssbo_size(b, 32, nir_get_io_index_src(intr)->ssa); + nir_def *offset = get_offset(b, intr); + nir_def *val = intr->intrinsic == nir_intrinsic_store_ssbo + ? nir_get_io_data_src(intr)->ssa + : &intr->def; + nir_def *max_offset = + nir_iadd_imm(b, offset, val->bit_size * val->num_components / 8 - 1); + nir_push_if(b, nir_ult(b, max_offset, ssbo_size)); + } + nir_def *def = NULL; switch (intr->intrinsic) { case nir_intrinsic_load_ssbo: @@ -102,6 +115,19 @@ pass(nir_builder *b, nir_intrinsic_instr *intr, void *data) return false; } + if (bounds_check) { + nir_push_else(b, NULL); + nir_def *zero; + + if (def) + zero = nir_imm_zero(b, def->num_components, def->bit_size); + + nir_pop_if(b, NULL); + + if (def) + def = nir_if_phi(b, def, zero); + } + if (min_ssbo_size) { nir_push_else(b, NULL); nir_instr *ssbo_clone = nir_instr_clone(b->shader, &intr->instr);