dri: prevent read_sbc from going backward

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 <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39857>
This commit is contained in:
Pierre-Eric Pelloux-Prayer 2026-02-12 15:41:58 +01:00 committed by Marge Bot
parent d616d9aed8
commit 85394f39e5

View file

@ -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;