From 8657fa6b868880021046b0ef73a4a8a20648d93a Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Sun, 7 Nov 2021 23:41:05 +0200 Subject: [PATCH] pps: allow drivers to report timestamps in their own time domain For this each driver must : - report its clock_id (if no particular clock just default to cpu boottime one) - be able to sample its clock (gpu_timestamp()) The PPSDataSource will then emit timestamp correlation events in the trace ensuring perfetto is able to display GPU & CPU events appropriately on its timeline. Signed-off-by: Lionel Landwerlin Reviewed-by: Antonio Caggiano Part-of: --- src/freedreno/ds/fd_pps_driver.cc | 12 ++++++ src/freedreno/ds/fd_pps_driver.h | 2 + src/intel/ds/intel_pps_driver.cc | 10 +++++ src/intel/ds/intel_pps_driver.h | 3 ++ src/panfrost/ds/pan_pps_driver.cc | 10 +++++ src/panfrost/ds/pan_pps_driver.h | 2 + src/tool/pps/pps_datasource.cc | 66 ++++++++++++++++++++++++++----- src/tool/pps/pps_datasource.h | 8 +++- src/tool/pps/pps_driver.h | 8 +++- 9 files changed, 109 insertions(+), 12 deletions(-) diff --git a/src/freedreno/ds/fd_pps_driver.cc b/src/freedreno/ds/fd_pps_driver.cc index 88697bf6111..97305c911ae 100644 --- a/src/freedreno/ds/fd_pps_driver.cc +++ b/src/freedreno/ds/fd_pps_driver.cc @@ -389,4 +389,16 @@ FreedrenoDriver::counter(std::string name, Counter::Units units, return counter; } +uint32_t +FreedrenoDriver::gpu_clock_id() const +{ + return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME; +} + +uint64_t +FreedrenoDriver::gpu_timestamp() const +{ + return perfetto::base::GetBootTimeNs().count(); +} + } // namespace pps diff --git a/src/freedreno/ds/fd_pps_driver.h b/src/freedreno/ds/fd_pps_driver.h index 8a738e26dbd..29f738b313e 100644 --- a/src/freedreno/ds/fd_pps_driver.h +++ b/src/freedreno/ds/fd_pps_driver.h @@ -28,6 +28,8 @@ public: void disable_perfcnt() override; bool dump_perfcnt() override; uint64_t next() override; + uint32_t gpu_clock_id() const override; + uint64_t gpu_timestamp() const override; private: struct fd_device *dev; diff --git a/src/intel/ds/intel_pps_driver.cc b/src/intel/ds/intel_pps_driver.cc index 6c79acd0ad0..6966db8fdc1 100644 --- a/src/intel/ds/intel_pps_driver.cc +++ b/src/intel/ds/intel_pps_driver.cc @@ -400,4 +400,14 @@ uint64_t IntelDriver::next() return cpu_next(); } +uint32_t IntelDriver::gpu_clock_id() const +{ + return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME; +} + +uint64_t IntelDriver::gpu_timestamp() const +{ + return perfetto::base::GetBootTimeNs().count(); +} + } // namespace pps diff --git a/src/intel/ds/intel_pps_driver.h b/src/intel/ds/intel_pps_driver.h index 5df48e2f4ec..cac029a973e 100644 --- a/src/intel/ds/intel_pps_driver.h +++ b/src/intel/ds/intel_pps_driver.h @@ -51,7 +51,10 @@ class IntelDriver : public Driver void disable_perfcnt() override; bool dump_perfcnt() override; uint64_t next() override; + uint32_t gpu_clock_id() const override; + uint64_t gpu_timestamp() const override; + private: /// @brief Requests the next perf sample /// @return The sample GPU timestamp uint32_t gpu_next(); diff --git a/src/panfrost/ds/pan_pps_driver.cc b/src/panfrost/ds/pan_pps_driver.cc index fbe9263748d..0453475b46d 100644 --- a/src/panfrost/ds/pan_pps_driver.cc +++ b/src/panfrost/ds/pan_pps_driver.cc @@ -157,4 +157,14 @@ void PanfrostDriver::disable_perfcnt() enabled_counters.clear(); } +uint32_t PanfrostDriver::gpu_clock_id() const +{ + return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME; +} + +uint64_t PanfrostDriver::gpu_timestamp() const +{ + return perfetto::base::GetBootTimeNs().count(); +} + } // namespace pps diff --git a/src/panfrost/ds/pan_pps_driver.h b/src/panfrost/ds/pan_pps_driver.h index de764b18aae..f6476d9dee3 100644 --- a/src/panfrost/ds/pan_pps_driver.h +++ b/src/panfrost/ds/pan_pps_driver.h @@ -41,6 +41,8 @@ class PanfrostDriver : public Driver void disable_perfcnt() override; bool dump_perfcnt() override; uint64_t next() override; + uint32_t gpu_clock_id() const override; + uint64_t gpu_timestamp() const override; uint64_t last_dump_ts = 0; diff --git a/src/tool/pps/pps_datasource.cc b/src/tool/pps/pps_datasource.cc index 3b5a083b80f..9eac41b9ade 100644 --- a/src/tool/pps/pps_datasource.cc +++ b/src/tool/pps/pps_datasource.cc @@ -18,6 +18,8 @@ // Minimum supported sampling period in nanoseconds #define MIN_SAMPLING_PERIOD_NS 50000 +#define CORRELATION_TIMESTAMP_PERIOD (1000000000ull) + namespace pps { static std::string driver_name; @@ -232,11 +234,37 @@ void add_samples(perfetto::protos::pbzero::GpuCounterEvent &event, const Driver } } +void add_timestamp(perfetto::protos::pbzero::ClockSnapshot *event, const Driver *driver) +{ + uint32_t gpu_clock_id = driver->gpu_clock_id(); + if (perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME == gpu_clock_id) + return; + + // Send a correlation event between GPU & CPU timestamps + uint64_t cpu_ts = perfetto::base::GetBootTimeNs().count(); + uint64_t gpu_ts = driver->gpu_timestamp(); + + { + 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); + } +} + void GpuDataSource::trace(TraceContext &ctx) { using namespace perfetto::protos::pbzero; - if (auto state = ctx.GetIncrementalState(); state->was_cleared) { + auto state = ctx.GetIncrementalState(); + if (state->was_cleared) { // Mark any incremental state before this point invalid { auto packet = ctx.NewTracePacket(); @@ -248,14 +276,23 @@ void GpuDataSource::trace(TraceContext &ctx) descriptor_timestamp = perfetto::base::GetBootTimeNs().count(); packet->set_timestamp(descriptor_timestamp); - auto event = packet->set_gpu_counter_event(); - event->set_gpu_id(driver->drm_device.gpu_num); + { + auto event = packet->set_gpu_counter_event(); + event->set_gpu_id(driver->drm_device.gpu_num); - auto &groups = driver->groups; - auto &counters = driver->enabled_counters; - PPS_LOG("Sending counter descriptors"); - add_descriptors(event, groups, counters, *driver); + auto &groups = driver->groups; + auto &counters = driver->enabled_counters; + PPS_LOG("Sending counter descriptors"); + add_descriptors(event, groups, counters, *driver); + } + { + last_correlation_timestamp = perfetto::base::GetBootTimeNs().count(); + auto event = packet->set_clock_snapshot(); + add_timestamp(event, driver); + } + + descriptor_gpu_timestamp = driver->gpu_timestamp(); state->was_cleared = false; } @@ -272,15 +309,16 @@ void GpuDataSource::trace(TraceContext &ctx) sched_setscheduler(0, sched_policy, &priority_param); if (driver->dump_perfcnt()) { - while (auto timestamp = driver->next()) { - if (timestamp <= descriptor_timestamp) { + while (auto gpu_timestamp = driver->next()) { + if (gpu_timestamp <= descriptor_gpu_timestamp) { // Do not send counter values before counter descriptors PPS_LOG_ERROR("Skipping counter values coming before descriptors"); continue; } auto packet = ctx.NewTracePacket(); - packet->set_timestamp(timestamp); + packet->set_timestamp_clock_id(driver->gpu_clock_id()); + packet->set_timestamp(gpu_timestamp); auto event = packet->set_gpu_counter_event(); event->set_gpu_id(driver->drm_device.gpu_num); @@ -289,6 +327,14 @@ void GpuDataSource::trace(TraceContext &ctx) } } + uint64_t cpu_ts = perfetto::base::GetBootTimeNs().count(); + if ((cpu_ts - last_correlation_timestamp) > CORRELATION_TIMESTAMP_PERIOD) { + auto packet = ctx.NewTracePacket(); + auto event = packet->set_clock_snapshot(); + add_timestamp(event, driver); + last_correlation_timestamp = cpu_ts; + } + // Reset normal scheduler sched_setscheduler(0, prev_sched_policy, &prev_priority_param); } diff --git a/src/tool/pps/pps_datasource.h b/src/tool/pps/pps_datasource.h index 96a83b5ae97..f2946cbd6a5 100644 --- a/src/tool/pps/pps_datasource.h +++ b/src/tool/pps/pps_datasource.h @@ -53,12 +53,18 @@ class GpuDataSource : public perfetto::DataSource