mirror of
https://github.com/libretro/RetroArch
synced 2025-02-28 12:40:23 +00:00
Vulkan: Emulate mailbox on Windows.
This commit is contained in:
parent
af534f0fa8
commit
9ebac87638
@ -38,6 +38,12 @@
|
||||
#include "../../libretro-common/include/retro_math.h"
|
||||
#include "../../libretro-common/include/string/stdstring.h"
|
||||
|
||||
// Windows is not particularly good at recreating swapchains.
|
||||
// Emulate vsync toggling by using vkAcquireNextImageKHR timeouts.
|
||||
#if defined(_WIN32)
|
||||
#define VULKAN_EMULATE_MAILBOX
|
||||
#endif
|
||||
|
||||
static dylib_t vulkan_library;
|
||||
static VkInstance cached_instance_vk;
|
||||
static VkDevice cached_device_vk;
|
||||
@ -1494,6 +1500,10 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk)
|
||||
"VK_KHR_sampler_mirror_clamp_to_edge",
|
||||
};
|
||||
|
||||
#ifdef VULKAN_EMULATE_MAILBOX
|
||||
vk->emulate_mailbox = true;
|
||||
#endif
|
||||
|
||||
#ifdef VULKAN_DEBUG
|
||||
static const char *device_layers[] = { "VK_LAYER_LUNARG_standard_validation" };
|
||||
#endif
|
||||
@ -2333,6 +2343,7 @@ static void vulkan_destroy_swapchain(gfx_ctx_vulkan_data_t *vk)
|
||||
vkDestroySwapchainKHR(vk->context.device, vk->swapchain, NULL);
|
||||
memset(vk->context.swapchain_images, 0, sizeof(vk->context.swapchain_images));
|
||||
vk->swapchain = VK_NULL_HANDLE;
|
||||
vk->context.has_acquired_swapchain = false;
|
||||
}
|
||||
|
||||
for (i = 0; i < VULKAN_MAX_SWAPCHAIN_IMAGES; i++)
|
||||
@ -2351,9 +2362,13 @@ static void vulkan_destroy_swapchain(gfx_ctx_vulkan_data_t *vk)
|
||||
|
||||
void vulkan_present(gfx_ctx_vulkan_data_t *vk, unsigned index)
|
||||
{
|
||||
VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
|
||||
VkResult result = VK_SUCCESS;
|
||||
VkResult err = VK_SUCCESS;
|
||||
VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
|
||||
VkResult result = VK_SUCCESS;
|
||||
VkResult err = VK_SUCCESS;
|
||||
|
||||
if (!vk->context.has_acquired_swapchain)
|
||||
return;
|
||||
vk->context.has_acquired_swapchain = false;
|
||||
|
||||
/* We're still waiting for a proper swapchain, so just fake it. */
|
||||
if (vk->swapchain == VK_NULL_HANDLE)
|
||||
@ -2525,12 +2540,29 @@ retry:
|
||||
|
||||
vkCreateFence(vk->context.device, &fence_info, NULL, &fence);
|
||||
|
||||
err = vkAcquireNextImageKHR(vk->context.device,
|
||||
vk->swapchain, UINT64_MAX,
|
||||
VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index);
|
||||
if (vk->emulating_mailbox)
|
||||
{
|
||||
/* Non-blocking acquire. If we don't get a swapchain frame right away,
|
||||
* just skip rendering to the swapchain this frame, similar to what
|
||||
* MAILBOX would do. */
|
||||
err = vkAcquireNextImageKHR(vk->context.device,
|
||||
vk->swapchain, 0,
|
||||
VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = vkAcquireNextImageKHR(vk->context.device,
|
||||
vk->swapchain, UINT64_MAX,
|
||||
VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index);
|
||||
}
|
||||
|
||||
if (err == VK_SUCCESS)
|
||||
{
|
||||
vkWaitForFences(vk->context.device, 1, &fence, true, UINT64_MAX);
|
||||
vk->context.has_acquired_swapchain = true;
|
||||
}
|
||||
else
|
||||
vk->context.has_acquired_swapchain = false;
|
||||
|
||||
#ifdef WSI_HARDENING_TEST
|
||||
trigger_spurious_error_vkresult(&err);
|
||||
@ -2538,7 +2570,13 @@ retry:
|
||||
|
||||
vkDestroyFence(vk->context.device, fence, NULL);
|
||||
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
if (err == VK_NOT_READY || err == VK_TIMEOUT)
|
||||
{
|
||||
/* Just pretend we have a swapchain index, round-robin style. */
|
||||
vk->context.current_swapchain_index =
|
||||
(vk->context.current_swapchain_index + 1) % vk->context.num_swapchain_images;
|
||||
}
|
||||
else if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
{
|
||||
/* Throw away the old swapchain and try again. */
|
||||
vulkan_destroy_swapchain(vk);
|
||||
@ -2601,6 +2639,14 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
|
||||
vkDeviceWaitIdle(vk->context.device);
|
||||
vulkan_acquire_clear_fences(vk);
|
||||
|
||||
if (swap_interval == 0 && vk->emulate_mailbox)
|
||||
{
|
||||
swap_interval = 1;
|
||||
vk->emulating_mailbox = true;
|
||||
}
|
||||
else
|
||||
vk->emulating_mailbox = false;
|
||||
|
||||
vk->created_new_swapchain = true;
|
||||
if (vk->swapchain != VK_NULL_HANDLE &&
|
||||
!vk->context.invalid_swapchain &&
|
||||
|
@ -96,6 +96,7 @@ typedef struct vulkan_context
|
||||
/* Used by screenshot to get blits with correct colorspace. */
|
||||
bool swapchain_is_srgb;
|
||||
bool swap_interval_emulation_lock;
|
||||
bool has_acquired_swapchain;
|
||||
|
||||
unsigned swapchain_width;
|
||||
unsigned swapchain_height;
|
||||
@ -131,6 +132,8 @@ typedef struct gfx_ctx_vulkan_data
|
||||
{
|
||||
bool need_new_swapchain;
|
||||
bool created_new_swapchain;
|
||||
bool emulate_mailbox;
|
||||
bool emulating_mailbox;
|
||||
vulkan_context_t context;
|
||||
VkSurfaceKHR vk_surface;
|
||||
VkSwapchainKHR swapchain;
|
||||
|
@ -1778,7 +1778,7 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
(vulkan_filter_chain_t*)vk->filter_chain,
|
||||
vk->cmd, &vk->vk_vp);
|
||||
/* Render to backbuffer. */
|
||||
if (chain->backbuffer.image != VK_NULL_HANDLE)
|
||||
if (chain->backbuffer.image != VK_NULL_HANDLE && vk->context->has_acquired_swapchain)
|
||||
{
|
||||
rp_info.renderPass = vk->render_pass;
|
||||
rp_info.framebuffer = chain->backbuffer.framebuffer;
|
||||
@ -1874,6 +1874,7 @@ static bool vulkan_frame(void *data, const void *frame,
|
||||
vulkan_filter_chain_end_frame((vulkan_filter_chain_t*)vk->filter_chain, vk->cmd);
|
||||
|
||||
if (chain->backbuffer.image != VK_NULL_HANDLE &&
|
||||
vk->context->has_acquired_swapchain &&
|
||||
(vk->readback.pending || vk->readback.streamed))
|
||||
{
|
||||
/* We cannot safely read back from an image which
|
||||
|
Loading…
x
Reference in New Issue
Block a user