mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-02-22 06:36:24 +00:00
u/rt: Refactor render timing
This commit is contained in:
parent
670906ea0e
commit
8215af5e5c
src/xrt
auxiliary
compositor/multi
ipc/server
|
@ -152,7 +152,6 @@ set(UTIL_SOURCE_FILES
|
||||||
util/u_timing_fake.c
|
util/u_timing_fake.c
|
||||||
util/u_timing_frame.c
|
util/u_timing_frame.c
|
||||||
util/u_timing_render.c
|
util/u_timing_render.c
|
||||||
util/u_timing_render.h
|
|
||||||
util/u_trace_marker.c
|
util/u_trace_marker.c
|
||||||
util/u_trace_marker.h
|
util/u_trace_marker.h
|
||||||
util/u_var.cpp
|
util/u_var.cpp
|
||||||
|
|
|
@ -58,7 +58,6 @@ lib_aux_util = static_library(
|
||||||
'util/u_timing_fake.c',
|
'util/u_timing_fake.c',
|
||||||
'util/u_timing_frame.c',
|
'util/u_timing_frame.c',
|
||||||
'util/u_timing_render.c',
|
'util/u_timing_render.c',
|
||||||
'util/u_timing_render.h',
|
|
||||||
'util/u_trace_marker.c',
|
'util/u_trace_marker.c',
|
||||||
'util/u_trace_marker.h',
|
'util/u_trace_marker.h',
|
||||||
'util/u_var.cpp',
|
'util/u_var.cpp',
|
||||||
|
|
|
@ -25,12 +25,6 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Frame timing helper.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* For marking timepoints on a frame's lifetime, not a async event.
|
* For marking timepoints on a frame's lifetime, not a async event.
|
||||||
*
|
*
|
||||||
|
@ -43,6 +37,13 @@ enum u_timing_point
|
||||||
U_TIMING_POINT_SUBMIT, //!< Submitted work to the GPU.
|
U_TIMING_POINT_SUBMIT, //!< Submitted work to the GPU.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Frame timing helper.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Frame timing helper struct, used for the compositors own frame timing.
|
* Frame timing helper struct, used for the compositors own frame timing.
|
||||||
*
|
*
|
||||||
|
@ -103,13 +104,6 @@ struct u_frame_timing
|
||||||
void (*destroy)(struct u_frame_timing *uft);
|
void (*destroy)(struct u_frame_timing *uft);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Helper functions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @copydoc u_frame_timing::predict
|
* @copydoc u_frame_timing::predict
|
||||||
*
|
*
|
||||||
|
@ -194,6 +188,186 @@ u_ft_destroy(struct u_frame_timing **uft_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Render timing helper.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This render timing helper is designed to schedule the rendering time of
|
||||||
|
* clients that submit frames to a compositor, which runs its own render loop
|
||||||
|
* that picks latest completed frames for that client.
|
||||||
|
*
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
struct u_render_timing
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* Predict when the client's next: rendered frame will be display; when the
|
||||||
|
* client should be woken up from sleeping; and its display period.
|
||||||
|
*
|
||||||
|
* This is called from `xrWaitFrame`, but it does not do any waiting, the caller
|
||||||
|
* should wait till `out_wake_up_time`.
|
||||||
|
*
|
||||||
|
* @param urth Render timing helper.
|
||||||
|
* @param[out] out_frame_id Frame ID of this predicted frame.
|
||||||
|
* @param[out] out_wake_up_time When the client should be woken up.
|
||||||
|
* @param[out] out_predicted_display_time Predicted display time.
|
||||||
|
* @param[out] out_predicted_display_period Predicted display period.
|
||||||
|
*/
|
||||||
|
void (*predict)(struct u_render_timing *urt,
|
||||||
|
int64_t *out_frame_id,
|
||||||
|
uint64_t *out_wake_up_time,
|
||||||
|
uint64_t *out_predicted_display_time,
|
||||||
|
uint64_t *out_predicted_display_period);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mark a point on the frame's lifetime.
|
||||||
|
*
|
||||||
|
* @see @ref frame-timing.
|
||||||
|
*/
|
||||||
|
void (*mark_point)(struct u_render_timing *urt, int64_t frame_id, enum u_timing_point point, uint64_t when_ns);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* When a frame has been discarded.
|
||||||
|
*/
|
||||||
|
void (*mark_discarded)(struct u_render_timing *urt, int64_t frame_id);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A frame has been delivered from the client, see `xrEndFrame`. The GPU might
|
||||||
|
* still be rendering the work.
|
||||||
|
*/
|
||||||
|
void (*mark_delivered)(struct u_render_timing *urt, int64_t frame_id);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Add a new sample point from the main render loop.
|
||||||
|
*
|
||||||
|
* This is called in the main renderer loop that tightly submits frames to the
|
||||||
|
* real compositor for displaying. This is only used to inform the render helper
|
||||||
|
* when the frame will be shown, not any timing information about the client.
|
||||||
|
*
|
||||||
|
* When this is called doesn't matter that much, as the render timing will need
|
||||||
|
* to be able to predict one or more frames into the future anyways. But
|
||||||
|
* preferably as soon as the main loop wakes up from wait frame.
|
||||||
|
*
|
||||||
|
* @param urth Self pointer
|
||||||
|
* @param predicted_display_time_ns Predicted display time for this sample.
|
||||||
|
* @param predicted_display_period_ns Predicted display period for this sample.
|
||||||
|
* @param extra_ns Time between display and when this sample
|
||||||
|
* was created, that is when the main loop
|
||||||
|
* was woken up by the main compositor.
|
||||||
|
*/
|
||||||
|
void (*info)(struct u_render_timing *urt,
|
||||||
|
uint64_t predicted_display_time_ns,
|
||||||
|
uint64_t predicted_display_period_ns,
|
||||||
|
uint64_t extra_ns);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Destroy this u_render_timing.
|
||||||
|
*/
|
||||||
|
void (*destroy)(struct u_render_timing *urt);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc u_frame_timing::predict
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof u_render_timing
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
u_rt_predict(struct u_render_timing *urt,
|
||||||
|
int64_t *out_frame_id,
|
||||||
|
uint64_t *out_wake_up_time,
|
||||||
|
uint64_t *out_predicted_display_time,
|
||||||
|
uint64_t *out_predicted_display_period)
|
||||||
|
{
|
||||||
|
urt->predict(urt, out_frame_id, out_wake_up_time, out_predicted_display_time, out_predicted_display_period);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc u_frame_timing::mark_point
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof u_render_timing
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
u_rt_mark_point(struct u_render_timing *urt, int64_t frame_id, enum u_timing_point point, uint64_t when_ns)
|
||||||
|
{
|
||||||
|
urt->mark_point(urt, frame_id, point, when_ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc u_frame_timing::mark_discarded
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof u_render_timing
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
u_rt_mark_discarded(struct u_render_timing *urt, int64_t frame_id)
|
||||||
|
{
|
||||||
|
urt->mark_discarded(urt, frame_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc u_frame_timing::mark_delivered
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof u_render_timing
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
u_rt_mark_delivered(struct u_render_timing *urt, int64_t frame_id)
|
||||||
|
{
|
||||||
|
urt->mark_delivered(urt, frame_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc u_frame_timing::info
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer.
|
||||||
|
*
|
||||||
|
* @public @memberof u_render_timing
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
u_rt_info(struct u_render_timing *urt,
|
||||||
|
uint64_t predicted_display_time_ns,
|
||||||
|
uint64_t predicted_display_period_ns,
|
||||||
|
uint64_t extra_ns)
|
||||||
|
{
|
||||||
|
urt->info(urt, predicted_display_time_ns, predicted_display_period_ns, extra_ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @copydoc u_render_timing::destroy
|
||||||
|
*
|
||||||
|
* Helper for calling through the function pointer: does a null check and sets
|
||||||
|
* urt_ptr to null if freed.
|
||||||
|
*
|
||||||
|
* @public @memberof u_frame_timing
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
u_rt_destroy(struct u_render_timing **urt_ptr)
|
||||||
|
{
|
||||||
|
struct u_render_timing *urt = *urt_ptr;
|
||||||
|
if (urt == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
urt->destroy(urt);
|
||||||
|
*urt_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Implementations.
|
* Implementations.
|
||||||
|
@ -216,6 +390,14 @@ u_ft_display_timing_create(uint64_t estimated_frame_period_ns, struct u_frame_ti
|
||||||
xrt_result_t
|
xrt_result_t
|
||||||
u_ft_fake_create(uint64_t estimated_frame_period_ns, struct u_frame_timing **out_uft);
|
u_ft_fake_create(uint64_t estimated_frame_period_ns, struct u_frame_timing **out_uft);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Creates a new render timing.
|
||||||
|
*
|
||||||
|
* @ingroup aux_timing
|
||||||
|
*/
|
||||||
|
xrt_result_t
|
||||||
|
u_rt_create(struct u_render_timing **out_urt);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,23 +7,98 @@
|
||||||
* @ingroup aux_util
|
* @ingroup aux_util
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "os/os_time.h"
|
||||||
|
|
||||||
#include "util/u_time.h"
|
#include "util/u_time.h"
|
||||||
#include "util/u_misc.h"
|
#include "util/u_misc.h"
|
||||||
#include "util/u_debug.h"
|
#include "util/u_debug.h"
|
||||||
#include "util/u_logging.h"
|
#include "util/u_logging.h"
|
||||||
#include "util/u_timing_render.h"
|
#include "util/u_timing.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Structs enums, and defines.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum u_rt_state
|
||||||
|
{
|
||||||
|
U_RT_READY,
|
||||||
|
U_RT_WAIT_LEFT,
|
||||||
|
U_RT_PREDICTED,
|
||||||
|
U_RT_BEGUN,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct u_rt_frame
|
||||||
|
{
|
||||||
|
//! When we predicted this frame to be shown.
|
||||||
|
uint64_t predicted_display_time_ns;
|
||||||
|
//! When the client should have delivered the frame.
|
||||||
|
uint64_t predicted_delivery_time_ns;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t predicted_ns;
|
||||||
|
uint64_t wait_woke_ns;
|
||||||
|
uint64_t begin_ns;
|
||||||
|
uint64_t delivered_ns;
|
||||||
|
} when; //!< When something happened.
|
||||||
|
|
||||||
|
int64_t frame_id;
|
||||||
|
enum u_rt_state state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct render_timing
|
||||||
|
{
|
||||||
|
struct u_render_timing base;
|
||||||
|
|
||||||
|
struct u_rt_frame frames[2];
|
||||||
|
uint32_t current_frame;
|
||||||
|
uint32_t next_frame;
|
||||||
|
|
||||||
|
int64_t frame_counter;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
//! App time between wait returning and begin being called.
|
||||||
|
uint64_t cpu_time_ns;
|
||||||
|
//! Time between begin and frame rendering completeing.
|
||||||
|
uint64_t draw_time_ns;
|
||||||
|
//! Exrta time between end of draw time and when the compositor wakes up.
|
||||||
|
uint64_t margin_ns;
|
||||||
|
} app; //!< App statistics.
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
//! The last display time that the thing driving this helper got.
|
||||||
|
uint64_t predicted_display_time_ns;
|
||||||
|
//! The last display period the hardware is running at.
|
||||||
|
uint64_t predicted_display_period_ns;
|
||||||
|
//! The extra time needed by the thing driving this helper.
|
||||||
|
uint64_t extra_ns;
|
||||||
|
} last_input;
|
||||||
|
|
||||||
|
uint64_t last_returned_ns;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Helpers
|
* Helpers
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static inline struct render_timing *
|
||||||
|
render_timing(struct u_render_timing *urt)
|
||||||
|
{
|
||||||
|
return (struct render_timing *)urt;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_GET_ONCE_LOG_OPTION(ll, "U_TIMING_RENDER_LOG", U_LOGGING_WARN)
|
DEBUG_GET_ONCE_LOG_OPTION(ll, "U_TIMING_RENDER_LOG", U_LOGGING_WARN)
|
||||||
|
|
||||||
#define RT_LOG_T(...) U_LOG_IFL_T(debug_get_log_option_ll(), __VA_ARGS__)
|
#define RT_LOG_T(...) U_LOG_IFL_T(debug_get_log_option_ll(), __VA_ARGS__)
|
||||||
|
@ -33,59 +108,59 @@ DEBUG_GET_ONCE_LOG_OPTION(ll, "U_TIMING_RENDER_LOG", U_LOGGING_WARN)
|
||||||
#define RT_LOG_E(...) U_LOG_IFL_E(debug_get_log_option_ll(), __VA_ARGS__)
|
#define RT_LOG_E(...) U_LOG_IFL_E(debug_get_log_option_ll(), __VA_ARGS__)
|
||||||
|
|
||||||
#define DEBUG_PRINT_FRAME_ID() RT_LOG_T("%" PRIi64, frame_id)
|
#define DEBUG_PRINT_FRAME_ID() RT_LOG_T("%" PRIi64, frame_id)
|
||||||
#define GET_INDEX_FROM_ID(URTH, ID) ((uint64_t)(ID) % ARRAY_SIZE((URTH)->frames))
|
#define GET_INDEX_FROM_ID(RT, ID) ((uint64_t)(ID) % ARRAY_SIZE((RT)->frames))
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
min_period(const struct u_rt_helper *urth)
|
min_period(const struct render_timing *rt)
|
||||||
{
|
{
|
||||||
return urth->last_input.predicted_display_period_ns;
|
return rt->last_input.predicted_display_period_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
last_sample_displayed(const struct u_rt_helper *urth)
|
last_sample_displayed(const struct render_timing *rt)
|
||||||
{
|
{
|
||||||
return urth->last_input.predicted_display_time_ns;
|
return rt->last_input.predicted_display_time_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
last_return_predicted_display(const struct u_rt_helper *urth)
|
last_return_predicted_display(const struct render_timing *rt)
|
||||||
{
|
{
|
||||||
return urth->last_returned_ns;
|
return rt->last_returned_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
total_app_time_ns(const struct u_rt_helper *urth)
|
total_app_time_ns(const struct render_timing *rt)
|
||||||
{
|
{
|
||||||
return urth->app.cpu_time_ns + urth->app.draw_time_ns;
|
return rt->app.cpu_time_ns + rt->app.draw_time_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
total_app_and_compositor_time_ns(const struct u_rt_helper *urth)
|
total_app_and_compositor_time_ns(const struct render_timing *rt)
|
||||||
{
|
{
|
||||||
return total_app_time_ns(urth) + urth->app.margin_ns + urth->last_input.extra_ns;
|
return total_app_time_ns(rt) + rt->app.margin_ns + rt->last_input.extra_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
predict_display_time(struct u_rt_helper *urth)
|
predict_display_time(const struct render_timing *rt)
|
||||||
{
|
{
|
||||||
// Now
|
// Now
|
||||||
uint64_t now_ns = os_monotonic_get_ns();
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
|
|
||||||
// Error checking.
|
// Error checking.
|
||||||
uint64_t period_ns = min_period(urth);
|
uint64_t period_ns = min_period(rt);
|
||||||
if (period_ns == 0) {
|
if (period_ns == 0) {
|
||||||
assert(false && "Have not yet received and samples from timing driver.");
|
assert(false && "Have not yet received and samples from timing driver.");
|
||||||
return now_ns;
|
return now_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total app and compositor time to produce a frame
|
// Total app and compositor time to produce a frame
|
||||||
uint64_t app_and_compositor_time_ns = total_app_and_compositor_time_ns(urth);
|
uint64_t app_and_compositor_time_ns = total_app_and_compositor_time_ns(rt);
|
||||||
|
|
||||||
// Start from the last time that the driver displayed something.
|
// Start from the last time that the driver displayed something.
|
||||||
uint64_t val = last_sample_displayed(urth);
|
uint64_t val = last_sample_displayed(rt);
|
||||||
|
|
||||||
// Return a time after the last returned display time.
|
// Return a time after the last returned display time.
|
||||||
while (val < last_return_predicted_display(urth)) {
|
while (val < last_return_predicted_display(rt)) {
|
||||||
val += period_ns;
|
val += period_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,122 +175,110 @@ predict_display_time(struct u_rt_helper *urth)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* 'Exported' functions.
|
* Member functions.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static void
|
||||||
u_rt_helper_client_clear(struct u_rt_helper *urth)
|
rt_predict(struct u_render_timing *urt,
|
||||||
|
int64_t *out_frame_id,
|
||||||
|
uint64_t *out_wake_up_time,
|
||||||
|
uint64_t *out_predicted_display_time,
|
||||||
|
uint64_t *out_predicted_display_period)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(urth->frames); i++) {
|
struct render_timing *rt = render_timing(urt);
|
||||||
urth->frames[i].state = U_RT_READY;
|
|
||||||
urth->frames[i].frame_id = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
urth->app.cpu_time_ns = U_TIME_1MS_IN_NS * 2;
|
int64_t frame_id = ++rt->frame_counter;
|
||||||
urth->app.draw_time_ns = U_TIME_1MS_IN_NS * 2;
|
|
||||||
urth->app.margin_ns = U_TIME_1MS_IN_NS / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
u_rt_helper_init(struct u_rt_helper *urth)
|
|
||||||
{
|
|
||||||
U_ZERO(urth);
|
|
||||||
u_rt_helper_client_clear(urth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
u_rt_helper_predict(struct u_rt_helper *urth,
|
|
||||||
int64_t *out_frame_id,
|
|
||||||
uint64_t *out_wake_up_time,
|
|
||||||
uint64_t *out_predicted_display_time,
|
|
||||||
uint64_t *out_predicted_display_period)
|
|
||||||
{
|
|
||||||
int64_t frame_id = ++urth->frame_counter;
|
|
||||||
*out_frame_id = frame_id;
|
*out_frame_id = frame_id;
|
||||||
|
|
||||||
DEBUG_PRINT_FRAME_ID();
|
DEBUG_PRINT_FRAME_ID();
|
||||||
|
|
||||||
uint64_t predict_ns = predict_display_time(urth);
|
uint64_t predict_ns = predict_display_time(rt);
|
||||||
|
|
||||||
urth->last_returned_ns = predict_ns;
|
rt->last_returned_ns = predict_ns;
|
||||||
|
|
||||||
*out_wake_up_time = predict_ns - total_app_and_compositor_time_ns(urth);
|
*out_wake_up_time = predict_ns - total_app_and_compositor_time_ns(rt);
|
||||||
*out_predicted_display_time = predict_ns;
|
*out_predicted_display_time = predict_ns;
|
||||||
*out_predicted_display_period = min_period(urth);
|
*out_predicted_display_period = min_period(rt);
|
||||||
|
|
||||||
size_t index = GET_INDEX_FROM_ID(urth, frame_id);
|
size_t index = GET_INDEX_FROM_ID(rt, frame_id);
|
||||||
assert(urth->frames[index].frame_id == -1);
|
assert(rt->frames[index].frame_id == -1);
|
||||||
assert(urth->frames[index].state == U_RT_READY);
|
assert(rt->frames[index].state == U_RT_READY);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When the client should deliver the frame to us, take into account the
|
* When the client should deliver the frame to us, take into account the
|
||||||
* extra time needed by the main loop, plus a bit of extra time.
|
* extra time needed by the main loop, plus a bit of extra time.
|
||||||
*/
|
*/
|
||||||
uint64_t delivery_time_ns = predict_ns - urth->last_input.extra_ns - U_TIME_HALF_MS_IN_NS;
|
uint64_t delivery_time_ns = predict_ns - rt->last_input.extra_ns - U_TIME_HALF_MS_IN_NS;
|
||||||
|
|
||||||
urth->frames[index].when.predicted_ns = os_monotonic_get_ns();
|
rt->frames[index].when.predicted_ns = os_monotonic_get_ns();
|
||||||
urth->frames[index].state = U_RT_PREDICTED;
|
rt->frames[index].state = U_RT_PREDICTED;
|
||||||
urth->frames[index].frame_id = frame_id;
|
rt->frames[index].frame_id = frame_id;
|
||||||
urth->frames[index].predicted_delivery_time_ns = delivery_time_ns;
|
rt->frames[index].predicted_delivery_time_ns = delivery_time_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
u_rt_helper_mark(struct u_rt_helper *urth, int64_t frame_id, enum u_timing_point point, uint64_t when_ns)
|
rt_mark_point(struct u_render_timing *urt, int64_t frame_id, enum u_timing_point point, uint64_t when_ns)
|
||||||
{
|
{
|
||||||
|
struct render_timing *rt = render_timing(urt);
|
||||||
|
|
||||||
DEBUG_PRINT_FRAME_ID();
|
DEBUG_PRINT_FRAME_ID();
|
||||||
|
|
||||||
size_t index = GET_INDEX_FROM_ID(urth, frame_id);
|
size_t index = GET_INDEX_FROM_ID(rt, frame_id);
|
||||||
assert(urth->frames[index].frame_id == frame_id);
|
assert(rt->frames[index].frame_id == frame_id);
|
||||||
|
|
||||||
switch (point) {
|
switch (point) {
|
||||||
case U_TIMING_POINT_WAKE_UP:
|
case U_TIMING_POINT_WAKE_UP:
|
||||||
assert(urth->frames[index].state == U_RT_PREDICTED);
|
assert(rt->frames[index].state == U_RT_PREDICTED);
|
||||||
|
|
||||||
urth->frames[index].when.wait_woke_ns = when_ns;
|
rt->frames[index].when.wait_woke_ns = when_ns;
|
||||||
urth->frames[index].state = U_RT_WAIT_LEFT;
|
rt->frames[index].state = U_RT_WAIT_LEFT;
|
||||||
break;
|
break;
|
||||||
case U_TIMING_POINT_BEGIN:
|
case U_TIMING_POINT_BEGIN:
|
||||||
assert(urth->frames[index].state == U_RT_WAIT_LEFT);
|
assert(rt->frames[index].state == U_RT_WAIT_LEFT);
|
||||||
|
|
||||||
urth->frames[index].when.begin_ns = os_monotonic_get_ns();
|
rt->frames[index].when.begin_ns = os_monotonic_get_ns();
|
||||||
urth->frames[index].state = U_RT_BEGUN;
|
rt->frames[index].state = U_RT_BEGUN;
|
||||||
break;
|
break;
|
||||||
case U_TIMING_POINT_SUBMIT:
|
case U_TIMING_POINT_SUBMIT:
|
||||||
default: assert(false);
|
default: assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
u_rt_helper_mark_discarded(struct u_rt_helper *urth, int64_t frame_id)
|
rt_mark_discarded(struct u_render_timing *urt, int64_t frame_id)
|
||||||
{
|
{
|
||||||
|
struct render_timing *rt = render_timing(urt);
|
||||||
|
|
||||||
DEBUG_PRINT_FRAME_ID();
|
DEBUG_PRINT_FRAME_ID();
|
||||||
|
|
||||||
size_t index = GET_INDEX_FROM_ID(urth, frame_id);
|
size_t index = GET_INDEX_FROM_ID(rt, frame_id);
|
||||||
assert(urth->frames[index].frame_id == frame_id);
|
assert(rt->frames[index].frame_id == frame_id);
|
||||||
assert(urth->frames[index].state == U_RT_WAIT_LEFT || urth->frames[index].state == U_RT_BEGUN);
|
assert(rt->frames[index].state == U_RT_WAIT_LEFT || rt->frames[index].state == U_RT_BEGUN);
|
||||||
|
|
||||||
urth->frames[index].when.delivered_ns = os_monotonic_get_ns();
|
rt->frames[index].when.delivered_ns = os_monotonic_get_ns();
|
||||||
urth->frames[index].state = U_RT_READY;
|
rt->frames[index].state = U_RT_READY;
|
||||||
urth->frames[index].frame_id = -1;
|
rt->frames[index].frame_id = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id)
|
rt_mark_delivered(struct u_render_timing *urt, int64_t frame_id)
|
||||||
{
|
{
|
||||||
|
struct render_timing *rt = render_timing(urt);
|
||||||
|
|
||||||
DEBUG_PRINT_FRAME_ID();
|
DEBUG_PRINT_FRAME_ID();
|
||||||
|
|
||||||
size_t index = GET_INDEX_FROM_ID(urth, frame_id);
|
size_t index = GET_INDEX_FROM_ID(rt, frame_id);
|
||||||
assert(urth->frames[index].frame_id == frame_id);
|
assert(rt->frames[index].frame_id == frame_id);
|
||||||
assert(urth->frames[index].state == U_RT_BEGUN);
|
assert(rt->frames[index].state == U_RT_BEGUN);
|
||||||
|
|
||||||
uint64_t now_ns = os_monotonic_get_ns();
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
|
|
||||||
urth->frames[index].when.delivered_ns = now_ns;
|
rt->frames[index].when.delivered_ns = now_ns;
|
||||||
urth->frames[index].state = U_RT_READY;
|
rt->frames[index].state = U_RT_READY;
|
||||||
urth->frames[index].frame_id = -1;
|
rt->frames[index].frame_id = -1;
|
||||||
|
|
||||||
int64_t diff_ns = urth->frames[index].predicted_delivery_time_ns - now_ns;
|
int64_t diff_ns = rt->frames[index].predicted_delivery_time_ns - now_ns;
|
||||||
bool late = false;
|
bool late = false;
|
||||||
if (diff_ns < 0) {
|
if (diff_ns < 0) {
|
||||||
diff_ns = -diff_ns;
|
diff_ns = -diff_ns;
|
||||||
|
@ -226,13 +289,52 @@ u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id)
|
||||||
RT_LOG_D("Delivered frame %i.%02ims %s.", (int)ms100 / 100, (int)ms100 % 100, late ? "late" : "early");
|
RT_LOG_D("Delivered frame %i.%02ims %s.", (int)ms100 / 100, (int)ms100 % 100, late ? "late" : "early");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
u_rt_helper_new_sample(struct u_rt_helper *urth,
|
rt_info(struct u_render_timing *urt,
|
||||||
uint64_t predicted_display_time_ns,
|
uint64_t predicted_display_time_ns,
|
||||||
uint64_t predicted_display_period_ns,
|
uint64_t predicted_display_period_ns,
|
||||||
uint64_t extra_ns)
|
uint64_t extra_ns)
|
||||||
{
|
{
|
||||||
urth->last_input.predicted_display_time_ns = predicted_display_time_ns;
|
struct render_timing *rt = render_timing(urt);
|
||||||
urth->last_input.predicted_display_period_ns = predicted_display_period_ns;
|
|
||||||
urth->last_input.extra_ns = extra_ns;
|
rt->last_input.predicted_display_time_ns = predicted_display_time_ns;
|
||||||
|
rt->last_input.predicted_display_period_ns = predicted_display_period_ns;
|
||||||
|
rt->last_input.extra_ns = extra_ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rt_destroy(struct u_render_timing *urt)
|
||||||
|
{
|
||||||
|
free(urt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 'Exported' functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
xrt_result_t
|
||||||
|
u_rt_create(struct u_render_timing **out_urt)
|
||||||
|
{
|
||||||
|
struct render_timing *rt = U_TYPED_CALLOC(struct render_timing);
|
||||||
|
rt->base.predict = rt_predict;
|
||||||
|
rt->base.mark_point = rt_mark_point;
|
||||||
|
rt->base.mark_discarded = rt_mark_discarded;
|
||||||
|
rt->base.mark_delivered = rt_mark_delivered;
|
||||||
|
rt->base.info = rt_info;
|
||||||
|
rt->base.destroy = rt_destroy;
|
||||||
|
rt->app.cpu_time_ns = U_TIME_1MS_IN_NS * 2;
|
||||||
|
rt->app.draw_time_ns = U_TIME_1MS_IN_NS * 2;
|
||||||
|
rt->app.margin_ns = U_TIME_1MS_IN_NS / 2;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(rt->frames); i++) {
|
||||||
|
rt->frames[i].state = U_RT_READY;
|
||||||
|
rt->frames[i].frame_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_urt = &rt->base;
|
||||||
|
|
||||||
|
return XRT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
// Copyright 2020-2021, Collabora, Ltd.
|
|
||||||
// SPDX-License-Identifier: BSL-1.0
|
|
||||||
/*!
|
|
||||||
* @file
|
|
||||||
* @brief Shared frame timing code.
|
|
||||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
|
||||||
* @ingroup aux_util
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "xrt/xrt_compiler.h"
|
|
||||||
#include "os/os_time.h"
|
|
||||||
#include "util/u_timing.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
enum u_rt_state
|
|
||||||
{
|
|
||||||
U_RT_READY,
|
|
||||||
U_RT_WAIT_LEFT,
|
|
||||||
U_RT_PREDICTED,
|
|
||||||
U_RT_BEGUN,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct u_rt_frame
|
|
||||||
{
|
|
||||||
//! When we predicted this frame to be shown.
|
|
||||||
uint64_t predicted_display_time_ns;
|
|
||||||
//! When the client should have delivered the frame.
|
|
||||||
uint64_t predicted_delivery_time_ns;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint64_t predicted_ns;
|
|
||||||
uint64_t wait_woke_ns;
|
|
||||||
uint64_t begin_ns;
|
|
||||||
uint64_t delivered_ns;
|
|
||||||
} when; //!< When something happened.
|
|
||||||
|
|
||||||
int64_t frame_id;
|
|
||||||
enum u_rt_state state;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This render timing helper is designed to schedule the rendering time of
|
|
||||||
* clients that submit frames to a compositor, which runs its own render loop
|
|
||||||
* that picks latest completed frames for that client.
|
|
||||||
*/
|
|
||||||
struct u_rt_helper
|
|
||||||
{
|
|
||||||
struct u_rt_frame frames[2];
|
|
||||||
uint32_t current_frame;
|
|
||||||
uint32_t next_frame;
|
|
||||||
|
|
||||||
int64_t frame_counter;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
//! App time between wait returning and begin being called.
|
|
||||||
uint64_t cpu_time_ns;
|
|
||||||
//! Time between begin and frame rendering completeing.
|
|
||||||
uint64_t draw_time_ns;
|
|
||||||
//! Exrta time between end of draw time and when the compositor wakes up.
|
|
||||||
uint64_t margin_ns;
|
|
||||||
} app; //!< App statistics.
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
//! The last display time that the thing driving this helper got.
|
|
||||||
uint64_t predicted_display_time_ns;
|
|
||||||
//! The last display period the hardware is running at.
|
|
||||||
uint64_t predicted_display_period_ns;
|
|
||||||
//! The extra time needed by the thing driving this helper.
|
|
||||||
uint64_t extra_ns;
|
|
||||||
} last_input;
|
|
||||||
|
|
||||||
uint64_t last_returned_ns;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
u_rt_helper_init(struct u_rt_helper *urth);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This function gets the client part of the render timing helper ready to be
|
|
||||||
* used. If you use init you will also clear all of the timing information.
|
|
||||||
*
|
|
||||||
* Call this when resetting a client.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
u_rt_helper_client_clear(struct u_rt_helper *urth);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Predict when the client's next: rendered frame will be display; when the
|
|
||||||
* client should be woken up from sleeping; and its display period.
|
|
||||||
*
|
|
||||||
* This is called from `xrWaitFrame`, but it does not do any waiting, the caller
|
|
||||||
* should wait till `out_wake_up_time`.
|
|
||||||
*
|
|
||||||
* @param urth Render timing helper.
|
|
||||||
* @param[out] out_frame_id Frame ID of this predicted frame.
|
|
||||||
* @param[out] out_wake_up_time When the client should be woken up.
|
|
||||||
* @param[out] out_predicted_display_time Predicted display time.
|
|
||||||
* @param[out] out_predicted_display_period Predicted display period.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
u_rt_helper_predict(struct u_rt_helper *urth,
|
|
||||||
int64_t *out_frame_id,
|
|
||||||
uint64_t *out_wake_up_time,
|
|
||||||
uint64_t *out_predicted_display_time,
|
|
||||||
uint64_t *out_predicted_display_period);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Mark a point on the frame's lifetime.
|
|
||||||
*
|
|
||||||
* @see @ref frame-timing.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
u_rt_helper_mark(struct u_rt_helper *urth, int64_t frame_id, enum u_timing_point point, uint64_t when_ns);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* When a frame has been discarded.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
u_rt_helper_mark_discarded(struct u_rt_helper *urth, int64_t frame_id);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* A frame has been delivered from the client, see `xrEndFrame`. The GPU might
|
|
||||||
* still be rendering the work.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Add a new sample point from the main render loop.
|
|
||||||
*
|
|
||||||
* This is called in the main renderer loop that tightly submits frames to the
|
|
||||||
* real compositor for displaying. This is only used to inform the render helper
|
|
||||||
* when the frame will be shown, not any timing information about the client.
|
|
||||||
*
|
|
||||||
* When this is called doesn't matter that much, as the render timing will need
|
|
||||||
* to be able to predict one or more frames into the future anyways. But
|
|
||||||
* preferably as soon as the main loop wakes up from wait frame.
|
|
||||||
*
|
|
||||||
* @param urth Self pointer
|
|
||||||
* @param predicted_display_time_ns Predicted display time for this sample.
|
|
||||||
* @param predicted_display_period_ns Predicted display period for this sample.
|
|
||||||
* @param extra_ns Time between display and when this sample
|
|
||||||
* was created, that is when the main loop
|
|
||||||
* was woken up by the main compositor.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
u_rt_helper_new_sample(struct u_rt_helper *urth,
|
|
||||||
uint64_t predicted_display_time_ns,
|
|
||||||
uint64_t predicted_display_period_ns,
|
|
||||||
uint64_t extra_ns);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -197,8 +197,8 @@ multi_compositor_predict_frame(struct xrt_compositor *xc,
|
||||||
|
|
||||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||||
|
|
||||||
u_rt_helper_predict( //
|
u_rt_predict( //
|
||||||
&mc->urth, //
|
mc->urt, //
|
||||||
out_frame_id, //
|
out_frame_id, //
|
||||||
out_wake_time_ns, //
|
out_wake_time_ns, //
|
||||||
out_predicted_display_time_ns, //
|
out_predicted_display_time_ns, //
|
||||||
|
@ -223,7 +223,7 @@ multi_compositor_mark_frame(struct xrt_compositor *xc,
|
||||||
case XRT_COMPOSITOR_FRAME_POINT_WOKE:
|
case XRT_COMPOSITOR_FRAME_POINT_WOKE:
|
||||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||||
uint64_t now_ns = os_monotonic_get_ns();
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
u_rt_helper_mark(&mc->urth, frame_id, U_TIMING_POINT_WAKE_UP, now_ns);
|
u_rt_mark_point(mc->urt, frame_id, U_TIMING_POINT_WAKE_UP, now_ns);
|
||||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||||
break;
|
break;
|
||||||
default: assert(false);
|
default: assert(false);
|
||||||
|
@ -255,7 +255,7 @@ multi_compositor_begin_frame(struct xrt_compositor *xc, int64_t frame_id)
|
||||||
|
|
||||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||||
uint64_t now_ns = os_monotonic_get_ns();
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
u_rt_helper_mark(&mc->urth, frame_id, U_TIMING_POINT_BEGIN, now_ns);
|
u_rt_mark_point(mc->urt, frame_id, U_TIMING_POINT_BEGIN, now_ns);
|
||||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||||
|
|
||||||
return XRT_SUCCESS;
|
return XRT_SUCCESS;
|
||||||
|
@ -269,7 +269,7 @@ multi_compositor_discard_frame(struct xrt_compositor *xc, int64_t frame_id)
|
||||||
struct multi_compositor *mc = multi_compositor(xc);
|
struct multi_compositor *mc = multi_compositor(xc);
|
||||||
|
|
||||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||||
u_rt_helper_mark_discarded(&mc->urth, frame_id);
|
u_rt_mark_discarded(mc->urt, frame_id);
|
||||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||||
|
|
||||||
return XRT_SUCCESS;
|
return XRT_SUCCESS;
|
||||||
|
@ -451,7 +451,7 @@ multi_compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id, xrt_g
|
||||||
|
|
||||||
slot_move_and_clear(&mc->delivered, &mc->progress);
|
slot_move_and_clear(&mc->delivered, &mc->progress);
|
||||||
|
|
||||||
u_rt_helper_mark_delivered(&mc->urth, frame_id);
|
u_rt_mark_delivered(mc->urt, frame_id);
|
||||||
|
|
||||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||||
|
|
||||||
|
@ -494,6 +494,9 @@ multi_compositor_destroy(struct xrt_compositor *xc)
|
||||||
slot_clear(&mc->progress);
|
slot_clear(&mc->progress);
|
||||||
slot_clear(&mc->delivered);
|
slot_clear(&mc->delivered);
|
||||||
|
|
||||||
|
// Does null checking.
|
||||||
|
u_rt_destroy(&mc->urt);
|
||||||
|
|
||||||
free(mc);
|
free(mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,8 +537,7 @@ multi_compositor_create(struct multi_system_compositor *msc,
|
||||||
mc->base.base.info = msc->xcn->base.info;
|
mc->base.base.info = msc->xcn->base.info;
|
||||||
|
|
||||||
// This is safe to do without a lock since we are not on the list yet.
|
// This is safe to do without a lock since we are not on the list yet.
|
||||||
u_rt_helper_init(&mc->urth);
|
u_rt_create(&mc->urt);
|
||||||
u_rt_helper_client_clear(&mc->urth);
|
|
||||||
|
|
||||||
os_mutex_lock(&msc->list_and_timing_lock);
|
os_mutex_lock(&msc->list_and_timing_lock);
|
||||||
|
|
||||||
|
@ -548,8 +550,8 @@ multi_compositor_create(struct multi_system_compositor *msc,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_rt_helper_new_sample( //
|
u_rt_info( //
|
||||||
&mc->urth, //
|
mc->urt, //
|
||||||
msc->last_timings.predicted_display_time_ns, //
|
msc->last_timings.predicted_display_time_ns, //
|
||||||
msc->last_timings.predicted_display_period_ns, //
|
msc->last_timings.predicted_display_period_ns, //
|
||||||
msc->last_timings.diff_ns); //
|
msc->last_timings.diff_ns); //
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include "os/os_time.h"
|
#include "os/os_time.h"
|
||||||
#include "os/os_threading.h"
|
#include "os/os_threading.h"
|
||||||
|
|
||||||
#include "util/u_timing_render.h"
|
#include "util/u_timing.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -128,7 +128,7 @@ struct multi_compositor
|
||||||
//! Fully ready to be used.
|
//! Fully ready to be used.
|
||||||
struct multi_layer_slot delivered;
|
struct multi_layer_slot delivered;
|
||||||
|
|
||||||
struct u_rt_helper urth;
|
struct u_render_timing *urt;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct multi_compositor *
|
static inline struct multi_compositor *
|
||||||
|
|
|
@ -271,8 +271,8 @@ broadcast_timings(struct multi_system_compositor *msc,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_rt_helper_new_sample( //
|
u_rt_info( //
|
||||||
&mc->urth, //
|
mc->urt, //
|
||||||
predicted_display_time_ns, //
|
predicted_display_time_ns, //
|
||||||
predicted_display_period_ns, //
|
predicted_display_period_ns, //
|
||||||
diff_ns); //
|
diff_ns); //
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "xrt/xrt_compiler.h"
|
#include "xrt/xrt_compiler.h"
|
||||||
|
|
||||||
#include "util/u_logging.h"
|
#include "util/u_logging.h"
|
||||||
#include "util/u_timing_render.h"
|
|
||||||
|
|
||||||
#include "os/os_threading.h"
|
#include "os/os_threading.h"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue