1
0
Fork 0

kms/impl-device: Track dispatch duration in crtc_frame_deadline_dispatch

And take it into account in meta_kms_crtc_get_deadline_evasion.

This uses the same fundamental approach as clutter frame clock scheduling:

Measure the deadline timer dispatch duration, keep track of the longest
duration, and set the timer to fire such that the longest measured
dispatch duration would result in it completing shortly before start of
vblank.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3612

v2:
* Move DEADLINE_EVASION_CONSTANT_US addition from
  meta_kms_crtc_determine_deadline to meta_kms_crtc_get_deadline_evasion.
* Calculate how long before start of vblank dispatch completed for
  debug output in crtc_frame_deadline_dispatch.
* Shorten over-long lines in crtc_frame_deadline_dispatch.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3934>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
(cherry picked from commit 88e7f353)
This commit is contained in:
Michel Dänzer 2024-08-08 16:36:05 +02:00 committed by Mingi Sung
parent b5dffcdc67
commit e3bbee2630
Signed by: sungmg
GPG key ID: 41BAFD6FFD8036C5
3 changed files with 76 additions and 13 deletions

View file

@ -28,8 +28,7 @@
#include "backends/native/meta-kms-update-private.h"
#include "backends/native/meta-kms-utils.h"
#define DEADLINE_EVASION_US 800
#define DEADLINE_EVASION_WITH_KMS_TOPIC_US 1000
#define DEADLINE_EVASION_CONSTANT_US 200
#define MINIMUM_REFRESH_RATE 30.f
@ -50,6 +49,10 @@ struct _MetaKmsCrtc
MetaKmsCrtcState current_state;
MetaKmsCrtcPropTable prop_table;
int64_t shortterm_max_dispatch_duration_us;
int64_t deadline_evasion_us;
int64_t deadline_evasion_update_time_us;
};
G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT)
@ -543,6 +546,33 @@ get_crtc_type_bitmask (MetaKmsCrtc *crtc)
}
}
static void
maybe_update_deadline_evasion (MetaKmsCrtc *crtc,
int64_t next_presentation_time_us)
{
/* Do not update long-term max if there has been no measurement */
if (!crtc->shortterm_max_dispatch_duration_us)
return;
if (next_presentation_time_us - crtc->deadline_evasion_update_time_us <
G_USEC_PER_SEC)
return;
if (crtc->deadline_evasion_us > crtc->shortterm_max_dispatch_duration_us)
{
/* Exponential drop-off toward the clamped short-term max */
crtc->deadline_evasion_us -=
(crtc->deadline_evasion_us - crtc->shortterm_max_dispatch_duration_us) / 2;
}
else
{
crtc->deadline_evasion_us = crtc->shortterm_max_dispatch_duration_us;
}
crtc->shortterm_max_dispatch_duration_us = 0;
crtc->deadline_evasion_update_time_us = next_presentation_time_us;
}
gboolean
meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
int64_t *out_next_deadline_us,
@ -611,6 +641,7 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
*/
deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc);
maybe_update_deadline_evasion (crtc, next_presentation_us);
vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode);
next_deadline_us = next_presentation_us - (vblank_duration_us +
@ -623,11 +654,25 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
return TRUE;
}
void
meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc,
int64_t duration_us)
{
int64_t refresh_interval_us;
if (duration_us <= crtc->shortterm_max_dispatch_duration_us)
return;
refresh_interval_us =
(int64_t) (0.5 + G_USEC_PER_SEC /
meta_calculate_drm_mode_refresh_rate (&crtc->current_state.drm_mode));
crtc->shortterm_max_dispatch_duration_us = MIN (duration_us, refresh_interval_us);
}
int64_t
meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc)
{
if (meta_is_topic_enabled (META_DEBUG_KMS))
return DEADLINE_EVASION_WITH_KMS_TOPIC_US;
else
return DEADLINE_EVASION_US;
return MAX (crtc->shortterm_max_dispatch_duration_us,
crtc->deadline_evasion_us) + DEADLINE_EVASION_CONSTANT_US;
}

View file

@ -66,4 +66,7 @@ int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc);
META_EXPORT_TEST
gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc);
void meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc,
int64_t duration_us);
int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc);

View file

@ -39,6 +39,7 @@
#include "backends/native/meta-kms-plane-private.h"
#include "backends/native/meta-kms-plane.h"
#include "backends/native/meta-kms-private.h"
#include "backends/native/meta-kms-utils.h"
#include "backends/native/meta-thread-private.h"
#include "meta-default-modes.h"
@ -1394,12 +1395,13 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl,
GError **error)
{
CrtcFrame *crtc_frame = user_data;
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc);
MetaKmsCrtc *crtc = crtc_frame->crtc;
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc);
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
g_autoptr (MetaKmsFeedback) feedback = NULL;
uint64_t timer_value;
ssize_t ret;
int64_t dispatch_time_us = 0;
int64_t dispatch_time_us = 0, update_done_time_us, interval_us;
if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
dispatch_time_us = g_get_monotonic_time ();
@ -1425,22 +1427,35 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl,
g_steal_pointer (&crtc_frame->pending_update),
META_KMS_UPDATE_FLAG_NONE);
update_done_time_us = g_get_monotonic_time ();
/* Calculate how long after the planned start of deadline dispatch it finished */
interval_us = update_done_time_us - crtc_frame->deadline.expected_deadline_time_us;
if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
{
int64_t lateness_us, duration_us;
int64_t deadline_evasion_us, lateness_us, duration_us, vblank_delta_us;
deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc);
lateness_us = dispatch_time_us -
crtc_frame->deadline.expected_deadline_time_us;
duration_us = g_get_monotonic_time () - dispatch_time_us;
duration_us = update_done_time_us - dispatch_time_us;
vblank_delta_us = deadline_evasion_us - lateness_us - duration_us;
meta_topic (META_DEBUG_KMS_DEADLINE,
"Deadline dispatch started %3"G_GINT64_FORMAT "µs %s and "
"completed %3"G_GINT64_FORMAT "µs after that.",
"Deadline evasion %3"G_GINT64_FORMAT "µs, "
"dispatch started %3"G_GINT64_FORMAT "µs %s and "
"completed %3"G_GINT64_FORMAT "µs after that, "
"%3"G_GINT64_FORMAT "µs %s start of vblank.",
deadline_evasion_us,
ABS (lateness_us),
lateness_us >= 0 ? "late" : "early",
duration_us);
duration_us,
ABS (vblank_delta_us),
vblank_delta_us >= 0 ? "before" : "after");
}
meta_kms_crtc_update_shortterm_max_dispatch_duration (crtc, interval_us);
if (meta_kms_feedback_did_pass (feedback))
crtc_frame->deadline.is_deadline_page_flip = TRUE;
disarm_crtc_frame_deadline_timer (crtc_frame);