mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-09 10:20:07 +00:00
frameclock: Make timings history dynamic
Keep at least 1 second of frame timings. This is necessary for 2 reasons - a real one and a fun one. First, with the difference in monitor refresh rates, we can have 48Hz latops as well as 240Hz high refresh rate monitors. That's a factor of 4, and tracking frame rates in both situations reliably is kind of hard - either we track over too many frames and the fps take a lot of time to adjust, or we track too little time and the fps fluctuate wildly. Second, when benchmarking with GDK_DEBUG=no-vsync with a somewhat fast renderer (*cough*Vulkan*cough*) frame rates can go into insane dimensions and only very few frames are actually getting presentation times reported. So to report accurate frame rates in those cases, we need a *very* large history that can be 1000s of times larger than the usual history. And that's just a waste for normal usage.
This commit is contained in:
parent
2861ab38ac
commit
8df6e2cdaf
@ -79,14 +79,23 @@ static guint signals[LAST_SIGNAL];
|
||||
|
||||
static guint fps_counter;
|
||||
|
||||
#define FRAME_HISTORY_MAX_LENGTH 128
|
||||
/* 60Hz plus some extra for monotonic time inaccuracy */
|
||||
#define FRAME_HISTORY_DEFAULT_LENGTH 64
|
||||
|
||||
#define frame_timings_unref(x) gdk_frame_timings_unref((GdkFrameTimings *) (x))
|
||||
|
||||
#define GDK_ARRAY_NAME timings
|
||||
#define GDK_ARRAY_TYPE_NAME Timings
|
||||
#define GDK_ARRAY_ELEMENT_TYPE GdkFrameTimings *
|
||||
#define GDK_ARRAY_PREALLOC FRAME_HISTORY_DEFAULT_LENGTH
|
||||
#define GDK_ARRAY_FREE_FUNC frame_timings_unref
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
struct _GdkFrameClockPrivate
|
||||
{
|
||||
gint64 frame_counter;
|
||||
int n_timings;
|
||||
int current;
|
||||
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
|
||||
Timings timings;
|
||||
int n_freeze_inhibitors;
|
||||
};
|
||||
|
||||
@ -99,11 +108,8 @@ static void
|
||||
gdk_frame_clock_finalize (GObject *object)
|
||||
{
|
||||
GdkFrameClockPrivate *priv = GDK_FRAME_CLOCK (object)->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FRAME_HISTORY_MAX_LENGTH; i++)
|
||||
if (priv->timings[i] != 0)
|
||||
gdk_frame_timings_unref (priv->timings[i]);
|
||||
timings_clear (&priv->timings);
|
||||
|
||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
|
||||
}
|
||||
@ -257,7 +263,8 @@ gdk_frame_clock_init (GdkFrameClock *clock)
|
||||
clock->priv = priv = gdk_frame_clock_get_instance_private (clock);
|
||||
|
||||
priv->frame_counter = -1;
|
||||
priv->current = FRAME_HISTORY_MAX_LENGTH - 1;
|
||||
priv->current = 0;
|
||||
timings_init (&priv->timings);
|
||||
|
||||
if (fps_counter == 0)
|
||||
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
|
||||
@ -416,7 +423,7 @@ gdk_frame_clock_get_frame_counter (GdkFrameClock *frame_clock)
|
||||
static inline gint64
|
||||
_gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
||||
{
|
||||
return frame_clock->priv->frame_counter + 1 - frame_clock->priv->n_timings;
|
||||
return frame_clock->priv->frame_counter + 1 - timings_get_size (&frame_clock->priv->timings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -445,31 +452,44 @@ gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock)
|
||||
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock,
|
||||
gint64 monotonic_time)
|
||||
{
|
||||
GdkFrameClockPrivate *priv;
|
||||
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||
|
||||
priv = frame_clock->priv;
|
||||
|
||||
priv->frame_counter++;
|
||||
priv->current = (priv->current + 1) % FRAME_HISTORY_MAX_LENGTH;
|
||||
|
||||
/* Try to steal the previous frame timing instead of discarding
|
||||
* and allocating a new one.
|
||||
*/
|
||||
if G_LIKELY (priv->n_timings == FRAME_HISTORY_MAX_LENGTH &&
|
||||
_gdk_frame_timings_steal (priv->timings[priv->current],
|
||||
priv->frame_counter))
|
||||
return;
|
||||
|
||||
if (priv->n_timings < FRAME_HISTORY_MAX_LENGTH)
|
||||
priv->n_timings++;
|
||||
if (G_UNLIKELY (timings_get_size (&priv->timings) == 0))
|
||||
timings_append (&priv->timings, _gdk_frame_timings_new (priv->frame_counter));
|
||||
else
|
||||
gdk_frame_timings_unref (priv->timings[priv->current]);
|
||||
{
|
||||
GdkFrameTimings *timings;
|
||||
|
||||
priv->timings[priv->current] = _gdk_frame_timings_new (priv->frame_counter);
|
||||
priv->current = (priv->current + 1) % timings_get_size (&priv->timings);
|
||||
|
||||
timings = timings_get (&priv->timings, priv->current);
|
||||
|
||||
if (timings->frame_time + G_USEC_PER_SEC > monotonic_time)
|
||||
{
|
||||
/* Keep the timings, not a second old yet */
|
||||
timings = _gdk_frame_timings_new (priv->frame_counter);
|
||||
timings_splice (&priv->timings, priv->current, 0, FALSE, &timings, 1);
|
||||
}
|
||||
else if (_gdk_frame_timings_steal (timings, priv->frame_counter))
|
||||
{
|
||||
/* Stole the previous frame timing instead of discarding
|
||||
* and allocating a new one, so nothing to do
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
timings = _gdk_frame_timings_new (priv->frame_counter);
|
||||
timings_splice (&priv->timings, priv->current, 1, FALSE, &timings, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline GdkFrameTimings *
|
||||
@ -477,17 +497,21 @@ _gdk_frame_clock_get_timings (GdkFrameClock *frame_clock,
|
||||
gint64 frame_counter)
|
||||
{
|
||||
GdkFrameClockPrivate *priv = frame_clock->priv;
|
||||
int pos;
|
||||
gsize size, pos;
|
||||
|
||||
if (frame_counter > priv->frame_counter)
|
||||
return NULL;
|
||||
|
||||
if (frame_counter <= priv->frame_counter - priv->n_timings)
|
||||
size = timings_get_size (&priv->timings);
|
||||
if (G_UNLIKELY (size == 0))
|
||||
return NULL;
|
||||
|
||||
pos = (priv->current - (priv->frame_counter - frame_counter) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH;
|
||||
if (priv->frame_counter - frame_counter >= size)
|
||||
return NULL;
|
||||
|
||||
return priv->timings[pos];
|
||||
pos = (priv->current - (priv->frame_counter - frame_counter) + size) % size;
|
||||
|
||||
return timings_get (&priv->timings, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -555,7 +555,7 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
priv->smoothed_frame_time_period = frame_interval;
|
||||
priv->smoothed_frame_time_reported = priv->smoothed_frame_time_base;
|
||||
|
||||
_gdk_frame_clock_begin_frame (clock);
|
||||
_gdk_frame_clock_begin_frame (clock, priv->frame_time);
|
||||
/* Note "current" is different now so timings != prev_timings */
|
||||
timings = gdk_frame_clock_get_current_timings (clock);
|
||||
|
||||
|
@ -106,7 +106,8 @@ struct _GdkFrameTimings
|
||||
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
|
||||
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock,
|
||||
gint64 monotonic_time);
|
||||
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
|
||||
GdkFrameTimings *timings);
|
||||
void _gdk_frame_clock_add_timings_to_profiler (GdkFrameClock *frame_clock,
|
||||
|
Loading…
Reference in New Issue
Block a user