From 85394f39e52c324a656d28dc7e0bce9ea93ea95c Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Thu, 12 Feb 2026 15:41:58 +0100 Subject: [PATCH] dri: prevent read_sbc from going backward MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some situations we can have multiple present queued with the same target_msc and in this case we might get the last one signaled before the previous ones. Here's an example with some debug logs added to the relevant functions: loader_dri3_swap_buffers_msc: new send_sbc=2323 - target_msc=337 dri3_handle_present_event: old recv_sbc=2322 msc=338 new_recv_sbc=2323 loader_dri3_swap_buffers_msc: new send_sbc=2324 - target_msc=338 dri3_handle_present_event: old recv_sbc=2323 msc=338 new_recv_sbc=2324 loader_dri3_swap_buffers_msc: new send_sbc=2325 - target_msc=338 dri3_handle_present_event: old recv_sbc=2324 msc=338 new_recv_sbc=2325 loader_dri3_swap_buffers_msc: new send_sbc=2326 - target_msc=338 loader_dri3_swap_buffers_msc: new send_sbc=2327 - target_msc=338 loader_dri3_swap_buffers_msc: new send_sbc=2328 - target_msc=338 dri3_handle_present_event: old recv_sbc=2325 msc=338 new_recv_sbc=2327 loader_dri3_swap_buffers_msc: new send_sbc=2329 - target_msc=338 dri3_handle_present_event: old recv_sbc=2327 msc=338 new_recv_sbc=2328 loader_dri3_swap_buffers_msc: new send_sbc=2330 - target_msc=338 dri3_handle_present_event: old recv_sbc=2328 msc=338 new_recv_sbc=2329 loader_dri3_swap_buffers_msc: new send_sbc=2331 - target_msc=338 dri3_handle_present_event: old recv_sbc=2329 msc=338 new_recv_sbc=2330 dri3_handle_present_event: old recv_sbc=2330 msc=338 new_recv_sbc=2326 # oops dri3_handle_present_event: old recv_sbc=2326 msc=339 new_recv_sbc=2331 It's usually harmless, except if Mesa ends up using loader_dri3_swapbuffer_barrier right after the out-of-order event. In this example it's ok because more swaps are executed after 2330, so waiting for read_sbc>=2330 would work anyway. But if this wasn't the case, loader_dri3_swapbuffer_barrier would never return, waiting for recv_sbc to become >= 2330 while it's stuck at 2326 because the later swaps were processed earlier. Reviewed-by: Marek Olšák Part-of: --- src/gallium/frontends/dri/loader_dri3_helper.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gallium/frontends/dri/loader_dri3_helper.c b/src/gallium/frontends/dri/loader_dri3_helper.c index 0801e8b3d60..8898bd23fdf 100644 --- a/src/gallium/frontends/dri/loader_dri3_helper.c +++ b/src/gallium/frontends/dri/loader_dri3_helper.c @@ -513,9 +513,11 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw, /* Only assume wraparound if that results in exactly the previous * SBC + 1, otherwise ignore received SBC > sent SBC (those are * probably from a previous loader_dri3_drawable instance) to avoid - * calculating bogus target MSC values in loader_dri3_swap_buffers_msc + * calculating bogus target MSC values in loader_dri3_swap_buffers_msc. + * Since events can be received out of order, don't let recv_sbc go + * back unless for wraparound. */ - if (recv_sbc <= draw->send_sbc) + if (recv_sbc <= draw->send_sbc && draw->recv_sbc <= recv_sbc) draw->recv_sbc = recv_sbc; else if (recv_sbc == (draw->recv_sbc + 0x100000001ULL)) draw->recv_sbc = recv_sbc - 0x100000000ULL;