diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index df76df56d20..8a894878bbc 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -6712,6 +6712,14 @@ bool nir_dedup_inline_samplers(nir_shader *shader); typedef struct nir_lower_ssbo_options { bool native_loads; bool native_offset; + + /* If non-zero, use @get_ssbo_size to only use global memory accesses for + * SSBOs larger than this. Keep the existing SSBO accesses for smaller + * SSBOs. This is useful for HW hat has native SSBO access instructions + * that only support a limited size to only fall back to global memory for + * larger buffers. + */ + uint32_t min_ssbo_size; } 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 95cedd5db9a..10378faf7e0 100644 --- a/src/compiler/nir/nir_lower_ssbo.c +++ b/src/compiler/nir/nir_lower_ssbo.c @@ -39,10 +39,30 @@ calc_address(nir_builder *b, nir_intrinsic_instr *intr, static bool pass(nir_builder *b, nir_intrinsic_instr *intr, void *data) { + /* Exit early for intrinsics that we don't lower to avoid emitting empty + * if/else blocks. + */ + switch (intr->intrinsic) { + case nir_intrinsic_load_ssbo: + case nir_intrinsic_store_ssbo: + case nir_intrinsic_ssbo_atomic: + case nir_intrinsic_ssbo_atomic_swap: + break; + default: + return false; + } + const nir_lower_ssbo_options *opts = data; + uint32_t min_ssbo_size = opts ? opts->min_ssbo_size : 0; b->cursor = nir_before_instr(&intr->instr); + if (min_ssbo_size) { + nir_def *ssbo_size = + nir_get_ssbo_size(b, 32, nir_get_io_index_src(intr)->ssa); + nir_push_if(b, nir_uge_imm(b, ssbo_size, min_ssbo_size)); + } + nir_def *def = NULL; switch (intr->intrinsic) { case nir_intrinsic_load_ssbo: @@ -82,6 +102,16 @@ pass(nir_builder *b, nir_intrinsic_instr *intr, void *data) return false; } + if (min_ssbo_size) { + nir_push_else(b, NULL); + nir_instr *ssbo_clone = nir_instr_clone(b->shader, &intr->instr); + nir_instr_insert(b->cursor, ssbo_clone); + nir_pop_if(b, NULL); + + if (def) + def = nir_if_phi(b, def, nir_instr_def(ssbo_clone)); + } + if (def) nir_def_rewrite_uses(&intr->def, def);