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/macros.h"
13 
14 #if defined(HAVE_PERFETTO)
15 
16 /* note that util_perfetto_is_category_enabled always returns false util
17  * util_perfetto_init is called
18  */
19 #define _MESA_TRACE_BEGIN(category, name)                                    \
20    do {                                                                      \
21       if (unlikely(util_perfetto_is_category_enabled(category)))             \
22          util_perfetto_trace_begin(category, name);                          \
23    } while (0)
24 
25 #define _MESA_TRACE_END(category)                                            \
26    do {                                                                      \
27       if (unlikely(util_perfetto_is_category_enabled(category)))             \
28          util_perfetto_trace_end(category);                                  \
29    } while (0)
30 
31 /* NOTE: for now disable atrace for C++ to workaround a ndk bug with ordering
32  * between stdatomic.h and atomic.h.  See:
33  *
34  *   https://github.com/android/ndk/issues/1178
35  */
36 #elif defined(ANDROID) && !defined(__cplusplus)
37 
38 #include <cutils/trace.h>
39 
40 #define _MESA_TRACE_BEGIN(category, name)                                    \
41    atrace_begin(ATRACE_TAG_GRAPHICS, name)
42 #define _MESA_TRACE_END(category) atrace_end(ATRACE_TAG_GRAPHICS)
43 
44 #else
45 
46 #define _MESA_TRACE_BEGIN(category, name)
47 #define _MESA_TRACE_END(category)
48 
49 #endif /* HAVE_PERFETTO */
50 
51 #if defined(HAVE_GPUVIS)
52 
53 #define _MESA_GPUVIS_TRACE_BEGIN(name) util_gpuvis_begin(name)
54 #define _MESA_GPUVIS_TRACE_END() util_gpuvis_end()
55 
56 #else
57 
58 #define _MESA_GPUVIS_TRACE_BEGIN(name)
59 #define _MESA_GPUVIS_TRACE_END()
60 
61 #endif /* HAVE_GPUVIS */
62 
63 
64 #define _MESA_COMBINED_TRACE_BEGIN(category, name)                           \
65    do {                                                                      \
66       _MESA_TRACE_BEGIN(category, name);                                     \
67       _MESA_GPUVIS_TRACE_BEGIN(name);                                        \
68    } while (0)
69 
70 #define _MESA_COMBINED_TRACE_END(category)                                   \
71    do {                                                                      \
72       _MESA_GPUVIS_TRACE_END();                                              \
73       _MESA_TRACE_END(category);                                             \
74    } while (0)
75 
76 #if __has_attribute(cleanup) && __has_attribute(unused)
77 
78 #define _MESA_TRACE_SCOPE_VAR_CONCAT(name, suffix) name##suffix
79 #define _MESA_TRACE_SCOPE_VAR(suffix)                                        \
80    _MESA_TRACE_SCOPE_VAR_CONCAT(_mesa_trace_scope_, suffix)
81 
82 /* This must expand to a single non-scoped statement for
83  *
84  *    if (cond)
85  *       _MESA_TRACE_SCOPE(...)
86  *
87  * to work.
88  */
89 #define _MESA_TRACE_SCOPE(category, name)                                    \
90    int _MESA_TRACE_SCOPE_VAR(__LINE__)                                       \
91       __attribute__((cleanup(_mesa_trace_scope_end), unused)) =              \
92          _mesa_trace_scope_begin(category, name)
93 
94 static inline int
_mesa_trace_scope_begin(enum util_perfetto_category category,const char * name)95 _mesa_trace_scope_begin(enum util_perfetto_category category,
96                         const char *name)
97 {
98    _MESA_COMBINED_TRACE_BEGIN(category, name);
99    return category;
100 }
101 
102 static inline void
_mesa_trace_scope_end(int * scope)103 _mesa_trace_scope_end(int *scope)
104 {
105    /* we save the category in the scope variable */
106    _MESA_COMBINED_TRACE_END((enum util_perfetto_category) * scope);
107 }
108 
109 #else
110 
111 #define _MESA_TRACE_SCOPE(category, name)
112 
113 #endif /* __has_attribute(cleanup) && __has_attribute(unused) */
114 
115 /* These use the default category.  Drivers or subsystems can use these, or
116  * define their own categories/macros.
117  */
118 #define MESA_TRACE_BEGIN(name)                                               \
119    _MESA_COMBINED_TRACE_BEGIN(UTIL_PERFETTO_CATEGORY_DEFAULT, name)
120 #define MESA_TRACE_END()                                                     \
121   _MESA_COMBINED_TRACE_END(UTIL_PERFETTO_CATEGORY_DEFAULT)
122 #define MESA_TRACE_SCOPE(name)                                               \
123    _MESA_TRACE_SCOPE(UTIL_PERFETTO_CATEGORY_DEFAULT, name)
124 #define MESA_TRACE_FUNC()                                                    \
125    _MESA_TRACE_SCOPE(UTIL_PERFETTO_CATEGORY_DEFAULT, __func__)
126 
127 /* these use the slow category */
128 #define MESA_TRACE_BEGIN_SLOW(name)                                          \
129    _MESA_COMBINED_TRACE_BEGIN(UTIL_PERFETTO_CATEGORY_SLOW, name)
130 #define MESA_TRACE_END_SLOW()                                                \
131   _MESA_COMBINED_TRACE_END(UTIL_PERFETTO_CATEGORY_SLOW)
132 #define MESA_TRACE_SCOPE_SLOW(name)                                          \
133    _MESA_TRACE_SCOPE(UTIL_PERFETTO_CATEGORY_SLOW, name)
134 #define MESA_TRACE_FUNC_SLOW()                                               \
135    _MESA_TRACE_SCOPE(UTIL_PERFETTO_CATEGORY_SLOW, __func__)
136 
137 static inline void
util_cpu_trace_init()138 util_cpu_trace_init()
139 {
140    util_perfetto_init();
141    util_gpuvis_init();
142 }
143 
144 #endif /* CPU_TRACE_H */
145