From 5c9950702880bf68dc87019e410de38739759262 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 8 May 2023 15:30:06 -0400 Subject: [PATCH] nir: Add pass to lower atomics to unified MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the future, we'd like to have all drivers only ingest unified atomics, and all frontends only produce unified atomics, and garbage collect the existing non-unified atomics. To get to that future, it's a lot nicer to convert drivers one-by-one. Add a pass to translate old-style atomics to new-style atomics so drivers can opt-in to the new form one-by-one. Once all drivers are converted, we can convert producers one-by-one. Finally, we can just drop the calls to the pass and garbage collect this pass and the old atomics. That's probably a while out, though, so this will be out bridge to get there. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Jesse Natalie Reviewed-by: Timur Kristóf Reviewed-by: Rob Clark Part-of: --- src/compiler/nir/meson.build | 1 + src/compiler/nir/nir.h | 1 + src/compiler/nir/nir_lower_legacy_atomics.c | 86 +++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/compiler/nir/nir_lower_legacy_atomics.c diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build index ce903da95bc..9c688e9117d 100644 --- a/src/compiler/nir/meson.build +++ b/src/compiler/nir/meson.build @@ -163,6 +163,7 @@ files_libnir = files( 'nir_lower_goto_ifs.c', 'nir_lower_gs_intrinsics.c', 'nir_lower_helper_writes.c', + 'nir_lower_legacy_atomics.c', 'nir_lower_load_const_to_scalar.c', 'nir_lower_locals_to_regs.c', 'nir_lower_idiv.c', diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 5a60b0a61c9..05efa36aec1 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5626,6 +5626,7 @@ typedef struct nir_lower_bitmap_options { void nir_lower_bitmap(nir_shader *shader, const nir_lower_bitmap_options *options); bool nir_lower_atomics_to_ssbo(nir_shader *shader, unsigned offset_align_state); +bool nir_lower_legacy_atomics(nir_shader *shader); typedef enum { nir_lower_int_source_mods = 1 << 0, diff --git a/src/compiler/nir/nir_lower_legacy_atomics.c b/src/compiler/nir/nir_lower_legacy_atomics.c new file mode 100644 index 00000000000..32bf7f19c05 --- /dev/null +++ b/src/compiler/nir/nir_lower_legacy_atomics.c @@ -0,0 +1,86 @@ +/* + * Copyright 2023 Valve Corporation + * Copyright 2023 Collabora, Ltd. + * SPDX-License-Identifier: MIT + */ + +#include "compiler/nir/nir_builder.h" + +static bool +get_atomic_op(const nir_intrinsic_instr *atomic, nir_intrinsic_op *out_intr, + nir_atomic_op *out_op) +{ +#define CASE(prefix, suffix, atom, op, swap) \ + case nir_intrinsic_##prefix##_atomic_##atom##suffix: \ + *out_op = nir_atomic_op_##op; \ + *out_intr = swap ? nir_intrinsic_##prefix##_atomic_swap##suffix : \ + nir_intrinsic_##prefix##_atomic##suffix; \ + return true; + +#define CASES_NO_IMAGE(atom, op, swap) \ + CASE(deref,, atom, op, swap) \ + CASE(ssbo,, atom, op, swap) \ + CASE(shared,, atom, op, swap) \ + CASE(task_payload,, atom, op, swap) \ + CASE(global,, atom, op, swap) \ + CASE(global, _2x32, atom, op, swap) \ + CASE(global, _amd, atom, op, swap) + +#define CASES_IMAGE(atom, op, swap) \ + CASE(image,, atom, op, swap) \ + CASE(image_deref,, atom, op, swap) \ + CASE(bindless_image,, atom, op, swap) + +#define CASES(atom, op, swap) \ + CASES_NO_IMAGE(atom, op, swap) \ + CASES_IMAGE(atom, op, swap) \ + + switch (atomic->intrinsic) { + CASES(add, iadd, false); + CASES(imin, imin, false); + CASES(umin, umin, false); + CASES(imax, imax, false); + CASES(umax, umax, false); + CASES(and, iand, false); + CASES(or, ior, false); + CASES(xor, ixor, false); + CASES(exchange, xchg, false); + CASES(fadd, fadd, false); + CASES(fmin, fmin, false); + CASES(fmax, fmax, false); + CASES(comp_swap, cmpxchg, true); + CASES_NO_IMAGE(fcomp_swap, fcmpxchg, true); + CASES_IMAGE(inc_wrap, inc_wrap, false); + CASES_IMAGE(dec_wrap, dec_wrap, false); + default: + return false; + } + +#undef CASE +#undef CASES_NO_IMAGE +#undef CASES +} + +static bool +pass(nir_builder *b, nir_instr *instr, UNUSED void *data) +{ + if (instr->type != nir_instr_type_intrinsic) + return false; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + nir_intrinsic_op intr_op; + nir_atomic_op op; + if (!get_atomic_op(intr, &intr_op, &op)) + return false; + + intr->intrinsic = intr_op; + nir_intrinsic_set_atomic_op(intr, op); + return false; +} + +bool +nir_lower_legacy_atomics(nir_shader *shader) +{ + return nir_shader_instructions_pass( + shader, pass, nir_metadata_block_index | nir_metadata_dominance, NULL); +}