From 8215af5e5c0aabeb78d4249689cd0e2d983947f6 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz <jakob@collabora.com> Date: Fri, 2 Apr 2021 19:43:01 +0100 Subject: [PATCH] u/rt: Refactor render timing --- src/xrt/auxiliary/CMakeLists.txt | 1 - src/xrt/auxiliary/meson.build | 1 - src/xrt/auxiliary/util/u_timing.h | 208 ++++++++++++- src/xrt/auxiliary/util/u_timing_render.c | 284 ++++++++++++------ src/xrt/auxiliary/util/u_timing_render.h | 165 ---------- .../compositor/multi/comp_multi_compositor.c | 22 +- src/xrt/compositor/multi/comp_multi_private.h | 4 +- src/xrt/compositor/multi/comp_multi_system.c | 4 +- src/xrt/ipc/server/ipc_server.h | 1 - 9 files changed, 404 insertions(+), 286 deletions(-) delete mode 100644 src/xrt/auxiliary/util/u_timing_render.h diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index 455945fb9..0827faac9 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -152,7 +152,6 @@ set(UTIL_SOURCE_FILES util/u_timing_fake.c util/u_timing_frame.c util/u_timing_render.c - util/u_timing_render.h util/u_trace_marker.c util/u_trace_marker.h util/u_var.cpp diff --git a/src/xrt/auxiliary/meson.build b/src/xrt/auxiliary/meson.build index 42ad0a246..aac2fc21a 100644 --- a/src/xrt/auxiliary/meson.build +++ b/src/xrt/auxiliary/meson.build @@ -58,7 +58,6 @@ lib_aux_util = static_library( 'util/u_timing_fake.c', 'util/u_timing_frame.c', 'util/u_timing_render.c', - 'util/u_timing_render.h', 'util/u_trace_marker.c', 'util/u_trace_marker.h', 'util/u_var.cpp', diff --git a/src/xrt/auxiliary/util/u_timing.h b/src/xrt/auxiliary/util/u_timing.h index 09709e18d..d0f704f04 100644 --- a/src/xrt/auxiliary/util/u_timing.h +++ b/src/xrt/auxiliary/util/u_timing.h @@ -25,12 +25,6 @@ extern "C" { */ -/* - * - * Frame timing helper. - * - */ - /*! * 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. }; + +/* + * + * Frame timing helper. + * + */ + /*! * 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); }; - -/* - * - * Helper functions. - * - */ - /*! * @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. @@ -216,6 +390,14 @@ u_ft_display_timing_create(uint64_t estimated_frame_period_ns, struct u_frame_ti xrt_result_t 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 } diff --git a/src/xrt/auxiliary/util/u_timing_render.c b/src/xrt/auxiliary/util/u_timing_render.c index f6824b1cd..68e729d56 100644 --- a/src/xrt/auxiliary/util/u_timing_render.c +++ b/src/xrt/auxiliary/util/u_timing_render.c @@ -7,23 +7,98 @@ * @ingroup aux_util */ +#include "os/os_time.h" + #include "util/u_time.h" #include "util/u_misc.h" #include "util/u_debug.h" #include "util/u_logging.h" -#include "util/u_timing_render.h" +#include "util/u_timing.h" #include <stdio.h> #include <assert.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 * */ +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) #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 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 -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 -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 -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 -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 -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 -predict_display_time(struct u_rt_helper *urth) +predict_display_time(const struct render_timing *rt) { // Now uint64_t now_ns = os_monotonic_get_ns(); // Error checking. - uint64_t period_ns = min_period(urth); + uint64_t period_ns = min_period(rt); if (period_ns == 0) { assert(false && "Have not yet received and samples from timing driver."); return now_ns; } // 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. - uint64_t val = last_sample_displayed(urth); + uint64_t val = last_sample_displayed(rt); // 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; } @@ -100,122 +175,110 @@ predict_display_time(struct u_rt_helper *urth) /* * - * 'Exported' functions. + * Member functions. * */ -void -u_rt_helper_client_clear(struct u_rt_helper *urth) +static void +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++) { - urth->frames[i].state = U_RT_READY; - urth->frames[i].frame_id = -1; - } + struct render_timing *rt = render_timing(urt); - urth->app.cpu_time_ns = U_TIME_1MS_IN_NS * 2; - 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; + int64_t frame_id = ++rt->frame_counter; *out_frame_id = 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_period = min_period(urth); + *out_predicted_display_period = min_period(rt); - size_t index = GET_INDEX_FROM_ID(urth, frame_id); - assert(urth->frames[index].frame_id == -1); - assert(urth->frames[index].state == U_RT_READY); + size_t index = GET_INDEX_FROM_ID(rt, frame_id); + assert(rt->frames[index].frame_id == -1); + assert(rt->frames[index].state == U_RT_READY); /* * 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. */ - 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(); - urth->frames[index].state = U_RT_PREDICTED; - urth->frames[index].frame_id = frame_id; - urth->frames[index].predicted_delivery_time_ns = delivery_time_ns; + rt->frames[index].when.predicted_ns = os_monotonic_get_ns(); + rt->frames[index].state = U_RT_PREDICTED; + rt->frames[index].frame_id = frame_id; + rt->frames[index].predicted_delivery_time_ns = delivery_time_ns; } -void -u_rt_helper_mark(struct u_rt_helper *urth, int64_t frame_id, enum u_timing_point point, uint64_t when_ns) +static void +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(); - size_t index = GET_INDEX_FROM_ID(urth, frame_id); - assert(urth->frames[index].frame_id == frame_id); + size_t index = GET_INDEX_FROM_ID(rt, frame_id); + assert(rt->frames[index].frame_id == frame_id); switch (point) { 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; - urth->frames[index].state = U_RT_WAIT_LEFT; + rt->frames[index].when.wait_woke_ns = when_ns; + rt->frames[index].state = U_RT_WAIT_LEFT; break; 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(); - urth->frames[index].state = U_RT_BEGUN; + rt->frames[index].when.begin_ns = os_monotonic_get_ns(); + rt->frames[index].state = U_RT_BEGUN; break; case U_TIMING_POINT_SUBMIT: default: assert(false); } } -void -u_rt_helper_mark_discarded(struct u_rt_helper *urth, int64_t frame_id) +static void +rt_mark_discarded(struct u_render_timing *urt, int64_t frame_id) { + struct render_timing *rt = render_timing(urt); + DEBUG_PRINT_FRAME_ID(); - size_t index = GET_INDEX_FROM_ID(urth, frame_id); - assert(urth->frames[index].frame_id == frame_id); - assert(urth->frames[index].state == U_RT_WAIT_LEFT || urth->frames[index].state == U_RT_BEGUN); + size_t index = GET_INDEX_FROM_ID(rt, frame_id); + assert(rt->frames[index].frame_id == frame_id); + 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(); - urth->frames[index].state = U_RT_READY; - urth->frames[index].frame_id = -1; + rt->frames[index].when.delivered_ns = os_monotonic_get_ns(); + rt->frames[index].state = U_RT_READY; + rt->frames[index].frame_id = -1; } -void -u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id) +static void +rt_mark_delivered(struct u_render_timing *urt, int64_t frame_id) { + struct render_timing *rt = render_timing(urt); + DEBUG_PRINT_FRAME_ID(); - size_t index = GET_INDEX_FROM_ID(urth, frame_id); - assert(urth->frames[index].frame_id == frame_id); - assert(urth->frames[index].state == U_RT_BEGUN); + size_t index = GET_INDEX_FROM_ID(rt, frame_id); + assert(rt->frames[index].frame_id == frame_id); + assert(rt->frames[index].state == U_RT_BEGUN); uint64_t now_ns = os_monotonic_get_ns(); - urth->frames[index].when.delivered_ns = now_ns; - urth->frames[index].state = U_RT_READY; - urth->frames[index].frame_id = -1; + rt->frames[index].when.delivered_ns = now_ns; + rt->frames[index].state = U_RT_READY; + 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; if (diff_ns < 0) { 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"); } -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) +static void +rt_info(struct u_render_timing *urt, + uint64_t predicted_display_time_ns, + uint64_t predicted_display_period_ns, + uint64_t extra_ns) { - urth->last_input.predicted_display_time_ns = predicted_display_time_ns; - urth->last_input.predicted_display_period_ns = predicted_display_period_ns; - urth->last_input.extra_ns = extra_ns; + struct render_timing *rt = render_timing(urt); + + 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; } diff --git a/src/xrt/auxiliary/util/u_timing_render.h b/src/xrt/auxiliary/util/u_timing_render.h deleted file mode 100644 index 1be3bad3c..000000000 --- a/src/xrt/auxiliary/util/u_timing_render.h +++ /dev/null @@ -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 diff --git a/src/xrt/compositor/multi/comp_multi_compositor.c b/src/xrt/compositor/multi/comp_multi_compositor.c index facad36d2..9c8ad55ef 100644 --- a/src/xrt/compositor/multi/comp_multi_compositor.c +++ b/src/xrt/compositor/multi/comp_multi_compositor.c @@ -197,8 +197,8 @@ multi_compositor_predict_frame(struct xrt_compositor *xc, os_mutex_lock(&mc->msc->list_and_timing_lock); - u_rt_helper_predict( // - &mc->urth, // + u_rt_predict( // + mc->urt, // out_frame_id, // out_wake_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: os_mutex_lock(&mc->msc->list_and_timing_lock); 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); break; 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); 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); 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); 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); 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); - 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); @@ -494,6 +494,9 @@ multi_compositor_destroy(struct xrt_compositor *xc) slot_clear(&mc->progress); slot_clear(&mc->delivered); + // Does null checking. + u_rt_destroy(&mc->urt); + free(mc); } @@ -534,8 +537,7 @@ multi_compositor_create(struct multi_system_compositor *msc, mc->base.base.info = msc->xcn->base.info; // This is safe to do without a lock since we are not on the list yet. - u_rt_helper_init(&mc->urth); - u_rt_helper_client_clear(&mc->urth); + u_rt_create(&mc->urt); os_mutex_lock(&msc->list_and_timing_lock); @@ -548,8 +550,8 @@ multi_compositor_create(struct multi_system_compositor *msc, break; } - u_rt_helper_new_sample( // - &mc->urth, // + u_rt_info( // + mc->urt, // msc->last_timings.predicted_display_time_ns, // msc->last_timings.predicted_display_period_ns, // msc->last_timings.diff_ns); // diff --git a/src/xrt/compositor/multi/comp_multi_private.h b/src/xrt/compositor/multi/comp_multi_private.h index b27261d15..64f4cb551 100644 --- a/src/xrt/compositor/multi/comp_multi_private.h +++ b/src/xrt/compositor/multi/comp_multi_private.h @@ -16,7 +16,7 @@ #include "os/os_time.h" #include "os/os_threading.h" -#include "util/u_timing_render.h" +#include "util/u_timing.h" #ifdef __cplusplus extern "C" { @@ -128,7 +128,7 @@ struct multi_compositor //! Fully ready to be used. struct multi_layer_slot delivered; - struct u_rt_helper urth; + struct u_render_timing *urt; }; static inline struct multi_compositor * diff --git a/src/xrt/compositor/multi/comp_multi_system.c b/src/xrt/compositor/multi/comp_multi_system.c index 20fd21f1a..f2a44a82a 100644 --- a/src/xrt/compositor/multi/comp_multi_system.c +++ b/src/xrt/compositor/multi/comp_multi_system.c @@ -271,8 +271,8 @@ broadcast_timings(struct multi_system_compositor *msc, continue; } - u_rt_helper_new_sample( // - &mc->urth, // + u_rt_info( // + mc->urt, // predicted_display_time_ns, // predicted_display_period_ns, // diff_ns); // diff --git a/src/xrt/ipc/server/ipc_server.h b/src/xrt/ipc/server/ipc_server.h index b247d53c2..5abf0bc1b 100644 --- a/src/xrt/ipc/server/ipc_server.h +++ b/src/xrt/ipc/server/ipc_server.h @@ -14,7 +14,6 @@ #include "xrt/xrt_compiler.h" #include "util/u_logging.h" -#include "util/u_timing_render.h" #include "os/os_threading.h"