Monado OpenXR Runtime
Frame and Render timing/pacing
Collaboration diagram for Frame and Render timing/pacing:

Data Structures

struct  u_pacing_compositor
 Compositor pacing helper interface. More...
 
struct  u_pacing_app
 This application pacing 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. More...
 

Enumerations

enum  u_timing_point { U_TIMING_POINT_WAKE_UP , U_TIMING_POINT_BEGIN , U_TIMING_POINT_SUBMIT_BEGIN , U_TIMING_POINT_SUBMIT_END }
 For marking timepoints on a frame's lifetime, not a async event. More...
 

Functions

xrt_result_t 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)
 Creates a new composition pacing helper that uses real display timing information. More...
 
xrt_result_t u_pc_fake_create (int64_t estimated_frame_period_ns, int64_t now_ns, struct u_pacing_compositor **out_upc)
 Creates a new composition pacing helper that does not depend on display timing information. More...
 
xrt_result_t u_pa_factory_create (struct u_pacing_app_factory **out_upaf)
 Creates a new application pacing factory helper. More...
 
static void u_pacing_compositor::u_pc_predict (struct u_pacing_compositor *upc, int64_t now_ns, int64_t *out_frame_id, 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)
 Predict the next frame. More...
 
static void u_pacing_compositor::u_pc_mark_point (struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, int64_t when_ns)
 Mark a point on the frame's lifetime. More...
 
