summaryrefslogtreecommitdiff
path: root/src/tool
diff options
context:
space:
mode:
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>2021-11-07 23:41:05 +0200
committerMarge Bot <emma+marge@anholt.net>2021-11-22 11:52:46 +0000
commit8657fa6b868880021046b0ef73a4a8a20648d93a (patch)
treefeda3858cc41c03429c8469df793da256e2af774 /src/tool
parent457dbb81f5c3bc86d4968c6f099154abd39c829e (diff)
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 <lionel.g.landwerlin@intel.com> Reviewed-by: Antonio Caggiano <antonio.caggiano@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13831>
Diffstat (limited to 'src/tool')
-rw-r--r--src/tool/pps/pps_datasource.cc66
-rw-r--r--src/tool/pps/pps_datasource.h8
-rw-r--r--src/tool/pps/pps_driver.h8
3 files changed, 70 insertions, 12 deletions
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<GpuDataSource, GpuDataSourceTr
/// Used to check whether the datasource is quick enough
std::chrono::nanoseconds time_to_trace;
+ /// Last CPU timestamp at which we correlated CPU/GPU timestamps
+ uint64_t last_correlation_timestamp = 0;
+
/// A data source supports one driver at a time, but if you need more
/// than one gpu datasource you can just run another producer
Driver *driver = nullptr;
- /// Timestamp of packet sent with counter descriptors
+ /// CPU timestamp of packet sent with counter descriptors
uint64_t descriptor_timestamp = 0;
+
+ /// GPU timestamp of packet sent with counter descriptors
+ uint64_t descriptor_gpu_timestamp = 0;
};
} // namespace pps
diff --git a/src/tool/pps/pps_driver.h b/src/tool/pps/pps_driver.h
index 55849d07ada..8d1c59631ac 100644
--- a/src/tool/pps/pps_driver.h
+++ b/src/tool/pps/pps_driver.h
@@ -72,9 +72,15 @@ class Driver
/// @brief After dumping performance counters, with this function you can iterate
/// through the samples collected.
- /// @return The CPU timestamp associated to current sample, or 0 if there are no more samples
+ /// @return The GPU timestamp associated to current sample, or 0 if there are no more samples
virtual uint64_t next() = 0;
+ /// Clock ID in which the values returned by gpu_timestamp() belong
+ virtual uint32_t gpu_clock_id() const = 0;
+
+ /// Sample a timestamp from the GPU
+ virtual uint64_t gpu_timestamp() const = 0;
+
DrmDevice drm_device;
/// List of counter groups