1 /*
2 * Copyright 2022 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef CPU_TRACE_H
7 #define CPU_TRACE_H
8
9 #include "u_perfetto.h"
10 #include "u_gpuvis.h"
11
12 #include "util/detect_os.h"
13 #include "util/macros.h"
14
15 #if defined(HAVE_PERFETTO)
16
17 /* note that util_perfetto_is_tracing_enabled always returns false util
18 * util_perfetto_init is called
19 */
20 #define _MESA_TRACE_BEGIN(name) \
21 do { \
22 if (unlikely(util_perfetto_is_tracing_enabled())) \
23 util_perfetto_trace_begin(name); \
24 } while (0)
25
26 #define _MESA_TRACE_FLOW_BEGIN(name, id) \
27 do { \
28 if (unlikely(util_perfetto_is_tracing_enabled())) \
29 util_perfetto_trace_begin_flow(name, id); \
30 } while (0)
31
32 #define _MESA_TRACE_END() \
33 do { \
34 if (unlikely(util_perfetto_is_tracing_enabled())) \
35 util_perfetto_trace_end(); \
36 } while (0)
37
38 #define _MESA_TRACE_SET_COUNTER(name, value) \
39 do { \
40 if (unlikely(util_perfetto_is_tracing_enabled())) \
41 util_perfetto_counter_set(name, value); \
42 } while (0)
43
44 #define _MESA_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, timestamp) \
45 do { \
46 if (unlikely(util_perfetto_is_tracing_enabled())) \
47 util_perfetto_trace_full_begin(name, track_id, flow_id, timestamp); \
48 } while (0)
49
50 #define _MESA_TRACE_TIMESTAMP_END(name, track_id, timestamp) \
51 do { \
52 if (unlikely(util_perfetto_is_tracing_enabled())) \
53 util_perfetto_trace_full_end(name, track_id, timestamp); \
54 } while (0)
55
56 /* NOTE: for now disable atrace for C++ to workaround a ndk bug with ordering
57 * between stdatomic.h and atomic.h. See:
58 *
59 * https://github.com/android/ndk/issues/1178
60 */
61 #elif DETECT_OS_ANDROID && !defined(__cplusplus)
62
63 #include <cutils/trace.h>
64
65 #define _MESA_TRACE_BEGIN(name) \
66 atrace_begin(ATRACE_TAG_GRAPHICS, name)
67 #define _MESA_TRACE_END() atrace_end(ATRACE_TAG_GRAPHICS)
68 #define _MESA_TRACE_FLOW_BEGIN(name, id) \
69 atrace_begin(ATRACE_TAG_GRAPHICS, name)
70 #define _MESA_TRACE_SET_COUNTER(name, value)
71 #define _MESA_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, timestamp)
72 #define _MESA_TRACE_TIMESTAMP_END(name, track_id, timestamp)
73 #else
74
75 #define _MESA_TRACE_BEGIN(name)
76 #define _MESA_TRACE_END()
77 #define _MESA_TRACE_FLOW_BEGIN(name, id)
78 #define _MESA_TRACE_SET_COUNTER(name, value)
79 #define _MESA_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, timestamp)
80 #define _MESA_TRACE_TIMESTAMP_END(name, track_id, timestamp)
81
82 #endif /* HAVE_PERFETTO */
83
84 #if defined(HAVE_GPUVIS)
85
86 #define _MESA_GPUVIS_TRACE_BEGIN(name) util_gpuvis_begin(name)
87 #define _MESA_GPUVIS_TRACE_END() util_gpuvis_end()
88
89 #else
90
91 #define _MESA_GPUVIS_TRACE_BEGIN(name)
92 #define _MESA_GPUVIS_TRACE_END()
93
94 #endif /* HAVE_GPUVIS */
95
96 #if __has_attribute(cleanup) && __has_attribute(unused)
97
98 #define _MESA_TRACE_SCOPE_VAR_CONCAT(name, suffix) name##suffix
99 #define _MESA_TRACE_SCOPE_VAR(suffix) \
100 _MESA_TRACE_SCOPE_VAR_CONCAT(_mesa_trace_scope_, suffix)
101
102 /* This must expand to a single non-scoped statement for
103 *
104 * if (cond)
105 * _MESA_TRACE_SCOPE(...)
106 *
107 * to work.
108 */
109 #define _MESA_TRACE_SCOPE(name) \
110 int _MESA_TRACE_SCOPE_VAR(__LINE__) \
111 __attribute__((cleanup(_mesa_trace_scope_end), unused)) = \
112 _mesa_trace_scope_begin(name)
113
114 #define _MESA_TRACE_SCOPE_FLOW(name, id) \
115 int _MESA_TRACE_SCOPE_VAR(__LINE__) \
116 __attribute__((cleanup(_mesa_trace_scope_end), unused)) = \
117 _mesa_trace_scope_flow_begin(name, id)
118
119 static inline int
_mesa_trace_scope_begin(const char * name)120 _mesa_trace_scope_begin(const char *name)
121 {
122 _MESA_TRACE_BEGIN(name);
123 _MESA_GPUVIS_TRACE_BEGIN(name);
124 return 0;
125 }
126
127 static inline int
_mesa_trace_scope_flow_begin(const char * name,uint64_t * id)128 _mesa_trace_scope_flow_begin(const char *name, uint64_t *id)
129 {
130 if (*id == 0)
131 *id = util_perfetto_next_id();
132 _MESA_TRACE_FLOW_BEGIN(name, *id);
133 _MESA_GPUVIS_TRACE_BEGIN(name);
134 return 0;
135 }
136
137 static inline void
_mesa_trace_scope_end(UNUSED int * scope)138 _mesa_trace_scope_end(UNUSED int *scope)
139 {
140 _MESA_GPUVIS_TRACE_END();
141 _MESA_TRACE_END();
142 }
143
144 #else
145
146 #define _MESA_TRACE_SCOPE(name)
147
148 #endif /* __has_attribute(cleanup) && __has_attribute(unused) */
149
150 #define MESA_TRACE_SCOPE(name) _MESA_TRACE_SCOPE(name)
151 #define MESA_TRACE_SCOPE_FLOW(name, id) _MESA_TRACE_SCOPE_FLOW(name, id)
152 #define MESA_TRACE_FUNC() _MESA_TRACE_SCOPE(__func__)
153 #define MESA_TRACE_FUNC_FLOW(id) _MESA_TRACE_SCOPE_FLOW(__func__, id)
154 #define MESA_TRACE_SET_COUNTER(name, value) _MESA_TRACE_SET_COUNTER(name, value)
155 #define MESA_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, timestamp) \
156 _MESA_TRACE_TIMESTAMP_BEGIN(name, track_id, flow_id, timestamp)
157 #define MESA_TRACE_TIMESTAMP_END(name, track_id, timestamp) \
158 _MESA_TRACE_TIMESTAMP_END(name, track_id, timestamp)
159
160 static inline void
util_cpu_trace_init()161 util_cpu_trace_init()
162 {
163 util_perfetto_init();
164 util_gpuvis_init();
165 }
166
167 #endif /* CPU_TRACE_H */
168