The open source OpenXR runtime
0
fork

Configure Feed

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

a/util: Frame pacing docs and some error handling

authored by

Ryan Pavlik and committed by
Jakob Bornecrantz
6677d426 a7c22fd1

+39 -1
+39 -1
src/xrt/auxiliary/util/u_pacing_compositor.c
··· 1 - // Copyright 2020-2021, Collabora, Ltd. 1 + // Copyright 2020-2022, Collabora, Ltd. 2 2 // SPDX-License-Identifier: BSL-1.0 3 3 /*! 4 4 * @file ··· 194 194 return is_within_of_each_other(l, r, U_TIME_HALF_MS_IN_NS); 195 195 } 196 196 197 + /*! 198 + * Gets a frame data structure based on the @p frame_id. 199 + * 200 + * Note that this is done modulo the number of frame data structs we hold: the data in the frame you receive may not 201 + * match the @p frame_id you passed! 202 + * 203 + * @see create_frame to create a frame id and (partially) initialize the frame data structure, @ref do_clean_slate_frame 204 + * for a more complete initialization 205 + */ 197 206 static struct frame * 198 207 get_frame(struct display_timing *dt, int64_t frame_id) 199 208 { ··· 205 214 return &dt->frames[index]; 206 215 } 207 216 217 + /*! 218 + * Assign the next available frame ID, initialize the corresponding frame data with the ID and @p state, and return a 219 + * pointer to that frame data. 220 + * 221 + * Fields other than frame::frame_id and frame::state are not modified, so may have old data in them. This may be a 222 + * feature rather than a bug. 223 + */ 208 224 static struct frame * 209 225 create_frame(struct display_timing *dt, enum frame_state state) 210 226 { ··· 217 233 return f; 218 234 } 219 235 236 + /*! 237 + * Gets the most recent frame data whose state is greater than or equal to @p state, if any 238 + * 239 + * @return a frame pointer, or null if no frames have at least @p state 240 + */ 220 241 static struct frame * 221 242 get_latest_frame_with_state_at_least(struct display_timing *dt, enum frame_state state) 222 243 { ··· 233 254 return NULL; 234 255 } 235 256 257 + /*! 258 + * "Create" a frame ID in state @ref STATE_PREDICTED (by calling @ref create_frame), and additionally initialize 259 + * frame::desired_present_time_ns (with a crude estimate) and frame::when_predict_ns. 260 + */ 236 261 static struct frame * 237 262 do_clean_slate_frame(struct display_timing *dt) 238 263 { ··· 247 272 return f; 248 273 } 249 274 275 + /*! 276 + * Find the next possible present time for rendering that has not yet occurred, and create a frame/frame id with that 277 + * prediction in it. 278 + */ 250 279 static struct frame * 251 280 walk_forward_through_frames(struct display_timing *dt, uint64_t last_present_time_ns) 252 281 { 253 282 uint64_t now_ns = os_monotonic_get_ns(); 283 + // This is the earliest possible time we could present, assuming rendering still must take place. 254 284 uint64_t from_time_ns = now_ns + calc_total_app_time(dt); 255 285 uint64_t desired_present_time_ns = last_present_time_ns + dt->frame_period_ns; 256 286 ··· 441 471 442 472 struct frame *last = get_latest_frame_with_state_at_least(dt, STATE_INFO); 443 473 struct frame *f = get_frame(dt, frame_id); 474 + if (f->frame_id != frame_id) { 475 + FT_LOG_W("Discarded info for unsubmitted or expired frame_id %" PRIx64, frame_id); 476 + if (last != NULL) { 477 + FT_LOG_W("The latest frame_id we have info for is %" PRIx64, last->frame_id); 478 + } 479 + return; 480 + } 444 481 assert(f->state == STATE_SUBMITTED); 482 + assert(f->desired_present_time_ns == desired_present_time_ns); 445 483 446 484 f->when_infoed_ns = os_monotonic_get_ns(); 447 485 f->actual_present_time_ns = actual_present_time_ns;