mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-09 14:50:11 +01:00
zink: Don't present to Wayland surfaces asynchronously
Wayland EGL has a driver invariant which requires that any `wl_surface` (or wp_linux_drm_syncobj_surface_v1) calls happen inside the client's call to eglSwapBuffers(). Submitting surface messages after eglSwapBuffers() returns causes serialization issues with the Wayland surface protocol and can lead to the compositor booting the app. Fixes:8ade5588e3("zink: add kopper api") Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12736 Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33859> (cherry picked from commitb92117d9bb)
This commit is contained in:
parent
d8b47159b7
commit
3f7abae2fc
3 changed files with 21 additions and 12 deletions
|
|
@ -204,7 +204,7 @@
|
|||
"description": "zink: Don't present to Wayland surfaces asynchronously",
|
||||
"nominated": true,
|
||||
"nomination_type": 2,
|
||||
"resolution": 0,
|
||||
"resolution": 1,
|
||||
"main_sha": null,
|
||||
"because_sha": "8ade5588e39d736bdeab9bdd8ffa7cbfb6a5191e",
|
||||
"notes": null
|
||||
|
|
|
|||
|
|
@ -259,9 +259,6 @@ kopper_CreateSwapchain(struct zink_screen *screen, struct kopper_displaytarget *
|
|||
bool has_alpha = cdt->info.has_alpha && (cdt->caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR);
|
||||
if (cdt->swapchain) {
|
||||
cswap->scci = cdt->swapchain->scci;
|
||||
/* avoid UAF if async present needs to-be-retired swapchain */
|
||||
if (cdt->type == KOPPER_WAYLAND && cdt->swapchain->swapchain)
|
||||
util_queue_fence_wait(&cdt->swapchain->present_fence);
|
||||
cswap->scci.oldSwapchain = cdt->swapchain->swapchain;
|
||||
} else {
|
||||
cswap->scci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
|
|
@ -331,7 +328,7 @@ kopper_CreateSwapchain(struct zink_screen *screen, struct kopper_displaytarget *
|
|||
error = VKSCR(CreateSwapchainKHR)(screen->dev, &cswap->scci, NULL,
|
||||
&cswap->swapchain);
|
||||
if (error == VK_ERROR_NATIVE_WINDOW_IN_USE_KHR) {
|
||||
if (util_queue_is_initialized(&screen->flush_queue))
|
||||
if (cdt->async)
|
||||
util_queue_finish(&screen->flush_queue);
|
||||
simple_mtx_lock(&screen->queue_lock);
|
||||
VkResult wait_result = VKSCR(QueueWaitIdle)(screen->queue);
|
||||
|
|
@ -503,6 +500,16 @@ zink_kopper_displaytarget_create(struct zink_screen *screen, unsigned tex_usage,
|
|||
}
|
||||
simple_mtx_unlock(&screen->dt_lock);
|
||||
|
||||
/* Wayland EGL has a driver invariant which requires that any `wl_surface`
|
||||
* (or wp_linux_drm_syncobj_surface_v1) calls happen inside the client's
|
||||
* call to eglSwapBuffers(). Submitting surface messages after
|
||||
* eglSwapBuffers() returns causes serialization issues with the Wayland
|
||||
* surface protocol and can lead to the compositor booting the app. This
|
||||
* means we can't do async submit on Wayland.
|
||||
*/
|
||||
cdt->async = util_queue_is_initialized(&screen->flush_queue) &&
|
||||
cdt->type != KOPPER_WAYLAND;
|
||||
|
||||
*stride = cdt->stride;
|
||||
return cdt;
|
||||
|
||||
|
|
@ -549,7 +556,7 @@ kopper_acquire(struct zink_screen *screen, struct zink_resource *res, uint64_t t
|
|||
res->obj->access = 0;
|
||||
res->obj->access_stage = 0;
|
||||
}
|
||||
if (timeout == UINT64_MAX && util_queue_is_initialized(&screen->flush_queue) &&
|
||||
if (timeout == UINT64_MAX && cdt->async &&
|
||||
p_atomic_read_relaxed(&cdt->swapchain->num_acquires) >= cdt->swapchain->max_acquires) {
|
||||
util_queue_fence_wait(&cdt->swapchain->present_fence);
|
||||
/* With a sequence of
|
||||
|
|
@ -877,13 +884,15 @@ zink_kopper_present_queue(struct zink_screen *screen, struct zink_resource *res,
|
|||
cdt->swapchain->images[i].age += 1;
|
||||
}
|
||||
}
|
||||
if (util_queue_is_initialized(&screen->flush_queue)) {
|
||||
if (cdt->async) {
|
||||
p_atomic_inc(&cpi->swapchain->async_presents);
|
||||
struct pipe_resource *pres = NULL;
|
||||
pipe_resource_reference(&pres, &res->base.b);
|
||||
util_queue_add_job(&screen->flush_queue, cpi, &cdt->swapchain->present_fence,
|
||||
kopper_present, NULL, 0);
|
||||
} else {
|
||||
if (screen->threaded_submit)
|
||||
util_queue_finish(&screen->flush_queue);
|
||||
kopper_present(cpi, screen, -1);
|
||||
}
|
||||
res->obj->indefinite_acquire = false;
|
||||
|
|
@ -961,7 +970,7 @@ zink_kopper_acquire_readback(struct zink_context *ctx, struct zink_resource *res
|
|||
if (res->obj->dt_idx != UINT32_MAX) {
|
||||
if (!zink_kopper_present_readback(ctx, res))
|
||||
break;
|
||||
} else if (util_queue_is_initialized(&screen->flush_queue)) {
|
||||
} else if (cdt->async) {
|
||||
/* AcquireNextImageKHR and QueuePresentKHR both access the swapchain, and
|
||||
* if res->obj->dt_idx == UINT32_MAX then zink_kopper_present_readback is
|
||||
* not called and we don't wait for the cdt->swapchain->present_fence.
|
||||
|
|
@ -998,6 +1007,7 @@ bool
|
|||
zink_kopper_present_readback(struct zink_context *ctx, struct zink_resource *res)
|
||||
{
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
struct kopper_displaytarget *cdt = res->obj->dt;
|
||||
VkSubmitInfo si = {0};
|
||||
assert(zink_is_swapchain(res));
|
||||
if (res->obj->last_dt_idx == UINT32_MAX)
|
||||
|
|
@ -1024,10 +1034,8 @@ zink_kopper_present_readback(struct zink_context *ctx, struct zink_resource *res
|
|||
return false;
|
||||
|
||||
zink_kopper_present_queue(screen, res, 0, NULL);
|
||||
if (util_queue_is_initialized(&screen->flush_queue)) {
|
||||
struct kopper_displaytarget *cdt = res->obj->dt;
|
||||
if (cdt->async)
|
||||
util_queue_fence_wait(&cdt->swapchain->present_fence);
|
||||
}
|
||||
|
||||
simple_mtx_lock(&screen->queue_lock);
|
||||
error = VKSCR(QueueWaitIdle)(screen->queue);
|
||||
|
|
@ -1037,7 +1045,6 @@ zink_kopper_present_readback(struct zink_context *ctx, struct zink_resource *res
|
|||
util_dynarray_append(&screen->semaphores, VkSemaphore, acquire);
|
||||
simple_mtx_unlock(&screen->semaphores_lock);
|
||||
|
||||
struct kopper_displaytarget *cdt = res->obj->dt;
|
||||
cdt->age_locked = false;
|
||||
|
||||
return zink_screen_handle_vkresult(screen, error);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ struct kopper_displaytarget
|
|||
|
||||
struct kopper_loader_info info;
|
||||
|
||||
bool async; // True if submits should go through zink_screen::flush_queue
|
||||
|
||||
VkSurfaceCapabilitiesKHR caps;
|
||||
VkImageFormatListCreateInfo format_list;
|
||||
enum kopper_type type;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue