xref: /aosp_15_r20/external/mesa3d/src/freedreno/common/freedreno_common.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Google, Inc.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #ifndef FREEDRENO_COMMON_H_
7*61046927SAndroid Build Coastguard Worker #define FREEDRENO_COMMON_H_
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker #include <tuple>
14*61046927SAndroid Build Coastguard Worker 
15*61046927SAndroid Build Coastguard Worker #define __FD_GPU_GENS A6XX, A7XX
16*61046927SAndroid Build Coastguard Worker #define FD_GENX(FUNC_NAME)                                                   \
17*61046927SAndroid Build Coastguard Worker    template <chip... CHIPs> constexpr auto FUNC_NAME##instantiate()          \
18*61046927SAndroid Build Coastguard Worker    {                                                                         \
19*61046927SAndroid Build Coastguard Worker       return std::tuple_cat(std::make_tuple(FUNC_NAME<CHIPs>)...);           \
20*61046927SAndroid Build Coastguard Worker    }                                                                         \
21*61046927SAndroid Build Coastguard Worker    static constexpr auto FUNC_NAME##tmpl __attribute__((used)) =             \
22*61046927SAndroid Build Coastguard Worker       FUNC_NAME##instantiate<__FD_GPU_GENS>();
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #define FD_CALLX(info, thing)                                                \
25*61046927SAndroid Build Coastguard Worker    ({                                                                        \
26*61046927SAndroid Build Coastguard Worker       decltype(&thing<A6XX>) genX_thing;                                     \
27*61046927SAndroid Build Coastguard Worker       switch (info->chip) {                                                  \
28*61046927SAndroid Build Coastguard Worker       case 6:                                                                \
29*61046927SAndroid Build Coastguard Worker          genX_thing = &thing<A6XX>;                                          \
30*61046927SAndroid Build Coastguard Worker          break;                                                              \
31*61046927SAndroid Build Coastguard Worker       case 7:                                                                \
32*61046927SAndroid Build Coastguard Worker          genX_thing = &thing<A7XX>;                                          \
33*61046927SAndroid Build Coastguard Worker          break;                                                              \
34*61046927SAndroid Build Coastguard Worker       default:                                                               \
35*61046927SAndroid Build Coastguard Worker          unreachable("Unknown hardware generation");                         \
36*61046927SAndroid Build Coastguard Worker       }                                                                      \
37*61046927SAndroid Build Coastguard Worker       genX_thing;                                                            \
38*61046927SAndroid Build Coastguard Worker    })
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker template<typename E>
42*61046927SAndroid Build Coastguard Worker struct BitmaskEnum {
43*61046927SAndroid Build Coastguard Worker    E value;
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    using underlying = typename std::underlying_type_t<E>;
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker #define FOREACH_TYPE(M, ...) \
48*61046927SAndroid Build Coastguard Worker    M(E,          ##__VA_ARGS__) \
49*61046927SAndroid Build Coastguard Worker    M(bool,       ##__VA_ARGS__) \
50*61046927SAndroid Build Coastguard Worker    M(uint8_t,    ##__VA_ARGS__) \
51*61046927SAndroid Build Coastguard Worker    M(int8_t,     ##__VA_ARGS__) \
52*61046927SAndroid Build Coastguard Worker    M(uint16_t,   ##__VA_ARGS__) \
53*61046927SAndroid Build Coastguard Worker    M(int16_t,    ##__VA_ARGS__) \
54*61046927SAndroid Build Coastguard Worker    M(uint32_t,   ##__VA_ARGS__) \
55*61046927SAndroid Build Coastguard Worker    M(int32_t,    ##__VA_ARGS__)
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker #define CONSTRUCTOR(T) BitmaskEnum(T value) :  value(static_cast<E>(value)) {}
58*61046927SAndroid Build Coastguard Worker    FOREACH_TYPE(CONSTRUCTOR)
59*61046927SAndroid Build Coastguard Worker #undef CONSTRUCTOR
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker #define CAST(T) inline operator T() const { return static_cast<T>(value); }
62*61046927SAndroid Build Coastguard Worker    FOREACH_TYPE(CAST)
63*61046927SAndroid Build Coastguard Worker #undef CAST
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker #define BOP(T, OP)                          \
66*61046927SAndroid Build Coastguard Worker    inline E operator OP(T rhs) const {      \
67*61046927SAndroid Build Coastguard Worker       return static_cast<E> (               \
68*61046927SAndroid Build Coastguard Worker          static_cast<underlying>(value) OP  \
69*61046927SAndroid Build Coastguard Worker          static_cast<underlying>(rhs)       \
70*61046927SAndroid Build Coastguard Worker       );                                    \
71*61046927SAndroid Build Coastguard Worker    }
72*61046927SAndroid Build Coastguard Worker    FOREACH_TYPE(BOP, |)
73*61046927SAndroid Build Coastguard Worker    FOREACH_TYPE(BOP, &)
74*61046927SAndroid Build Coastguard Worker #undef BOP
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker #define BOP(OP)                                                    \
77*61046927SAndroid Build Coastguard Worker    inline BitmaskEnum<E> operator OP(BitmaskEnum<E> rhs) const {   \
78*61046927SAndroid Build Coastguard Worker       return static_cast<E> (                                      \
79*61046927SAndroid Build Coastguard Worker          static_cast<underlying>(value) OP                         \
80*61046927SAndroid Build Coastguard Worker          static_cast<underlying>(rhs.value)                        \
81*61046927SAndroid Build Coastguard Worker       );                                                           \
82*61046927SAndroid Build Coastguard Worker    }
83*61046927SAndroid Build Coastguard Worker    BOP(|)
84*61046927SAndroid Build Coastguard Worker    BOP(&)
85*61046927SAndroid Build Coastguard Worker #undef BOP
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker #if defined(__GNUC__) && !defined(__clang)
88*61046927SAndroid Build Coastguard Worker /*
89*61046927SAndroid Build Coastguard Worker  * Silence:
90*61046927SAndroid Build Coastguard Worker  *
91*61046927SAndroid Build Coastguard Worker  *   ../src/freedreno/common/freedreno_common.h: In instantiation of 'E& BitmaskEnum<E>::operator|=(BitmaskEnum<E>::underlying) [with E = fd_dirty_3d_state; BitmaskEnum<E>::underlying = unsigned int]':
92*61046927SAndroid Build Coastguard Worker  *   ../src/gallium/drivers/freedreno/freedreno_context.h:620:16:   required from here
93*61046927SAndroid Build Coastguard Worker  *   ../src/freedreno/common/freedreno_common.h:68:39: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
94*61046927SAndroid Build Coastguard Worker  *      68 |         reinterpret_cast<underlying&>(value) OP static_cast<underlying>(rhs) ); \
95*61046927SAndroid Build Coastguard Worker  *         |                                       ^~~~~
96*61046927SAndroid Build Coastguard Worker  *
97*61046927SAndroid Build Coastguard Worker  * I cannot reproduce on gcc 12.2.1 or with clang 14.0.5 so I'm going to assume
98*61046927SAndroid Build Coastguard Worker  * this is a bug with gcc 10.x
99*61046927SAndroid Build Coastguard Worker  */
100*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic push
101*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wstrict-aliasing"
102*61046927SAndroid Build Coastguard Worker #endif
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker #define UOP(T, OP)                          \
105*61046927SAndroid Build Coastguard Worker    inline E& operator OP(T rhs) {           \
106*61046927SAndroid Build Coastguard Worker       return reinterpret_cast<E&>(          \
107*61046927SAndroid Build Coastguard Worker         reinterpret_cast<underlying&>(value) OP static_cast<underlying>(rhs) ); \
108*61046927SAndroid Build Coastguard Worker    }
109*61046927SAndroid Build Coastguard Worker    UOP(underlying, |=)
110*61046927SAndroid Build Coastguard Worker    UOP(underlying, &=)
111*61046927SAndroid Build Coastguard Worker #undef UOP
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker #if defined(__GNUC__) && !defined(__clang) && (__GNUC__ < 7)
114*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
115*61046927SAndroid Build Coastguard Worker #endif
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    inline E operator ~() const {
118*61046927SAndroid Build Coastguard Worker       static_assert(sizeof(E) == sizeof(BitmaskEnum<E>));
119*61046927SAndroid Build Coastguard Worker       return static_cast<E> (
120*61046927SAndroid Build Coastguard Worker             ~static_cast<underlying>(value)
121*61046927SAndroid Build Coastguard Worker       );
122*61046927SAndroid Build Coastguard Worker    }
123*61046927SAndroid Build Coastguard Worker #undef FOREACH_TYPE
124*61046927SAndroid Build Coastguard Worker };
125*61046927SAndroid Build Coastguard Worker #define BITMASK_ENUM(E) BitmaskEnum<E>
126*61046927SAndroid Build Coastguard Worker #else
127*61046927SAndroid Build Coastguard Worker #define BITMASK_ENUM(E) enum E
128*61046927SAndroid Build Coastguard Worker #endif
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
131*61046927SAndroid Build Coastguard Worker #  define EXTERNC extern "C"
132*61046927SAndroid Build Coastguard Worker #  define BEGINC EXTERNC {
133*61046927SAndroid Build Coastguard Worker #  define ENDC }
134*61046927SAndroid Build Coastguard Worker #else
135*61046927SAndroid Build Coastguard Worker #  define EXTERNC
136*61046927SAndroid Build Coastguard Worker #  define BEGINC
137*61046927SAndroid Build Coastguard Worker #  define ENDC
138*61046927SAndroid Build Coastguard Worker #endif
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker /*
141*61046927SAndroid Build Coastguard Worker  * SWAP - swap value of @a and @b
142*61046927SAndroid Build Coastguard Worker  */
143*61046927SAndroid Build Coastguard Worker #define SWAP(a, b)                                                             \
144*61046927SAndroid Build Coastguard Worker    do {                                                                        \
145*61046927SAndroid Build Coastguard Worker       __typeof(a) __tmp = (a);                                                 \
146*61046927SAndroid Build Coastguard Worker       (a) = (b);                                                               \
147*61046927SAndroid Build Coastguard Worker       (b) = __tmp;                                                             \
148*61046927SAndroid Build Coastguard Worker    } while (0)
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker /* for conditionally setting boolean flag(s): */
151*61046927SAndroid Build Coastguard Worker #define COND(bool, val) ((bool) ? (val) : 0)
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker #define BIT(bit) BITFIELD64_BIT(bit)
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker /**
156*61046927SAndroid Build Coastguard Worker  * Helper for allocating sequence #s where zero is a non-valid seqno
157*61046927SAndroid Build Coastguard Worker  */
158*61046927SAndroid Build Coastguard Worker typedef struct {
159*61046927SAndroid Build Coastguard Worker    uint32_t counter;
160*61046927SAndroid Build Coastguard Worker } seqno_t;
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker static inline uint32_t
seqno_next(seqno_t * seq)163*61046927SAndroid Build Coastguard Worker seqno_next(seqno_t *seq)
164*61046927SAndroid Build Coastguard Worker {
165*61046927SAndroid Build Coastguard Worker    uint32_t n;
166*61046927SAndroid Build Coastguard Worker    do {
167*61046927SAndroid Build Coastguard Worker       n = p_atomic_inc_return(&seq->counter);
168*61046927SAndroid Build Coastguard Worker    } while (n == 0);
169*61046927SAndroid Build Coastguard Worker    return n;
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker static inline uint16_t
seqno_next_u16(seqno_t * seq)173*61046927SAndroid Build Coastguard Worker seqno_next_u16(seqno_t *seq)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker    uint16_t n;
176*61046927SAndroid Build Coastguard Worker    do {
177*61046927SAndroid Build Coastguard Worker       n = p_atomic_inc_return(&seq->counter);
178*61046927SAndroid Build Coastguard Worker    } while (n == 0);
179*61046927SAndroid Build Coastguard Worker    return n;
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker #endif /* FREEDRENO_COMMON_H_ */
183