diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 356c76dec8..7a44b87a84 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -2207,6 +2207,7 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, present_modes[i]); } + vk->context.swap_interval = swap_interval; for (i = 0; i < present_mode_count; i++) { if (!swap_interval && present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 92d63dc382..b182d5eb8b 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -105,6 +105,7 @@ typedef struct vulkan_context uint32_t current_swapchain_index; unsigned swapchain_width; unsigned swapchain_height; + unsigned swap_interval; VkFormat swapchain_format; slock_t *queue_lock; @@ -116,6 +117,7 @@ typedef struct vulkan_context /* Used by screenshot to get blits with correct colorspace. */ bool swapchain_is_srgb; + bool swap_interval_emulation_lock; } vulkan_context_t; typedef struct gfx_ctx_vulkan_data diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 4371ebe9b6..4c788ac69f 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -1889,7 +1889,8 @@ static bool vulkan_frame(void *data, const void *frame, video_context_driver_swap_buffers(); performance_counter_stop(&swapbuffers); - video_context_driver_update_window_title(); + if (!vk->context->swap_interval_emulation_lock) + video_context_driver_update_window_title(); /* Handle spurious swapchain invalidations as soon as we can, * i.e. right after swap buffers. */ @@ -1915,6 +1916,22 @@ static bool vulkan_frame(void *data, const void *frame, vulkan_inject_black_frame(vk); } + /* Vulkan doesn't directly support swap_interval > 1, so we fake it by duping out more frames. */ + if (vk->context->swap_interval > 1 && !vk->context->swap_interval_emulation_lock) + { + unsigned i; + vk->context->swap_interval_emulation_lock = true; + for (i = 1; i < vk->context->swap_interval; i++) + { + if (!vulkan_frame(vk, NULL, 0, 0, frame_count, 0, msg)) + { + vk->context->swap_interval_emulation_lock = false; + return false; + } + } + vk->context->swap_interval_emulation_lock = false; + } + return true; }