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:
parent
ba7faa6f43
commit
1989e1e6d8
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ¤t_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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue