summaryrefslogtreecommitdiffstats
path: root/video/out/vulkan/context.c
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-09-29 13:52:27 +0200
committerMartin Herkt <652892+lachs0r@users.noreply.github.com>2017-12-25 00:47:53 +0100
commit8b0a111c5961a27d37e78e07efa8ab2aa6408afa (patch)
tree198487953535da76d443511758a2a64687a3b5e0 /video/out/vulkan/context.c
parentdcda8bd36aa8eb0003c301b4564cd01f7870fe34 (diff)
downloadmpv-8b0a111c5961a27d37e78e07efa8ab2aa6408afa.tar.bz2
mpv-8b0a111c5961a27d37e78e07efa8ab2aa6408afa.tar.xz
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.
Diffstat (limited to 'video/out/vulkan/context.c')
-rw-r--r--video/out/vulkan/context.c73
1 files changed, 50 insertions, 23 deletions
diff --git a/video/out/vulkan/context.c b/video/out/vulkan/context.c
index 4f96440652..98162eb12f 100644
--- a/video/out/vulkan/context.c
+++ b/video/out/vulkan/context.c
@@ -446,27 +446,43 @@ static bool start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
struct priv *p = sw->priv;
struct mpvk_ctx *vk = p->vk;
if (!p->swapchain)
- goto error;
+ return false;
MP_TRACE(vk, "vkAcquireNextImageKHR signals %p\n",
(void *)p->sems_in[p->idx_sems]);
- uint32_t imgidx = 0;
- VkResult res = vkAcquireNextImageKHR(vk->dev, p->swapchain, UINT64_MAX,
- p->sems_in[p->idx_sems], NULL,
- &imgidx);
- if (res == VK_ERROR_OUT_OF_DATE_KHR)
- goto error; // just return in this case
- VK_ASSERT(res, "Failed acquiring swapchain image");
-
- p->last_imgidx = imgidx;
- *out_fbo = (struct ra_fbo) {
- .tex = p->images[imgidx],
- .flip = false,
- };
- return true;
+ for (int attempts = 0; attempts < 2; attempts++) {
+ uint32_t imgidx = 0;
+ VkResult res = vkAcquireNextImageKHR(vk->dev, p->swapchain, UINT64_MAX,
+ p->sems_in[p->idx_sems], NULL,
+ &imgidx);
+
+ switch (res) {
+ case VK_SUCCESS:
+ p->last_imgidx = imgidx;
+ *out_fbo = (struct ra_fbo) {
+ .tex = p->images[imgidx],
+ .flip = false,
+ };
+ return true;
+
+ 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;
+ }
-error:
+ 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;
}
@@ -481,11 +497,11 @@ static bool submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame)
struct ra *ra = sw->ctx->ra;
struct mpvk_ctx *vk = p->vk;
if (!p->swapchain)
- goto error;
+ return false;
struct vk_cmd *cmd = ra_vk_submit(ra, p->images[p->last_imgidx]);
if (!cmd)
- goto error;
+ return false;
int semidx = p->idx_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);
if (!mpvk_flush_commands(vk))
- goto error;
+ return false;
// Older nvidia drivers can spontaneously combust when submitting to the
// 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]);
- VK(vkQueuePresentKHR(queue, &pinfo));
- return true;
+ VkResult res = vkQueuePresentKHR(queue, &pinfo);
+ switch (res) {
+ case VK_SUCCESS:
+ case VK_SUBOPTIMAL_KHR:
+ return true;
-error:
- return false;
+ case VK_ERROR_OUT_OF_DATE_KHR:
+ // 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)