The open source OpenXR runtime
0
fork

Configure Feed

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

c/multi: Be slightly smarter about late frames

+67 -32
+18 -2
src/xrt/compositor/multi/comp_multi_compositor.c
··· 177 177 178 178 os_mutex_lock(&mc->slot_lock); 179 179 180 + struct multi_compositor volatile *v_mc = mc; 181 + 180 182 // Block here if the scheduled slot is not clear. 181 - while (mc->scheduled.active) { 183 + while (v_mc->scheduled.active) { 184 + 185 + // This frame is for the next frame, drop the old one no matter what. 186 + if (time_is_within_half_ms(mc->progress.display_time_ns, mc->slot_next_frame_display)) { 187 + U_LOG_W("Dropping old missed frame in favour for completed new frame"); 188 + break; 189 + } 182 190 183 191 // Replace the scheduled frame if it's in the past. 184 192 uint64_t now_ns = os_monotonic_get_ns(); 185 - if (mc->scheduled.display_time_ns < now_ns) { 193 + if (v_mc->scheduled.display_time_ns < now_ns) { 186 194 break; 187 195 } 196 + 197 + U_LOG_D("next: %f (%" PRIu64 ")\nprogress: %f (%" PRIu64 ")\nscheduled: %f (%" PRIu64 ")\n", 198 + time_ns_to_ms_f((int64_t)v_mc->slot_next_frame_display - now_ns), // 199 + v_mc->slot_next_frame_display, // 200 + time_ns_to_ms_f((int64_t)v_mc->progress.display_time_ns - now_ns), // 201 + v_mc->progress.display_time_ns, // 202 + time_ns_to_ms_f((int64_t)v_mc->scheduled.display_time_ns - now_ns), // 203 + v_mc->scheduled.display_time_ns); // 188 204 189 205 os_mutex_unlock(&mc->slot_lock); 190 206
+5
src/xrt/compositor/multi/comp_multi_private.h
··· 154 154 struct os_mutex slot_lock; 155 155 156 156 /*! 157 + * The next which the next frames to be picked up will be displayed. 158 + */ 159 + uint64_t slot_next_frame_display; 160 + 161 + /*! 157 162 * Currently being transferred or waited on. 158 163 * Not protected by the slot lock as it is only touched by the client thread. 159 164 */
+44 -30
src/xrt/compositor/multi/comp_multi_system.c
··· 1 - // Copyright 2019-2021, Collabora, Ltd. 1 + // Copyright 2019-2022, Collabora, Ltd. 2 2 // SPDX-License-Identifier: BSL-1.0 3 3 /*! 4 4 * @file ··· 282 282 } 283 283 284 284 static void 285 - broadcast_timings(struct multi_system_compositor *msc, 286 - uint64_t predicted_display_time_ns, 287 - uint64_t predicted_display_period_ns, 288 - uint64_t diff_ns) 285 + broadcast_timings_to_clients(struct multi_system_compositor *msc, uint64_t predicted_display_time_ns) 286 + { 287 + COMP_TRACE_MARKER(); 288 + 289 + os_mutex_lock(&msc->list_and_timing_lock); 290 + 291 + for (size_t i = 0; i < ARRAY_SIZE(msc->clients); i++) { 292 + struct multi_compositor *mc = msc->clients[i]; 293 + if (mc == NULL) { 294 + continue; 295 + } 296 + 297 + os_mutex_lock(&mc->slot_lock); 298 + mc->slot_next_frame_display = predicted_display_time_ns; 299 + os_mutex_unlock(&mc->slot_lock); 300 + } 301 + 302 + os_mutex_unlock(&msc->list_and_timing_lock); 303 + } 304 + 305 + static void 306 + broadcast_timings_to_pacers(struct multi_system_compositor *msc, 307 + uint64_t predicted_display_time_ns, 308 + uint64_t predicted_display_period_ns, 309 + uint64_t diff_ns) 289 310 { 290 311 COMP_TRACE_MARKER(); 291 312 ··· 302 323 predicted_display_time_ns, // 303 324 predicted_display_period_ns, // 304 325 diff_ns); // 326 + 327 + os_mutex_lock(&mc->slot_lock); 328 + mc->slot_next_frame_display = predicted_display_time_ns; 329 + os_mutex_unlock(&mc->slot_lock); 305 330 } 306 331 307 332 msc->last_timings.predicted_display_time_ns = predicted_display_time_ns; ··· 312 337 } 313 338 314 339 static void 315 - wait_frame(struct xrt_compositor *xc, 316 - int64_t *out_frame_id, 317 - uint64_t *out_wake_time_ns, 318 - uint64_t *out_predicted_gpu_time_ns, 319 - uint64_t *out_predicted_display_time_ns, 320 - uint64_t *out_predicted_display_period_ns) 340 + wait_frame(struct xrt_compositor *xc, int64_t frame_id, uint64_t wake_up_time_ns) 321 341 { 322 342 COMP_TRACE_MARKER(); 323 343 324 - int64_t frame_id = -1; 325 - uint64_t wake_up_time_ns = 0; 326 - 327 - xrt_comp_predict_frame( // 328 - xc, // 329 - &frame_id, // 330 - &wake_up_time_ns, // 331 - out_predicted_gpu_time_ns, // 332 - out_predicted_display_time_ns, // 333 - out_predicted_display_period_ns); // 334 - 335 344 uint64_t now_ns = os_monotonic_get_ns(); 336 345 if (now_ns < wake_up_time_ns) { 337 346 os_nanosleep(wake_up_time_ns - now_ns); ··· 340 349 now_ns = os_monotonic_get_ns(); 341 350 342 351 xrt_comp_mark_frame(xc, frame_id, XRT_COMPOSITOR_FRAME_POINT_WOKE, now_ns); 343 - 344 - *out_frame_id = frame_id; 345 - *out_wake_time_ns = wake_up_time_ns; 346 352 } 347 353 348 354 static int ··· 361 367 while (os_thread_helper_is_running_locked(&msc->oth)) { 362 368 os_thread_helper_unlock(&msc->oth); 363 369 364 - int64_t frame_id; 365 - uint64_t wake_time_ns = 0; 370 + int64_t frame_id = -1; 371 + uint64_t wake_up_time_ns = 0; 366 372 uint64_t predicted_gpu_time_ns = 0; 367 373 uint64_t predicted_display_time_ns = 0; 368 374 uint64_t predicted_display_period_ns = 0; 369 375 370 - wait_frame( // 376 + // Get the information for the next frame. 377 + xrt_comp_predict_frame( // 371 378 xc, // 372 379 &frame_id, // 373 - &wake_time_ns, // 380 + &wake_up_time_ns, // 374 381 &predicted_gpu_time_ns, // 375 382 &predicted_display_time_ns, // 376 383 &predicted_display_period_ns); // 377 384 385 + // Do this as soon as we have the new display time. 386 + broadcast_timings_to_clients(msc, predicted_display_time_ns); 387 + 388 + // Now we can wait. 389 + wait_frame(xc, frame_id, wake_up_time_ns); 390 + 378 391 uint64_t now_ns = os_monotonic_get_ns(); 379 392 uint64_t diff_ns = predicted_display_time_ns - now_ns; 380 393 381 - broadcast_timings(msc, predicted_display_time_ns, predicted_display_period_ns, diff_ns); 394 + // Now we know the diff, broadcast to pacers. 395 + broadcast_timings_to_pacers(msc, predicted_display_time_ns, predicted_display_period_ns, diff_ns); 382 396 383 397 xrt_comp_begin_frame(xc, frame_id); 384 398 xrt_comp_layer_begin(xc, frame_id, 0, 0);