1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-04 14:12:10 +00:00

vo_gpu: vulkan: make the swapchain more robust

Now handles both VK_ERROR_OUT_OF_DATE_KHR and VK_SUBOPTIMAL_KHR for both
vkAcquireNextImageKHR and vkQueuePresentKHR in the correct way.
This commit is contained in:
Niklas Haas 2017-09-29 13:52:27 +02:00 committed by Martin Herkt
parent dcda8bd36a
commit 8b0a111c59

View File

@ -446,27 +446,43 @@ static bool start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
struct priv *p = sw->priv; struct priv *p = sw->priv;
struct mpvk_ctx *vk = p->vk; struct mpvk_ctx *vk = p->vk;
if (!p->swapchain) if (!p->swapchain)
goto error; return false;
MP_TRACE(vk, "vkAcquireNextImageKHR signals %p\n", MP_TRACE(vk, "vkAcquireNextImageKHR signals %p\n",
(void *)p->sems_in[p->idx_sems]); (void *)p->sems_in[p->idx_sems]);
uint32_t imgidx = 0; for (int attempts = 0; attempts < 2; attempts++) {
VkResult res = vkAcquireNextImageKHR(vk->dev, p->swapchain, UINT64_MAX, uint32_t imgidx = 0;
p->sems_in[p->idx_sems], NULL, VkResult res = vkAcquireNextImageKHR(vk->dev, p->swapchain, UINT64_MAX,
&imgidx); p->sems_in[p->idx_sems], NULL,
if (res == VK_ERROR_OUT_OF_DATE_KHR) &imgidx);
goto error; // just return in this case
VK_ASSERT(res, "Failed acquiring swapchain image");
p->last_imgidx = imgidx; switch (res) {
*out_fbo = (struct ra_fbo) { case VK_SUCCESS:
.tex = p->images[imgidx], p->last_imgidx = imgidx;
.flip = false, *out_fbo = (struct ra_fbo) {
}; .tex = p->images[imgidx],
return true; .flip = false,
};
return true;
error: case VK_ERROR_OUT_OF_DATE_KHR: {
// In these cases try recreating the swapchain
int w = p->w, h = p->h;
p->w = p->h = 0; // invalidate the current state
if (!ra_vk_ctx_resize(sw, w, h))
return false;
continue;
}
default:
MP_ERR(vk, "Failed acquiring swapchain image: %s\n", vk_err(res));
return false;
}
}
// If we've exhausted the number of attempts to recreate the swapchain,
// just give up silently.
return false; return false;
} }
@ -481,11 +497,11 @@ static bool submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame)
struct ra *ra = sw->ctx->ra; struct ra *ra = sw->ctx->ra;
struct mpvk_ctx *vk = p->vk; struct mpvk_ctx *vk = p->vk;
if (!p->swapchain) if (!p->swapchain)
goto error; return false;
struct vk_cmd *cmd = ra_vk_submit(ra, p->images[p->last_imgidx]); struct vk_cmd *cmd = ra_vk_submit(ra, p->images[p->last_imgidx]);
if (!cmd) if (!cmd)
goto error; return false;
int semidx = p->idx_sems++; int semidx = p->idx_sems++;
p->idx_sems %= p->num_sems; p->idx_sems %= p->num_sems;
@ -503,7 +519,7 @@ static bool submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame)
vk_cmd_queue(vk, cmd); vk_cmd_queue(vk, cmd);
if (!mpvk_flush_commands(vk)) if (!mpvk_flush_commands(vk))
goto error; return false;
// Older nvidia drivers can spontaneously combust when submitting to the // Older nvidia drivers can spontaneously combust when submitting to the
// same queue as we're rendering from, in a multi-queue scenario. Safest // same queue as we're rendering from, in a multi-queue scenario. Safest
@ -522,11 +538,22 @@ static bool submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame)
}; };
MP_TRACE(vk, "vkQueuePresentKHR waits on %p\n", (void *)p->sems_out[semidx]); MP_TRACE(vk, "vkQueuePresentKHR waits on %p\n", (void *)p->sems_out[semidx]);
VK(vkQueuePresentKHR(queue, &pinfo)); VkResult res = vkQueuePresentKHR(queue, &pinfo);
return true; switch (res) {
case VK_SUCCESS:
case VK_SUBOPTIMAL_KHR:
return true;
error: case VK_ERROR_OUT_OF_DATE_KHR:
return false; // We can silently ignore this error, since the next start_frame will
// recreate the swapchain automatically.
return true;
default:
MP_ERR(vk, "Failed presenting to queue %p: %s\n", (void *)queue,
vk_err(res));
return false;
}
} }
static void swap_buffers(struct ra_swapchain *sw) static void swap_buffers(struct ra_swapchain *sw)