static void u_pacing_compositor::u_pc_info (struct u_pacing_compositor *upc, int64_t frame_id, 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 a delivered frame. More...
 
static void u_pacing_compositor::u_pc_info_gpu (struct u_pacing_compositor *upc, int64_t frame_id, int64_t gpu_start_ns, int64_t gpu_end_ns, int64_t when_ns)
 Provide frame timing information about GPU start and stop time. More...
 
static void u_pacing_compositor::u_pc_update_vblank_from_display_control (struct u_pacing_compositor *upc, int64_t last_vblank_ns)
 Provide a vblank timing information, derived from the VK_EXT_display_control extension. More...
 
static void u_pacing_compositor::u_pc_update_present_offset (struct u_pacing_compositor *upc, int64_t frame_id, int64_t present_to_display_offset_ns)
 Provide an updated estimate of the present offset. More...
 
static void u_pacing_compositor::u_pc_destroy (struct u_pacing_compositor **upc_ptr)
 Destroy this u_pacing_compositor. More...
 
static void u_pacing_app::u_pa_predict (struct u_pacing_app *upa, int64_t now_ns, int64_t *out_frame_id, int64_t *out_wake_up_time, int64_t *out_predicted_display_time, int64_t *out_predicted_display_period)
 Predict when the client's next rendered frame will be displayed; when the client should be woken up from sleeping; and its display period. More...
 
static void u_pacing_app::u_pa_mark_point (struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, int64_t when_ns)
 Mark a point on the frame's lifetime. More...
 
static void u_pacing_app::u_pa_mark_discarded (struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
 When a frame has been discarded. More...
 
static void u_pacing_app::u_pa_mark_delivered (struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t display_time_ns)
 A frame has been delivered from the client, see xrEndFrame. More...
 
static void u_pacing_app::u_pa_mark_gpu_done (struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
 A frame has been completed rendered by the GPU, this can happen after xrEndFrame has returned. More...
 
static void u_pacing_app::u_pa_info (struct u_pacing_app *upa, int64_t predicted_display_time_ns, int64_t predicted_display_period_ns, int64_t extra_ns)
 Add a new sample point from the main render loop. More...
 
static void u_pacing_app::u_pa_latched (struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t system_frame_id)
 Latch a frame for rendering for delivery to the native compositor, may be called multiple times for the same frame should the app be on a frame cadence that is lower then the native compositor. More...
 
static void u_pacing_app::u_pa_retired (struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
 Mark a frame as completely retired, will never be latched (used by the native compositor again) as a new frame has been latched or a shutdown condition has been met. More...
 
static void u_pacing_app::u_pa_destroy (struct u_pacing_app **upa_ptr)
 Destroy this u_pacing_app. More...
 
static void u_pacing_app_factory::u_paf_create (struct u_pacing_app_factory *upaf, struct u_pacing_app **out_upa)
 Create a u_pacing_app. More...
 
static void u_pacing_app_factory::u_paf_destroy (struct u_pacing_app_factory **upaf_ptr)
 Destroy this u_pacing_app_factory. More...
 

Detailed Description

See also
Frame Pacing/Timing.

Enumeration Type Documentation

◆ u_timing_point

#include <auxiliary/util/u_pacing.h>

For marking timepoints on a frame's lifetime, not a async event.

Enumerator
U_TIMING_POINT_WAKE_UP 

Woke up after sleeping in "wait frame".

U_TIMING_POINT_BEGIN 

Began CPU side work for GPU.

U_TIMING_POINT_SUBMIT_BEGIN 

Began submitting work to the GPU, only used by the compositor.

U_TIMING_POINT_SUBMIT_END 

Finished submitting work to the GPU, only used by the compositor.

Function Documentation

◆ u_pa_destroy()

static void u_pa_destroy ( struct u_pacing_app **  upa_ptr)
inlinestatic

Destroy this u_pacing_app.

Helper for calling through the function pointer: does a null check and sets upa_ptr to null if freed.

References u_pacing_app::destroy.

◆ u_pa_factory_create()

xrt_result_t u_pa_factory_create ( struct u_pacing_app_factory **  out_upaf)

#include <auxiliary/util/u_pacing.h>

Creates a new application pacing factory helper.

See also
u_pacing_app

References u_pacing_app_factory::create, and U_TYPED_CALLOC.

◆ u_pa_info()

static void u_pa_info ( struct u_pacing_app upa,
int64_t  predicted_display_time_ns,
int64_t  predicted_display_period_ns,
int64_t  extra_ns 
)
inlinestatic

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.

Parameters
upaSelf pointer
predicted_display_time_nsPredicted display time for this sample.
predicted_display_period_nsPredicted display period for this sample.
extra_nsTime between display and when this sample was created, that is when the main loop was woken up by the main compositor.

Helper for calling through the function pointer.

References u_pacing_app::info.

◆ u_pa_latched()

static void u_pa_latched ( struct u_pacing_app upa,
int64_t  frame_id,
int64_t  when_ns,
int64_t  system_frame_id 
)
inlinestatic

Latch a frame for rendering for delivery to the native compositor, may be called multiple times for the same frame should the app be on a frame cadence that is lower then the native compositor.

Parameters
upaApp pacer struct.
[in]frame_idThe frame ID of the latched frame.
[in]when_nsTime when the latching happened.
[in]system_frame_idThe ID of the system frame that is latching the app's frame.

Helper for calling through the function pointer.

References u_pacing_app::latched.

◆ u_pa_mark_delivered()

static void u_pa_mark_delivered ( struct u_pacing_app upa,
int64_t  frame_id,
int64_t  when_ns,
int64_t  display_time_ns 
)
inlinestatic

A frame has been delivered from the client, see xrEndFrame.

The GPU might still be rendering the work.

Parameters
upaRender timing helper.
[in]frame_idThe frame ID to mark as delivered.
[in]when_nsThe time when it was delivered, nominally from os_monotonic_get_ns
[in]display_time_nsThe time the frame is to be displayed.

Helper for calling through the function pointer.

References u_pacing_app::mark_delivered.

◆ u_pa_mark_discarded()

static void u_pa_mark_discarded ( struct u_pacing_app upa,
int64_t  frame_id,
int64_t  when_ns 
)
inlinestatic

When a frame has been discarded.

Parameters
upaRender timing helper.
[in]frame_idThe frame ID to mark as discarded.
[in]when_nsThe time when it was discarded, nominally from os_monotonic_get_ns

Helper for calling through the function pointer.

References u_pacing_app::mark_discarded.

◆ u_pa_mark_gpu_done()

static void u_pa_mark_gpu_done ( struct u_pacing_app upa,
int64_t  frame_id,
int64_t  when_ns 
)
inlinestatic

A frame has been completed rendered by the GPU, this can happen after xrEndFrame has returned.

Parameters
upaRender timing helper.
[in]frame_idThe frame ID to mark as delivered.
[in]when_nsThe time when it the gpu was finished, nominally from os_monotonic_get_ns

Helper for calling through the function pointer.

References u_pacing_app::mark_gpu_done.

◆ u_pa_mark_point()

static void u_pa_mark_point ( struct u_pacing_app upa,
int64_t  frame_id,
enum u_timing_point  point,
int64_t  when_ns 
)
inlinestatic

Mark a point on the frame's lifetime.

Parameters
upaRender timing helper.
[in]frame_idThe frame ID to record for.
[in]pointThe point/event to record
[in]when_nsThe timestamp
See also
Frame Pacing/Timing.

Helper for calling through the function pointer.

References u_pacing_app::mark_point.

◆ u_pa_predict()

static void u_pa_predict ( struct u_pacing_app upa,
int64_t  now_ns,
int64_t *  out_frame_id,
int64_t *  out_wake_up_time,
int64_t *  out_predicted_display_time,
int64_t *  out_predicted_display_period 
)
inlinestatic

Predict when the client's next rendered frame will be displayed; 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.

Parameters
upaRender timing helper.
[in]now_nsThe current timestamp in nanoseconds, nominally from os_monotonic_get_ns
[out]out_frame_idFrame ID of this predicted frame.
[out]out_wake_up_timeWhen the client should be woken up.
[out]out_predicted_display_timePredicted display time.
[out]out_predicted_display_periodPredicted display period.

Helper for calling through the function pointer.

References u_pacing_app::predict.

◆ u_pa_retired()

static void u_pa_retired ( struct u_pacing_app upa,
int64_t  frame_id,
int64_t  when_ns 
)
inlinestatic

Mark a frame as completely retired, will never be latched (used by the native compositor again) as a new frame has been latched or a shutdown condition has been met.

Parameters
upaApp pacer struct.
[in]frame_idThe frame ID of the latched frame.
[in]when_nsTime when the latching happened.

Helper for calling through the function pointer.

References u_pacing_app::retired.

Referenced by slot_clear_locked().

◆ u_paf_create()

static void u_paf_create ( struct u_pacing_app_factory upaf,
struct u_pacing_app **  out_upa 
)
inlinestatic

Create a u_pacing_app.

Parameters
upafApp pacing factory.
[out]out_upaCreated app pacer.

Helper for calling through the function pointer.

References u_pacing_app_factory::create.

◆ u_paf_destroy()

static void u_paf_destroy ( struct u_pacing_app_factory **  upaf_ptr)
inlinestatic

Destroy this u_pacing_app_factory.

Helper for calling through the function pointer: does a null check and sets upa_ptr to null if freed.

References u_pacing_app_factory::destroy.

◆ u_pc_destroy()

static void u_pc_destroy ( struct u_pacing_compositor **  upc_ptr)
inlinestatic

Destroy this u_pacing_compositor.

Helper for calling through the function pointer: does a null check and sets upc_ptr to null if freed.

References u_pacing_compositor::destroy.

◆ u_pc_display_timing_create()

xrt_result_t 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 
)

#include <auxiliary/util/u_pacing.h>

Creates a new composition pacing helper that uses real display timing information.

Meant to be used with VK_GOOGLE_display_timing.

See also
u_pacing_compositor

References u_pacing_compositor::predict, and U_TYPED_CALLOC.

◆ u_pc_fake_create()

xrt_result_t u_pc_fake_create ( int64_t  estimated_frame_period_ns,
int64_t  now_ns,
struct u_pacing_compositor **  out_upc 
)

#include <auxiliary/util/u_pacing.h>

Creates a new composition pacing helper that does not depend on display timing information.

When you cannot get display timing information, use this.

Parameters
[in]estimated_frame_period_nsThe estimated duration/period of a frame in nanoseconds.
[in]now_nsThe current timestamp in nanoseconds, nominally from os_monotonic_get_ns
[out]out_upcThe pointer to populate with the created compositor pacing helper
See also
u_pacing_compositor

References u_pacing_compositor::predict, and U_TYPED_CALLOC.

◆ u_pc_info()

static void u_pc_info ( struct u_pacing_compositor upc,
int64_t  frame_id,
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 
)
inlinestatic

Provide frame timing information about a delivered frame.

This is usually provided after-the-fact by the display system. These arguments currently matches 1-to-1 what VK_GOOGLE_display_timing provides, see https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPastPresentationTimingGOOGLE.html

Depend on when the information is delivered this can be called at any point of the following frames.

Parameters
[in]upcThe compositor pacing helper.
[in]frame_idThe frame ID to record for.
[in]desired_present_time_nsThe time that we indicated the GPU should start scanning out at, or zero if we didn't provide such a time.
[in]actual_present_time_nsThe time that the GPU actually started scanning out.
[in]earliest_present_time_nsThe earliest the GPU could have presented - might be before actual_present_time_ns if a desired_present_time_ns was passed.
[in]present_margin_nsHow "early" present happened compared to when it needed to happen in order to finish at earliestPresentTime.
[in]when_nsThe time when we got the info, nominally from os_monotonic_get_ns
See also
Frame Pacing/Timing.

Helper for calling through the function pointer.

References u_pacing_compositor::info.

◆ u_pc_info_gpu()

static void u_pc_info_gpu ( struct u_pacing_compositor upc,
int64_t  frame_id,
int64_t  gpu_start_ns,
int64_t  gpu_end_ns,
int64_t  when_ns 
)
inlinestatic

Provide frame timing information about GPU start and stop time.

Depend on when the information is delivered this can be called at any point of the following frames.

Parameters
[in]upcThe compositor pacing helper.
[in]frame_idThe frame ID to record for.
[in]gpu_start_nsWhen the GPU work startred.
[in]gpu_end_nsWhen the GPU work stopped.
[in]when_nsWhen the informatioon collected, nominally from os_monotonic_get_ns.
See also
Frame Pacing/Timing.

Helper for calling through the function pointer.

References u_pacing_compositor::info_gpu.

◆ u_pc_mark_point()

static void u_pc_mark_point ( struct u_pacing_compositor upc,
enum u_timing_point  point,
int64_t  frame_id,
int64_t  when_ns 
)
inlinestatic

Mark a point on the frame's lifetime.

This is usually provided "when it happens" because the points to mark are steps in the CPU workload of the compositor.

Parameters
[in]upcThe compositor pacing helper.
[in]pointThe point to record for a frame.
[in]frame_idThe frame ID to record for.
[in]when_nsThe timestamp of the event.
See also
Frame Pacing/Timing.

Helper for calling through the function pointer.

References u_pacing_compositor::mark_point.

◆ u_pc_predict()

static void u_pc_predict ( struct u_pacing_compositor upc,
int64_t  now_ns,
int64_t *  out_frame_id,
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 
)
inlinestatic

Predict the next frame.

Parameters
[in]upcThe compositor pacing helper.
[in]now_nsThe current timestamp in nanoseconds, nominally from os_monotonic_get_ns
[out]out_frame_idId used to refer to this frame again.
[out]out_wake_up_time_nsWhen should the compositor wake up.
[out]out_desired_present_time_nsThe GPU should start scanning out at this time.
[out]out_present_slop_nsAny looseness to the desired present timing.
[out]out_predicted_display_time_nsAt what time have we predicted that pixels turns to photons.
[out]out_predicted_display_period_nsDisplay period that we are running on.
[out]out_min_display_period_nsThe fastest theoretical display period.
See also
Frame Pacing/Timing.

Helper for calling through the function pointer.

References u_pacing_compositor::predict.

◆ u_pc_update_present_offset()

static void u_pc_update_present_offset ( struct u_pacing_compositor upc,
int64_t  frame_id,
int64_t  present_to_display_offset_ns 
)
inlinestatic

Provide an updated estimate of the present offset.

This is usually used only for more complicated display systems.

Parameters
[in]upcThe compositor pacing helper.
[in]frame_idThe frame ID to record for.
[in]present_to_display_offset_nsThe improved estimate of the time between "present" and photons.
See also
Frame Pacing/Timing.

Helper for calling through the function pointer.

References u_pacing_compositor::update_present_offset.

◆ u_pc_update_vblank_from_display_control()

static void u_pc_update_vblank_from_display_control ( struct u_pacing_compositor upc,
int64_t  last_vblank_ns 
)
inlinestatic

Provide a vblank timing information, derived from the VK_EXT_display_control extension.

Since the extension only says when a vblank happened (somewhat inaccurate as well) but not if a specific present happened at that time no frame_id is given.

Parameters
[in]upcThe compositor pacing helper.
[in]last_vblank_nsThe last time that the GPU started scanning out.
See also
Frame Pacing/Timing.

Helper for calling through the function pointer.

References u_pacing_compositor::update_vblank_from_display_control.