Module: Mesa
Branch: main
Commit: 54b105f75d39203b70607b5e494d25cc322a0461
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=54b105f75d39203b70607b5e494d25cc322a0461

Author: Chia-I Wu <[email protected]>
Date:   Sun May 16 21:29:49 2021 -0700

util/perfetto: add a simple C wrapper for track events

The C wrapper only uses public APIs from the C++ SDK.  For efficient
tracepoint skipping, it copies the states of categories (there is one
category in this commit) to a util_perfetto_category_states array.

Other options are to use percetto, or wait for an official C SDK.

Signed-off-by: Chia-I Wu <[email protected]>
Acked-by: Rob Clark <[email protected]>
Reviewed-by: Antonio Caggiano <[email protected]>
Reviewed-by: Yiwei Zhang <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18260>

---

 src/util/perf/u_perfetto.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++-
 src/util/perf/u_perfetto.h  | 54 +++++++++++++++++++++++++++-
 2 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/src/util/perf/u_perfetto.cc b/src/util/perf/u_perfetto.cc
index 5158c9442e9..10facb38645 100644
--- a/src/util/perf/u_perfetto.cc
+++ b/src/util/perf/u_perfetto.cc
@@ -21,11 +21,93 @@
  * SOFTWARE.
  */
 
+#include "u_perfetto.h"
+
 #include <perfetto.h>
 
 #include "c11/threads.h"
+#include "util/macros.h"
 
-#include "u_perfetto.h"
+/* perfetto requires string literals */
+#define UTIL_PERFETTO_CATEGORY_DEFAULT_STR "mesa.default"
+#define UTIL_PERFETTO_CATEGORY_SLOW_STR "mesa.slow"
+
+PERFETTO_DEFINE_CATEGORIES(
+   perfetto::Category(UTIL_PERFETTO_CATEGORY_DEFAULT_STR)
+      .SetDescription("Mesa default events"),
+   perfetto::Category(UTIL_PERFETTO_CATEGORY_SLOW_STR)
+      .SetDescription("Mesa slow events")
+      .SetTags("slow"));
+
+PERFETTO_TRACK_EVENT_STATIC_STORAGE();
+
+int util_perfetto_category_states[UTIL_PERFETTO_CATEGORY_COUNT];
+
+static void
+util_perfetto_update_category_states(void)
+{
+#define UPDATE_CATEGORY(cat)                                                 \
+   p_atomic_set(                                                             \
+      &util_perfetto_category_states[UTIL_PERFETTO_CATEGORY_##cat],          \
+      TRACE_EVENT_CATEGORY_ENABLED(UTIL_PERFETTO_CATEGORY_##cat##_STR))
+   UPDATE_CATEGORY(DEFAULT);
+   UPDATE_CATEGORY(SLOW);
+#undef UPDATE_CATEGORY
+}
+
+void
+util_perfetto_trace_begin(enum util_perfetto_category category,
+                          const char *name)
+{
+#define TRACE_BEGIN(cat, name)                                               \
+   TRACE_EVENT_BEGIN(                                                        \
+      UTIL_PERFETTO_CATEGORY_##cat##_STR, nullptr,                           \
+      [&](perfetto::EventContext ctx) { ctx.event()->set_name(name); })
+   switch (category) {
+   case UTIL_PERFETTO_CATEGORY_DEFAULT:
+      TRACE_BEGIN(DEFAULT, name);
+      break;
+   case UTIL_PERFETTO_CATEGORY_SLOW:
+      TRACE_BEGIN(SLOW, name);
+      break;
+   default:
+      unreachable("bad perfetto category");
+   }
+#undef TRACE_BEGIN
+}
+
+void
+util_perfetto_trace_end(enum util_perfetto_category category)
+{
+#define TRACE_END(cat) TRACE_EVENT_END(UTIL_PERFETTO_CATEGORY_##cat##_STR)
+   switch (category) {
+   case UTIL_PERFETTO_CATEGORY_DEFAULT:
+      TRACE_END(DEFAULT);
+      break;
+   case UTIL_PERFETTO_CATEGORY_SLOW:
+      TRACE_END(SLOW);
+      break;
+   default:
+      unreachable("bad perfetto category");
+   }
+#undef TRACE_END
+
+   util_perfetto_update_category_states();
+}
+
+class UtilPerfettoObserver : public perfetto::TrackEventSessionObserver {
+ public:
+   UtilPerfettoObserver() { perfetto::TrackEvent::AddSessionObserver(this); }
+
+   void OnStart(const perfetto::DataSourceBase::StartArgs &) override
+   {
+      util_perfetto_update_category_states();
+   }
+
+   /* XXX There is no PostStop callback.  We have to call
+    * util_perfetto_update_category_states occasionally to poll.
+    */
+};
 
 static void
 util_perfetto_fini(void)
@@ -40,6 +122,10 @@ util_perfetto_init_once(void)
    perfetto::TracingInitArgs args;
    args.backends = perfetto::kSystemBackend;
    perfetto::Tracing::Initialize(args);
+
+   static UtilPerfettoObserver observer;
+   perfetto::TrackEvent::Register();
+
    atexit(&util_perfetto_fini);
 }
 
diff --git a/src/util/perf/u_perfetto.h b/src/util/perf/u_perfetto.h
index a50f010b58f..fe8e88c3bd9 100644
--- a/src/util/perf/u_perfetto.h
+++ b/src/util/perf/u_perfetto.h
@@ -24,12 +24,64 @@
 #ifndef _UTIL_PERFETTO_H
 #define _UTIL_PERFETTO_H
 
+#include "util/u_atomic.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-void util_perfetto_init(void);
+enum util_perfetto_category {
+   UTIL_PERFETTO_CATEGORY_DEFAULT,
+   UTIL_PERFETTO_CATEGORY_SLOW,
+
+   UTIL_PERFETTO_CATEGORY_COUNT,
+};
+
+#ifdef HAVE_PERFETTO
+
+extern int util_perfetto_category_states[UTIL_PERFETTO_CATEGORY_COUNT];
+
+void
+util_perfetto_init(void);
+
+static inline bool
+util_perfetto_is_category_enabled(enum util_perfetto_category category)
+{
+   return p_atomic_read_relaxed(&util_perfetto_category_states[category]);
+}
+
+void
+util_perfetto_trace_begin(enum util_perfetto_category category,
+                          const char *name);
+
+void
+util_perfetto_trace_end(enum util_perfetto_category category);
+
+#else /* HAVE_PERFETTO */
+
+static inline void
+util_perfetto_init(void)
+{
+}
+
+static inline bool
+util_perfetto_is_category_enabled(enum util_perfetto_category category)
+{
+   return false;
+}
+
+static inline void
+util_perfetto_trace_begin(enum util_perfetto_category category,
+                          const char *name)
+{
+}
+
+static inline void
+util_perfetto_trace_end(enum util_perfetto_category category)
+{
+}
+
+#endif /* HAVE_PERFETTO */
 
 #ifdef __cplusplus
 }

Reply via email to