cogl/onscreen: Call _cogl_context_update_sync after the buffer swap

Indirectly via cogl_framebuffer_flush, since we also need to call
glFlush now. Need to do it in cogl_onscreen_egl_swap_* because
meta_onscreen_native_swap_buffers_with_damage uses
cogl_context_get_latest_sync_fd.

Doing it before the swap was problematic because the swap may do GPU
work of its own, which wasn't covered by the EGL sync object created in
_cogl_context_update_sync. This could result in visual artifacts. See
the discussion starting at
https://gitlab.freedesktop.org/mesa/mesa/-/issues/11996#note_2678104 for
details.

For similar reasons, move the cogl_framebuffer_finish calls after the
swap as well.

As a bonus, this eliminates one of 3 GPU work flushes to the kernel per
frame with the Mesa radeonsi driver, because the glFlush/glFinish call
in cogl_framebuffer_flush/finish doesn't have any GPU work to flush
after SwapBuffers.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4158>
This commit is contained in:
Michel Dänzer 2024-11-28 18:05:06 +01:00 committed by Marge Bot
parent cd765c2da9
commit 33a9a1cace
2 changed files with 12 additions and 10 deletions

View File

@ -289,17 +289,15 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
_cogl_framebuffer_flush_journal (framebuffer); _cogl_framebuffer_flush_journal (framebuffer);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SYNC_FRAME)))
cogl_framebuffer_finish (framebuffer);
else
_cogl_context_update_sync (context);
cogl_framebuffer_discard_buffers (framebuffer, cogl_framebuffer_discard_buffers (framebuffer,
COGL_BUFFER_BIT_DEPTH | COGL_BUFFER_BIT_DEPTH |
COGL_BUFFER_BIT_STENCIL); COGL_BUFFER_BIT_STENCIL);
klass->swap_buffers_with_damage (onscreen, region, info, user_data); klass->swap_buffers_with_damage (onscreen, region, info, user_data);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SYNC_FRAME)))
cogl_framebuffer_finish (framebuffer);
if (!cogl_context_has_winsys_feature (context, COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)) if (!cogl_context_has_winsys_feature (context, COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT))
{ {
g_autoptr (CoglFrameInfo) pending_info = NULL; g_autoptr (CoglFrameInfo) pending_info = NULL;
@ -341,11 +339,6 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
_cogl_framebuffer_flush_journal (framebuffer); _cogl_framebuffer_flush_journal (framebuffer);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SYNC_FRAME)))
cogl_framebuffer_finish (framebuffer);
else
_cogl_context_update_sync (context);
/* This should only be called if the winsys advertises /* This should only be called if the winsys advertises
COGL_WINSYS_FEATURE_SWAP_REGION */ COGL_WINSYS_FEATURE_SWAP_REGION */
g_return_if_fail (klass->swap_region); g_return_if_fail (klass->swap_region);
@ -356,6 +349,9 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
klass->swap_region (onscreen, region, info, user_data); klass->swap_region (onscreen, region, info, user_data);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SYNC_FRAME)))
cogl_framebuffer_finish (framebuffer);
if (!cogl_context_has_winsys_feature (context, COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)) if (!cogl_context_has_winsys_feature (context, COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT))
{ {
g_autoptr (CoglFrameInfo) pending_info = NULL; g_autoptr (CoglFrameInfo) pending_info = NULL;

View File

@ -236,6 +236,9 @@ cogl_onscreen_egl_swap_region (CoglOnscreen *onscreen,
n_rectangles, n_rectangles,
egl_rectangles) == EGL_FALSE) egl_rectangles) == EGL_FALSE)
g_warning ("Error reported by eglSwapBuffersRegion"); g_warning ("Error reported by eglSwapBuffersRegion");
/* Update latest sync object after buffer swap */
cogl_framebuffer_flush (framebuffer);
} }
static void static void
@ -339,6 +342,9 @@ cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen,
} }
else else
eglSwapBuffers (egl_renderer->edpy, priv->egl_surface); eglSwapBuffers (egl_renderer->edpy, priv->egl_surface);
/* Update latest sync object after buffer swap */
cogl_framebuffer_flush (framebuffer);
} }
void void