Monado OpenXR Runtime
u_pacing.h
Go to the documentation of this file.
1// Copyright 2020-2022, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Shared pacing code.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
8 * @ingroup aux_util
9 */
10
11#pragma once
12
13#include "xrt/xrt_compiler.h"
14#include "xrt/xrt_defines.h"
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
20
21/*!
22 * @defgroup aux_pacing Frame and Render timing/pacing
23 *
24 * @ingroup aux_util
25 * @see @ref frame-pacing.
26 */
27
28
29/*!
30 * For marking timepoints on a frame's lifetime, not a async event.
31 *
32 * @ingroup aux_pacing
33 */
35{
36 //! Woke up after sleeping in "wait frame".
38
39 //! Began CPU side work for GPU.
41
42 //! Began submitting work to the GPU, only used by the compositor.
44
45 //! Finished submitting work to the GPU, only used by the compositor.
47};
48
49
50/*
51 *
52 * Compositor pacing helper.
53 *
54 */
55
56/*!
57 * Compositor pacing helper interface.
58 *
59 * This is used for the compositor's own frame timing/pacing. It is not responsible for getting the timing data from the
60 * graphics API, etc: instead it consumes timing data from the graphics API (if available) and from "markers" in the
61 * compositor's CPU code, and produces predictions that are used to guide the compositor.
62 *
63 * Pacing of the underlying app/client is handled by @ref u_pacing_app
64 *
65 * @ingroup aux_pacing
66 */
68{
69 /*!
70 * Predict the next frame.
71 *
72 * @param[in] upc The compositor pacing helper.
73 * @param[in] now_ns The current timestamp in nanoseconds, nominally from @ref
74 * os_monotonic_get_ns
75 * @param[out] out_frame_id Id used to refer to this frame again.
76 * @param[out] out_wake_up_time_ns When should the compositor wake up.
77 * @param[out] out_desired_present_time_ns The GPU should start scanning out at this time.
78 * @param[out] out_present_slop_ns Any looseness to the desired present timing.
79 * @param[out] out_predicted_display_time_ns At what time have we predicted that pixels turns to photons.
80 * @param[out] out_predicted_display_period_ns Display period that we are running on.
81 * @param[out] out_min_display_period_ns The fastest theoretical display period.
82 *
83 * @see @ref frame-pacing.
84 */
85 void (*predict)(struct u_pacing_compositor *upc,
86 int64_t now_ns,
87 int64_t *out_frame_id,
88 int64_t *out_wake_up_time_ns,
89 int64_t *out_desired_present_time_ns,
90 int64_t *out_present_slop_ns,
91 int64_t *out_predicted_display_time_ns,
92 int64_t *out_predicted_display_period_ns,
93 int64_t *out_min_display_period_ns);
94
95 /*!
96 * Mark a point on the frame's lifetime.
97 *
98 * This is usually provided "when it happens" because the points to mark are steps in the CPU workload of the
99 * compositor.
100 *
101 * @param[in] upc The compositor pacing helper.
102 * @param[in] point The point to record for a frame.
103 * @param[in] frame_id The frame ID to record for.
104 * @param[in] when_ns The timestamp of the event.
105 *
106 * @see @ref frame-pacing.
107 */
108 void (*mark_point)(struct u_pacing_compositor *upc,
109 enum u_timing_point point,
110 int64_t frame_id,
111 int64_t when_ns);
112
113 /*!
114 * Provide frame timing information about a delivered frame.
115 *
116 * This is usually provided after-the-fact by the display system. These arguments currently
117 * matches 1-to-1 what VK_GOOGLE_display_timing provides, see
118 * https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPastPresentationTimingGOOGLE.html
119 *
120 * Depend on when the information is delivered this can be called at any
121 * point of the following frames.
122 *
123 * @param[in] upc The compositor pacing helper.
124 * @param[in] frame_id The frame ID to record for.
125 * @param[in] desired_present_time_ns The time that we indicated the GPU should start scanning out at, or zero
126 * if we didn't provide such a time.
127 * @param[in] actual_present_time_ns The time that the GPU actually started scanning out.
128 * @param[in] earliest_present_time_ns The earliest the GPU could have presented - might be before @p
129 * actual_present_time_ns if a @p desired_present_time_ns was passed.
130 * @param[in] present_margin_ns How "early" present happened compared to when it needed to happen in
131 * order to finish at @p earliestPresentTime.
132 * @param[in] when_ns The time when we got the info, nominally from @ref
133 * os_monotonic_get_ns
134 *
135 * @see @ref frame-pacing.
136 */
137 void (*info)(struct u_pacing_compositor *upc,
138 int64_t frame_id,
139 int64_t desired_present_time_ns,
140 int64_t actual_present_time_ns,
141 int64_t earliest_present_time_ns,
142 int64_t present_margin_ns,
143 int64_t when_ns);
144
145 /*!
146 * Provide frame timing information about GPU start and stop time.
147 *
148 * Depend on when the information is delivered this can be called at any
149 * point of the following frames.
150 *
151 * @param[in] upc The compositor pacing helper.
152 * @param[in] frame_id The frame ID to record for.
153 * @param[in] gpu_start_ns When the GPU work startred.
154 * @param[in] gpu_end_ns When the GPU work stopped.
155 * @param[in] when_ns When the informatioon collected, nominally
156 * from @ref os_monotonic_get_ns.
157 *
158 * @see @ref frame-pacing.
159 */
160 void (*info_gpu)(struct u_pacing_compositor *upc,
161 int64_t frame_id,
162 int64_t gpu_start_ns,
163 int64_t gpu_end_ns,
164 int64_t when_ns);
165
166 /*!
167 * Provide a vblank timing information, derived from the
168 * VK_EXT_display_control extension. Since the extension only says when
169 * a vblank happened (somewhat inaccurate as well) but not if a specific
170 * present happened at that time no frame_id is given.
171 *
172 * @param[in] upc The compositor pacing helper.
173 * @param[in] last_vblank_ns The last time that the GPU started scanning out.
174 *
175 * @see @ref frame-pacing.
176 */
177 void (*update_vblank_from_display_control)(struct u_pacing_compositor *upc, int64_t last_vblank_ns);
178
179 /*!
180 * Provide an updated estimate of the present offset.
181 *
182 * This is usually used only for more complicated display systems.
183 *
184 * @param[in] upc The compositor pacing helper.
185 * @param[in] frame_id The frame ID to record for.
186 * @param[in] present_to_display_offset_ns The improved estimate of the time between "present" and photons.
187 *
188 * @see @ref frame-pacing.
189 */
191 int64_t frame_id,
192 int64_t present_to_display_offset_ns);
193
194 /*!
195 * Destroy this u_pacing_compositor.
196 */
197 void (*destroy)(struct u_pacing_compositor *upc);
198};
199
200/*!
201 * @copydoc u_pacing_compositor::predict
202 *
203 * Helper for calling through the function pointer.
204 *
205 * @public @memberof u_pacing_compositor
206 * @ingroup aux_pacing
207 */
208static inline void
210 int64_t now_ns,
211 int64_t *out_frame_id,
212 int64_t *out_wake_up_time_ns,
213 int64_t *out_desired_present_time_ns,
214 int64_t *out_present_slop_ns,
215 int64_t *out_predicted_display_time_ns,
216 int64_t *out_predicted_display_period_ns,
217 int64_t *out_min_display_period_ns)
218{
219 upc->predict(upc, //
220 now_ns, //
221 out_frame_id, //
222 out_wake_up_time_ns, //
223 out_desired_present_time_ns, //
224 out_present_slop_ns, //
225 out_predicted_display_time_ns, //
226 out_predicted_display_period_ns, //
227 out_min_display_period_ns); //
228}
229
230/*!
231 * @copydoc u_pacing_compositor::mark_point
232 *
233 * Helper for calling through the function pointer.
234 *
235 * @public @memberof u_pacing_compositor
236 * @ingroup aux_pacing
237 */
238static inline void
239u_pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, int64_t when_ns)
240{
241 upc->mark_point(upc, point, frame_id, when_ns);
242}
243
244/*!
245 * @copydoc u_pacing_compositor::info
246 *
247 * Helper for calling through the function pointer.
248 *
249 * @public @memberof u_pacing_compositor
250 * @ingroup aux_pacing
251 */
252static inline void
254 int64_t frame_id,
255 int64_t desired_present_time_ns,
256 int64_t actual_present_time_ns,
257 int64_t earliest_present_time_ns,
258 int64_t present_margin_ns,
259 int64_t when_ns)
260{
261 upc->info(upc, frame_id, desired_present_time_ns, actual_present_time_ns, earliest_present_time_ns,
262 present_margin_ns, when_ns);
263}
264
265
266/*!
267 * @copydoc u_pacing_compositor::info_gpu
268 *
269 * Helper for calling through the function pointer.
270 *
271 * @public @memberof u_pacing_compositor
272 * @ingroup aux_pacing
273 */
274static inline void
276 struct u_pacing_compositor *upc, int64_t frame_id, int64_t gpu_start_ns, int64_t gpu_end_ns, int64_t when_ns)
277{
278 upc->info_gpu(upc, frame_id, gpu_start_ns, gpu_end_ns, when_ns);
279}
280
281/*!
282 * @copydoc u_pacing_compositor::update_vblank_from_display_control
283 *
284 * Helper for calling through the function pointer.
285 *
286 * @public @memberof u_pacing_compositor
287 * @ingroup aux_pacing
288 */
289static inline void
291{
292 upc->update_vblank_from_display_control(upc, last_vblank_ns);
293}
294
295/*!
296 * @copydoc u_pacing_compositor::update_present_offset
297 *
298 * Helper for calling through the function pointer.
299 *
300 * @public @memberof u_pacing_compositor
301 * @ingroup aux_pacing
302 */
303static inline void
304u_pc_update_present_offset(struct u_pacing_compositor *upc, int64_t frame_id, int64_t present_to_display_offset_ns)
305{
306 upc->update_present_offset(upc, frame_id, present_to_display_offset_ns);
307}
308
309/*!
310 * @copydoc u_pacing_compositor::destroy
311 *
312 * Helper for calling through the function pointer: does a null check and sets
313 * @p upc_ptr to null if freed.
314 *
315 * @public @memberof u_pacing_compositor
316 * @ingroup aux_pacing
317 */
318static inline void
320{
321 struct u_pacing_compositor *upc = *upc_ptr;
322 if (upc == NULL) {
323 return;
324 }
325
326 upc->destroy(upc);
327 *upc_ptr = NULL;
328}
329
330
331/*
332 *
333 * App pacer.
334 *
335 */
336
337/*!
338 * This application pacing helper is designed to schedule the rendering time of
339 * clients that submit frames to a compositor, which runs its own render loop
340 * that picks latest completed frames for that client.
341 *
342 * It manages the frame pacing of an app/client, rather than the compositor itself. The frame pacing of the compositor
343 * is handled by @ref u_pacing_compositor
344 *
345 * @ingroup aux_pacing
346 */
348{
349 /*!
350 * Predict when the client's next rendered frame will be displayed; when the
351 * client should be woken up from sleeping; and its display period.
352 *
353 * This is called from `xrWaitFrame`, but it does not do any waiting, the caller
354 * should wait till `out_wake_up_time`.
355 *
356 * @param upa Render timing helper.
357 * @param[in] now_ns The current timestamp in nanoseconds, nominally from @ref
358 * os_monotonic_get_ns
359 * @param[out] out_frame_id Frame ID of this predicted frame.
360 * @param[out] out_wake_up_time When the client should be woken up.
361 * @param[out] out_predicted_display_time Predicted display time.
362 * @param[out] out_predicted_display_period Predicted display period.
363 */
364 void (*predict)(struct u_pacing_app *upa,
365 int64_t now_ns,
366 int64_t *out_frame_id,
367 int64_t *out_wake_up_time,
368 int64_t *out_predicted_display_time,
369 int64_t *out_predicted_display_period);
370
371 /*!
372 * Mark a point on the frame's lifetime.
373 *
374 * @param upa Render timing helper.
375 * @param[in] frame_id The frame ID to record for.
376 * @param[in] point The point/event to record
377 * @param[in] when_ns The timestamp
378 *
379 * @see @ref frame-pacing.
380 */
381 void (*mark_point)(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, int64_t when_ns);
382
383 /*!
384 * When a frame has been discarded.
385 *
386 * @param upa Render timing helper.
387 * @param[in] frame_id The frame ID to mark as discarded.
388 * @param[in] when_ns The time when it was discarded, nominally from @ref os_monotonic_get_ns
389 */
390 void (*mark_discarded)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns);
391
392 /*!
393 * A frame has been delivered from the client, see `xrEndFrame`. The GPU might
394 * still be rendering the work.
395 *
396 * @param upa Render timing helper.
397 * @param[in] frame_id The frame ID to mark as delivered.
398 * @param[in] when_ns The time when it was delivered, nominally from @ref os_monotonic_get_ns
399 * @param[in] display_time_ns The time the frame is to be displayed.
400 */
401 void (*mark_delivered)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t display_time_ns);
402
403 /*!
404 * A frame has been completed rendered by the GPU, this can happen after `xrEndFrame` has returned.
405 *
406 * @param upa Render timing helper.
407 * @param[in] frame_id The frame ID to mark as delivered.
408 * @param[in] when_ns The time when it the gpu was finished, nominally from @ref os_monotonic_get_ns
409 */
410 void (*mark_gpu_done)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns);
411
412 /*!
413 * Latch a frame for rendering for delivery to the native compositor,
414 * may be called multiple times for the same frame should the app be on
415 * a frame cadence that is lower then the native compositor.
416 *
417 * @param upa App pacer struct.
418 * @param[in] frame_id The frame ID of the latched frame.
419 * @param[in] when_ns Time when the latching happened.
420 * @param[in] system_frame_id The ID of the system frame that is
421 * latching the app's frame.
422 */
423 void (*latched)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t system_frame_id);
424
425 /*!
426 * Mark a frame as completely retired, will never be latched (used by
427 * the native compositor again) as a new frame has been latched or a
428 * shutdown condition has been met.
429 *
430 * @param upa App pacer struct.
431 * @param[in] frame_id The frame ID of the latched frame.
432 * @param[in] when_ns Time when the latching happened.
433 */
434 void (*retired)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns);
435
436 /*!
437 * Add a new sample point from the main render loop.
438 *
439 * This is called in the main renderer loop that tightly submits frames to the
440 * real compositor for displaying. This is only used to inform the render helper
441 * when the frame will be shown, not any timing information about the client.
442 *
443 * When this is called doesn't matter that much, as the render timing will need
444 * to be able to predict one or more frames into the future anyways. But
445 * preferably as soon as the main loop wakes up from wait frame.
446 *
447 * @param upa Self pointer
448 * @param predicted_display_time_ns Predicted display time for this sample.
449 * @param predicted_display_period_ns Predicted display period for this sample.
450 * @param extra_ns Time between display and when this sample
451 * was created, that is when the main loop
452 * was woken up by the main compositor.
453 */
454 void (*info)(struct u_pacing_app *upa,
455 int64_t predicted_display_time_ns,
456 int64_t predicted_display_period_ns,
457 int64_t extra_ns);
458
459 /*!
460 * Destroy this u_pacing_app.
461 */
462 void (*destroy)(struct u_pacing_app *upa);
463};
464
465/*!
466 * @copydoc u_pacing_app::predict
467 *
468 * Helper for calling through the function pointer.
469 *
470 * @public @memberof u_pacing_app
471 * @ingroup aux_pacing
472 */
473static inline void
475 int64_t now_ns,
476 int64_t *out_frame_id,
477 int64_t *out_wake_up_time,
478 int64_t *out_predicted_display_time,
479 int64_t *out_predicted_display_period)
480{
481 upa->predict(upa, now_ns, out_frame_id, out_wake_up_time, out_predicted_display_time,
482 out_predicted_display_period);
483}
484
485/*!
486 * @copydoc u_pacing_app::mark_point
487 *
488 * Helper for calling through the function pointer.
489 *
490 * @public @memberof u_pacing_app
491 * @ingroup aux_pacing
492 */
493static inline void
494u_pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, int64_t when_ns)
495{
496 upa->mark_point(upa, frame_id, point, when_ns);
497}
498
499/*!
500 * @copydoc u_pacing_app::mark_discarded
501 *
502 * Helper for calling through the function pointer.
503 *
504 * @public @memberof u_pacing_app
505 * @ingroup aux_pacing
506 */
507static inline void
508u_pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
509{
510 upa->mark_discarded(upa, frame_id, when_ns);
511}
512
513/*!
514 * @copydoc u_pacing_app::mark_delivered
515 *
516 * Helper for calling through the function pointer.
517 *
518 * @public @memberof u_pacing_app
519 * @ingroup aux_pacing
520 */
521static inline void
522u_pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t display_time_ns)
523{
524 upa->mark_delivered(upa, frame_id, when_ns, display_time_ns);
525}
526
527/*!
528 * @copydoc u_pacing_app::mark_gpu_done
529 *
530 * Helper for calling through the function pointer.
531 *
532 * @public @memberof u_pacing_app
533 * @ingroup aux_pacing
534 */
535static inline void
536u_pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
537{
538 upa->mark_gpu_done(upa, frame_id, when_ns);
539}
540
541/*!
542 * @copydoc u_pacing_app::info
543 *
544 * Helper for calling through the function pointer.
545 *
546 * @public @memberof u_pacing_app
547 * @ingroup aux_pacing
548 */
549static inline void
551 int64_t predicted_display_time_ns,
552 int64_t predicted_display_period_ns,
553 int64_t extra_ns)
554{
555 upa->info(upa, predicted_display_time_ns, predicted_display_period_ns, extra_ns);
556}
557
558/*!
559 * @copydoc u_pacing_app::latched
560 *
561 * Helper for calling through the function pointer.
562 *
563 * @public @memberof u_pacing_app
564 * @ingroup aux_pacing
565 */
566static inline void
567u_pa_latched(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns, int64_t system_frame_id)
568{
569 upa->latched(upa, frame_id, when_ns, system_frame_id);
570}
571
572/*!
573 * @copydoc u_pacing_app::retired
574 *
575 * Helper for calling through the function pointer.
576 *
577 * @public @memberof u_pacing_app
578 * @ingroup aux_pacing
579 */
580static inline void
581u_pa_retired(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
582{
583 upa->retired(upa, frame_id, when_ns);
584}
585
586/*!
587 * @copydoc u_pacing_app::destroy
588 *
589 * Helper for calling through the function pointer: does a null check and sets
590 * upa_ptr to null if freed.
591 *
592 * @public @memberof u_pacing_app
593 * @ingroup aux_pacing
594 */
595static inline void
596u_pa_destroy(struct u_pacing_app **upa_ptr)
597{
598 struct u_pacing_app *upa = *upa_ptr;
599 if (upa == NULL) {
600 return;
601 }
602
603 upa->destroy(upa);
604 *upa_ptr = NULL;
605}
606
607
608/*
609 *
610 * App pacing factory.
611 *
612 */
613
614/*!
615 * Small helper that creates a app pacers, allows timing information to be
616 * collected and controlled to a central place.
617 */
619{
620 /*!
621 * Create a @ref u_pacing_app.
622 *
623 * @param upaf App pacing factory.
624 * @param[out] out_upa Created app pacer.
625 */
626 xrt_result_t (*create)(struct u_pacing_app_factory *upaf, struct u_pacing_app **out_upa);
627
628 /*!
629 * Destroy this u_pacing_app_factory.
630 */
631 void (*destroy)(struct u_pacing_app_factory *upaf);
632};
633
634/*!
635 * @copydoc u_pacing_app_factory::create
636 *
637 * Helper for calling through the function pointer.
638 *
639 * @public @memberof u_pacing_app_factory
640 * @ingroup aux_pacing
641 */
642static inline void
643u_paf_create(struct u_pacing_app_factory *upaf, struct u_pacing_app **out_upa)
644{
645 upaf->create(upaf, out_upa);
646}
647
648/*!
649 * @copydoc u_pacing_app_factory::destroy
650 *
651 * Helper for calling through the function pointer: does a null check and sets
652 * upa_ptr to null if freed.
653 *
654 * @public @memberof u_pacing_app_factory
655 * @ingroup aux_pacing
656 */
657static inline void
659{
660 struct u_pacing_app_factory *upaf = *upaf_ptr;
661 if (upaf == NULL) {
662 return;
663 }
664
665 upaf->destroy(upaf);
666 *upaf_ptr = NULL;
667}
668
669
670/*
671 *
672 * Configuration struct
673 *
674 */
675/*!
676 * Configuration for the "display-timing-aware" implementation of @ref u_pacing_compositor
677 *
678 * @see u_pc_display_timing_create
679 */
681{
682 //! How long after "present" is the image actually displayed
684 //! Extra margin that is added to compositor time, between end of draw and present
685 int64_t margin_ns;
686 /*!
687 * @name Frame-Relative Values
688 * All these values are in "percentage points of the nominal frame period" so they can work across
689 * devices of varying refresh rate/display interval.
690 * @{
691 */
692 //! The initial estimate of how much time the compositor needs
694 //! The maximum time we allow to the compositor
696 //! When missing a frame, back off in these increments
698 //! When not missing frames but adjusting app time at these increments
700 /*!
701 * @}
702 */
703};
704
705/*!
706 * Default configuration values for display-timing-aware compositor pacing.
707 *
708 * @see u_pc_display_timing_config, u_pc_display_timing_create
709 */
711
712
713/*
714 *
715 * Implementations.
716 *
717 */
718
719/*!
720 * Creates a new composition pacing helper that uses real display timing information.
721 *
722 * Meant to be used with `VK_GOOGLE_display_timing`.
723 *
724 * @ingroup aux_pacing
725 * @see u_pacing_compositor
726 */
728u_pc_display_timing_create(int64_t estimated_frame_period_ns,
729 const struct u_pc_display_timing_config *config,
730 struct u_pacing_compositor **out_upc);
731
732/*!
733 * Creates a new composition pacing helper that does not depend on display timing information.
734 *
735 * When you cannot get display timing information, use this.
736 *
737 * @param[in] estimated_frame_period_ns The estimated duration/period of a frame in nanoseconds.
738 * @param[in] now_ns The current timestamp in nanoseconds, nominally from @ref os_monotonic_get_ns
739 * @param[out] out_upc The pointer to populate with the created compositor pacing helper
740 *
741 * @ingroup aux_pacing
742 * @see u_pacing_compositor
743 */
745u_pc_fake_create(int64_t estimated_frame_period_ns, int64_t now_ns, struct u_pacing_compositor **out_upc);
746
747/*!
748 * Creates a new application pacing factory helper.
749 *
750 * @ingroup aux_pacing
751 * @see u_pacing_app
752 */
755
756
757#ifdef __cplusplus
758}
759#endif
static void u_pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
When a frame has been discarded.
Definition: u_pacing.h:508
u_timing_point
For marking timepoints on a frame's lifetime, not a async event.
Definition: u_pacing.h:35
static void 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.
Definition: u_pacing.h:494
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.
Definition: u_pacing_compositor.c:753
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)
Provide frame timing information about GPU start and stop time.
Definition: u_pacing.h:275
xrt_result_t u_pa_factory_create(struct u_pacing_app_factory **out_upaf)
Creates a new application pacing factory helper.
Definition: u_pacing_app.c:787
static void 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 ...
Definition: u_pacing.h:581
static void 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.
Definition: u_pacing.h:239
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)
Predict when the client's next rendered frame will be displayed; when the client should be woken up f...
Definition: u_pacing.h:474
static void u_pc_destroy(struct u_pacing_compositor **upc_ptr)
Destroy this u_pacing_compositor.
Definition: u_pacing.h:319
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)
Predict the next frame.
Definition: u_pacing.h:209
static void u_pa_destroy(struct u_pacing_app **upa_ptr)
Destroy this u_pacing_app.
Definition: u_pacing.h:596
static void 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.
Definition: u_pacing.h:522
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)
Add a new sample point from the main render loop.
Definition: u_pacing.h:550
static void u_paf_destroy(struct u_pacing_app_factory **upaf_ptr)
Destroy this u_pacing_app_factory.
Definition: u_pacing.h:658
static void u_paf_create(struct u_pacing_app_factory *upaf, struct u_pacing_app **out_upa)
Create a u_pacing_app.
Definition: u_pacing.h:643
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)
Provide frame timing information about a delivered frame.
Definition: u_pacing.h:253
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.
Definition: u_pacing_compositor_fake.c:444
static void 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.
Definition: u_pacing.h:290
static void 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.
Definition: u_pacing.h:536
static void 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 t...
Definition: u_pacing.h:567
static void 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.
Definition: u_pacing.h:304
@ U_TIMING_POINT_SUBMIT_END
Finished submitting work to the GPU, only used by the compositor.
Definition: u_pacing.h:46
@ U_TIMING_POINT_SUBMIT_BEGIN
Began submitting work to the GPU, only used by the compositor.
Definition: u_pacing.h:43
@ U_TIMING_POINT_BEGIN
Began CPU side work for GPU.
Definition: u_pacing.h:40
@ U_TIMING_POINT_WAKE_UP
Woke up after sleeping in "wait frame".
Definition: u_pacing.h:37
enum xrt_result xrt_result_t
Result type used across Monado.
Small helper that creates a app pacers, allows timing information to be collected and controlled to a...
Definition: u_pacing.h:619
void(* destroy)(struct u_pacing_app_factory *upaf)
Destroy this u_pacing_app_factory.
Definition: u_pacing.h:631
xrt_result_t(* create)(struct u_pacing_app_factory *upaf, struct u_pacing_app **out_upa)
Create a u_pacing_app.
Definition: u_pacing.h:626
This application pacing helper is designed to schedule the rendering time of clients that submit fram...
Definition: u_pacing.h:348
void(* destroy)(struct u_pacing_app *upa)
Destroy this u_pacing_app.
Definition: u_pacing.h:462
void(* mark_discarded)(struct u_pacing_app *upa, int64_t frame_id, int64_t when_ns)
When a frame has been discarded.
Definition: u_pacing.h:390
void(* 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.
Definition: u_pacing.h:454
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 delivered from the client, see xrEndFrame.
Definition: u_pacing.h:401
void(* 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 t...
Definition: u_pacing.h:423
void(* 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 ...
Definition: u_pacing.h:434
void(* 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.
Definition: u_pacing.h:381
void(* 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.
Definition: u_pacing.h:410
void(* 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 f...
Definition: u_pacing.h:364
Compositor pacing helper interface.
Definition: u_pacing.h:68
void(* 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.
Definition: u_pacing.h:85
void(* destroy)(struct u_pacing_compositor *upc)
Destroy this u_pacing_compositor.
Definition: u_pacing.h:197
void(* 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.
Definition: u_pacing.h:190
void(* 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.
Definition: u_pacing.h:177
void(* 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.
Definition: u_pacing.h:137
void(* 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.
Definition: u_pacing.h:108
void(* 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.
Definition: u_pacing.h:160
Configuration for the "display-timing-aware" implementation of u_pacing_compositor.
Definition: u_pacing.h:681
int64_t margin_ns
Extra margin that is added to compositor time, between end of draw and present.
Definition: u_pacing.h:685
uint32_t comp_time_max_fraction
The maximum time we allow to the compositor.
Definition: u_pacing.h:695
uint32_t adjust_missed_fraction
When missing a frame, back off in these increments.
Definition: u_pacing.h:697
uint32_t adjust_non_miss_fraction
When not missing frames but adjusting app time at these increments.
Definition: u_pacing.h:699
int64_t present_to_display_offset_ns
How long after "present" is the image actually displayed.
Definition: u_pacing.h:683
uint32_t comp_time_fraction
The initial estimate of how much time the compositor needs.
Definition: u_pacing.h:693
const struct u_pc_display_timing_config U_PC_DISPLAY_TIMING_CONFIG_DEFAULT
Default configuration values for display-timing-aware compositor pacing.
Definition: u_pacing_compositor.c:740
Header holding common defines.
Common defines and enums for XRT.