From f2cae170212b7a97b9aad4f8908897d25145ddd6 Mon Sep 17 00:00:00 2001 From: Themaister Date: Sun, 1 Jul 2018 14:13:02 +0200 Subject: [PATCH] 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. --- gfx/common/vulkan_common.c | 36 ++++++++++++++++++++++++++- gfx/common/vulkan_common.h | 1 + gfx/common/win32_common.c | 10 +++++--- gfx/drivers_context/android_ctx.c | 3 ++- gfx/drivers_context/khr_display_ctx.c | 3 ++- gfx/drivers_context/macos_ctx.m | 3 ++- gfx/drivers_context/wayland_ctx.c | 3 ++- gfx/drivers_context/wgl_ctx.c | 3 ++- gfx/drivers_context/x_ctx.c | 3 ++- 9 files changed, 55 insertions(+), 10 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index fa216c3e4f..5725ed6883 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -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; diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 7757e3f1d3..99be52e88e 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -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; diff --git a/gfx/common/win32_common.c b/gfx/common/win32_common.c index d8e8ffecb4..a95ee155c9 100644 --- a/gfx/common/win32_common.c +++ b/gfx/common/win32_common.c @@ -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; diff --git a/gfx/drivers_context/android_ctx.c b/gfx/drivers_context/android_ctx.c index 422dc821cf..b8d0f6779c 100644 --- a/gfx/drivers_context/android_ctx.c +++ b/gfx/drivers_context/android_ctx.c @@ -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 diff --git a/gfx/drivers_context/khr_display_ctx.c b/gfx/drivers_context/khr_display_ctx.c index 747d16e7f0..6aa9c13f60 100644 --- a/gfx/drivers_context/khr_display_ctx.c +++ b/gfx/drivers_context/khr_display_ctx.c @@ -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; diff --git a/gfx/drivers_context/macos_ctx.m b/gfx/drivers_context/macos_ctx.m index 3506a14cfa..7c1aedc2dd 100644 --- a/gfx/drivers_context/macos_ctx.m +++ b/gfx/drivers_context/macos_ctx.m @@ -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 { diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index fc24c4b977..1732b21e3c 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -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 { diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index d35387999b..88341b70ab 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -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 diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index aa097bb6cc..45c2d04c72 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -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; }