u/render_timing: Add helper code for frame timing

This commit is contained in:
Jakob Bornecrantz 2020-06-23 21:26:05 +01:00
parent 3275f00464
commit 83081f9cc1
4 changed files with 279 additions and 0 deletions

View file

@ -89,6 +89,8 @@ set(UTIL_SOURCE_FILES
util/u_hashset.h
util/u_json.c
util/u_json.h
util/u_render_timing.c
util/u_render_timing.h
util/u_sink.h
util/u_sink_converter.c
util/u_sink_deinterleaver.c

View file

@ -29,6 +29,8 @@ lib_aux_util = static_library(
'util/u_json.h',
'util/u_misc.c',
'util/u_misc.h',
'util/u_render_timing.c',
'util/u_render_timing.h',
'util/u_sink.h',
'util/u_sink_converter.c',
'util/u_sink_deinterleaver.c',

View file

@ -0,0 +1,188 @@
// Copyright 2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Shared frame timing code.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup aux_util
*/
#include "util/u_misc.h"
#include "u_render_timing.h"
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
/*
*
* Helpers
*
*/
#if 0
#define DEBUG_PRINT_FRAME_ID()
fprintf(stderr, "%s %" PRIi64 "\n", __func__, frame_id)
#else
#define DEBUG_PRINT_FRAME_ID() \
do { \
} while (false)
#endif
static uint64_t
get_last_input_plus_period_at_least_greater_then(struct u_rt_helper *urth,
uint64_t then_ns)
{
uint64_t val = urth->last_input;
while (val <= then_ns) {
val += urth->period;
}
return val;
}
/*
*
* 'Exported' functions.
*
*/
void
u_rt_helper_clear(struct u_rt_helper *urth)
{
U_ZERO(urth);
for (size_t i = 0; i < ARRAY_SIZE(urth->frames); i++) {
urth->frames[i].state = U_RT_READY;
urth->frames[i].frame_id = -1;
}
}
void
u_rt_helper_init(struct u_rt_helper *urth)
{
u_rt_helper_clear(urth);
}
void
u_rt_helper_predict(struct u_rt_helper *urth,
int64_t *out_frame_id,
uint64_t *predicted_display_time,
uint64_t *wake_up_time,
uint64_t *predicted_display_period,
uint64_t *min_display_period)
{
int64_t frame_id = ++urth->frame_counter;
*out_frame_id = frame_id;
DEBUG_PRINT_FRAME_ID();
uint64_t at_least_ns = os_monotonic_get_ns();
// Don't return a time before the last returned type.
if (at_least_ns < urth->last_returned) {
at_least_ns = urth->last_returned;
}
uint64_t predict_ns =
get_last_input_plus_period_at_least_greater_then(urth, at_least_ns);
urth->last_returned = predict_ns;
*wake_up_time = predict_ns - urth->period;
*predicted_display_time = predict_ns;
*predicted_display_period = urth->period;
*min_display_period = urth->period;
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
assert(urth->frames[index].frame_id == -1);
assert(urth->frames[index].state == U_RT_READY);
urth->frames[index].predicted = os_monotonic_get_ns();
urth->frames[index].state = U_RT_PREDICTED;
urth->frames[index].frame_id = frame_id;
}
void
u_rt_helper_mark_wait_woke(struct u_rt_helper *urth, int64_t frame_id)
{
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
assert(urth->frames[index].frame_id == frame_id);
assert(urth->frames[index].state == U_RT_PREDICTED);
urth->frames[index].wait_woke = os_monotonic_get_ns();
urth->frames[index].state = U_RT_WAIT_LEFT;
}
void
u_rt_helper_mark_begin(struct u_rt_helper *urth, int64_t frame_id)
{
DEBUG_PRINT_FRAME_ID();
DEBUG_PRINT_FRAME_ID();
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
assert(urth->frames[index].frame_id == frame_id);
assert(urth->frames[index].state == U_RT_WAIT_LEFT);
urth->frames[index].begin = os_monotonic_get_ns();
urth->frames[index].state = U_RT_BEGUN;
}
void
u_rt_helper_mark_discarded(struct u_rt_helper *urth, int64_t frame_id)
{
DEBUG_PRINT_FRAME_ID();
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
assert(urth->frames[index].frame_id == frame_id);
assert(urth->frames[index].state == U_RT_WAIT_LEFT ||
urth->frames[index].state == U_RT_BEGUN);
urth->frames[index].end_frame = os_monotonic_get_ns();
urth->frames[index].state = U_RT_READY;
urth->frames[index].frame_id = -1;
}
void
u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id)
{
DEBUG_PRINT_FRAME_ID();
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
assert(urth->frames[index].frame_id == frame_id);
assert(urth->frames[index].state == U_RT_BEGUN);
uint64_t now_ns = os_monotonic_get_ns();
urth->frames[index].end_frame = now_ns;
urth->frames[index].state = U_RT_READY;
urth->frames[index].frame_id = -1;
#if 0
uint64_t then_ns = urth->frames[index].wait_woke;
uint64_t diff_ns = now_ns - then_ns;
uint64_t ms100 = diff_ns / (1000 * 10);
fprintf(stderr, "%s: Diff %i.%02ims\n", __func__, (int)ms100 / 100,
(int)ms100 % 100);
#endif
}
void
u_rt_helper_new_sample(struct u_rt_helper *urth,
uint64_t predict,
uint64_t extra,
uint64_t min_period)
{
urth->last_input = predict;
urth->extra = extra;
urth->period = min_period;
if (urth->last_returned == 0) {
return;
}
}

View file

@ -0,0 +1,87 @@
// Copyright 2020, 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"
#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
{
uint64_t predicted;
uint64_t wait_woke;
uint64_t begin;
uint64_t end_frame;
int64_t frame_id;
enum u_rt_state state;
};
struct u_rt_helper
{
struct u_rt_frame frames[2];
uint32_t current_frame;
uint32_t next_frame;
int64_t frame_counter;
uint64_t extra;
uint64_t period;
uint64_t last_input;
uint64_t last_returned;
};
void
u_rt_helper_init(struct u_rt_helper *urth);
void
u_rt_helper_clear(struct u_rt_helper *urth);
void
u_rt_helper_predict(struct u_rt_helper *urth,
int64_t *out_frame_id,
uint64_t *out_predicted_display_time,
uint64_t *out_wake_up_time,
uint64_t *out_predicted_display_period,
uint64_t *out_min_display_period);
void
u_rt_helper_mark_wait_woke(struct u_rt_helper *urth, int64_t frame_id);
void
u_rt_helper_mark_begin(struct u_rt_helper *urth, int64_t frame_id);
void
u_rt_helper_mark_discarded(struct u_rt_helper *urth, int64_t frame_id);
void
u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id);
void
u_rt_helper_new_sample(struct u_rt_helper *urth,
uint64_t predict,
uint64_t extra,
uint64_t min_period);
#ifdef __cplusplus
}
#endif