Vulkan: Try to avoid creating swapchains redundantly.

Win32: Only make resize events when needed.
Do not create swapchain unless necessary.
Deal better with Windows WSI workarounds.
This commit is contained in:
Themaister 2018-07-01 14:13:02 +02:00
parent efe9fc7339
commit f2cae17021
9 changed files with 55 additions and 10 deletions

View File

@ -2326,12 +2326,18 @@ void vulkan_context_destroy(gfx_ctx_vulkan_data_t *vk,
if (vk->context.device)
vkDeviceWaitIdle(vk->context.device);
if (vk->swapchain)
{
vkDestroySwapchainKHR(vk->context.device,
vk->swapchain, NULL);
vk->swapchain = VK_NULL_HANDLE;
}
if (destroy_surface && vk->vk_surface != VK_NULL_HANDLE)
{
vkDestroySurfaceKHR(vk->context.instance,
vk->vk_surface, NULL);
vk->vk_surface = VK_NULL_HANDLE;
}
for (i = 0; i < VULKAN_MAX_SWAPCHAIN_IMAGES; i++)
{
@ -2506,6 +2512,19 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
vkDeviceWaitIdle(vk->context.device);
vk->created_new_swapchain = true;
if (vk->swapchain != VK_NULL_HANDLE &&
!vk->context.invalid_swapchain &&
vk->context.swapchain_width == width &&
vk->context.swapchain_height == height &&
vk->context.swap_interval == swap_interval)
{
/* Do not bother creating a swapchain redundantly. */
RARCH_LOG("[Vulkan]: Do not need to re-create swapchain.\n");
vk->created_new_swapchain = false;
return true;
}
present_mode_count = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(
vk->context.gpu, vk->vk_surface,
@ -2634,12 +2653,17 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
RARCH_LOG("[Vulkan]: Using swapchain size %u x %u.\n",
swapchain_size.width, swapchain_size.height);
desired_swapchain_images = surface_properties.minImageCount + 1;
/* Unless we have other reasons to clamp, we should prefer 3 images.
* We hard sync against the swapchain, so if we have 2 images,
* we would be unable to overlap CPU and GPU, which can get very slow
* for GPU-rendered cores. */
desired_swapchain_images = 3;
/* Limit latency. */
if (desired_swapchain_images > settings->uints.video_max_swapchain_images)
desired_swapchain_images = settings->uints.video_max_swapchain_images;
/* Clamp images requested to what is supported by the implementation. */
if (desired_swapchain_images < surface_properties.minImageCount)
desired_swapchain_images = surface_properties.minImageCount;
@ -2680,6 +2704,14 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
#ifdef _WIN32
/* On Windows, do not try to reuse the swapchain.
* It causes a lot of issues on nVidia for some reason. */
info.oldSwapchain = VK_NULL_HANDLE;
if (old_swapchain != VK_NULL_HANDLE)
vkDestroySwapchainKHR(vk->context.device, old_swapchain, NULL);
#endif
if (vkCreateSwapchainKHR(vk->context.device,
&info, NULL, &vk->swapchain) != VK_SUCCESS)
{
@ -2687,8 +2719,10 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk,
return false;
}
#ifndef _WIN32
if (old_swapchain != VK_NULL_HANDLE)
vkDestroySwapchainKHR(vk->context.device, old_swapchain, NULL);
#endif
vk->context.swapchain_width = swapchain_size.width;
vk->context.swapchain_height = swapchain_size.height;

View File

@ -130,6 +130,7 @@ typedef struct vulkan_context
typedef struct gfx_ctx_vulkan_data
{
bool need_new_swapchain;
bool created_new_swapchain;
vulkan_context_t context;
VkSurfaceKHR vk_surface;
VkSwapchainKHR swapchain;

View File

@ -741,9 +741,13 @@ static LRESULT CALLBACK WndProcCommon(bool *quit, HWND hwnd, UINT message,
if ( wparam != SIZE_MAXHIDE &&
wparam != SIZE_MINIMIZED)
{
g_win32_resize_width = LOWORD(lparam);
g_win32_resize_height = HIWORD(lparam);
g_win32_resized = true;
if (LOWORD(lparam) != g_win32_resize_width ||
HIWORD(lparam) != g_win32_resize_height)
{
g_win32_resize_width = LOWORD(lparam);
g_win32_resize_height = HIWORD(lparam);
g_win32_resized = true;
}
}
*quit = true;
break;

View File

@ -281,7 +281,8 @@ static bool android_gfx_ctx_set_resize(void *data,
return false;
}
vulkan_acquire_next_image(&and->vk);
if (and->vk.created_new_swapchain)
vulkan_acquire_next_image(&and->vk);
and->vk.context.invalid_swapchain = true;
and->vk.need_new_swapchain = false;
#endif

View File

@ -105,7 +105,8 @@ static bool gfx_ctx_khr_display_set_resize(void *data,
return false;
}
vulkan_acquire_next_image(&khr->vk);
if (khr->vk.created_new_swapchain)
vulkan_acquire_next_image(&khr->vk);
khr->vk.context.invalid_swapchain = true;
khr->vk.need_new_swapchain = false;

View File

@ -767,7 +767,8 @@ static bool cocoagl_gfx_ctx_set_resize(void *data, unsigned width, unsigned heig
if (vulkan_create_swapchain(&cocoa_ctx->vk, width, height, cocoa_ctx->swap_interval))
{
cocoa_ctx->vk.context.invalid_swapchain = true;
vulkan_acquire_next_image(&cocoa_ctx->vk);
if (cocoa_ctx->vk.created_new_swapchain)
vulkan_acquire_next_image(&cocoa_ctx->vk);
}
else
{

View File

@ -697,7 +697,8 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
if (vulkan_create_swapchain(&wl->vk, width, height, wl->swap_interval))
{
wl->vk.context.invalid_swapchain = true;
vulkan_acquire_next_image(&wl->vk);
if (wl->vk.created_new_swapchain)
vulkan_acquire_next_image(&wl->vk);
}
else
{

View File

@ -406,7 +406,8 @@ static bool gfx_ctx_wgl_set_resize(void *data,
return false;
}
vulkan_acquire_next_image(&win32_vk);
if (win32_vk.created_new_swapchain)
vulkan_acquire_next_image(&win32_vk);
win32_vk.context.invalid_swapchain = true;
win32_vk.need_new_swapchain = false;
#endif

View File

@ -460,7 +460,8 @@ static bool gfx_ctx_x_set_resize(void *data,
return false;
}
vulkan_acquire_next_image(&x->vk);
if (x->vk.created_new_swapchain)
vulkan_acquire_next_image(&x->vk);
x->vk.context.invalid_swapchain = true;
x->vk.need_new_swapchain = false;
}