aux/util: use int64_t for timestamps in u_pacing

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2298>
This commit is contained in:
Simon Zeni 2024-08-02 15:19:27 -04:00 committed by Rylie Pavlik
parent 8cf2e4bd2b
commit f88705a307
6 changed files with 281 additions and 364 deletions

View file

@ -83,14 +83,14 @@ struct u_pacing_compositor
* @see @ref frame-pacing.
*/
void (*predict)(struct u_pacing_compositor *upc,
uint64_t now_ns,
int64_t now_ns,
int64_t *out_frame_id,
uint64_t *out_wake_up_time_ns,
uint64_t *out_desired_present_time_ns,
uint64_t *out_present_slop_ns,
uint64_t *out_predicted_display_time_ns,
uint64_t *out_predicted_display_period_ns,
uint64_t *out_min_display_period_ns);
int64_t *out_wake_up_time_ns,
int64_t *out_desired_present_time_ns,
int64_t *out_present_slop_ns,
int64_t *out_predicted_display_time_ns,
int64_t *out_predicted_display_period_ns,
int64_t *out_min_display_period_ns);
/*!
* Mark a point on the frame's lifetime.
@ -108,7 +108,7 @@ struct u_pacing_compositor
void (*mark_point)(struct u_pacing_compositor *upc,
enum u_timing_point point,
int64_t frame_id,
uint64_t when_ns);
int64_t when_ns);
/*!
* Provide frame timing information about a delivered frame.
@ -136,11 +136,11 @@ struct u_pacing_compositor
*/
void (*info)(struct u_pacing_compositor *upc,
int64_t frame_id,
uint64_t desired_present_time_ns,
uint64_t actual_present_time_ns,
uint64_t earliest_present_time_ns,
uint64_t present_margin_ns,
uint64_t when_ns);
int64_t desired_present_time_ns,
int64_t actual_present_time_ns,
int64_t earliest_present_time_ns,
int64_t present_margin_ns,
int64_t when_ns);
/*!
* Provide frame timing information about GPU start and stop time.
@ -159,9 +159,9 @@ struct u_pacing_compositor
*/
void (*info_gpu)(struct u_pacing_compositor *upc,
int64_t frame_id,
uint64_t gpu_start_ns,
uint64_t gpu_end_ns,
uint64_t when_ns);
int64_t gpu_start_ns,
int64_t gpu_end_ns,
int64_t when_ns);
/*!
* Provide a vblank timing information, derived from the
@ -174,7 +174,7 @@ struct u_pacing_compositor
*
* @see @ref frame-pacing.
*/
void (*update_vblank_from_display_control)(struct u_pacing_compositor *upc, uint64_t last_vblank_ns);
void (*update_vblank_from_display_control)(struct u_pacing_compositor *upc, int64_t last_vblank_ns);
/*!
* Provide an updated estimate of the present offset.
@ -189,7 +189,7 @@ struct u_pacing_compositor
*/
void (*update_present_offset)(struct u_pacing_compositor *upc,
int64_t frame_id,
uint64_t present_to_display_offset_ns);
int64_t present_to_display_offset_ns);
/*!
* Destroy this u_pacing_compositor.
@ -207,14 +207,14 @@ struct u_pacing_compositor
*/
static inline void
u_pc_predict(struct u_pacing_compositor *upc,
uint64_t now_ns,
int64_t now_ns,
int64_t *out_frame_id,
uint64_t *out_wake_up_time_ns,
uint64_t *out_desired_present_time_ns,
uint64_t *out_present_slop_ns,
uint64_t *out_predicted_display_time_ns,
uint64_t *out_predicted_display_period_ns,
uint64_t *out_min_display_period_ns)
int64_t *out_wake_up_time_ns,
int64_t *out_desired_present_time_ns,
int64_t *out_present_slop_ns,
int64_t *out_predicted_display_time_ns,
int64_t *out_predicted_display_period_ns,
int64_t *out_min_display_period_ns)
{
upc->predict(upc, //
now_ns, //
@ -236,7 +236,7 @@ u_pc_predict(struct u_pacing_compositor *upc,
* @ingroup aux_pacing
*/
static inline void
u_pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, uint64_t when_ns)
u_pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, int64_t when_ns)
{
upc->mark_point(upc, point, frame_id, when_ns);
}
@ -252,11 +252,11 @@ u_pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int6
static inline void
u_pc_info(struct u_pacing_compositor *upc,
int64_t frame_id,
uint64_t desired_present_time_ns,
uint64_t actual_present_time_ns,
uint64_t earliest_present_time_ns,
uint64_t present_margin_ns,
uint64_t when_ns)
int64_t desired_present_time_ns,
int64_t actual_present_time_ns,
int64_t earliest_present_time_ns,
int64_t present_margin_ns,
int64_t when_ns)
{
upc->info(upc, frame_id, desired_present_time_ns, actual_present_time_ns, earliest_present_time_ns,
present_margin_ns, when_ns);
@ -273,7 +273,7 @@ u_pc_info(struct u_pacing_compositor *upc,
*/
static inline void
u_pc_info_gpu(
struct u_pacing_compositor *upc, int64_t frame_id, uint64_t gpu_start_ns, uint64_t gpu_end_ns, uint64_t when_ns)
struct u_pacing_compositor *upc, int64_t frame_id, int64_t gpu_start_ns, int64_t gpu_end_ns, int64_t when_ns)
{
upc->info_gpu(upc, frame_id, gpu_start_ns, gpu_end_ns, when_ns);
}
@ -287,7 +287,7 @@ u_pc_info_gpu(
* @ingroup aux_pacing
*/
static inline void
u_pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, uint64_t last_vblank_ns)
u_pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, int64_t last_vblank_ns)
{
upc->update_vblank_from_display_control(upc, last_vblank_ns);
}
@ -301,7 +301,7 @@ u_pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, uint64_
* @ingroup aux_pacing
*/
static inline void
u_pc_update_present_offset(struct u_pacing_compositor *upc, int64_t frame_id, uint64_t present_to_display_offset_ns)
u_pc_update_present_offset(struct u_pacing_compositor *upc, int64_t frame_id, int64_t present_to_display_offset_ns)
{
upc->update_present_offset(upc, frame_id, present_to_display_offset_ns);
}
@ -362,11 +362,11 @@ struct u_pacing_app
* @param[out] out_predicted_display_period Predicted display period.
*/
void (*predict)(struct u_pacing_app *upa,
uint64_t now_ns,
int64_t now_ns,
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 *out_wake_up_time,
int64_t *out_predicted_display_time,
int64_t *out_predicted_display_period);
/*!
* Mark a point on the frame's lifetime.
@ -378,7 +378,7 @@ struct u_pacing_app
*
* @see @ref frame-pacing.
*/
void (*mark_point)(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, uint64_t when_ns);
void (*mark_point)(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, int64_t when_ns);
/*!
* When a frame has been discarded.
@ -387,7 +387,7 @@ struct u_pacing_app
* @param[in] frame_id The frame ID to mark as discarded.
* @param[in] when_ns The time when it was discarded, nominally from @ref os_monotonic_get_ns
*/
void (*mark_discarded)(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns);
void (*mark_discarded)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns);
/*!
* A frame has been delivered from the client, see `xrEndFrame`. The GPU might
@ -398,7 +398,7 @@ struct u_pacing_app
* @param[in] when_ns The time when it was delivered, nominally from @ref os_monotonic_get_ns
* @param[in] display_time_ns The time the frame is to be displayed.
*/
void (*mark_delivered)(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, uint64_t display_time_ns);
void (*mark_delivered)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t display_time_ns);
/*!
* A frame has been completed rendered by the GPU, this can happen after `xrEndFrame` has returned.
@ -407,7 +407,7 @@ struct u_pacing_app
* @param[in] frame_id The frame ID to mark as delivered.
* @param[in] when_ns The time when it the gpu was finished, nominally from @ref os_monotonic_get_ns
*/
void (*mark_gpu_done)(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns);
void (*mark_gpu_done)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns);
/*!
* Latch a frame for rendering for delivery to the native compositor,
@ -420,7 +420,7 @@ struct u_pacing_app
* @param[in] system_frame_id The ID of the system frame that is
* latching the app's frame.
*/
void (*latched)(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, int64_t system_frame_id);
void (*latched)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t system_frame_id);
/*!
* Mark a frame as completely retired, will never be latched (used by
@ -431,7 +431,7 @@ struct u_pacing_app
* @param[in] frame_id The frame ID of the latched frame.
* @param[in] when_ns Time when the latching happened.
*/
void (*retired)(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns);
void (*retired)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns);
/*!
* Add a new sample point from the main render loop.
@ -452,9 +452,9 @@ struct u_pacing_app
* was woken up by the main compositor.
*/
void (*info)(struct u_pacing_app *upa,
uint64_t predicted_display_time_ns,
uint64_t predicted_display_period_ns,
uint64_t extra_ns);
int64_t predicted_display_time_ns,
int64_t predicted_display_period_ns,
int64_t extra_ns);
/*!
* Destroy this u_pacing_app.
@ -472,11 +472,11 @@ struct u_pacing_app
*/
static inline void
u_pa_predict(struct u_pacing_app *upa,
uint64_t now_ns,
int64_t now_ns,
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 *out_wake_up_time,
int64_t *out_predicted_display_time,
int64_t *out_predicted_display_period)
{
upa->predict(upa, now_ns, out_frame_id, out_wake_up_time, out_predicted_display_time,
out_predicted_display_period);
@ -491,7 +491,7 @@ u_pa_predict(struct u_pacing_app *upa,
* @ingroup aux_pacing
*/
static inline void
u_pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, uint64_t when_ns)
u_pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, int64_t when_ns)
{
upa->mark_point(upa, frame_id, point, when_ns);
}
@ -505,7 +505,7 @@ u_pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point
* @ingroup aux_pacing
*/
static inline void
u_pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
u_pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
{
upa->mark_discarded(upa, frame_id, when_ns);
}
@ -519,7 +519,7 @@ u_pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns
* @ingroup aux_pacing
*/
static inline void
u_pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, uint64_t display_time_ns)
u_pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t display_time_ns)
{
upa->mark_delivered(upa, frame_id, when_ns, display_time_ns);
}
@ -533,7 +533,7 @@ u_pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns
* @ingroup aux_pacing
*/
static inline void
u_pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
u_pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
{
upa->mark_gpu_done(upa, frame_id, when_ns);
}
@ -548,9 +548,9 @@ u_pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
*/
static inline void
u_pa_info(struct u_pacing_app *upa,
uint64_t predicted_display_time_ns,
uint64_t predicted_display_period_ns,
uint64_t extra_ns)
int64_t predicted_display_time_ns,
int64_t predicted_display_period_ns,
int64_t extra_ns)
{
upa->info(upa, predicted_display_time_ns, predicted_display_period_ns, extra_ns);
}
@ -564,7 +564,7 @@ u_pa_info(struct u_pacing_app *upa,
* @ingroup aux_pacing
*/
static inline void
u_pa_latched(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, int64_t system_frame_id)
u_pa_latched(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t system_frame_id)
{
upa->latched(upa, frame_id, when_ns, system_frame_id);
}
@ -578,7 +578,7 @@ u_pa_latched(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, int64
* @ingroup aux_pacing
*/
static inline void
u_pa_retired(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
u_pa_retired(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
{
upa->retired(upa, frame_id, when_ns);
}
@ -680,9 +680,9 @@ u_paf_destroy(struct u_pacing_app_factory **upaf_ptr)
struct u_pc_display_timing_config
{
//! How long after "present" is the image actually displayed
uint64_t present_to_display_offset_ns;
int64_t present_to_display_offset_ns;
//! Extra margin that is added to compositor time, between end of draw and present
uint64_t margin_ns;
int64_t margin_ns;
/*!
* @name Frame-Relative Values
* All these values are in "percentage points of the nominal frame period" so they can work across
@ -725,7 +725,7 @@ extern const struct u_pc_display_timing_config U_PC_DISPLAY_TIMING_CONFIG_DEFAUL
* @see u_pacing_compositor
*/
xrt_result_t
u_pc_display_timing_create(uint64_t estimated_frame_period_ns,
u_pc_display_timing_create(int64_t estimated_frame_period_ns,
const struct u_pc_display_timing_config *config,
struct u_pacing_compositor **out_upc);
@ -742,7 +742,7 @@ u_pc_display_timing_create(uint64_t estimated_frame_period_ns,
* @see u_pacing_compositor
*/
xrt_result_t
u_pc_fake_create(uint64_t estimated_frame_period_ns, uint64_t now_ns, struct u_pacing_compositor **out_upc);
u_pc_fake_create(int64_t estimated_frame_period_ns, int64_t now_ns, struct u_pacing_compositor **out_upc);
/*!
* Creates a new application pacing factory helper.

View file

@ -68,34 +68,34 @@ struct u_pa_frame
int64_t frame_id;
//! How long we thought the frame would take.
uint64_t predicted_frame_time_ns;
int64_t predicted_frame_time_ns;
//! When we predicted the app should wake up.
uint64_t predicted_wake_up_time_ns;
int64_t predicted_wake_up_time_ns;
//! When the client's GPU work should have completed.
uint64_t predicted_gpu_done_time_ns;
int64_t predicted_gpu_done_time_ns;
//! When we predicted this frame to be shown.
uint64_t predicted_display_time_ns;
int64_t predicted_display_time_ns;
//! The selected display period.
uint64_t predicted_display_period_ns;
int64_t predicted_display_period_ns;
/*!
* When the app told us to display this frame, can be different
* then the predicted display time so we track that separately.
*/
uint64_t display_time_ns;
int64_t display_time_ns;
//! When something happened.
struct
{
uint64_t predicted_ns;
uint64_t wait_woke_ns;
uint64_t begin_ns;
uint64_t delivered_ns;
uint64_t gpu_done_ns;
int64_t predicted_ns;
int64_t wait_woke_ns;
int64_t begin_ns;
int64_t delivered_ns;
int64_t gpu_done_ns;
} when;
enum u_pa_state state;
@ -140,24 +140,24 @@ struct pacing_app
struct
{
//! App time between wait returning and begin being called.
uint64_t cpu_time_ns;
int64_t cpu_time_ns;
//! Time between begin and frame data being delivered.
uint64_t draw_time_ns;
int64_t draw_time_ns;
//! Time between the frame data being delivered and GPU completing.
uint64_t gpu_time_ns;
int64_t gpu_time_ns;
} app; //!< App statistics.
struct
{
//! The last display time that the thing driving this helper got.
uint64_t predicted_display_time_ns;
int64_t predicted_display_time_ns;
//! The last display period the hardware is running at.
uint64_t predicted_display_period_ns;
int64_t predicted_display_period_ns;
//! The extra time needed by the thing driving this helper.
uint64_t extra_ns;
int64_t extra_ns;
} last_input;
uint64_t last_returned_ns;
int64_t last_returned_ns;
};
@ -204,56 +204,56 @@ point_to_str(enum u_timing_point point)
#define DEBUG_PRINT_ID_FRAME_POINT(ID, F, P) \
UPA_LOG_T("%" PRIi64 " (%" PRIi64 ", %s) %s", frame_id, F->frame_id, state_to_str(F->state), point_to_str(P));
#define GET_INDEX_FROM_ID(RT, ID) ((uint64_t)(ID) % FRAME_COUNT)
#define GET_INDEX_FROM_ID(RT, ID) ((int64_t)(ID) % FRAME_COUNT)
#define IIR_ALPHA_LT 0.8
#define IIR_ALPHA_GT 0.8
static void
do_iir_filter(uint64_t *target, double alpha_lt, double alpha_gt, uint64_t sample)
do_iir_filter(int64_t *target, double alpha_lt, double alpha_gt, int64_t sample)
{
uint64_t t = *target;
int64_t t = *target;
double alpha = t < sample ? alpha_lt : alpha_gt;
double a = time_ns_to_s(t) * alpha;
double b = time_ns_to_s(sample) * (1.0 - alpha);
*target = time_s_to_ns(a + b);
}
static uint64_t
static int64_t
min_period(const struct pacing_app *pa)
{
return pa->last_input.predicted_display_period_ns;
}
static uint64_t
static int64_t
min_app_time(const struct pacing_app *pa)
{
return (uint64_t)(pa->min_app_time_ms.val * (double)U_TIME_1MS_IN_NS);
return (int64_t)(pa->min_app_time_ms.val * (double)U_TIME_1MS_IN_NS);
}
static uint64_t
static int64_t
margin_time(const struct pacing_app *pa)
{
return (uint64_t)(pa->min_margin_ms.val * (double)U_TIME_1MS_IN_NS);
return (int64_t)(pa->min_margin_ms.val * (double)U_TIME_1MS_IN_NS);
}
static uint64_t
static int64_t
last_sample_displayed(const struct pacing_app *pa)
{
return pa->last_input.predicted_display_time_ns;
}
static uint64_t
static int64_t
last_return_predicted_display(const struct pacing_app *pa)
{
return pa->last_returned_ns;
}
static uint64_t
static int64_t
total_app_time_ns(const struct pacing_app *pa)
{
uint64_t total_ns = pa->app.cpu_time_ns + pa->app.draw_time_ns + pa->app.gpu_time_ns;
uint64_t min_ns = min_app_time(pa);
int64_t total_ns = pa->app.cpu_time_ns + pa->app.draw_time_ns + pa->app.gpu_time_ns;
int64_t min_ns = min_app_time(pa);
if (total_ns < min_ns) {
total_ns = min_ns;
@ -262,30 +262,30 @@ total_app_time_ns(const struct pacing_app *pa)
return total_ns;
}
static uint64_t
static int64_t
total_compositor_time_ns(const struct pacing_app *pa)
{
return margin_time(pa) + pa->last_input.extra_ns;
}
static uint64_t
static int64_t
total_app_and_compositor_time_ns(const struct pacing_app *pa)
{
return total_app_time_ns(pa) + total_compositor_time_ns(pa);
}
static uint64_t
static int64_t
calc_period(const struct pacing_app *pa)
{
// Error checking.
uint64_t base_period_ns = min_period(pa);
int64_t base_period_ns = min_period(pa);
if (base_period_ns == 0) {
assert(false && "Have not yet received and samples from timing driver.");
base_period_ns = U_TIME_1MS_IN_NS * 16; // Sure
}
// Calculate the using both values separately.
uint64_t period_ns = base_period_ns;
int64_t period_ns = base_period_ns;
while (pa->app.cpu_time_ns > period_ns) {
period_ns += base_period_ns;
}
@ -301,15 +301,15 @@ calc_period(const struct pacing_app *pa)
return period_ns;
}
static uint64_t
predict_display_time(const struct pacing_app *pa, uint64_t now_ns, uint64_t period_ns)
static int64_t
predict_display_time(const struct pacing_app *pa, int64_t now_ns, int64_t period_ns)
{
// Total app and compositor time to produce a frame
uint64_t app_and_compositor_time_ns = total_app_and_compositor_time_ns(pa);
int64_t app_and_compositor_time_ns = total_app_and_compositor_time_ns(pa);
// Start from the last time that the driver displayed something.
uint64_t val = last_sample_displayed(pa);
int64_t val = last_sample_displayed(pa);
// Return a time after the last returned display time. Add half the
// display period to the comparison for robustness when the last display
@ -368,16 +368,16 @@ do_tracing(struct pacing_app *pa, struct u_pa_frame *f)
}
#ifdef U_TRACE_TRACY // Uses Tracy specific things.
uint64_t cpu_ns = f->when.begin_ns - f->when.wait_woke_ns;
int64_t cpu_ns = f->when.begin_ns - f->when.wait_woke_ns;
TracyCPlot("App CPU(ms)", time_ns_to_ms_f(cpu_ns));
uint64_t draw_ns = f->when.delivered_ns - f->when.begin_ns;
int64_t draw_ns = f->when.delivered_ns - f->when.begin_ns;
TracyCPlot("App Draw(ms)", time_ns_to_ms_f(draw_ns));
uint64_t gpu_ns = f->when.gpu_done_ns - f->when.delivered_ns;
int64_t gpu_ns = f->when.gpu_done_ns - f->when.delivered_ns;
TracyCPlot("App GPU(ms)", time_ns_to_ms_f(gpu_ns));
uint64_t frame_ns = f->when.gpu_done_ns - f->when.wait_woke_ns;
int64_t frame_ns = f->when.gpu_done_ns - f->when.wait_woke_ns;
TracyCPlot("App Frame(ms)", time_ns_to_ms_f(frame_ns));
int64_t wake_diff_ns = (int64_t)f->when.wait_woke_ns - (int64_t)f->predicted_wake_up_time_ns;
@ -394,7 +394,7 @@ do_tracing(struct pacing_app *pa, struct u_pa_frame *f)
TE_BEG(pa_cpu, f->when.predicted_ns, "sleep");
TE_END(pa_cpu, f->when.wait_woke_ns);
uint64_t cpu_start_ns = f->when.wait_woke_ns + 1;
int64_t cpu_start_ns = f->when.wait_woke_ns + 1;
TE_BEG(pa_cpu, cpu_start_ns, "cpu");
TE_END(pa_cpu, f->when.begin_ns);
@ -432,11 +432,11 @@ do_tracing(struct pacing_app *pa, struct u_pa_frame *f)
static void
pa_predict(struct u_pacing_app *upa,
uint64_t now_ns,
int64_t now_ns,
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 *out_wake_up_time,
int64_t *out_predicted_display_time,
int64_t *out_predicted_display_period)
{
struct pacing_app *pa = pacing_app(upa);
@ -445,7 +445,7 @@ pa_predict(struct u_pacing_app *upa,
DEBUG_PRINT_ID(frame_id);
uint64_t period_ns;
int64_t period_ns;
/*
* We can either limit the application to a calculated frame rate that
@ -458,13 +458,13 @@ pa_predict(struct u_pacing_app *upa,
period_ns = calc_period(pa);
}
uint64_t predict_ns = predict_display_time(pa, now_ns, period_ns);
int64_t predict_ns = predict_display_time(pa, now_ns, period_ns);
// How long we think the frame should take.
uint64_t frame_time_ns = total_app_time_ns(pa);
int64_t frame_time_ns = total_app_time_ns(pa);
// When should the client wake up.
uint64_t wake_up_time_ns = predict_ns - total_app_and_compositor_time_ns(pa);
int64_t wake_up_time_ns = predict_ns - total_app_and_compositor_time_ns(pa);
// When the client's GPU work should have completed.
uint64_t gpu_done_time_ns = predict_ns - total_compositor_time_ns(pa);
int64_t gpu_done_time_ns = predict_ns - total_compositor_time_ns(pa);
pa->last_returned_ns = predict_ns;
@ -492,7 +492,7 @@ pa_predict(struct u_pacing_app *upa,
}
static void
pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, uint64_t when_ns)
pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, int64_t when_ns)
{
struct pacing_app *pa = pacing_app(upa);
@ -523,7 +523,7 @@ pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point po
}
static void
pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
{
struct pacing_app *pa = pacing_app(upa);
@ -548,7 +548,7 @@ pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
}
static void
pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, uint64_t display_time_ns)
pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t display_time_ns)
{
struct pacing_app *pa = pacing_app(upa);
@ -567,7 +567,7 @@ pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns,
}
static void
pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
{
struct pacing_app *pa = pacing_app(upa);
@ -595,9 +595,9 @@ pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
late = true;
}
uint64_t diff_cpu_ns = f->when.begin_ns - f->when.wait_woke_ns;
uint64_t diff_draw_ns = f->when.delivered_ns - f->when.begin_ns;
uint64_t diff_gpu_ns = f->when.gpu_done_ns - f->when.delivered_ns;
int64_t diff_cpu_ns = f->when.begin_ns - f->when.wait_woke_ns;
int64_t diff_draw_ns = f->when.delivered_ns - f->when.begin_ns;
int64_t diff_gpu_ns = f->when.gpu_done_ns - f->when.delivered_ns;
UPA_LOG_D(
"Delivered frame %.2fms %s." //
@ -628,7 +628,7 @@ pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
}
static void
pa_latched(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, int64_t system_frame_id)
pa_latched(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t system_frame_id)
{
struct pacing_app *pa = pacing_app(upa);
@ -652,7 +652,7 @@ pa_latched(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, int64_t
}
static void
pa_retired(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
pa_retired(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
{
struct pacing_app *pa = pacing_app(upa);
@ -673,9 +673,9 @@ pa_retired(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
static void
pa_info(struct u_pacing_app *upa,
uint64_t predicted_display_time_ns,
uint64_t predicted_display_period_ns,
uint64_t extra_ns)
int64_t predicted_display_time_ns,
int64_t predicted_display_period_ns,
int64_t extra_ns)
{
struct pacing_app *pa = pacing_app(upa);
@ -732,9 +732,9 @@ pa_create(int64_t session_id, struct u_pacing_app **out_upa)
u_var_add_root(pa, "App timing info", true);
u_var_add_draggable_f32(pa, &pa->min_margin_ms, "Minimum margin(ms)");
u_var_add_draggable_f32(pa, &pa->min_app_time_ms, "Minimum app time(ms)");
u_var_add_ro_u64(pa, &pa->app.cpu_time_ns, "CPU time(ns)");
u_var_add_ro_u64(pa, &pa->app.draw_time_ns, "Draw time(ns)");
u_var_add_ro_u64(pa, &pa->app.gpu_time_ns, "GPU time(ns)");
u_var_add_ro_i64(pa, &pa->app.cpu_time_ns, "CPU time(ns)");
u_var_add_ro_i64(pa, &pa->app.draw_time_ns, "Draw time(ns)");
u_var_add_ro_i64(pa, &pa->app.gpu_time_ns, "GPU time(ns)");
*out_upa = &pa->base;

View file

@ -56,33 +56,33 @@ struct frame
int64_t frame_id;
//! When this frame was last used for a prediction. Set in `predict_next_frame`.
uint64_t when_predict_ns;
int64_t when_predict_ns;
//! When should the compositor wake up. Set in `predict_next_frame`.
uint64_t wake_up_time_ns;
int64_t wake_up_time_ns;
//! When we last woke up the compositor after its equivalent of wait_frame. Set in `pc_mark_point` with
//! `U_TIMING_POINT_WAKE_UP`.
uint64_t when_woke_ns;
int64_t when_woke_ns;
//! When the compositor started rendering a frame
uint64_t when_began_ns;
int64_t when_began_ns;
//! When the compositor finished rendering a frame
uint64_t when_submitted_ns;
int64_t when_submitted_ns;
//! When new frame timing info was last added.
uint64_t when_infoed_ns;
int64_t when_infoed_ns;
//! How much time we currently expect the compositor to take rendering a frame. Updated in `predict_next_frame`
uint64_t current_comp_time_ns;
int64_t current_comp_time_ns;
uint64_t expected_done_time_ns; //!< When we expect the compositor to be done with its frame.
uint64_t desired_present_time_ns; //!< The GPU should start scanning out at this time.
uint64_t predicted_display_time_ns; //!< At what time have we predicted that pixels turns to photons.
uint64_t present_margin_ns;
uint64_t actual_present_time_ns;
uint64_t earliest_present_time_ns;
int64_t expected_done_time_ns; //!< When we expect the compositor to be done with its frame.
int64_t desired_present_time_ns; //!< The GPU should start scanning out at this time.
int64_t predicted_display_time_ns; //!< At what time have we predicted that pixels turns to photons.
int64_t present_margin_ns;
int64_t actual_present_time_ns;
int64_t earliest_present_time_ns;
enum frame_state state;
};
@ -96,17 +96,17 @@ struct pacing_compositor
* the display engine starts scanning out from the buffers we provided,
* and not when the pixels turned into photons that the user sees.
*/
uint64_t present_to_display_offset_ns;
int64_t present_to_display_offset_ns;
/*!
* Frame period of the device.
*/
uint64_t frame_period_ns;
int64_t frame_period_ns;
/*!
* The amount of time that the compositor needs to render frame.
*/
uint64_t comp_time_ns;
int64_t comp_time_ns;
/*!
* Used to generate frame IDs.
@ -116,23 +116,23 @@ struct pacing_compositor
/*!
* The maximum amount we give to the compositor.
*/
uint64_t comp_time_max_ns;
int64_t comp_time_max_ns;
/*!
* If we missed a frame, back off this much.
*/
uint64_t adjust_missed_ns;
int64_t adjust_missed_ns;
/*!
* Adjustment of time if we didn't miss the frame,
* also used as range to stay around timing target.
*/
uint64_t adjust_non_miss_ns;
int64_t adjust_non_miss_ns;
/*!
* Extra time between end of draw time and when the present happens.
*/
uint64_t margin_ns;
int64_t margin_ns;
/*!
* Frame store.
@ -159,34 +159,34 @@ ns_to_ms(int64_t t)
return (double)(t / 1000) / 1000.0;
}
static uint64_t
get_percent_of_time(uint64_t time_ns, uint32_t fraction_percent)
static int64_t
get_percent_of_time(int64_t time_ns, uint32_t fraction_percent)
{
double fraction = (double)fraction_percent / 100.0;
return time_s_to_ns(time_ns_to_s(time_ns) * fraction);
}
static uint64_t
static int64_t
calc_total_comp_time(struct pacing_compositor *pc)
{
return pc->comp_time_ns + pc->margin_ns;
}
static uint64_t
calc_display_time_from_present_time(struct pacing_compositor *pc, uint64_t desired_present_time_ns)
static int64_t
calc_display_time_from_present_time(struct pacing_compositor *pc, int64_t desired_present_time_ns)
{
return desired_present_time_ns + pc->present_to_display_offset_ns;
}
static inline bool
is_within_of_each_other(uint64_t l, uint64_t r, uint64_t range)
is_within_of_each_other(int64_t l, int64_t r, int64_t range)
{
int64_t t = (int64_t)l - (int64_t)r;
return (-(int64_t)range < t) && (t < (int64_t)range);
}
static inline bool
is_within_half_ms(uint64_t l, uint64_t r)
is_within_half_ms(int64_t l, int64_t r)
{
return is_within_of_each_other(l, r, U_TIME_HALF_MS_IN_NS);
}
@ -238,8 +238,8 @@ create_frame(struct pacing_compositor *pc, enum frame_state state)
static struct frame *
get_latest_frame_with_state_at_least(struct pacing_compositor *pc, enum frame_state state)
{
uint64_t start_from = pc->next_frame_id;
uint64_t count = 1;
int64_t start_from = pc->next_frame_id;
int64_t count = 1;
while (start_from >= count && count < NUM_FRAMES) {
int64_t frame_id = start_from - count;
@ -258,12 +258,12 @@ get_latest_frame_with_state_at_least(struct pacing_compositor *pc, enum frame_st
* initialize frame::desired_present_time_ns (with a crude estimate) and frame::when_predict_ns.
*/
static struct frame *
do_clean_slate_frame(struct pacing_compositor *pc, uint64_t now_ns)
do_clean_slate_frame(struct pacing_compositor *pc, int64_t now_ns)
{
struct frame *f = create_frame(pc, STATE_PREDICTED);
// Wild shot in the dark.
uint64_t the_time_ns = now_ns + pc->frame_period_ns * 10;
int64_t the_time_ns = now_ns + pc->frame_period_ns * 10;
f->when_predict_ns = now_ns;
f->desired_present_time_ns = the_time_ns;
@ -275,11 +275,11 @@ do_clean_slate_frame(struct pacing_compositor *pc, uint64_t now_ns)
* prediction in it.
*/
static struct frame *
walk_forward_through_frames(struct pacing_compositor *pc, uint64_t last_present_time_ns, uint64_t now_ns)
walk_forward_through_frames(struct pacing_compositor *pc, int64_t last_present_time_ns, int64_t now_ns)
{
// This is the earliest possible time we could present, assuming rendering still must take place.
uint64_t from_time_ns = now_ns + calc_total_comp_time(pc);
uint64_t desired_present_time_ns = last_present_time_ns + pc->frame_period_ns;
int64_t from_time_ns = now_ns + calc_total_comp_time(pc);
int64_t desired_present_time_ns = last_present_time_ns + pc->frame_period_ns;
while (desired_present_time_ns <= from_time_ns) {
UPC_LOG_D(
@ -303,7 +303,7 @@ walk_forward_through_frames(struct pacing_compositor *pc, uint64_t last_present_
}
static struct frame *
predict_next_frame(struct pacing_compositor *pc, uint64_t now_ns)
predict_next_frame(struct pacing_compositor *pc, int64_t now_ns)
{
struct frame *f = NULL;
// Last earliest display time, can be zero.
@ -320,7 +320,7 @@ predict_next_frame(struct pacing_compositor *pc, uint64_t now_ns)
int64_t diff_id = last_predicted->frame_id - last_completed->frame_id;
int64_t diff_ns = last_completed->desired_present_time_ns - last_completed->earliest_present_time_ns;
uint64_t adjusted_last_present_time_ns =
int64_t adjusted_last_present_time_ns =
last_completed->earliest_present_time_ns + diff_id * pc->frame_period_ns;
if (diff_ns > U_TIME_1MS_IN_NS) {
@ -356,7 +356,7 @@ predict_next_frame(struct pacing_compositor *pc, uint64_t now_ns)
static void
adjust_comp_time(struct pacing_compositor *pc, struct frame *f)
{
uint64_t comp_time_ns = pc->comp_time_ns;
int64_t comp_time_ns = pc->comp_time_ns;
if (f->actual_present_time_ns > f->desired_present_time_ns &&
!is_within_half_ms(f->actual_present_time_ns, f->desired_present_time_ns)) {
@ -448,7 +448,7 @@ do_tracing(struct pacing_compositor *pc, struct frame *f)
TE_BEG(pc_cpu, f->when_predict_ns, "sleep");
TE_END(pc_cpu, f->wake_up_time_ns);
uint64_t oversleep_start_ns = f->wake_up_time_ns + 1;
int64_t oversleep_start_ns = f->wake_up_time_ns + 1;
if (f->when_woke_ns > oversleep_start_ns) {
TE_BEG(pc_cpu, oversleep_start_ns, "oversleep");
TE_END(pc_cpu, f->when_woke_ns);
@ -461,7 +461,7 @@ do_tracing(struct pacing_compositor *pc, struct frame *f)
*
*/
uint64_t gpu_end_ns = f->actual_present_time_ns - f->present_margin_ns;
int64_t gpu_end_ns = f->actual_present_time_ns - f->present_margin_ns;
if (gpu_end_ns > f->when_submitted_ns) {
TE_BEG(pc_gpu, f->when_submitted_ns, "gpu");
TE_END(pc_gpu, gpu_end_ns);
@ -553,25 +553,25 @@ do_tracing(struct pacing_compositor *pc, struct frame *f)
static void
pc_predict(struct u_pacing_compositor *upc,
uint64_t now_ns,
int64_t now_ns,
int64_t *out_frame_id,
uint64_t *out_wake_up_time_ns,
uint64_t *out_desired_present_time_ns,
uint64_t *out_present_slop_ns,
uint64_t *out_predicted_display_time_ns,
uint64_t *out_predicted_display_period_ns,
uint64_t *out_min_display_period_ns)
int64_t *out_wake_up_time_ns,
int64_t *out_desired_present_time_ns,
int64_t *out_present_slop_ns,
int64_t *out_predicted_display_time_ns,
int64_t *out_predicted_display_period_ns,
int64_t *out_min_display_period_ns)
{
struct pacing_compositor *pc = pacing_compositor(upc);
struct frame *f = predict_next_frame(pc, now_ns);
uint64_t wake_up_time_ns = f->wake_up_time_ns;
uint64_t desired_present_time_ns = f->desired_present_time_ns;
uint64_t present_slop_ns = PRESENT_SLOP_NS;
uint64_t predicted_display_time_ns = f->predicted_display_time_ns;
uint64_t predicted_display_period_ns = pc->frame_period_ns;
uint64_t min_display_period_ns = pc->frame_period_ns;
int64_t wake_up_time_ns = f->wake_up_time_ns;
int64_t desired_present_time_ns = f->desired_present_time_ns;
int64_t present_slop_ns = PRESENT_SLOP_NS;
int64_t predicted_display_time_ns = f->predicted_display_time_ns;
int64_t predicted_display_period_ns = pc->frame_period_ns;
int64_t min_display_period_ns = pc->frame_period_ns;
*out_frame_id = f->frame_id;
*out_wake_up_time_ns = wake_up_time_ns;
@ -583,7 +583,7 @@ pc_predict(struct u_pacing_compositor *upc,
}
static void
pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, uint64_t when_ns)
pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, int64_t when_ns)
{
struct pacing_compositor *pc = pacing_compositor(upc);
struct frame *f = get_frame(pc, frame_id);
@ -622,11 +622,11 @@ pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_
static void
pc_info(struct u_pacing_compositor *upc,
int64_t frame_id,
uint64_t desired_present_time_ns,
uint64_t actual_present_time_ns,
uint64_t earliest_present_time_ns,
uint64_t present_margin_ns,
uint64_t when_ns)
int64_t desired_present_time_ns,
int64_t actual_present_time_ns,
int64_t earliest_present_time_ns,
int64_t present_margin_ns,
int64_t when_ns)
{
struct pacing_compositor *pc = pacing_compositor(upc);
(void)pc;
@ -642,7 +642,7 @@ pc_info(struct u_pacing_compositor *upc,
}
assert(f->state == STATE_SUBMITTED);
XRT_MAYBE_UNUSED uint64_t unslopped_desired_present_time_ns = desired_present_time_ns + PRESENT_SLOP_NS;
XRT_MAYBE_UNUSED int64_t unslopped_desired_present_time_ns = desired_present_time_ns + PRESENT_SLOP_NS;
assert(f->desired_present_time_ns == desired_present_time_ns ||
f->desired_present_time_ns == unslopped_desired_present_time_ns);
@ -652,7 +652,7 @@ pc_info(struct u_pacing_compositor *upc,
f->present_margin_ns = present_margin_ns;
f->state = STATE_INFO;
uint64_t since_last_frame_ns = 0;
int64_t since_last_frame_ns = 0;
if (last != NULL) {
since_last_frame_ns = f->desired_present_time_ns - last->desired_present_time_ns;
}
@ -695,7 +695,7 @@ pc_info(struct u_pacing_compositor *upc,
static void
pc_info_gpu(
struct u_pacing_compositor *upc, int64_t frame_id, uint64_t gpu_start_ns, uint64_t gpu_end_ns, uint64_t when_ns)
struct u_pacing_compositor *upc, int64_t frame_id, int64_t gpu_start_ns, int64_t gpu_end_ns, int64_t when_ns)
{
if (u_metrics_is_active()) {
struct u_metrics_system_gpu_info umgi = {
@ -710,7 +710,7 @@ pc_info_gpu(
}
static void
pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, uint64_t last_vblank_ns)
pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, int64_t last_vblank_ns)
{
/*
* This is a no-op, here in case display control is used at the
@ -719,7 +719,7 @@ pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, uint64_t
}
static void
pc_update_present_offset(struct u_pacing_compositor *upc, int64_t frame_id, uint64_t present_to_display_offset_ns)
pc_update_present_offset(struct u_pacing_compositor *upc, int64_t frame_id, int64_t present_to_display_offset_ns)
{
struct pacing_compositor *pc = pacing_compositor(upc);
@ -750,7 +750,7 @@ const struct u_pc_display_timing_config U_PC_DISPLAY_TIMING_CONFIG_DEFAULT = {
};
xrt_result_t
u_pc_display_timing_create(uint64_t estimated_frame_period_ns,
u_pc_display_timing_create(int64_t estimated_frame_period_ns,
const struct u_pc_display_timing_config *config,
struct u_pacing_compositor **out_upc)
{

View file

@ -45,44 +45,44 @@ struct frame
int64_t frame_id;
//! When should the compositor wake up. Set in `pc_predict`.
uint64_t predicted_wake_up_time_ns;
int64_t predicted_wake_up_time_ns;
//! When should the compositor present the frame.
uint64_t predicted_present_time_ns;
int64_t predicted_present_time_ns;
//! When should the frame be displayed.
uint64_t predicted_display_time_ns;
int64_t predicted_display_time_ns;
//! The period that the pacer used for this frame.
uint64_t predicted_display_period_ns;
int64_t predicted_display_period_ns;
//! When this frame was last used for a prediction. Set in `pc_predict`.
uint64_t when_predict_ns;
int64_t when_predict_ns;
/*!
* When the compositor woke up after its equivalent of wait_frame.
* Set in `pc_mark_point` with `U_TIMING_POINT_WAKE_UP`.
*/
uint64_t when_woke_ns;
int64_t when_woke_ns;
/*!
* When the compositor began rendering a frame. Set in `pc_mark_point`
* with `U_TIMING_POINT_BEGIN`.
*/
uint64_t when_began_ns;
int64_t when_began_ns;
/*!
* When the compositor began submitting the work to the GPU, after
* it completed building the command buffers. Set in `pc_mark_point`
* with `U_TIMING_POINT_SUBMIT_BEGIN`.
*/
uint64_t when_submit_began_ns;
int64_t when_submit_began_ns;
/*!
* When the compositor completed submitting the work to the GPU. Set in
* `pc_mark_point` with `U_TIMING_POINT_SUBMIT_END`.
*/
uint64_t when_submit_end_ns;
int64_t when_submit_end_ns;
};
/*!
@ -97,12 +97,12 @@ struct fake_timing
/*!
* The periodicity of the display.
*/
uint64_t frame_period_ns;
int64_t frame_period_ns;
/*!
* When the last frame was presented, not displayed.
*/
uint64_t last_present_time_ns;
int64_t last_present_time_ns;
/*!
* Very often the present time that we get from the system is only when
@ -112,7 +112,7 @@ struct fake_timing
struct u_var_draggable_f32 present_to_display_offset_ms;
//! The amount of time that the application needs to render frame.
uint64_t comp_time_ns;
int64_t comp_time_ns;
//! This won't run out, trust me.
int64_t frame_id_generator;
@ -165,11 +165,11 @@ get_new_frame(struct fake_timing *ft)
return f;
}
static uint64_t
predict_next_frame_present_time(struct fake_timing *ft, uint64_t now_ns)
static int64_t
predict_next_frame_present_time(struct fake_timing *ft, int64_t now_ns)
{
uint64_t time_needed_ns = ft->comp_time_ns;
uint64_t predicted_present_time_ns = ft->last_present_time_ns + ft->frame_period_ns;
int64_t time_needed_ns = ft->comp_time_ns;
int64_t predicted_present_time_ns = ft->last_present_time_ns + ft->frame_period_ns;
while (now_ns + time_needed_ns > predicted_present_time_ns) {
predicted_present_time_ns += ft->frame_period_ns;
@ -178,16 +178,16 @@ predict_next_frame_present_time(struct fake_timing *ft, uint64_t now_ns)
return predicted_present_time_ns;
}
static uint64_t
calc_display_time(struct fake_timing *ft, uint64_t present_time_ns)
static int64_t
calc_display_time(struct fake_timing *ft, int64_t present_time_ns)
{
double offset_ms = ft->present_to_display_offset_ms.val;
uint64_t offset_ns = time_ms_f_to_ns(offset_ms);
int64_t offset_ns = time_ms_f_to_ns(offset_ms);
return present_time_ns + offset_ns;
}
static uint64_t
get_percent_of_time(uint64_t time_ns, uint32_t fraction_percent)
static int64_t
get_percent_of_time(int64_t time_ns, uint32_t fraction_percent)
{
double fraction = (double)fraction_percent / 100.0;
return time_s_to_ns(time_ns_to_s(time_ns) * fraction);
@ -224,9 +224,9 @@ calc_frame_stats(struct fake_timing *ft, struct frame *f)
return;
}
uint64_t cpu_ns = f->when_began_ns - f->when_woke_ns;
uint64_t draw_ns = f->when_submit_began_ns - f->when_began_ns;
uint64_t submit_ns = f->when_submit_end_ns - f->when_submit_began_ns;
int64_t cpu_ns = f->when_began_ns - f->when_woke_ns;
int64_t draw_ns = f->when_submit_began_ns - f->when_began_ns;
int64_t submit_ns = f->when_submit_end_ns - f->when_submit_began_ns;
bool full = false;
full |= u_ls_ns_add(&ft->cpu, cpu_ns);
@ -239,16 +239,16 @@ calc_frame_stats(struct fake_timing *ft, struct frame *f)
}
static void
calc_gpu_stats(struct fake_timing *ft, struct frame *f, uint64_t gpu_start_ns, uint64_t gpu_end_ns)
calc_gpu_stats(struct fake_timing *ft, struct frame *f, int64_t gpu_start_ns, int64_t gpu_end_ns)
{
if (!debug_get_bool_option_live_stats()) {
return;
}
uint64_t then_ns = f->when_submit_began_ns;
uint64_t delay_ns = gpu_start_ns > then_ns ? gpu_start_ns - then_ns : 0;
uint64_t gpu_ns = gpu_end_ns - gpu_start_ns;
uint64_t frame_ns = gpu_end_ns - f->when_woke_ns;
int64_t then_ns = f->when_submit_began_ns;
int64_t delay_ns = gpu_start_ns > then_ns ? gpu_start_ns - then_ns : 0;
int64_t gpu_ns = gpu_end_ns - gpu_start_ns;
int64_t frame_ns = gpu_end_ns - f->when_woke_ns;
bool full = false;
full |= u_ls_ns_add(&ft->gpu, gpu_ns);
@ -269,27 +269,27 @@ calc_gpu_stats(struct fake_timing *ft, struct frame *f, uint64_t gpu_start_ns, u
static void
pc_predict(struct u_pacing_compositor *upc,
uint64_t now_ns,
int64_t now_ns,
int64_t *out_frame_id,
uint64_t *out_wake_up_time_ns,
uint64_t *out_desired_present_time_ns,
uint64_t *out_present_slop_ns,
uint64_t *out_predicted_display_time_ns,
uint64_t *out_predicted_display_period_ns,
uint64_t *out_min_display_period_ns)
int64_t *out_wake_up_time_ns,
int64_t *out_desired_present_time_ns,
int64_t *out_present_slop_ns,
int64_t *out_predicted_display_time_ns,
int64_t *out_predicted_display_period_ns,
int64_t *out_min_display_period_ns)
{
struct fake_timing *ft = fake_timing(upc);
struct frame *f = get_new_frame(ft);
int64_t frame_id = f->frame_id;
uint64_t desired_present_time_ns = predict_next_frame_present_time(ft, now_ns);
uint64_t predicted_display_time_ns = calc_display_time(ft, desired_present_time_ns);
int64_t desired_present_time_ns = predict_next_frame_present_time(ft, now_ns);
int64_t predicted_display_time_ns = calc_display_time(ft, desired_present_time_ns);
uint64_t wake_up_time_ns = desired_present_time_ns - ft->comp_time_ns;
uint64_t present_slop_ns = U_TIME_HALF_MS_IN_NS;
uint64_t predicted_display_period_ns = ft->frame_period_ns;
uint64_t min_display_period_ns = ft->frame_period_ns;
int64_t wake_up_time_ns = desired_present_time_ns - ft->comp_time_ns;
int64_t present_slop_ns = U_TIME_HALF_MS_IN_NS;
int64_t predicted_display_period_ns = ft->frame_period_ns;
int64_t min_display_period_ns = ft->frame_period_ns;
// Set the frame info.
f->predicted_wake_up_time_ns = wake_up_time_ns;
@ -322,7 +322,7 @@ pc_predict(struct u_pacing_compositor *upc,
}
static void
pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, uint64_t when_ns)
pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, int64_t when_ns)
{
struct fake_timing *ft = fake_timing(upc);
struct frame *f = get_frame_or_null(ft, frame_id);
@ -348,11 +348,11 @@ pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_
static void
pc_info(struct u_pacing_compositor *upc,
int64_t frame_id,
uint64_t desired_present_time_ns,
uint64_t actual_present_time_ns,
uint64_t earliest_present_time_ns,
uint64_t present_margin_ns,
uint64_t when_ns)
int64_t desired_present_time_ns,
int64_t actual_present_time_ns,
int64_t earliest_present_time_ns,
int64_t present_margin_ns,
int64_t when_ns)
{
/*
* The compositor might call this function because it selected the
@ -362,7 +362,7 @@ pc_info(struct u_pacing_compositor *upc,
static void
pc_info_gpu(
struct u_pacing_compositor *upc, int64_t frame_id, uint64_t gpu_start_ns, uint64_t gpu_end_ns, uint64_t when_ns)
struct u_pacing_compositor *upc, int64_t frame_id, int64_t gpu_start_ns, int64_t gpu_end_ns, int64_t when_ns)
{
struct fake_timing *ft = fake_timing(upc);
@ -396,13 +396,13 @@ pc_info_gpu(
#endif
#ifdef U_TRACE_TRACY
uint64_t diff_ns = gpu_end_ns - gpu_start_ns;
int64_t diff_ns = gpu_end_ns - gpu_start_ns;
TracyCPlot("Compositor GPU(ms)", time_ns_to_ms_f(diff_ns));
#endif
}
static void
pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, uint64_t last_vblank_ns)
pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, int64_t last_vblank_ns)
{
struct fake_timing *ft = fake_timing(upc);
@ -411,7 +411,7 @@ pc_update_vblank_from_display_control(struct u_pacing_compositor *upc, uint64_t
}
static void
pc_update_present_offset(struct u_pacing_compositor *upc, int64_t frame_id, uint64_t present_to_display_offset_ns)
pc_update_present_offset(struct u_pacing_compositor *upc, int64_t frame_id, int64_t present_to_display_offset_ns)
{
struct fake_timing *ft = fake_timing(upc);
@ -441,7 +441,7 @@ pc_destroy(struct u_pacing_compositor *upc)
*/
xrt_result_t
u_pc_fake_create(uint64_t estimated_frame_period_ns, uint64_t now_ns, struct u_pacing_compositor **out_upc)
u_pc_fake_create(int64_t estimated_frame_period_ns, int64_t now_ns, struct u_pacing_compositor **out_upc)
{
struct fake_timing *ft = U_TYPED_CALLOC(struct fake_timing);
ft->base.predict = pc_predict;
@ -479,7 +479,7 @@ u_pc_fake_create(uint64_t estimated_frame_period_ns, uint64_t now_ns, struct u_p
// Or at least a certain amount of time.
float min_comp_time_ms_f = debug_get_float_option_min_comp_time_ms();
uint64_t min_comp_time_ns = time_ms_f_to_ns(min_comp_time_ms_f);
int64_t min_comp_time_ns = time_ms_f_to_ns(min_comp_time_ms_f);
if (ft->comp_time_ns < min_comp_time_ns) {
ft->comp_time_ns = min_comp_time_ns;
@ -491,9 +491,9 @@ u_pc_fake_create(uint64_t estimated_frame_period_ns, uint64_t now_ns, struct u_p
// U variable tracking.
u_var_add_root(ft, "Compositor timing info", true);
u_var_add_draggable_f32(ft, &ft->present_to_display_offset_ms, "Present to display offset(ms)");
u_var_add_ro_u64(ft, &ft->frame_period_ns, "Frame period(ns)");
u_var_add_ro_u64(ft, &ft->comp_time_ns, "Compositor time(ns)");
u_var_add_ro_u64(ft, &ft->last_present_time_ns, "Last present time(ns)");
u_var_add_ro_i64(ft, &ft->frame_period_ns, "Frame period(ns)");
u_var_add_ro_i64(ft, &ft->comp_time_ns, "Compositor time(ns)");
u_var_add_ro_i64(ft, &ft->last_present_time_ns, "Last present time(ns)");
// Return value.
*out_upc = &ft->base;

View file

@ -25,8 +25,8 @@ static constexpr unanoseconds frame_interval_ns(16ms);
namespace {
uint64_t
getNextPresentAfterTimestampAndKnownPresent(uint64_t timestamp_ns, uint64_t known_present_ns)
int64_t
getNextPresentAfterTimestampAndKnownPresent(int64_t timestamp_ns, int64_t known_present_ns)
{
while (known_present_ns < timestamp_ns) {
@ -34,8 +34,8 @@ getNextPresentAfterTimestampAndKnownPresent(uint64_t timestamp_ns, uint64_t know
}
return known_present_ns;
}
uint64_t
getPresentBefore(uint64_t timestamp_ns, uint64_t known_present_ns)
int64_t
getPresentBefore(int64_t timestamp_ns, int64_t known_present_ns)
{
while (known_present_ns >= timestamp_ns && known_present_ns > frame_interval_ns.count()) {
@ -43,8 +43,8 @@ getPresentBefore(uint64_t timestamp_ns, uint64_t known_present_ns)
}
return known_present_ns;
}
uint64_t
getNextPresentAfterTimestamp(uint64_t timestamp_ns, uint64_t known_present_ns)
int64_t
getNextPresentAfterTimestamp(int64_t timestamp_ns, int64_t known_present_ns)
{
auto present_before_ns = getPresentBefore(timestamp_ns, known_present_ns);
return getNextPresentAfterTimestampAndKnownPresent(timestamp_ns, present_before_ns);
@ -53,17 +53,17 @@ getNextPresentAfterTimestamp(uint64_t timestamp_ns, uint64_t known_present_ns)
struct CompositorPredictions
{
int64_t frame_id{0};
uint64_t wake_up_time_ns{0};
uint64_t desired_present_time_ns{0};
uint64_t present_slop_ns{0};
uint64_t predicted_display_time_ns{0};
uint64_t predicted_display_period_ns{0};
uint64_t min_display_period_ns{0};
int64_t wake_up_time_ns{0};
int64_t desired_present_time_ns{0};
int64_t present_slop_ns{0};
int64_t predicted_display_time_ns{0};
int64_t predicted_display_period_ns{0};
int64_t min_display_period_ns{0};
};
} // namespace
static void
basicPredictionConsistencyChecks(uint64_t now_ns, CompositorPredictions const &predictions)
basicPredictionConsistencyChecks(int64_t now_ns, CompositorPredictions const &predictions)
{
INFO(predictions.frame_id);
INFO(now_ns);
@ -79,7 +79,7 @@ basicPredictionConsistencyChecks(uint64_t now_ns, CompositorPredictions const &p
struct SimulatedDisplayTimingData
{
SimulatedDisplayTimingData(int64_t id, uint64_t desired_present_time, uint64_t gpu_finish, uint64_t now)
SimulatedDisplayTimingData(int64_t id, int64_t desired_present_time, int64_t gpu_finish, int64_t now)
: frame_id(id), desired_present_time_ns(desired_present_time),
actual_present_time_ns(getNextPresentAfterTimestampAndKnownPresent(gpu_finish, desired_present_time)),
earliest_present_time_ns(getNextPresentAfterTimestamp(gpu_finish, desired_present_time)),
@ -87,11 +87,11 @@ struct SimulatedDisplayTimingData
{}
int64_t frame_id;
uint64_t desired_present_time_ns;
uint64_t actual_present_time_ns;
uint64_t earliest_present_time_ns;
uint64_t present_margin_ns;
uint64_t now_ns;
int64_t desired_present_time_ns;
int64_t actual_present_time_ns;
int64_t earliest_present_time_ns;
int64_t present_margin_ns;
int64_t now_ns;
void
call_u_pc_info(u_pacing_compositor *upc) const
{
@ -116,7 +116,7 @@ using SimulatedDisplayTimingQueue = std::priority_queue<SimulatedDisplayTimingDa
//! Process all simulated timing data in the queue that should be processed by now.
static void
processDisplayTimingQueue(SimulatedDisplayTimingQueue &display_timing_queue, uint64_t now_ns, u_pacing_compositor *upc)
processDisplayTimingQueue(SimulatedDisplayTimingQueue &display_timing_queue, int64_t now_ns, u_pacing_compositor *upc)
{
while (!display_timing_queue.empty() && display_timing_queue.top().now_ns <= now_ns) {
display_timing_queue.top().call_u_pc_info(upc);
@ -124,8 +124,8 @@ processDisplayTimingQueue(SimulatedDisplayTimingQueue &display_timing_queue, uin
}
}
//! Process all remaining simulated timing data in the queue and return the timestamp of the last one.
static uint64_t
drainDisplayTimingQueue(SimulatedDisplayTimingQueue &display_timing_queue, uint64_t now_ns, u_pacing_compositor *upc)
static int64_t
drainDisplayTimingQueue(SimulatedDisplayTimingQueue &display_timing_queue, int64_t now_ns, u_pacing_compositor *upc)
{
while (!display_timing_queue.empty()) {
now_ns = display_timing_queue.top().now_ns;
@ -139,8 +139,8 @@ static void
doFrame(SimulatedDisplayTimingQueue &display_timing_queue,
u_pacing_compositor *upc,
MockClock &clock,
uint64_t wake_time_ns,
uint64_t desired_present_time_ns,
int64_t wake_time_ns,
int64_t desired_present_time_ns,
int64_t frame_id,
unanoseconds wake_delay,
unanoseconds begin_delay,

View file

@ -8,97 +8,14 @@
#pragma once
#include <iostream>
#include <chrono>
#include <sstream>
#include <functional>
#include <iomanip>
using unanoseconds = std::chrono::duration<uint64_t, std::nano>;
template <typename T>
static inline std::string
stringifyNanos(std::chrono::duration<T, std::nano> value)
{
using namespace std::chrono;
std::ostringstream oss;
auto sec = duration_cast<duration<T>>(value);
if (duration<T, std::nano>(sec) == value) {
oss << sec.count() << "s";
return oss.str();
}
auto millis = duration_cast<duration<T, std::milli>>(value);
if (duration<T, std::nano>(millis) == value) {
oss << millis.count() << "ms";
return oss.str();
}
auto micros = duration_cast<duration<T, std::micro>>(value);
if (duration<T, std::nano>(micros) == value) {
oss << micros.count() << "us";
return oss.str();
}
oss << value.count() << "ns";
return oss.str();
}
static inline std::string
stringifyTimePoint(std::chrono::steady_clock::time_point tp)
{
auto dur = tp.time_since_epoch();
auto hr = std::chrono::duration_cast<std::chrono::hours>(dur);
dur -= hr;
auto sec = std::chrono::duration_cast<std::chrono::seconds>(dur);
dur -= sec;
std::ostringstream oss;
if (hr.count() > 0) {
oss << hr.count() << ":";
}
oss << sec.count() << ".";
using three_commas =
std::ratio_multiply<std::ratio<1, 1000>, std::ratio_multiply<std::ratio<1, 1000>, std::ratio<1, 1000>>>;
static_assert(std::ratio_equal<three_commas, std::nano>::value);
// 9 because of the preceding static assert: there's no compile-time rational log10? :-O
oss << std::setfill('0') << std::setw(9);
oss << dur.count();
return oss.str();
}
namespace Catch {
template <> struct StringMaker<unanoseconds>
{
static std::string
convert(unanoseconds const &value)
{
return stringifyNanos(value);
}
};
template <> struct StringMaker<std::chrono::nanoseconds>
{
static std::string
convert(std::chrono::nanoseconds const &value)
{
return stringifyNanos(value);
}
};
template <> struct StringMaker<std::chrono::steady_clock::time_point>
{
static std::string
convert(std::chrono::steady_clock::time_point const &value)
{
return stringifyTimePoint(value);
}
};
} // namespace Catch
using unanoseconds = std::chrono::duration<int64_t, std::nano>;
class MockClock
{
public:
uint64_t
int64_t
now() const noexcept
{
return std::chrono::duration_cast<unanoseconds>(now_.time_since_epoch()).count();
@ -117,7 +34,7 @@ public:
}
void
advance_to(uint64_t timestamp_ns)
advance_to(int64_t timestamp_ns)
{
CHECK(now() <= timestamp_ns);
now_ = std::chrono::steady_clock::time_point(