turnip/perfetto: handle gpu timestamps being non-monotonic

Perfetto requires time in clock snaphots to be monotonic, otherwise
the clock would be excluded.
GPU timestamps start from zero after every suspend-resume cycle
which makes them non-monotonic.

As a solution on msm we check whether GPU was just resumed and
remember previous highest timestamp to then add it to the next
timestamps.

If the functionality to get whether gpu is resumed is unavailable
or doesn't work - we fallback to a check for a discontinuity
in timestamps. For kgsl we always use fallback.

Fixes renderstage timeline disappearing in AGI.

Or you could avoid the issue altogether by preventing GPU from going to
sleep by increasing auto suspend delay e.g.:

  echo 5000 > /sys/devices/platform/soc\@0/3d00000.gpu/power/autosuspend_delay_ms

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14391>
This commit is contained in:
Danylo Piliaiev 2021-09-15 17:35:56 +03:00 committed by Marge Bot
parent ba7faa6f43
commit 1989e1e6d8
5 changed files with 65 additions and 1 deletions

View File

@ -120,6 +120,13 @@ tu_device_get_gpu_timestamp(struct tu_device *dev, uint64_t *ts)
return tu_drm_get_param(dev->physical_device, MSM_PARAM_TIMESTAMP, ts);
}
int
tu_device_get_suspend_count(struct tu_device *dev, uint64_t *suspend_count)
{
int ret = tu_drm_get_param(dev->physical_device, MSM_PARAM_SUSPENDS, suspend_count);
return ret;
}
int
tu_drm_submitqueue_new(const struct tu_device *dev,
int priority,

View File

@ -663,6 +663,14 @@ tu_device_get_gpu_timestamp(struct tu_device *dev, uint64_t *ts)
return 0;
}
int
tu_device_get_suspend_count(struct tu_device *dev, uint64_t *suspend_count)
{
/* kgsl doesn't have a way to get it */
*suspend_count = 0;
return 0;
}
#ifdef ANDROID
VKAPI_ATTR VkResult VKAPI_CALL
tu_QueueSignalReleaseImageANDROID(VkQueue _queue,

View File

@ -43,6 +43,11 @@ static uint64_t next_clock_sync_ns; /* cpu time of next clk sync */
*/
static uint64_t sync_gpu_ts;
static uint64_t last_suspend_count;
static uint64_t gpu_max_timestamp;
static uint64_t gpu_timestamp_offset;
struct TuRenderpassIncrementalState {
bool was_cleared = true;
};
@ -73,6 +78,10 @@ public:
*/
gpu_clock_id =
_mesa_hash_string("org.freedesktop.mesa.freedreno") | 0x80000000;
gpu_timestamp_offset = 0;
gpu_max_timestamp = 0;
last_suspend_count = 0;
}
void OnStop(const StopArgs &) override
@ -156,7 +165,9 @@ stage_end(struct tu_device *dev, uint64_t ts_ns, enum tu_stage_id stage,
auto packet = tctx.NewTracePacket();
packet->set_timestamp(p->start_ts[stage]);
gpu_max_timestamp = MAX2(gpu_max_timestamp, ts_ns + gpu_timestamp_offset);
packet->set_timestamp(p->start_ts[stage] + gpu_timestamp_offset);
packet->set_timestamp_clock_id(gpu_clock_id);
auto event = packet->set_gpu_render_stage_event();
@ -201,9 +212,39 @@ sync_timestamp(struct tu_device *dev)
return;
}
uint64_t current_suspend_count = 0;
/* If we fail to get it we will use a fallback */
tu_device_get_suspend_count(dev, &current_suspend_count);
/* convert GPU ts into ns: */
gpu_ts = tu_device_ticks_to_ns(dev, gpu_ts);
/* GPU timestamp is being reset after suspend-resume cycle.
* Perfetto requires clock snapshots to be monotonic,
* so we have to fix-up the time.
*/
if (current_suspend_count != last_suspend_count) {
gpu_timestamp_offset = gpu_max_timestamp;
last_suspend_count = current_suspend_count;
}
gpu_ts += gpu_timestamp_offset;
/* Fallback check, detect non-monotonic cases which would happen
* if we cannot retrieve suspend count.
*/
if (sync_gpu_ts > gpu_ts) {
gpu_ts += (gpu_max_timestamp - gpu_timestamp_offset);
gpu_timestamp_offset = gpu_max_timestamp;
}
if (sync_gpu_ts > gpu_ts) {
PERFETTO_ELOG("Non-monotonic gpu timestamp detected, bailing out");
return;
}
gpu_max_timestamp = gpu_ts;
TuRenderpassDataSource::Trace([=](TuRenderpassDataSource::TraceContext tctx) {
auto packet = tctx.NewTracePacket();

View File

@ -100,6 +100,10 @@ int
tu_device_get_gpu_timestamp(struct tu_device *dev,
uint64_t *ts);
int
tu_device_get_suspend_count(struct tu_device *dev,
uint64_t *suspend_count);
uint64_t
tu_device_ticks_to_ns(struct tu_device *dev, uint64_t ts);

View File

@ -1731,6 +1731,10 @@ int
tu_device_get_gpu_timestamp(struct tu_device *dev,
uint64_t *ts);
int
tu_device_get_suspend_count(struct tu_device *dev,
uint64_t *suspend_count);
int
tu_drm_submitqueue_new(const struct tu_device *dev,
int priority,