From 9c364a346faacd4ed506e91fa51b395b5b1f555e Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Thu, 16 Mar 2023 13:21:44 -0700 Subject: [PATCH] perfetto: Deduplicate clock sync packet emit from renderstage sources. This is way more horrifying than I hoped -- I can't figure out a way to have the method be on TraceContext, so it's a static method of the datasource, but then you have to name the templated types over and over. You have to pass in a TraceContext because intel emits the clock sync packet within a Trace(), and perfetto just silently corrupts the trace if you Trace() in a Trace(). Reviewed-by: Rob Clark Reviewed-by: Lionel Landwerlin Part-of: --- src/freedreno/vulkan/tu_perfetto.cc | 33 ++++----------- .../drivers/freedreno/freedreno_perfetto.cc | 30 ++++---------- src/intel/ds/intel_driver_ds.cc | 20 +-------- src/util/perf/u_perfetto_renderpass.h | 41 +++++++++++++++++++ 4 files changed, 58 insertions(+), 66 deletions(-) diff --git a/src/freedreno/vulkan/tu_perfetto.cc b/src/freedreno/vulkan/tu_perfetto.cc index 53e5149bdce..7ff386402b2 100644 --- a/src/freedreno/vulkan/tu_perfetto.cc +++ b/src/freedreno/vulkan/tu_perfetto.cc @@ -340,32 +340,15 @@ sync_timestamp(struct tu_device *dev) return; } - gpu_max_timestamp = gpu_ts; - - TuRenderpassDataSource::Trace([=](TuRenderpassDataSource::TraceContext tctx) { - auto packet = tctx.NewTracePacket(); - - packet->set_timestamp(cpu_ts); - - auto event = packet->set_clock_snapshot(); - - { - auto clock = event->add_clocks(); - - clock->set_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME); - clock->set_timestamp(cpu_ts); - } - - { - auto clock = event->add_clocks(); - - clock->set_clock_id(gpu_clock_id); - clock->set_timestamp(gpu_ts); - } - - sync_gpu_ts = gpu_ts; - next_clock_sync_ns = cpu_ts + 30000000; + TuRenderpassDataSource::Trace([=](auto tctx) { + MesaRenderpassDataSource::EmitClockSync(tctx, cpu_ts, + gpu_ts, gpu_clock_id); }); + + gpu_max_timestamp = gpu_ts; + sync_gpu_ts = gpu_ts; + next_clock_sync_ns = cpu_ts + 30000000; } static void diff --git a/src/gallium/drivers/freedreno/freedreno_perfetto.cc b/src/gallium/drivers/freedreno/freedreno_perfetto.cc index 046fd581837..95612aeb558 100644 --- a/src/gallium/drivers/freedreno/freedreno_perfetto.cc +++ b/src/gallium/drivers/freedreno/freedreno_perfetto.cc @@ -306,30 +306,14 @@ sync_timestamp(struct fd_context *ctx) /* convert GPU ts into ns: */ gpu_ts = ctx->ts_to_ns(gpu_ts); - FdRenderpassDataSource::Trace([=](FdRenderpassDataSource::TraceContext tctx) { - auto packet = tctx.NewTracePacket(); - - packet->set_timestamp(cpu_ts); - - auto event = packet->set_clock_snapshot(); - - { - auto clock = event->add_clocks(); - - clock->set_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME); - clock->set_timestamp(cpu_ts); - } - - { - auto clock = event->add_clocks(); - - clock->set_clock_id(gpu_clock_id); - clock->set_timestamp(gpu_ts); - } - - sync_gpu_ts = gpu_ts; - next_clock_sync_ns = cpu_ts + 30000000; + FdRenderpassDataSource::Trace([=](auto tctx) { + MesaRenderpassDataSource::EmitClockSync(tctx, cpu_ts, + gpu_ts, gpu_clock_id); }); + + sync_gpu_ts = gpu_ts; + next_clock_sync_ns = cpu_ts + 30000000; } static void diff --git a/src/intel/ds/intel_driver_ds.cc b/src/intel/ds/intel_driver_ds.cc index d7195155a38..54218b054e2 100644 --- a/src/intel/ds/intel_driver_ds.cc +++ b/src/intel/ds/intel_driver_ds.cc @@ -128,24 +128,8 @@ sync_timestamp(IntelRenderpassDataSource::TraceContext &ctx, device->sync_gpu_ts = gpu_ts; device->next_clock_sync_ns = cpu_ts + 1000000000ull; - auto packet = ctx.NewTracePacket(); - - packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME); - packet->set_timestamp(cpu_ts); - - auto event = packet->set_clock_snapshot(); - { - auto clock = event->add_clocks(); - - clock->set_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME); - clock->set_timestamp(cpu_ts); - } - { - auto clock = event->add_clocks(); - - clock->set_clock_id(device->gpu_clock_id); - clock->set_timestamp(gpu_ts); - } + MesaRenderpassDataSource::EmitClockSync(ctx, + cpu_ts, gpu_ts, device->gpu_clock_id); } static void diff --git a/src/util/perf/u_perfetto_renderpass.h b/src/util/perf/u_perfetto_renderpass.h index 0491d8c38b4..5083795c796 100644 --- a/src/util/perf/u_perfetto_renderpass.h +++ b/src/util/perf/u_perfetto_renderpass.h @@ -29,7 +29,12 @@ using perfetto::DataSource; template class MesaRenderpassDataSource : public perfetto::DataSource { + public: + typedef typename perfetto::DataSource::TraceContext + TraceContext; + void OnSetup(const perfetto::DataSourceBase::SetupArgs &) override { // Use this callback to apply any custom configuration to your data @@ -59,6 +64,42 @@ class MesaRenderpassDataSource ctx.Flush(); }); } + + /* Emits a clock sync trace event. Perfetto uses periodic clock events + * like this to sync up our GPU render stages with the CPU on the same + * timeline, since clocks always drift over time. Note that perfetto + * relies on gpu_ts being monotonic, and will perform badly if it goes + * backwards -- see tu_perfetto.cc for an example implemntation of handling + * going backwards. + */ + static void EmitClockSync(TraceContext &ctx, + uint64_t cpu_ts, + uint64_t gpu_ts, + uint32_t gpu_clock_id) + { + auto packet = ctx.NewTracePacket(); + + packet->set_timestamp_clock_id( + perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME); + packet->set_timestamp(cpu_ts); + + auto event = packet->set_clock_snapshot(); + + { + auto clock = event->add_clocks(); + + clock->set_clock_id( + perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME); + clock->set_timestamp(cpu_ts); + } + + { + auto clock = event->add_clocks(); + + clock->set_clock_id(gpu_clock_id); + clock->set_timestamp(gpu_ts); + } + } }; /* Begin the C API section. */