summaryrefslogtreecommitdiff
path: root/src/compiler/nir/nir_lower_legacy_atomics.c
blob: 32bf7f19c05c0309d92ce0e5171d956913b66b96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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);
}