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 <jnoorman@igalia.com>
Reviewed-by: Emma Anholt <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41477>
This commit is contained in:
Job Noorman 2026-06-10 08:16:12 +02:00 committed by Marge Bot
parent 7b2dfdf15d
commit 2fee7ac87f
2 changed files with 33 additions and 0 deletions

View file

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

View file

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