The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

a/util: Rename u_render_timing to u_pacing_app and u_frame_timing to u_pacing_compositor.

They both control pacing, but for different uses. Neither actually performs any timing.

authored by

Ryan Pavlik and committed by
Jakob Bornecrantz
a7c22fd1 365b3ca8

+693 -667
+7 -7
doc/frame-timing.md doc/frame-pacing.md
··· 1 - # Frame Timing {#frame-timing} 1 + # Frame Pacing/Timing {#frame-pacing} 2 2 3 3 <!-- 4 4 Copyright 2021, Collabora, Ltd. and the Monado contributors ··· 7 7 8 8 A "brief" overview of the various time-points that a frame goes through, from 9 9 when the application gets go ahead to render the frame to when pixels are turned 10 - into photons. This only a single frame, where all of the timings are hit and the 11 - application is single threaded. The HMD also only turns on the display during 12 - the vblank period, meaning the pixel to photon transformation is delayed from 13 - scanout starting to the vblank period (like for the Index). 10 + into photons. This is only a single frame, where all of the timings are hit and 11 + the application is single threaded. The HMD also only turns on the display 12 + during the vblank period, meaning the pixel to photon transformation is delayed 13 + from scanout starting to the vblank period (like for the Index). 14 14 15 15 * `xrWaitFrame` returns to the application, referred to as **wake_up**. 16 16 * The app does a logic step to move the simulation to the next predicted ··· 34 34 ## Main compositor perspective 35 35 36 36 * @ref xrt_comp_wait_frame - It is within this function that the frame timing is 37 - predicted, see @ref u_rt_predict. The compositor will then wait to 38 - **wake_up** time and then return from this function. 37 + predicted, see @ref u_pa_predict and @ref u_pc_predict. The compositor will 38 + then wait to **wake_up** time and then return from this function. 39 39 * @ref xrt_comp_begin_frame - The app or IPC server calls this function when it 40 40 is done with CPU work and ready to do GPU work. 41 41 * @ref xrt_comp_discard_frame - The frame is discarded.
+4 -4
src/xrt/auxiliary/CMakeLists.txt
··· 178 178 util/u_logging.h 179 179 util/u_misc.c 180 180 util/u_misc.h 181 + util/u_pacing.h 182 + util/u_pacing_app.c 183 + util/u_pacing_compositor.c 184 + util/u_pacing_compositor_fake.c 181 185 util/u_sink.h 182 186 util/u_sink_combiner.c 183 187 util/u_sink_converter.c ··· 191 195 util/u_template_historybuf.hpp 192 196 util/u_time.cpp 193 197 util/u_time.h 194 - util/u_timing.h 195 - util/u_timing_fake.c 196 - util/u_timing_frame.c 197 - util/u_timing_render.c 198 198 util/u_trace_marker.c 199 199 util/u_trace_marker.h 200 200 util/u_var.cpp
+5 -5
src/xrt/auxiliary/meson.build
··· 57 57 'util/u_logging.h', 58 58 'util/u_misc.c', 59 59 'util/u_misc.h', 60 + 'util/u_pacing.h', 61 + 'util/u_pacing_app.c', 62 + 'util/u_pacing_compositor.c', 63 + 'util/u_pacing_compositor_fake.c', 60 64 'util/u_sink.h', 61 65 'util/u_sink_combiner.c', 62 66 'util/u_sink_converter.c', ··· 67 71 'util/u_string_list.cpp', 68 72 'util/u_string_list.h', 69 73 'util/u_string_list.hpp', 74 + 'util/u_template_historybuf.hpp', 70 75 'util/u_time.cpp', 71 76 'util/u_time.h', 72 - 'util/u_timing.h', 73 - 'util/u_timing_fake.c', 74 - 'util/u_timing_frame.c', 75 - 'util/u_timing_render.c', 76 - 'util/u_template_historybuf.hpp', 77 77 'util/u_trace_marker.c', 78 78 'util/u_trace_marker.h', 79 79 'util/u_var.cpp',
+426
src/xrt/auxiliary/util/u_pacing_app.c
··· 1 + // Copyright 2020-2021, Collabora, Ltd. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Shared frame timing code. 6 + * @author Jakob Bornecrantz <jakob@collabora.com> 7 + * @ingroup aux_util 8 + */ 9 + 10 + #include "os/os_time.h" 11 + 12 + #include "util/u_time.h" 13 + #include "util/u_misc.h" 14 + #include "util/u_debug.h" 15 + #include "util/u_pacing.h" 16 + #include "util/u_logging.h" 17 + #include "util/u_trace_marker.h" 18 + 19 + #include <stdio.h> 20 + #include <assert.h> 21 + #include <inttypes.h> 22 + 23 + 24 + /* 25 + * 26 + * Structs enums, and defines. 27 + * 28 + */ 29 + 30 + enum u_pa_state 31 + { 32 + U_PA_READY, 33 + U_RT_WAIT_LEFT, 34 + U_RT_PREDICTED, 35 + U_RT_BEGUN, 36 + }; 37 + 38 + struct u_pa_frame 39 + { 40 + //! When we predicted this frame to be shown. 41 + uint64_t predicted_display_time_ns; 42 + 43 + //! The selected display period. 44 + uint64_t predicted_display_period_ns; 45 + 46 + //! When the client should have delivered the frame. 47 + uint64_t predicted_delivery_time_ns; 48 + 49 + struct 50 + { 51 + uint64_t predicted_ns; 52 + uint64_t wait_woke_ns; 53 + uint64_t begin_ns; 54 + uint64_t delivered_ns; 55 + } when; //!< When something happened. 56 + 57 + int64_t frame_id; 58 + enum u_pa_state state; 59 + }; 60 + 61 + struct pacing_app 62 + { 63 + struct u_pacing_app base; 64 + 65 + struct u_pa_frame frames[2]; 66 + uint32_t current_frame; 67 + uint32_t next_frame; 68 + 69 + int64_t frame_counter; 70 + 71 + struct 72 + { 73 + //! App time between wait returning and begin being called. 74 + uint64_t cpu_time_ns; 75 + //! Time between begin and frame rendering completeing. 76 + uint64_t draw_time_ns; 77 + //! Exrta time between end of draw time and when the compositor wakes up. 78 + uint64_t margin_ns; 79 + } app; //!< App statistics. 80 + 81 + struct 82 + { 83 + //! The last display time that the thing driving this helper got. 84 + uint64_t predicted_display_time_ns; 85 + //! The last display period the hardware is running at. 86 + uint64_t predicted_display_period_ns; 87 + //! The extra time needed by the thing driving this helper. 88 + uint64_t extra_ns; 89 + } last_input; 90 + 91 + uint64_t last_returned_ns; 92 + }; 93 + 94 + 95 + /* 96 + * 97 + * Helpers 98 + * 99 + */ 100 + 101 + static inline struct pacing_app * 102 + pacing_app(struct u_pacing_app *upa) 103 + { 104 + return (struct pacing_app *)upa; 105 + } 106 + 107 + DEBUG_GET_ONCE_LOG_OPTION(log_level, "U_TIMING_RENDER_LOG", U_LOGGING_WARN) 108 + 109 + #define RT_LOG_T(...) U_LOG_IFL_T(debug_get_log_option_log_level(), __VA_ARGS__) 110 + #define RT_LOG_D(...) U_LOG_IFL_D(debug_get_log_option_log_level(), __VA_ARGS__) 111 + #define RT_LOG_I(...) U_LOG_IFL_I(debug_get_log_option_log_level(), __VA_ARGS__) 112 + #define RT_LOG_W(...) U_LOG_IFL_W(debug_get_log_option_log_level(), __VA_ARGS__) 113 + #define RT_LOG_E(...) U_LOG_IFL_E(debug_get_log_option_log_level(), __VA_ARGS__) 114 + 115 + #define DEBUG_PRINT_FRAME_ID() RT_LOG_T("%" PRIi64, frame_id) 116 + #define GET_INDEX_FROM_ID(RT, ID) ((uint64_t)(ID) % ARRAY_SIZE((RT)->frames)) 117 + 118 + #define IIR_ALPHA_LT 0.8 119 + #define IIR_ALPHA_GT 0.8 120 + 121 + static void 122 + do_iir_filter(uint64_t *target, double alpha_lt, double alpha_gt, uint64_t sample) 123 + { 124 + uint64_t t = *target; 125 + double alpha = t < sample ? alpha_lt : alpha_gt; 126 + double a = time_ns_to_s(t) * alpha; 127 + double b = time_ns_to_s(sample) * (1.0 - alpha); 128 + *target = time_s_to_ns(a + b); 129 + } 130 + 131 + static uint64_t 132 + min_period(const struct pacing_app *pa) 133 + { 134 + return pa->last_input.predicted_display_period_ns; 135 + } 136 + 137 + static uint64_t 138 + last_sample_displayed(const struct pacing_app *pa) 139 + { 140 + return pa->last_input.predicted_display_time_ns; 141 + } 142 + 143 + static uint64_t 144 + last_return_predicted_display(const struct pacing_app *pa) 145 + { 146 + return pa->last_returned_ns; 147 + } 148 + 149 + static uint64_t 150 + total_app_time_ns(const struct pacing_app *pa) 151 + { 152 + return pa->app.cpu_time_ns + pa->app.draw_time_ns; 153 + } 154 + 155 + static uint64_t 156 + total_compositor_time_ns(const struct pacing_app *pa) 157 + { 158 + return pa->app.margin_ns + pa->last_input.extra_ns; 159 + } 160 + 161 + static uint64_t 162 + total_app_and_compositor_time_ns(const struct pacing_app *pa) 163 + { 164 + return total_app_time_ns(pa) + total_compositor_time_ns(pa); 165 + } 166 + 167 + static uint64_t 168 + calc_period(const struct pacing_app *pa) 169 + { 170 + // Error checking. 171 + uint64_t base_period_ns = min_period(pa); 172 + if (base_period_ns == 0) { 173 + assert(false && "Have not yet received and samples from timing driver."); 174 + base_period_ns = U_TIME_1MS_IN_NS * 16; // Sure 175 + } 176 + 177 + // Calculate the using both values separately. 178 + uint64_t period_ns = base_period_ns; 179 + while (pa->app.cpu_time_ns > period_ns) { 180 + period_ns += base_period_ns; 181 + } 182 + 183 + while (pa->app.draw_time_ns > period_ns) { 184 + period_ns += base_period_ns; 185 + } 186 + 187 + return period_ns; 188 + } 189 + 190 + static uint64_t 191 + predict_display_time(const struct pacing_app *pa, uint64_t period_ns) 192 + { 193 + // Now 194 + uint64_t now_ns = os_monotonic_get_ns(); 195 + 196 + 197 + // Total app and compositor time to produce a frame 198 + uint64_t app_and_compositor_time_ns = total_app_and_compositor_time_ns(pa); 199 + 200 + // Start from the last time that the driver displayed something. 201 + uint64_t val = last_sample_displayed(pa); 202 + 203 + // Return a time after the last returned display time. 204 + while (val <= last_return_predicted_display(pa)) { 205 + val += period_ns; 206 + } 207 + 208 + // Have to have enough time to perform app work. 209 + while ((val - app_and_compositor_time_ns) <= now_ns) { 210 + val += period_ns; 211 + } 212 + 213 + return val; 214 + } 215 + 216 + 217 + /* 218 + * 219 + * Member functions. 220 + * 221 + */ 222 + 223 + static void 224 + pa_predict(struct u_pacing_app *upa, 225 + int64_t *out_frame_id, 226 + uint64_t *out_wake_up_time, 227 + uint64_t *out_predicted_display_time, 228 + uint64_t *out_predicted_display_period) 229 + { 230 + struct pacing_app *pa = pacing_app(upa); 231 + 232 + int64_t frame_id = ++pa->frame_counter; 233 + *out_frame_id = frame_id; 234 + 235 + DEBUG_PRINT_FRAME_ID(); 236 + 237 + uint64_t period_ns = calc_period(pa); 238 + uint64_t predict_ns = predict_display_time(pa, period_ns); 239 + // When should the client wake up. 240 + uint64_t wake_up_time_ns = predict_ns - total_app_and_compositor_time_ns(pa); 241 + // When the client should deliver the frame to us. 242 + uint64_t delivery_time_ns = predict_ns - total_compositor_time_ns(pa); 243 + 244 + pa->last_returned_ns = predict_ns; 245 + 246 + *out_wake_up_time = wake_up_time_ns; 247 + *out_predicted_display_time = predict_ns; 248 + *out_predicted_display_period = period_ns; 249 + 250 + size_t index = GET_INDEX_FROM_ID(pa, frame_id); 251 + assert(pa->frames[index].frame_id == -1); 252 + assert(pa->frames[index].state == U_PA_READY); 253 + 254 + pa->frames[index].state = U_RT_PREDICTED; 255 + pa->frames[index].frame_id = frame_id; 256 + pa->frames[index].predicted_delivery_time_ns = delivery_time_ns; 257 + pa->frames[index].predicted_display_period_ns = period_ns; 258 + pa->frames[index].when.predicted_ns = os_monotonic_get_ns(); 259 + } 260 + 261 + static void 262 + pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, uint64_t when_ns) 263 + { 264 + struct pacing_app *pa = pacing_app(upa); 265 + 266 + RT_LOG_T("%" PRIi64 " (%u)", frame_id, point); 267 + 268 + size_t index = GET_INDEX_FROM_ID(pa, frame_id); 269 + assert(pa->frames[index].frame_id == frame_id); 270 + 271 + switch (point) { 272 + case U_TIMING_POINT_WAKE_UP: 273 + assert(pa->frames[index].state == U_RT_PREDICTED); 274 + 275 + pa->frames[index].when.wait_woke_ns = when_ns; 276 + pa->frames[index].state = U_RT_WAIT_LEFT; 277 + break; 278 + case U_TIMING_POINT_BEGIN: 279 + assert(pa->frames[index].state == U_RT_WAIT_LEFT); 280 + 281 + pa->frames[index].when.begin_ns = os_monotonic_get_ns(); 282 + pa->frames[index].state = U_RT_BEGUN; 283 + break; 284 + case U_TIMING_POINT_SUBMIT: 285 + default: assert(false); 286 + } 287 + } 288 + 289 + static void 290 + pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id) 291 + { 292 + struct pacing_app *pa = pacing_app(upa); 293 + 294 + DEBUG_PRINT_FRAME_ID(); 295 + 296 + size_t index = GET_INDEX_FROM_ID(pa, frame_id); 297 + assert(pa->frames[index].frame_id == frame_id); 298 + assert(pa->frames[index].state == U_RT_WAIT_LEFT || pa->frames[index].state == U_RT_BEGUN); 299 + 300 + pa->frames[index].when.delivered_ns = os_monotonic_get_ns(); 301 + pa->frames[index].state = U_PA_READY; 302 + pa->frames[index].frame_id = -1; 303 + } 304 + 305 + static void 306 + pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id) 307 + { 308 + struct pacing_app *pa = pacing_app(upa); 309 + 310 + DEBUG_PRINT_FRAME_ID(); 311 + 312 + size_t index = GET_INDEX_FROM_ID(pa, frame_id); 313 + struct u_pa_frame *f = &pa->frames[index]; 314 + assert(f->frame_id == frame_id); 315 + assert(f->state == U_RT_BEGUN); 316 + 317 + uint64_t now_ns = os_monotonic_get_ns(); 318 + 319 + // Update all data. 320 + f->when.delivered_ns = now_ns; 321 + 322 + 323 + /* 324 + * Process data. 325 + */ 326 + 327 + int64_t diff_ns = f->predicted_delivery_time_ns - now_ns; 328 + bool late = false; 329 + if (diff_ns < 0) { 330 + diff_ns = -diff_ns; 331 + late = true; 332 + } 333 + 334 + #define NS_TO_MS_F(ns) (time_ns_to_s(ns) * 1000.0) 335 + 336 + uint64_t diff_cpu_ns = f->when.begin_ns - f->when.wait_woke_ns; 337 + uint64_t diff_draw_ns = f->when.delivered_ns - f->when.begin_ns; 338 + 339 + RT_LOG_D( 340 + "Delivered frame %.2fms %s." // 341 + "\n\tperiod: %.2f" // 342 + "\n\tcpu o: %.2f, n: %.2f" // 343 + "\n\tdraw o: %.2f, n: %.2f", // 344 + time_ns_to_ms_f(diff_ns), late ? "late" : "early", // 345 + time_ns_to_ms_f(f->predicted_display_period_ns), // 346 + time_ns_to_ms_f(pa->app.cpu_time_ns), time_ns_to_ms_f(diff_cpu_ns), // 347 + time_ns_to_ms_f(pa->app.draw_time_ns), time_ns_to_ms_f(diff_draw_ns)); // 348 + 349 + do_iir_filter(&pa->app.cpu_time_ns, IIR_ALPHA_LT, IIR_ALPHA_GT, diff_cpu_ns); 350 + do_iir_filter(&pa->app.draw_time_ns, IIR_ALPHA_LT, IIR_ALPHA_GT, diff_draw_ns); 351 + 352 + // Trace the data. 353 + #ifdef XRT_FEATURE_TRACING 354 + #define TE_BEG(TRACK, TIME, NAME) U_TRACE_EVENT_BEGIN_ON_TRACK_DATA(timing, TRACK, TIME, NAME, PERCETTO_I(f->frame_id)) 355 + #define TE_END(TRACK, TIME) U_TRACE_EVENT_END_ON_TRACK(timing, TRACK, TIME) 356 + 357 + if (U_TRACE_CATEGORY_IS_ENABLED(timing)) { 358 + TE_BEG(pa_cpu, f->when.predicted_ns, "sleep"); 359 + TE_END(pa_cpu, f->when.wait_woke_ns); 360 + 361 + uint64_t cpu_start_ns = f->when.wait_woke_ns + 1; 362 + TE_BEG(pa_cpu, cpu_start_ns, "cpu"); 363 + TE_END(pa_cpu, f->when.begin_ns); 364 + 365 + TE_BEG(pa_draw, f->when.begin_ns, "draw"); 366 + TE_END(pa_draw, f->when.delivered_ns); 367 + } 368 + 369 + #undef TE_BEG 370 + #undef TE_END 371 + #endif 372 + 373 + // Reset the frame. 374 + f->state = U_PA_READY; 375 + f->frame_id = -1; 376 + } 377 + 378 + static void 379 + pa_info(struct u_pacing_app *upa, 380 + uint64_t predicted_display_time_ns, 381 + uint64_t predicted_display_period_ns, 382 + uint64_t extra_ns) 383 + { 384 + struct pacing_app *pa = pacing_app(upa); 385 + 386 + pa->last_input.predicted_display_time_ns = predicted_display_time_ns; 387 + pa->last_input.predicted_display_period_ns = predicted_display_period_ns; 388 + pa->last_input.extra_ns = extra_ns; 389 + } 390 + 391 + static void 392 + pa_destroy(struct u_pacing_app *upa) 393 + { 394 + free(upa); 395 + } 396 + 397 + 398 + /* 399 + * 400 + * 'Exported' functions. 401 + * 402 + */ 403 + 404 + xrt_result_t 405 + u_pa_create(struct u_pacing_app **out_urt) 406 + { 407 + struct pacing_app *pa = U_TYPED_CALLOC(struct pacing_app); 408 + pa->base.predict = pa_predict; 409 + pa->base.mark_point = pa_mark_point; 410 + pa->base.mark_discarded = pa_mark_discarded; 411 + pa->base.mark_delivered = pa_mark_delivered; 412 + pa->base.info = pa_info; 413 + pa->base.destroy = pa_destroy; 414 + pa->app.cpu_time_ns = U_TIME_1MS_IN_NS * 2; 415 + pa->app.draw_time_ns = U_TIME_1MS_IN_NS * 2; 416 + pa->app.margin_ns = U_TIME_1MS_IN_NS * 2; 417 + 418 + for (size_t i = 0; i < ARRAY_SIZE(pa->frames); i++) { 419 + pa->frames[i].state = U_PA_READY; 420 + pa->frames[i].frame_id = -1; 421 + } 422 + 423 + *out_urt = &pa->base; 424 + 425 + return XRT_SUCCESS; 426 + }
+131 -105
src/xrt/auxiliary/util/u_timing.h src/xrt/auxiliary/util/u_pacing.h
··· 2 2 // SPDX-License-Identifier: BSL-1.0 3 3 /*! 4 4 * @file 5 - * @brief Shared timing code. 5 + * @brief Shared pacing code. 6 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 + * @author Ryan Pavlik <ryan.pavlik@collabora.com> 7 8 * @ingroup aux_util 8 9 */ 9 10 ··· 18 19 19 20 20 21 /*! 21 - * @defgroup aux_timing Frame and Render timing 22 + * @defgroup aux_pacing Frame and Render timing/pacing 22 23 * 23 24 * @ingroup aux_util 24 - * @see @ref frame-timing. 25 + * @see @ref frame-pacing. 25 26 */ 26 27 27 28 28 29 /*! 29 30 * For marking timepoints on a frame's lifetime, not a async event. 30 31 * 31 - * @ingroup aux_timing 32 + * @ingroup aux_pacing 32 33 */ 33 34 enum u_timing_point 34 35 { ··· 40 41 41 42 /* 42 43 * 43 - * Frame timing helper. 44 + * Compositor pacing helper. 44 45 * 45 46 */ 46 47 47 48 /*! 48 - * Frame timing helper struct, used for the compositors own frame timing. 49 + * Compositor pacing helper interface. 49 50 * 50 - * @ingroup aux_timing 51 + * This is used for the compositor's own frame timing/pacing. It is not responsible for getting the timing data from the 52 + * graphics API, etc: instead it consumes timing data from the graphics API (if available) and from "markers" in the 53 + * compositor's CPU code, and produces predictions that are used to guide the compositor. 54 + * 55 + * Pacing of the underlying app/client is handled by @ref u_pacing_app 56 + * 57 + * @ingroup aux_pacing 51 58 */ 52 - struct u_frame_timing 59 + struct u_pacing_compositor 53 60 { 54 61 /*! 55 62 * Predict the next frame. 56 63 * 57 - * @param[in] uft The frame timing struct. 64 + * @param[in] upc The compositor pacing helper. 58 65 * @param[out] out_frame_id Id used to refer to this frame again. 59 66 * @param[out] out_wake_up_time_ns When should the compositor wake up. 60 67 * @param[out] out_desired_present_time_ns The GPU should start scanning out at this time. ··· 65 72 * 66 73 * @see @ref frame-timing. 67 74 */ 68 - void (*predict)(struct u_frame_timing *uft, 75 + void (*predict)(struct u_pacing_compositor *upc, 69 76 int64_t *out_frame_id, 70 77 uint64_t *out_wake_up_time_ns, 71 78 uint64_t *out_desired_present_time_ns, ··· 77 84 /*! 78 85 * Mark a point on the frame's lifetime. 79 86 * 80 - * @param[in] uft The frame timing struct. 87 + * This is usually provided "when it happens" because the points to mark are steps in the CPU workload of the 88 + * compositor. 89 + * 90 + * @param[in] upc The compositor pacing helper. 81 91 * @param[in] point The point to record for a frame. 82 92 * @param[in] frame_id The frame ID to record for. 83 93 * @param[in] when_ns The timestamp of the event. 84 94 * 85 95 * @see @ref frame-timing. 86 96 */ 87 - void (*mark_point)(struct u_frame_timing *uft, enum u_timing_point point, int64_t frame_id, uint64_t when_ns); 97 + void (*mark_point)(struct u_pacing_compositor *upc, 98 + enum u_timing_point point, 99 + int64_t frame_id, 100 + uint64_t when_ns); 88 101 89 102 /*! 90 - * Provide frame timing information about a delivered frame, this is 91 - * usually provided by the display system. These arguments currently 103 + * Provide frame timing information about a delivered frame. 104 + * 105 + * This is usually provided after-the-fact by the display system. These arguments currently 92 106 * matches 1-to-1 what VK_GOOGLE_display_timing provides, see 93 107 * https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPastPresentationTimingGOOGLE.html 94 108 * 95 109 * Depend on when the information is delivered this can be called at any 96 110 * point of the following frames. 97 111 * 98 - * @param[in] uft The frame timing struct. 112 + * @param[in] upc The compositor pacing helper. 99 113 * @param[in] frame_id The frame ID to record for. 100 114 * @param[in] desired_present_time_ns The time that we indicated the GPU should start scanning out at, or zero 101 115 * if we didn't provide such a time. ··· 107 121 * 108 122 * @see @ref frame-timing. 109 123 */ 110 - void (*info)(struct u_frame_timing *uft, 124 + void (*info)(struct u_pacing_compositor *upc, 111 125 int64_t frame_id, 112 126 uint64_t desired_present_time_ns, 113 127 uint64_t actual_present_time_ns, ··· 115 129 uint64_t present_margin_ns); 116 130 117 131 /*! 118 - * Destroy this u_frame_timing. 132 + * Destroy this u_pacing_compositor. 119 133 */ 120 - void (*destroy)(struct u_frame_timing *uft); 134 + void (*destroy)(struct u_pacing_compositor *upc); 121 135 }; 122 136 123 137 /*! 124 - * @copydoc u_frame_timing::predict 138 + * @copydoc u_pacing_compositor::predict 125 139 * 126 140 * Helper for calling through the function pointer. 127 141 * 128 - * @public @memberof u_frame_timing 129 - * @ingroup aux_timing 142 + * @public @memberof u_pacing_compositor 143 + * @ingroup aux_pacing 130 144 */ 131 145 static inline void 132 - u_ft_predict(struct u_frame_timing *uft, 146 + u_pc_predict(struct u_pacing_compositor *upc, 133 147 int64_t *out_frame_id, 134 148 uint64_t *out_wake_up_time_ns, 135 149 uint64_t *out_desired_present_time_ns, ··· 138 152 uint64_t *out_predicted_display_period_ns, 139 153 uint64_t *out_min_display_period_ns) 140 154 { 141 - uft->predict(uft, // 155 + upc->predict(upc, // 142 156 out_frame_id, // 143 157 out_wake_up_time_ns, // 144 158 out_desired_present_time_ns, // ··· 149 163 } 150 164 151 165 /*! 152 - * @copydoc u_frame_timing::mark_point 166 + * @copydoc u_pacing_compositor::mark_point 153 167 * 154 168 * Helper for calling through the function pointer. 155 169 * 156 - * @public @memberof u_frame_timing 157 - * @ingroup aux_timing 170 + * @public @memberof u_pacing_compositor 171 + * @ingroup aux_pacing 158 172 */ 159 173 static inline void 160 - u_ft_mark_point(struct u_frame_timing *uft, enum u_timing_point point, int64_t frame_id, uint64_t when_ns) 174 + u_pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, uint64_t when_ns) 161 175 { 162 - uft->mark_point(uft, point, frame_id, when_ns); 176 + upc->mark_point(upc, point, frame_id, when_ns); 163 177 } 164 178 165 179 /*! 166 - * @copydoc u_frame_timing::info 180 + * @copydoc u_pacing_compositor::info 167 181 * 168 182 * Helper for calling through the function pointer. 169 183 * 170 - * @public @memberof u_frame_timing 171 - * @ingroup aux_timing 184 + * @public @memberof u_pacing_compositor 185 + * @ingroup aux_pacing 172 186 */ 173 187 static inline void 174 - u_ft_info(struct u_frame_timing *uft, 188 + u_pc_info(struct u_pacing_compositor *upc, 175 189 int64_t frame_id, 176 190 uint64_t desired_present_time_ns, 177 191 uint64_t actual_present_time_ns, 178 192 uint64_t earliest_present_time_ns, 179 193 uint64_t present_margin_ns) 180 194 { 181 - uft->info(uft, frame_id, desired_present_time_ns, actual_present_time_ns, earliest_present_time_ns, 195 + upc->info(upc, frame_id, desired_present_time_ns, actual_present_time_ns, earliest_present_time_ns, 182 196 present_margin_ns); 183 197 } 184 198 185 199 /*! 186 - * @copydoc u_frame_timing::destroy 200 + * @copydoc u_pacing_compositor::destroy 187 201 * 188 202 * Helper for calling through the function pointer: does a null check and sets 189 - * uft_ptr to null if freed. 203 + * @p upc_ptr to null if freed. 190 204 * 191 - * @public @memberof u_frame_timing 192 - * @ingroup aux_timing 205 + * @public @memberof u_pacing_compositor 206 + * @ingroup aux_pacing 193 207 */ 194 208 static inline void 195 - u_ft_destroy(struct u_frame_timing **uft_ptr) 209 + u_pc_destroy(struct u_pacing_compositor **upc_ptr) 196 210 { 197 - struct u_frame_timing *uft = *uft_ptr; 198 - if (uft == NULL) { 211 + struct u_pacing_compositor *upc = *upc_ptr; 212 + if (upc == NULL) { 199 213 return; 200 214 } 201 215 202 - uft->destroy(uft); 203 - *uft_ptr = NULL; 216 + upc->destroy(upc); 217 + *upc_ptr = NULL; 204 218 } 205 219 206 220 ··· 211 225 */ 212 226 213 227 /*! 214 - * This render timing helper is designed to schedule the rendering time of 228 + * This application pacing helper is designed to schedule the rendering time of 215 229 * clients that submit frames to a compositor, which runs its own render loop 216 230 * that picks latest completed frames for that client. 217 231 * 218 - * @ingroup aux_timing 232 + * It manages the frame pacing of an app/client, rather than the compositor itself. The frame pacing of the compositor 233 + * is handled by @ref u_pacing_compositor 234 + * 235 + * @ingroup aux_pacing 219 236 */ 220 - struct u_render_timing 237 + struct u_pacing_app 221 238 { 222 239 /*! 223 240 * Predict when the client's next rendered frame will be displayed; when the ··· 226 243 * This is called from `xrWaitFrame`, but it does not do any waiting, the caller 227 244 * should wait till `out_wake_up_time`. 228 245 * 229 - * @param urt Render timing helper. 246 + * @param upa Render timing helper. 230 247 * @param[out] out_frame_id Frame ID of this predicted frame. 231 248 * @param[out] out_wake_up_time When the client should be woken up. 232 249 * @param[out] out_predicted_display_time Predicted display time. 233 250 * @param[out] out_predicted_display_period Predicted display period. 234 251 */ 235 - void (*predict)(struct u_render_timing *urt, 252 + void (*predict)(struct u_pacing_app *upa, 236 253 int64_t *out_frame_id, 237 254 uint64_t *out_wake_up_time, 238 255 uint64_t *out_predicted_display_time, ··· 241 258 /*! 242 259 * Mark a point on the frame's lifetime. 243 260 * 261 + * @param upa Render timing helper. 262 + * @param[in] frame_id The frame ID to record for. 244 263 * @see @ref frame-timing. 245 264 */ 246 - void (*mark_point)(struct u_render_timing *urt, int64_t frame_id, enum u_timing_point point, uint64_t when_ns); 265 + void (*mark_point)(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, uint64_t when_ns); 247 266 248 267 /*! 249 268 * When a frame has been discarded. 250 269 */ 251 - void (*mark_discarded)(struct u_render_timing *urt, int64_t frame_id); 270 + void (*mark_discarded)(struct u_pacing_app *upa, int64_t frame_id); 252 271 253 272 /*! 254 273 * A frame has been delivered from the client, see `xrEndFrame`. The GPU might 255 274 * still be rendering the work. 256 275 */ 257 - void (*mark_delivered)(struct u_render_timing *urt, int64_t frame_id); 276 + void (*mark_delivered)(struct u_pacing_app *upa, int64_t frame_id); 258 277 259 278 /*! 260 279 * Add a new sample point from the main render loop. ··· 267 286 * to be able to predict one or more frames into the future anyways. But 268 287 * preferably as soon as the main loop wakes up from wait frame. 269 288 * 270 - * @param urt Self pointer 289 + * @param upa Self pointer 271 290 * @param predicted_display_time_ns Predicted display time for this sample. 272 291 * @param predicted_display_period_ns Predicted display period for this sample. 273 292 * @param extra_ns Time between display and when this sample 274 293 * was created, that is when the main loop 275 294 * was woken up by the main compositor. 276 295 */ 277 - void (*info)(struct u_render_timing *urt, 296 + void (*info)(struct u_pacing_app *upa, 278 297 uint64_t predicted_display_time_ns, 279 298 uint64_t predicted_display_period_ns, 280 299 uint64_t extra_ns); 281 300 282 301 /*! 283 - * Destroy this u_render_timing. 302 + * Destroy this u_pacing_app. 284 303 */ 285 - void (*destroy)(struct u_render_timing *urt); 304 + void (*destroy)(struct u_pacing_app *upa); 286 305 }; 287 306 288 307 /*! 289 - * @copydoc u_render_timing::predict 308 + * @copydoc u_pacing_app::predict 290 309 * 291 310 * Helper for calling through the function pointer. 292 311 * 293 - * @public @memberof u_render_timing 294 - * @ingroup aux_timing 312 + * @public @memberof u_pacing_app 313 + * @ingroup aux_pacing 295 314 */ 296 315 static inline void 297 - u_rt_predict(struct u_render_timing *urt, 316 + u_pa_predict(struct u_pacing_app *upa, 298 317 int64_t *out_frame_id, 299 318 uint64_t *out_wake_up_time, 300 319 uint64_t *out_predicted_display_time, 301 320 uint64_t *out_predicted_display_period) 302 321 { 303 - urt->predict(urt, out_frame_id, out_wake_up_time, out_predicted_display_time, out_predicted_display_period); 322 + upa->predict(upa, out_frame_id, out_wake_up_time, out_predicted_display_time, out_predicted_display_period); 304 323 } 305 324 306 325 /*! 307 - * @copydoc u_render_timing::mark_point 326 + * @copydoc u_pacing_app::mark_point 308 327 * 309 328 * Helper for calling through the function pointer. 310 329 * 311 - * @public @memberof u_render_timing 312 - * @ingroup aux_timing 330 + * @public @memberof u_pacing_app 331 + * @ingroup aux_pacing 313 332 */ 314 333 static inline void 315 - u_rt_mark_point(struct u_render_timing *urt, int64_t frame_id, enum u_timing_point point, uint64_t when_ns) 334 + u_pa_mark_point(struct u_pacing_app *upa, int64_t frame_id, enum u_timing_point point, uint64_t when_ns) 316 335 { 317 - urt->mark_point(urt, frame_id, point, when_ns); 336 + upa->mark_point(upa, frame_id, point, when_ns); 318 337 } 319 338 320 339 /*! 321 - * @copydoc u_render_timing::mark_discarded 340 + * @copydoc u_pacing_app::mark_discarded 322 341 * 323 342 * Helper for calling through the function pointer. 324 343 * 325 - * @public @memberof u_render_timing 326 - * @ingroup aux_timing 344 + * @public @memberof u_pacing_app 345 + * @ingroup aux_pacing 327 346 */ 328 347 static inline void 329 - u_rt_mark_discarded(struct u_render_timing *urt, int64_t frame_id) 348 + u_pa_mark_discarded(struct u_pacing_app *upa, int64_t frame_id) 330 349 { 331 - urt->mark_discarded(urt, frame_id); 350 + upa->mark_discarded(upa, frame_id); 332 351 } 333 352 334 353 /*! 335 - * @copydoc u_render_timing::mark_delivered 354 + * @copydoc u_pacing_app::mark_delivered 336 355 * 337 356 * Helper for calling through the function pointer. 338 357 * 339 - * @public @memberof u_render_timing 340 - * @ingroup aux_timing 358 + * @public @memberof u_pacing_app 359 + * @ingroup aux_pacing 341 360 */ 342 361 static inline void 343 - u_rt_mark_delivered(struct u_render_timing *urt, int64_t frame_id) 362 + u_pa_mark_delivered(struct u_pacing_app *upa, int64_t frame_id) 344 363 { 345 - urt->mark_delivered(urt, frame_id); 364 + upa->mark_delivered(upa, frame_id); 346 365 } 347 366 348 367 /*! 349 - * @copydoc u_render_timing::info 368 + * @copydoc u_pacing_app::info 350 369 * 351 370 * Helper for calling through the function pointer. 352 371 * 353 - * @public @memberof u_render_timing 354 - * @ingroup aux_timing 372 + * @public @memberof u_pacing_app 373 + * @ingroup aux_pacing 355 374 */ 356 375 static inline void 357 - u_rt_info(struct u_render_timing *urt, 376 + u_pa_info(struct u_pacing_app *upa, 358 377 uint64_t predicted_display_time_ns, 359 378 uint64_t predicted_display_period_ns, 360 379 uint64_t extra_ns) 361 380 { 362 - urt->info(urt, predicted_display_time_ns, predicted_display_period_ns, extra_ns); 381 + upa->info(upa, predicted_display_time_ns, predicted_display_period_ns, extra_ns); 363 382 } 364 383 365 384 /*! 366 - * @copydoc u_render_timing::destroy 385 + * @copydoc u_pacing_app::destroy 367 386 * 368 387 * Helper for calling through the function pointer: does a null check and sets 369 - * urt_ptr to null if freed. 388 + * upa_ptr to null if freed. 370 389 * 371 - * @public @memberof u_frame_timing 372 - * @ingroup aux_timing 390 + * @public @memberof u_pacing_compositor 391 + * @ingroup aux_pacing 373 392 */ 374 393 static inline void 375 - u_rt_destroy(struct u_render_timing **urt_ptr) 394 + u_pa_destroy(struct u_pacing_app **upa_ptr) 376 395 { 377 - struct u_render_timing *urt = *urt_ptr; 378 - if (urt == NULL) { 396 + struct u_pacing_app *upa = *upa_ptr; 397 + if (upa == NULL) { 379 398 return; 380 399 } 381 400 382 - urt->destroy(urt); 383 - *urt_ptr = NULL; 401 + upa->destroy(upa); 402 + *upa_ptr = NULL; 384 403 } 385 404 386 405 /* ··· 389 408 * 390 409 */ 391 410 /*! 392 - * Configuration for the "display_timing" implementation of u_ft 411 + * Configuration for the "display-timing-aware" implementation of @ref u_pacing_compositor 393 412 * 394 - * @see u_ft_display_timing_create 413 + * @see u_pc_display_timing_create 395 414 */ 396 - struct u_ft_display_timing_config 415 + struct u_pc_display_timing_config 397 416 { 398 417 //! How long after "present" is the image actually displayed 399 418 uint64_t present_offset_ns; ··· 419 438 }; 420 439 421 440 /*! 422 - * Default configuration values 441 + * Default configuration values for display-timing-aware compositor pacing. 423 442 * 424 - * @see u_ft_display_timing_config, u_ft_display_timing_create 443 + * @see u_pc_display_timing_config, u_pc_display_timing_create 425 444 */ 426 - extern const struct u_ft_display_timing_config U_FT_DISPLAY_TIMING_CONFIG_DEFAULT; 445 + extern const struct u_pc_display_timing_config U_PC_DISPLAY_TIMING_CONFIG_DEFAULT; 427 446 428 447 /* 429 448 * ··· 432 451 */ 433 452 434 453 /*! 435 - * Meant to be used with VK_GOOGLE_display_timing. 454 + * Creates a new composition pacing helper that uses real display timing information. 436 455 * 437 - * @ingroup aux_timing 456 + * Meant to be used with `VK_GOOGLE_display_timing`. 457 + * 458 + * @ingroup aux_pacing 459 + * @see u_pacing_compositor 438 460 */ 439 461 xrt_result_t 440 - u_ft_display_timing_create(uint64_t estimated_frame_period_ns, 441 - const struct u_ft_display_timing_config *config, 442 - struct u_frame_timing **out_uft); 462 + u_pc_display_timing_create(uint64_t estimated_frame_period_ns, 463 + const struct u_pc_display_timing_config *config, 464 + struct u_pacing_compositor **out_upc); 443 465 444 466 /*! 445 - * When you can not get display timing information use this. 467 + * Creates a new composition pacing helper that does not depend on display timing information. 468 + * 469 + * When you cannot get display timing information, use this. 446 470 * 447 - * @ingroup aux_timing 471 + * @ingroup aux_pacing 472 + * @see u_pacing_compositor 448 473 */ 449 474 xrt_result_t 450 - u_ft_fake_create(uint64_t estimated_frame_period_ns, struct u_frame_timing **out_uft); 475 + u_pc_fake_create(uint64_t estimated_frame_period_ns, struct u_pacing_compositor **out_upc); 451 476 452 477 /*! 453 - * Creates a new render timing. 478 + * Creates a new application pacing helper. 454 479 * 455 - * @ingroup aux_timing 480 + * @ingroup aux_pacing 481 + * @see u_pacing_app 456 482 */ 457 483 xrt_result_t 458 - u_rt_create(struct u_render_timing **out_urt); 484 + u_pa_create(struct u_pacing_app **out_upa); 459 485 460 486 461 487 #ifdef __cplusplus
+15 -15
src/xrt/auxiliary/util/u_timing_fake.c src/xrt/auxiliary/util/u_pacing_compositor_fake.c
··· 12 12 #include "util/u_time.h" 13 13 #include "util/u_misc.h" 14 14 #include "util/u_debug.h" 15 - #include "util/u_timing.h" 15 + #include "util/u_pacing.h" 16 16 #include "util/u_logging.h" 17 17 #include "util/u_trace_marker.h" 18 18 ··· 30 30 31 31 struct fake_timing 32 32 { 33 - struct u_frame_timing base; 33 + struct u_pacing_compositor base; 34 34 35 35 /*! 36 36 * The periodicity of the display. ··· 63 63 */ 64 64 65 65 static inline struct fake_timing * 66 - fake_timing(struct u_frame_timing *uft) 66 + fake_timing(struct u_pacing_compositor *upc) 67 67 { 68 - return (struct fake_timing *)uft; 68 + return (struct fake_timing *)upc; 69 69 } 70 70 71 71 static uint64_t ··· 97 97 */ 98 98 99 99 static void 100 - ft_predict(struct u_frame_timing *uft, 100 + pc_predict(struct u_pacing_compositor *upc, 101 101 int64_t *out_frame_id, 102 102 uint64_t *out_wake_up_time_ns, 103 103 uint64_t *out_desired_present_time_ns, ··· 106 106 uint64_t *out_predicted_display_period_ns, 107 107 uint64_t *out_min_display_period_ns) 108 108 { 109 - struct fake_timing *ft = fake_timing(uft); 109 + struct fake_timing *ft = fake_timing(upc); 110 110 111 111 int64_t frame_id = ft->frame_id_generator++; 112 112 uint64_t predicted_display_time_ns = predict_next_frame(ft); ··· 126 126 } 127 127 128 128 static void 129 - ft_mark_point(struct u_frame_timing *uft, enum u_timing_point point, int64_t frame_id, uint64_t when_ns) 129 + pc_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, uint64_t when_ns) 130 130 { 131 131 // To help validate calling code. 132 132 switch (point) { ··· 138 138 } 139 139 140 140 static void 141 - ft_info(struct u_frame_timing *uft, 141 + pc_info(struct u_pacing_compositor *upc, 142 142 int64_t frame_id, 143 143 uint64_t desired_present_time_ns, 144 144 uint64_t actual_present_time_ns, ··· 152 152 } 153 153 154 154 static void 155 - ft_destroy(struct u_frame_timing *uft) 155 + pc_destroy(struct u_pacing_compositor *upc) 156 156 { 157 - struct fake_timing *ft = fake_timing(uft); 157 + struct fake_timing *ft = fake_timing(upc); 158 158 free(ft); 159 159 } 160 160 ··· 166 166 */ 167 167 168 168 xrt_result_t 169 - u_ft_fake_create(uint64_t estimated_frame_period_ns, struct u_frame_timing **out_uft) 169 + u_pc_fake_create(uint64_t estimated_frame_period_ns, struct u_pacing_compositor **out_uft) 170 170 { 171 171 struct fake_timing *ft = U_TYPED_CALLOC(struct fake_timing); 172 - ft->base.predict = ft_predict; 173 - ft->base.mark_point = ft_mark_point; 174 - ft->base.info = ft_info; 175 - ft->base.destroy = ft_destroy; 172 + ft->base.predict = pc_predict; 173 + ft->base.mark_point = pc_mark_point; 174 + ft->base.info = pc_info; 175 + ft->base.destroy = pc_destroy; 176 176 ft->frame_period_ns = estimated_frame_period_ns; 177 177 178 178 // To make sure the code can start from a non-zero frame id.
+39 -39
src/xrt/auxiliary/util/u_timing_frame.c src/xrt/auxiliary/util/u_pacing_compositor.c
··· 12 12 #include "util/u_time.h" 13 13 #include "util/u_misc.h" 14 14 #include "util/u_debug.h" 15 - #include "util/u_timing.h" 15 + #include "util/u_pacing.h" 16 16 #include "util/u_logging.h" 17 17 #include "util/u_trace_marker.h" 18 18 ··· 87 87 88 88 struct display_timing 89 89 { 90 - struct u_frame_timing base; 90 + struct u_pacing_compositor base; 91 91 92 92 /*! 93 93 * Very often the present time that we get from the system is only when ··· 151 151 */ 152 152 153 153 static inline struct display_timing * 154 - display_timing(struct u_frame_timing *uft) 154 + display_timing(struct u_pacing_compositor *upc) 155 155 { 156 - return (struct display_timing *)uft; 156 + return (struct display_timing *)upc; 157 157 } 158 158 159 159 static double ··· 373 373 */ 374 374 375 375 static void 376 - dt_predict(struct u_frame_timing *uft, 376 + dt_predict(struct u_pacing_compositor *upc, 377 377 int64_t *out_frame_id, 378 378 uint64_t *out_wake_up_time_ns, 379 379 uint64_t *out_desired_present_time_ns, ··· 382 382 uint64_t *out_predicted_display_period_ns, 383 383 uint64_t *out_min_display_period_ns) 384 384 { 385 - struct display_timing *dt = display_timing(uft); 385 + struct display_timing *dt = display_timing(upc); 386 386 387 387 struct frame *f = predict_next_frame(dt); 388 388 ··· 403 403 } 404 404 405 405 static void 406 - dt_mark_point(struct u_frame_timing *uft, enum u_timing_point point, int64_t frame_id, uint64_t when_ns) 406 + dt_mark_point(struct u_pacing_compositor *upc, enum u_timing_point point, int64_t frame_id, uint64_t when_ns) 407 407 { 408 - struct display_timing *dt = display_timing(uft); 408 + struct display_timing *dt = display_timing(upc); 409 409 struct frame *f = get_frame(dt, frame_id); 410 410 411 411 switch (point) { ··· 429 429 } 430 430 431 431 static void 432 - dt_info(struct u_frame_timing *uft, 432 + dt_info(struct u_pacing_compositor *upc, 433 433 int64_t frame_id, 434 434 uint64_t desired_present_time_ns, 435 435 uint64_t actual_present_time_ns, 436 436 uint64_t earliest_present_time_ns, 437 437 uint64_t present_margin_ns) 438 438 { 439 - struct display_timing *dt = display_timing(uft); 439 + struct display_timing *dt = display_timing(upc); 440 440 (void)dt; 441 441 442 442 struct frame *last = get_latest_frame_with_state_at_least(dt, STATE_INFO); ··· 500 500 * 501 501 */ 502 502 503 - TE_BEG(rt_cpu, f->when_predict_ns, "sleep"); 504 - TE_END(rt_cpu, f->wake_up_time_ns); 503 + TE_BEG(pc_cpu, f->when_predict_ns, "sleep"); 504 + TE_END(pc_cpu, f->wake_up_time_ns); 505 505 506 506 uint64_t oversleep_start_ns = f->wake_up_time_ns + 1; 507 507 if (f->when_woke_ns > oversleep_start_ns) { 508 - TE_BEG(rt_cpu, oversleep_start_ns, "oversleep"); 509 - TE_END(rt_cpu, f->when_woke_ns); 508 + TE_BEG(pc_cpu, oversleep_start_ns, "oversleep"); 509 + TE_END(pc_cpu, f->when_woke_ns); 510 510 } 511 511 512 512 ··· 518 518 519 519 uint64_t gpu_end_ns = f->actual_present_time_ns - f->present_margin_ns; 520 520 if (gpu_end_ns > f->when_submitted_ns) { 521 - TE_BEG(rt_gpu, f->when_submitted_ns, "gpu"); 522 - TE_END(rt_gpu, gpu_end_ns); 521 + TE_BEG(pc_gpu, f->when_submitted_ns, "gpu"); 522 + TE_END(pc_gpu, gpu_end_ns); 523 523 } else { 524 - TE_BEG(rt_gpu, gpu_end_ns, "gpu-time-travel"); 525 - TE_END(rt_gpu, f->when_submitted_ns); 524 + TE_BEG(pc_gpu, gpu_end_ns, "gpu-time-travel"); 525 + TE_END(pc_gpu, f->when_submitted_ns); 526 526 } 527 527 528 528 ··· 533 533 */ 534 534 535 535 if (gpu_end_ns < f->desired_present_time_ns) { 536 - TE_BEG(rt_margin, gpu_end_ns, "margin"); 537 - TE_END(rt_margin, f->desired_present_time_ns); 536 + TE_BEG(pc_margin, gpu_end_ns, "margin"); 537 + TE_END(pc_margin, f->desired_present_time_ns); 538 538 } 539 539 540 540 ··· 546 546 547 547 if (!is_within_half_ms(f->actual_present_time_ns, f->desired_present_time_ns)) { 548 548 if (f->actual_present_time_ns > f->desired_present_time_ns) { 549 - TE_BEG(rt_error, f->desired_present_time_ns, "slippage"); 550 - TE_END(rt_error, f->actual_present_time_ns); 549 + TE_BEG(pc_error, f->desired_present_time_ns, "slippage"); 550 + TE_END(pc_error, f->actual_present_time_ns); 551 551 } else { 552 - TE_BEG(rt_error, f->actual_present_time_ns, "run-ahead"); 553 - TE_END(rt_error, f->desired_present_time_ns); 552 + TE_BEG(pc_error, f->actual_present_time_ns, "run-ahead"); 553 + TE_END(pc_error, f->desired_present_time_ns); 554 554 } 555 555 } 556 556 ··· 562 562 */ 563 563 564 564 if (f->when_infoed_ns >= f->actual_present_time_ns) { 565 - TE_BEG(rt_info, f->actual_present_time_ns, "info"); 566 - TE_END(rt_info, f->when_infoed_ns); 565 + TE_BEG(pc_info, f->actual_present_time_ns, "info"); 566 + TE_END(pc_info, f->when_infoed_ns); 567 567 } else { 568 - TE_BEG(rt_info, f->when_infoed_ns, "info_before"); 569 - TE_END(rt_info, f->actual_present_time_ns); 568 + TE_BEG(pc_info, f->when_infoed_ns, "info_before"); 569 + TE_END(pc_info, f->actual_present_time_ns); 570 570 } 571 571 572 572 ··· 577 577 */ 578 578 579 579 if (f->actual_present_time_ns != f->earliest_present_time_ns) { 580 - U_TRACE_INSTANT_ON_TRACK(timing, rt_present, f->earliest_present_time_ns, "earliest"); 580 + U_TRACE_INSTANT_ON_TRACK(timing, pc_present, f->earliest_present_time_ns, "earliest"); 581 581 } 582 582 if (!is_within_half_ms(f->desired_present_time_ns, f->earliest_present_time_ns)) { 583 - U_TRACE_INSTANT_ON_TRACK(timing, rt_present, f->desired_present_time_ns, "predicted"); 583 + U_TRACE_INSTANT_ON_TRACK(timing, pc_present, f->desired_present_time_ns, "predicted"); 584 584 } 585 - U_TRACE_INSTANT_ON_TRACK(timing, rt_present, f->actual_present_time_ns, "vsync"); 585 + U_TRACE_INSTANT_ON_TRACK(timing, pc_present, f->actual_present_time_ns, "vsync"); 586 586 587 587 588 588 /* ··· 591 591 * 592 592 */ 593 593 594 - TE_BEG(rt_allotted, f->wake_up_time_ns, "allotted"); 595 - TE_END(rt_allotted, f->wake_up_time_ns + f->current_app_time_ns); 594 + TE_BEG(pc_allotted, f->wake_up_time_ns, "allotted"); 595 + TE_END(pc_allotted, f->wake_up_time_ns + f->current_app_time_ns); 596 596 597 597 #undef TE_BEG 598 598 #undef TE_END 599 599 } 600 600 601 601 static void 602 - dt_destroy(struct u_frame_timing *uft) 602 + dt_destroy(struct u_pacing_compositor *upc) 603 603 { 604 - struct display_timing *dt = display_timing(uft); 604 + struct display_timing *dt = display_timing(upc); 605 605 606 606 free(dt); 607 607 } 608 608 609 - const struct u_ft_display_timing_config U_FT_DISPLAY_TIMING_CONFIG_DEFAULT = { 609 + const struct u_pc_display_timing_config U_PC_DISPLAY_TIMING_CONFIG_DEFAULT = { 610 610 // Just a wild guess. 611 611 .present_offset_ns = U_TIME_1MS_IN_NS * 4, 612 612 .margin_ns = U_TIME_1MS_IN_NS, ··· 617 617 }; 618 618 619 619 xrt_result_t 620 - u_ft_display_timing_create(uint64_t estimated_frame_period_ns, 621 - const struct u_ft_display_timing_config *config, 622 - struct u_frame_timing **out_uft) 620 + u_pc_display_timing_create(uint64_t estimated_frame_period_ns, 621 + const struct u_pc_display_timing_config *config, 622 + struct u_pacing_compositor **out_uft) 623 623 { 624 624 struct display_timing *dt = U_TYPED_CALLOC(struct display_timing); 625 625 dt->base.predict = dt_predict;
-426
src/xrt/auxiliary/util/u_timing_render.c
··· 1 - // Copyright 2020-2021, Collabora, Ltd. 2 - // SPDX-License-Identifier: BSL-1.0 3 - /*! 4 - * @file 5 - * @brief Shared frame timing code. 6 - * @author Jakob Bornecrantz <jakob@collabora.com> 7 - * @ingroup aux_util 8 - */ 9 - 10 - #include "os/os_time.h" 11 - 12 - #include "util/u_time.h" 13 - #include "util/u_misc.h" 14 - #include "util/u_debug.h" 15 - #include "util/u_timing.h" 16 - #include "util/u_logging.h" 17 - #include "util/u_trace_marker.h" 18 - 19 - #include <stdio.h> 20 - #include <assert.h> 21 - #include <inttypes.h> 22 - 23 - 24 - /* 25 - * 26 - * Structs enums, and defines. 27 - * 28 - */ 29 - 30 - enum u_rt_state 31 - { 32 - U_RT_READY, 33 - U_RT_WAIT_LEFT, 34 - U_RT_PREDICTED, 35 - U_RT_BEGUN, 36 - }; 37 - 38 - struct u_rt_frame 39 - { 40 - //! When we predicted this frame to be shown. 41 - uint64_t predicted_display_time_ns; 42 - 43 - //! The selected display period. 44 - uint64_t predicted_display_period_ns; 45 - 46 - //! When the client should have delivered the frame. 47 - uint64_t predicted_delivery_time_ns; 48 - 49 - struct 50 - { 51 - uint64_t predicted_ns; 52 - uint64_t wait_woke_ns; 53 - uint64_t begin_ns; 54 - uint64_t delivered_ns; 55 - } when; //!< When something happened. 56 - 57 - int64_t frame_id; 58 - enum u_rt_state state; 59 - }; 60 - 61 - struct render_timing 62 - { 63 - struct u_render_timing base; 64 - 65 - struct u_rt_frame frames[2]; 66 - uint32_t current_frame; 67 - uint32_t next_frame; 68 - 69 - int64_t frame_counter; 70 - 71 - struct 72 - { 73 - //! App time between wait returning and begin being called. 74 - uint64_t cpu_time_ns; 75 - //! Time between begin and frame rendering completeing. 76 - uint64_t draw_time_ns; 77 - //! Exrta time between end of draw time and when the compositor wakes up. 78 - uint64_t margin_ns; 79 - } app; //!< App statistics. 80 - 81 - struct 82 - { 83 - //! The last display time that the thing driving this helper got. 84 - uint64_t predicted_display_time_ns; 85 - //! The last display period the hardware is running at. 86 - uint64_t predicted_display_period_ns; 87 - //! The extra time needed by the thing driving this helper. 88 - uint64_t extra_ns; 89 - } last_input; 90 - 91 - uint64_t last_returned_ns; 92 - }; 93 - 94 - 95 - /* 96 - * 97 - * Helpers 98 - * 99 - */ 100 - 101 - static inline struct render_timing * 102 - render_timing(struct u_render_timing *urt) 103 - { 104 - return (struct render_timing *)urt; 105 - } 106 - 107 - DEBUG_GET_ONCE_LOG_OPTION(log_level, "U_TIMING_RENDER_LOG", U_LOGGING_WARN) 108 - 109 - #define RT_LOG_T(...) U_LOG_IFL_T(debug_get_log_option_log_level(), __VA_ARGS__) 110 - #define RT_LOG_D(...) U_LOG_IFL_D(debug_get_log_option_log_level(), __VA_ARGS__) 111 - #define RT_LOG_I(...) U_LOG_IFL_I(debug_get_log_option_log_level(), __VA_ARGS__) 112 - #define RT_LOG_W(...) U_LOG_IFL_W(debug_get_log_option_log_level(), __VA_ARGS__) 113 - #define RT_LOG_E(...) U_LOG_IFL_E(debug_get_log_option_log_level(), __VA_ARGS__) 114 - 115 - #define DEBUG_PRINT_FRAME_ID() RT_LOG_T("%" PRIi64, frame_id) 116 - #define GET_INDEX_FROM_ID(RT, ID) ((uint64_t)(ID) % ARRAY_SIZE((RT)->frames)) 117 - 118 - #define IIR_ALPHA_LT 0.8 119 - #define IIR_ALPHA_GT 0.8 120 - 121 - static void 122 - do_iir_filter(uint64_t *target, double alpha_lt, double alpha_gt, uint64_t sample) 123 - { 124 - uint64_t t = *target; 125 - double alpha = t < sample ? alpha_lt : alpha_gt; 126 - double a = time_ns_to_s(t) * alpha; 127 - double b = time_ns_to_s(sample) * (1.0 - alpha); 128 - *target = time_s_to_ns(a + b); 129 - } 130 - 131 - static uint64_t 132 - min_period(const struct render_timing *rt) 133 - { 134 - return rt->last_input.predicted_display_period_ns; 135 - } 136 - 137 - static uint64_t 138 - last_sample_displayed(const struct render_timing *rt) 139 - { 140 - return rt->last_input.predicted_display_time_ns; 141 - } 142 - 143 - static uint64_t 144 - last_return_predicted_display(const struct render_timing *rt) 145 - { 146 - return rt->last_returned_ns; 147 - } 148 - 149 - static uint64_t 150 - total_app_time_ns(const struct render_timing *rt) 151 - { 152 - return rt->app.cpu_time_ns + rt->app.draw_time_ns; 153 - } 154 - 155 - static uint64_t 156 - total_compositor_time_ns(const struct render_timing *rt) 157 - { 158 - return rt->app.margin_ns + rt->last_input.extra_ns; 159 - } 160 - 161 - static uint64_t 162 - total_app_and_compositor_time_ns(const struct render_timing *rt) 163 - { 164 - return total_app_time_ns(rt) + total_compositor_time_ns(rt); 165 - } 166 - 167 - static uint64_t 168 - calc_period(const struct render_timing *rt) 169 - { 170 - // Error checking. 171 - uint64_t base_period_ns = min_period(rt); 172 - if (base_period_ns == 0) { 173 - assert(false && "Have not yet received and samples from timing driver."); 174 - base_period_ns = U_TIME_1MS_IN_NS * 16; // Sure 175 - } 176 - 177 - // Calculate the using both values separately. 178 - uint64_t period_ns = base_period_ns; 179 - while (rt->app.cpu_time_ns > period_ns) { 180 - period_ns += base_period_ns; 181 - } 182 - 183 - while (rt->app.draw_time_ns > period_ns) { 184 - period_ns += base_period_ns; 185 - } 186 - 187 - return period_ns; 188 - } 189 - 190 - static uint64_t 191 - predict_display_time(const struct render_timing *rt, uint64_t period_ns) 192 - { 193 - // Now 194 - uint64_t now_ns = os_monotonic_get_ns(); 195 - 196 - 197 - // Total app and compositor time to produce a frame 198 - uint64_t app_and_compositor_time_ns = total_app_and_compositor_time_ns(rt); 199 - 200 - // Start from the last time that the driver displayed something. 201 - uint64_t val = last_sample_displayed(rt); 202 - 203 - // Return a time after the last returned display time. 204 - while (val <= last_return_predicted_display(rt)) { 205 - val += period_ns; 206 - } 207 - 208 - // Have to have enough time to perform app work. 209 - while ((val - app_and_compositor_time_ns) <= now_ns) { 210 - val += period_ns; 211 - } 212 - 213 - return val; 214 - } 215 - 216 - 217 - /* 218 - * 219 - * Member functions. 220 - * 221 - */ 222 - 223 - static void 224 - rt_predict(struct u_render_timing *urt, 225 - int64_t *out_frame_id, 226 - uint64_t *out_wake_up_time, 227 - uint64_t *out_predicted_display_time, 228 - uint64_t *out_predicted_display_period) 229 - { 230 - struct render_timing *rt = render_timing(urt); 231 - 232 - int64_t frame_id = ++rt->frame_counter; 233 - *out_frame_id = frame_id; 234 - 235 - DEBUG_PRINT_FRAME_ID(); 236 - 237 - uint64_t period_ns = calc_period(rt); 238 - uint64_t predict_ns = predict_display_time(rt, period_ns); 239 - // When should the client wake up. 240 - uint64_t wake_up_time_ns = predict_ns - total_app_and_compositor_time_ns(rt); 241 - // When the client should deliver the frame to us. 242 - uint64_t delivery_time_ns = predict_ns - total_compositor_time_ns(rt); 243 - 244 - rt->last_returned_ns = predict_ns; 245 - 246 - *out_wake_up_time = wake_up_time_ns; 247 - *out_predicted_display_time = predict_ns; 248 - *out_predicted_display_period = period_ns; 249 - 250 - size_t index = GET_INDEX_FROM_ID(rt, frame_id); 251 - assert(rt->frames[index].frame_id == -1); 252 - assert(rt->frames[index].state == U_RT_READY); 253 - 254 - rt->frames[index].state = U_RT_PREDICTED; 255 - rt->frames[index].frame_id = frame_id; 256 - rt->frames[index].predicted_delivery_time_ns = delivery_time_ns; 257 - rt->frames[index].predicted_display_period_ns = period_ns; 258 - rt->frames[index].when.predicted_ns = os_monotonic_get_ns(); 259 - } 260 - 261 - static void 262 - rt_mark_point(struct u_render_timing *urt, int64_t frame_id, enum u_timing_point point, uint64_t when_ns) 263 - { 264 - struct render_timing *rt = render_timing(urt); 265 - 266 - RT_LOG_T("%" PRIi64 " (%u)", frame_id, point); 267 - 268 - size_t index = GET_INDEX_FROM_ID(rt, frame_id); 269 - assert(rt->frames[index].frame_id == frame_id); 270 - 271 - switch (point) { 272 - case U_TIMING_POINT_WAKE_UP: 273 - assert(rt->frames[index].state == U_RT_PREDICTED); 274 - 275 - rt->frames[index].when.wait_woke_ns = when_ns; 276 - rt->frames[index].state = U_RT_WAIT_LEFT; 277 - break; 278 - case U_TIMING_POINT_BEGIN: 279 - assert(rt->frames[index].state == U_RT_WAIT_LEFT); 280 - 281 - rt->frames[index].when.begin_ns = os_monotonic_get_ns(); 282 - rt->frames[index].state = U_RT_BEGUN; 283 - break; 284 - case U_TIMING_POINT_SUBMIT: 285 - default: assert(false); 286 - } 287 - } 288 - 289 - static void 290 - rt_mark_discarded(struct u_render_timing *urt, int64_t frame_id) 291 - { 292 - struct render_timing *rt = render_timing(urt); 293 - 294 - DEBUG_PRINT_FRAME_ID(); 295 - 296 - size_t index = GET_INDEX_FROM_ID(rt, frame_id); 297 - assert(rt->frames[index].frame_id == frame_id); 298 - assert(rt->frames[index].state == U_RT_WAIT_LEFT || rt->frames[index].state == U_RT_BEGUN); 299 - 300 - rt->frames[index].when.delivered_ns = os_monotonic_get_ns(); 301 - rt->frames[index].state = U_RT_READY; 302 - rt->frames[index].frame_id = -1; 303 - } 304 - 305 - static void 306 - rt_mark_delivered(struct u_render_timing *urt, int64_t frame_id) 307 - { 308 - struct render_timing *rt = render_timing(urt); 309 - 310 - DEBUG_PRINT_FRAME_ID(); 311 - 312 - size_t index = GET_INDEX_FROM_ID(rt, frame_id); 313 - struct u_rt_frame *f = &rt->frames[index]; 314 - assert(f->frame_id == frame_id); 315 - assert(f->state == U_RT_BEGUN); 316 - 317 - uint64_t now_ns = os_monotonic_get_ns(); 318 - 319 - // Update all data. 320 - f->when.delivered_ns = now_ns; 321 - 322 - 323 - /* 324 - * Process data. 325 - */ 326 - 327 - int64_t diff_ns = f->predicted_delivery_time_ns - now_ns; 328 - bool late = false; 329 - if (diff_ns < 0) { 330 - diff_ns = -diff_ns; 331 - late = true; 332 - } 333 - 334 - #define NS_TO_MS_F(ns) (time_ns_to_s(ns) * 1000.0) 335 - 336 - uint64_t diff_cpu_ns = f->when.begin_ns - f->when.wait_woke_ns; 337 - uint64_t diff_draw_ns = f->when.delivered_ns - f->when.begin_ns; 338 - 339 - RT_LOG_D( 340 - "Delivered frame %.2fms %s." // 341 - "\n\tperiod: %.2f" // 342 - "\n\tcpu o: %.2f, n: %.2f" // 343 - "\n\tdraw o: %.2f, n: %.2f", // 344 - time_ns_to_ms_f(diff_ns), late ? "late" : "early", // 345 - time_ns_to_ms_f(f->predicted_display_period_ns), // 346 - time_ns_to_ms_f(rt->app.cpu_time_ns), time_ns_to_ms_f(diff_cpu_ns), // 347 - time_ns_to_ms_f(rt->app.draw_time_ns), time_ns_to_ms_f(diff_draw_ns)); // 348 - 349 - do_iir_filter(&rt->app.cpu_time_ns, IIR_ALPHA_LT, IIR_ALPHA_GT, diff_cpu_ns); 350 - do_iir_filter(&rt->app.draw_time_ns, IIR_ALPHA_LT, IIR_ALPHA_GT, diff_draw_ns); 351 - 352 - // Trace the data. 353 - #ifdef XRT_FEATURE_TRACING 354 - #define TE_BEG(TRACK, TIME, NAME) U_TRACE_EVENT_BEGIN_ON_TRACK_DATA(timing, TRACK, TIME, NAME, PERCETTO_I(f->frame_id)) 355 - #define TE_END(TRACK, TIME) U_TRACE_EVENT_END_ON_TRACK(timing, TRACK, TIME) 356 - 357 - if (U_TRACE_CATEGORY_IS_ENABLED(timing)) { 358 - TE_BEG(ft_cpu, f->when.predicted_ns, "sleep"); 359 - TE_END(ft_cpu, f->when.wait_woke_ns); 360 - 361 - uint64_t cpu_start_ns = f->when.wait_woke_ns + 1; 362 - TE_BEG(ft_cpu, cpu_start_ns, "cpu"); 363 - TE_END(ft_cpu, f->when.begin_ns); 364 - 365 - TE_BEG(ft_draw, f->when.begin_ns, "draw"); 366 - TE_END(ft_draw, f->when.delivered_ns); 367 - } 368 - 369 - #undef TE_BEG 370 - #undef TE_END 371 - #endif 372 - 373 - // Reset the frame. 374 - f->state = U_RT_READY; 375 - f->frame_id = -1; 376 - } 377 - 378 - static void 379 - rt_info(struct u_render_timing *urt, 380 - uint64_t predicted_display_time_ns, 381 - uint64_t predicted_display_period_ns, 382 - uint64_t extra_ns) 383 - { 384 - struct render_timing *rt = render_timing(urt); 385 - 386 - rt->last_input.predicted_display_time_ns = predicted_display_time_ns; 387 - rt->last_input.predicted_display_period_ns = predicted_display_period_ns; 388 - rt->last_input.extra_ns = extra_ns; 389 - } 390 - 391 - static void 392 - rt_destroy(struct u_render_timing *urt) 393 - { 394 - free(urt); 395 - } 396 - 397 - 398 - /* 399 - * 400 - * 'Exported' functions. 401 - * 402 - */ 403 - 404 - xrt_result_t 405 - u_rt_create(struct u_render_timing **out_urt) 406 - { 407 - struct render_timing *rt = U_TYPED_CALLOC(struct render_timing); 408 - rt->base.predict = rt_predict; 409 - rt->base.mark_point = rt_mark_point; 410 - rt->base.mark_discarded = rt_mark_discarded; 411 - rt->base.mark_delivered = rt_mark_delivered; 412 - rt->base.info = rt_info; 413 - rt->base.destroy = rt_destroy; 414 - rt->app.cpu_time_ns = U_TIME_1MS_IN_NS * 2; 415 - rt->app.draw_time_ns = U_TIME_1MS_IN_NS * 2; 416 - rt->app.margin_ns = U_TIME_1MS_IN_NS * 2; 417 - 418 - for (size_t i = 0; i < ARRAY_SIZE(rt->frames); i++) { 419 - rt->frames[i].state = U_RT_READY; 420 - rt->frames[i].frame_id = -1; 421 - } 422 - 423 - *out_urt = &rt->base; 424 - 425 - return XRT_SUCCESS; 426 - }
+27 -27
src/xrt/auxiliary/util/u_trace_marker.c
··· 22 22 23 23 PERCETTO_CATEGORY_DEFINE(U_TRACE_CATEGORIES) 24 24 25 - PERCETTO_TRACK_DEFINE(rt_cpu, PERCETTO_TRACK_EVENTS); 26 - PERCETTO_TRACK_DEFINE(rt_allotted, PERCETTO_TRACK_EVENTS); 27 - PERCETTO_TRACK_DEFINE(rt_gpu, PERCETTO_TRACK_EVENTS); 28 - PERCETTO_TRACK_DEFINE(rt_margin, PERCETTO_TRACK_EVENTS); 29 - PERCETTO_TRACK_DEFINE(rt_error, PERCETTO_TRACK_EVENTS); 30 - PERCETTO_TRACK_DEFINE(rt_info, PERCETTO_TRACK_EVENTS); 31 - PERCETTO_TRACK_DEFINE(rt_present, PERCETTO_TRACK_EVENTS); 32 - PERCETTO_TRACK_DEFINE(ft_cpu, PERCETTO_TRACK_EVENTS); 33 - PERCETTO_TRACK_DEFINE(ft_draw, PERCETTO_TRACK_EVENTS); 25 + PERCETTO_TRACK_DEFINE(pc_cpu, PERCETTO_TRACK_EVENTS); 26 + PERCETTO_TRACK_DEFINE(pc_allotted, PERCETTO_TRACK_EVENTS); 27 + PERCETTO_TRACK_DEFINE(pc_gpu, PERCETTO_TRACK_EVENTS); 28 + PERCETTO_TRACK_DEFINE(pc_margin, PERCETTO_TRACK_EVENTS); 29 + PERCETTO_TRACK_DEFINE(pc_error, PERCETTO_TRACK_EVENTS); 30 + PERCETTO_TRACK_DEFINE(pc_info, PERCETTO_TRACK_EVENTS); 31 + PERCETTO_TRACK_DEFINE(pc_present, PERCETTO_TRACK_EVENTS); 32 + PERCETTO_TRACK_DEFINE(pa_cpu, PERCETTO_TRACK_EVENTS); 33 + PERCETTO_TRACK_DEFINE(pa_draw, PERCETTO_TRACK_EVENTS); 34 34 35 35 36 36 static enum u_trace_which static_which; ··· 41 41 { 42 42 static_which = which; 43 43 44 - I_PERCETTO_TRACK_PTR(rt_cpu)->name = "RT 1 Sleep"; 45 - I_PERCETTO_TRACK_PTR(rt_allotted)->name = "RT 2 Allotted time"; 46 - I_PERCETTO_TRACK_PTR(rt_gpu)->name = "RT 3 GPU"; 47 - I_PERCETTO_TRACK_PTR(rt_margin)->name = "RT 4 Margin"; 48 - I_PERCETTO_TRACK_PTR(rt_error)->name = "RT 5 Error"; 49 - I_PERCETTO_TRACK_PTR(rt_info)->name = "RT 6 Info"; 50 - I_PERCETTO_TRACK_PTR(rt_present)->name = "RT 7 Present"; 44 + I_PERCETTO_TRACK_PTR(pc_cpu)->name = "PC 1 Sleep"; 45 + I_PERCETTO_TRACK_PTR(pc_allotted)->name = "PC 2 Allotted time"; 46 + I_PERCETTO_TRACK_PTR(pc_gpu)->name = "PC 3 GPU"; 47 + I_PERCETTO_TRACK_PTR(pc_margin)->name = "PC 4 Margin"; 48 + I_PERCETTO_TRACK_PTR(pc_error)->name = "PC 5 Error"; 49 + I_PERCETTO_TRACK_PTR(pc_info)->name = "PC 6 Info"; 50 + I_PERCETTO_TRACK_PTR(pc_present)->name = "PC 7 Present"; 51 51 52 - I_PERCETTO_TRACK_PTR(ft_cpu)->name = "FT 1 App"; 53 - I_PERCETTO_TRACK_PTR(ft_draw)->name = "FT 2 Draw"; 52 + I_PERCETTO_TRACK_PTR(pa_cpu)->name = "PA 1 App"; 53 + I_PERCETTO_TRACK_PTR(pa_draw)->name = "PA 2 Draw"; 54 54 } 55 55 56 56 void ··· 67 67 } 68 68 69 69 if (static_which == U_TRACE_WHICH_SERVICE) { 70 - PERCETTO_REGISTER_TRACK(rt_cpu); 71 - PERCETTO_REGISTER_TRACK(rt_allotted); 72 - PERCETTO_REGISTER_TRACK(rt_gpu); 73 - PERCETTO_REGISTER_TRACK(rt_margin); 74 - PERCETTO_REGISTER_TRACK(rt_error); 75 - PERCETTO_REGISTER_TRACK(rt_info); 76 - PERCETTO_REGISTER_TRACK(rt_present); 70 + PERCETTO_REGISTER_TRACK(pc_cpu); 71 + PERCETTO_REGISTER_TRACK(pc_allotted); 72 + PERCETTO_REGISTER_TRACK(pc_gpu); 73 + PERCETTO_REGISTER_TRACK(pc_margin); 74 + PERCETTO_REGISTER_TRACK(pc_error); 75 + PERCETTO_REGISTER_TRACK(pc_info); 76 + PERCETTO_REGISTER_TRACK(pc_present); 77 77 78 - PERCETTO_REGISTER_TRACK(ft_cpu); 79 - PERCETTO_REGISTER_TRACK(ft_draw); 78 + PERCETTO_REGISTER_TRACK(pa_cpu); 79 + PERCETTO_REGISTER_TRACK(pa_draw); 80 80 } 81 81 } 82 82
+9 -9
src/xrt/auxiliary/util/u_trace_marker.h
··· 90 90 91 91 PERCETTO_CATEGORY_DECLARE(U_TRACE_CATEGORIES) 92 92 93 - PERCETTO_TRACK_DECLARE(rt_cpu); 94 - PERCETTO_TRACK_DECLARE(rt_allotted); 95 - PERCETTO_TRACK_DECLARE(rt_gpu); 96 - PERCETTO_TRACK_DECLARE(rt_margin); 97 - PERCETTO_TRACK_DECLARE(rt_error); 98 - PERCETTO_TRACK_DECLARE(rt_info); 99 - PERCETTO_TRACK_DECLARE(rt_present); 100 - PERCETTO_TRACK_DECLARE(ft_cpu); 101 - PERCETTO_TRACK_DECLARE(ft_draw); 93 + PERCETTO_TRACK_DECLARE(pc_cpu); 94 + PERCETTO_TRACK_DECLARE(pc_allotted); 95 + PERCETTO_TRACK_DECLARE(pc_gpu); 96 + PERCETTO_TRACK_DECLARE(pc_margin); 97 + PERCETTO_TRACK_DECLARE(pc_error); 98 + PERCETTO_TRACK_DECLARE(pc_info); 99 + PERCETTO_TRACK_DECLARE(pc_present); 100 + PERCETTO_TRACK_DECLARE(pa_cpu); 101 + PERCETTO_TRACK_DECLARE(pa_draw); 102 102 103 103 #define U_TRACE_EVENT(CATEGORY, NAME) TRACE_EVENT(CATEGORY, NAME) 104 104 #define U_TRACE_EVENT_BEGIN_ON_TRACK(CATEGORY, TRACK, TIME, NAME) \
+12 -12
src/xrt/compositor/main/comp_target_swapchain.c
··· 11 11 #include "xrt/xrt_config_os.h" 12 12 13 13 #include "util/u_misc.h" 14 - #include "util/u_timing.h" 14 + #include "util/u_pacing.h" 15 15 16 16 #include "main/comp_compositor.h" 17 17 #include "main/comp_target_swapchain.h" ··· 125 125 126 126 // Some platforms really don't like the display_timing code. 127 127 bool use_display_timing_if_available = cts->timing_usage == COMP_TARGET_USE_DISPLAY_IF_AVAILABLE; 128 - if (cts->uft == NULL && use_display_timing_if_available && vk->has_GOOGLE_display_timing) { 129 - u_ft_display_timing_create(ct->c->settings.nominal_frame_interval_ns, 130 - &U_FT_DISPLAY_TIMING_CONFIG_DEFAULT, &cts->uft); 131 - } else if (cts->uft == NULL) { 132 - u_ft_fake_create(ct->c->settings.nominal_frame_interval_ns, &cts->uft); 128 + if (cts->upc == NULL && use_display_timing_if_available && vk->has_GOOGLE_display_timing) { 129 + u_pc_display_timing_create(ct->c->settings.nominal_frame_interval_ns, 130 + &U_PC_DISPLAY_TIMING_CONFIG_DEFAULT, &cts->upc); 131 + } else if (cts->upc == NULL) { 132 + u_pc_fake_create(ct->c->settings.nominal_frame_interval_ns, &cts->upc); 133 133 } 134 134 135 135 // Free old image views. ··· 599 599 uint64_t predicted_display_period_ns = 0; 600 600 uint64_t min_display_period_ns = 0; 601 601 602 - u_ft_predict(cts->uft, // 602 + u_pc_predict(cts->upc, // 603 603 &frame_id, // 604 604 &wake_up_time_ns, // 605 605 &desired_present_time_ns, // ··· 628 628 629 629 switch (point) { 630 630 case COMP_TARGET_TIMING_POINT_WAKE_UP: 631 - u_ft_mark_point(cts->uft, U_TIMING_POINT_WAKE_UP, cts->current_frame_id, when_ns); 631 + u_pc_mark_point(cts->upc, U_TIMING_POINT_WAKE_UP, cts->current_frame_id, when_ns); 632 632 break; 633 633 case COMP_TARGET_TIMING_POINT_BEGIN: 634 - u_ft_mark_point(cts->uft, U_TIMING_POINT_BEGIN, cts->current_frame_id, when_ns); 634 + u_pc_mark_point(cts->upc, U_TIMING_POINT_BEGIN, cts->current_frame_id, when_ns); 635 635 break; 636 636 case COMP_TARGET_TIMING_POINT_SUBMIT: 637 - u_ft_mark_point(cts->uft, U_TIMING_POINT_SUBMIT, cts->current_frame_id, when_ns); 637 + u_pc_mark_point(cts->upc, U_TIMING_POINT_SUBMIT, cts->current_frame_id, when_ns); 638 638 break; 639 639 default: assert(false); 640 640 } ··· 672 672 timings); // 673 673 674 674 for (uint32_t i = 0; i < count; i++) { 675 - u_ft_info(cts->uft, // 675 + u_pc_info(cts->upc, // 676 676 timings[i].presentID, // 677 677 timings[i].desiredPresentTime, // 678 678 timings[i].actualPresentTime, // ··· 713 713 cts->swapchain.handle = VK_NULL_HANDLE; 714 714 } 715 715 716 - u_ft_destroy(&cts->uft); 716 + u_pc_destroy(&cts->upc); 717 717 } 718 718 719 719 void
+3 -3
src/xrt/compositor/main/comp_target_swapchain.h
··· 26 26 * 27 27 */ 28 28 29 - struct u_frame_timing; 29 + struct u_pacing_compositor; 30 30 31 31 /*! 32 32 * Wraps and manage VkSwapchainKHR and VkSurfaceKHR, used by @ref comp code. ··· 38 38 //! Base target. 39 39 struct comp_target base; 40 40 41 - //! Frame timing tracker. 42 - struct u_frame_timing *uft; 41 + //! Compositor frame pacing helper 42 + struct u_pacing_compositor *upc; 43 43 44 44 //! If we should use display timing. 45 45 enum comp_target_display_timing_usage timing_usage;
+11 -11
src/xrt/compositor/multi/comp_multi_compositor.c
··· 197 197 198 198 os_mutex_lock(&mc->msc->list_and_timing_lock); 199 199 200 - u_rt_predict( // 201 - mc->urt, // 200 + u_pa_predict( // 201 + mc->upa, // 202 202 out_frame_id, // 203 203 out_wake_time_ns, // 204 204 out_predicted_display_time_ns, // ··· 223 223 case XRT_COMPOSITOR_FRAME_POINT_WOKE: 224 224 os_mutex_lock(&mc->msc->list_and_timing_lock); 225 225 uint64_t now_ns = os_monotonic_get_ns(); 226 - u_rt_mark_point(mc->urt, frame_id, U_TIMING_POINT_WAKE_UP, now_ns); 226 + u_pa_mark_point(mc->upa, frame_id, U_TIMING_POINT_WAKE_UP, now_ns); 227 227 os_mutex_unlock(&mc->msc->list_and_timing_lock); 228 228 break; 229 229 default: assert(false); ··· 278 278 279 279 os_mutex_lock(&mc->msc->list_and_timing_lock); 280 280 uint64_t now_ns = os_monotonic_get_ns(); 281 - u_rt_mark_point(mc->urt, frame_id, U_TIMING_POINT_BEGIN, now_ns); 281 + u_pa_mark_point(mc->upa, frame_id, U_TIMING_POINT_BEGIN, now_ns); 282 282 os_mutex_unlock(&mc->msc->list_and_timing_lock); 283 283 284 284 return XRT_SUCCESS; ··· 292 292 struct multi_compositor *mc = multi_compositor(xc); 293 293 294 294 os_mutex_lock(&mc->msc->list_and_timing_lock); 295 - u_rt_mark_discarded(mc->urt, frame_id); 295 + u_pa_mark_discarded(mc->upa, frame_id); 296 296 os_mutex_unlock(&mc->msc->list_and_timing_lock); 297 297 298 298 return XRT_SUCCESS; ··· 509 509 wait_for_scheduled_free(mc); 510 510 511 511 os_mutex_lock(&mc->msc->list_and_timing_lock); 512 - u_rt_mark_delivered(mc->urt, frame_id); 512 + u_pa_mark_delivered(mc->upa, frame_id); 513 513 os_mutex_unlock(&mc->msc->list_and_timing_lock); 514 514 515 515 return XRT_SUCCESS; ··· 553 553 slot_clear(&mc->delivered); 554 554 555 555 // Does null checking. 556 - u_rt_destroy(&mc->urt); 556 + u_pa_destroy(&mc->upa); 557 557 558 558 os_precise_sleeper_deinit(&mc->sleeper); 559 559 ··· 623 623 os_precise_sleeper_init(&mc->sleeper); 624 624 625 625 // This is safe to do without a lock since we are not on the list yet. 626 - u_rt_create(&mc->urt); 626 + u_pa_create(&mc->upa); 627 627 628 628 os_mutex_lock(&msc->list_and_timing_lock); 629 629 630 - // Meh if we have to many clients just ignore it. 630 + // If we have too many clients, just ignore it. 631 631 for (size_t i = 0; i < MULTI_MAX_CLIENTS; i++) { 632 632 if (mc->msc->clients[i] != NULL) { 633 633 continue; ··· 636 636 break; 637 637 } 638 638 639 - u_rt_info( // 640 - mc->urt, // 639 + u_pa_info( // 640 + mc->upa, // 641 641 msc->last_timings.predicted_display_time_ns, // 642 642 msc->last_timings.predicted_display_period_ns, // 643 643 msc->last_timings.diff_ns); //
+2 -2
src/xrt/compositor/multi/comp_multi_private.h
··· 16 16 #include "os/os_time.h" 17 17 #include "os/os_threading.h" 18 18 19 - #include "util/u_timing.h" 19 + #include "util/u_pacing.h" 20 20 21 21 #ifdef __cplusplus 22 22 extern "C" { ··· 144 144 */ 145 145 struct multi_layer_slot delivered; 146 146 147 - struct u_render_timing *urt; 147 + struct u_pacing_app *upa; 148 148 }; 149 149 150 150 static inline struct multi_compositor *
+2 -2
src/xrt/compositor/multi/comp_multi_system.c
··· 297 297 continue; 298 298 } 299 299 300 - u_rt_info( // 301 - mc->urt, // 300 + u_pa_info( // 301 + mc->upa, // 302 302 predicted_display_time_ns, // 303 303 predicted_display_period_ns, // 304 304 diff_ns); //