From e7b4f4fd4d2869bab7f1b578de69077176d9b692 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Mon, 13 Jun 2016 17:47:52 +0200 Subject: [PATCH] Fix various Android Vulkan issues. Was getting bogus swapchain width/height causing weird issues. Also, create swapchain after swap interval is correctly set. --- gfx/common/vksym.h | 3 + gfx/common/vulkan_common.c | 107 ++++++++++++++++++++++++++++-- gfx/drivers_context/android_ctx.c | 58 ++++++++++++---- 3 files changed, 151 insertions(+), 17 deletions(-) diff --git a/gfx/common/vksym.h b/gfx/common/vksym.h index 51f3f5d07c..10410eef20 100644 --- a/gfx/common/vksym.h +++ b/gfx/common/vksym.h @@ -82,6 +82,9 @@ typedef struct vulkan_context_fp PFN_vkCreateInstance vkCreateInstance; PFN_vkDestroyInstance vkDestroyInstance; + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; + PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; + /* Device */ PFN_vkCreateDevice vkCreateDevice; PFN_vkDestroyDevice vkDestroyDevice; diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 74a71bd4d7..963c6c199c 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -1045,6 +1045,7 @@ void vulkan_buffer_chain_free( static bool vulkan_load_instance_symbols(gfx_ctx_vulkan_data_t *vk) { + VK_GET_INSTANCE_PROC_ADDR(EnumerateDeviceExtensionProperties); VK_GET_INSTANCE_PROC_ADDR(GetDeviceProcAddr); VK_GET_INSTANCE_PROC_ADDR(DestroyInstance); VK_GET_INSTANCE_PROC_ADDR(GetPhysicalDeviceFormatProperties); @@ -1207,6 +1208,98 @@ static bool vulkan_load_device_symbols(gfx_ctx_vulkan_data_t *vk) return true; } +static bool vulkan_find_extensions(const char **exts, unsigned num_exts, + const VkExtensionProperties *properties, unsigned property_count) +{ + unsigned i, ext; + bool found; + for (ext = 0; ext < num_exts; ext++) + { + found = false; + for (i = 0; i < property_count; i++) + { + if (!strcmp(exts[ext], properties[i].extensionName)) + { + found = true; + break; + } + } + + if (!found) + return false; + } + return true; +} + +static bool vulkan_find_instance_extensions(const char **exts, unsigned num_exts) +{ + bool ret = true; + VkExtensionProperties *properties = NULL; + uint32_t property_count; + + if (VKFUNC(vkEnumerateInstanceExtensionProperties(NULL, &property_count, NULL)) != VK_SUCCESS) + return false; + + properties = (VkExtensionProperties*)malloc(property_count * sizeof(*properties)); + if (!properties) + { + ret = false; + goto end; + } + + if (VKFUNC(vkEnumerateInstanceExtensionProperties(NULL, &property_count, properties)) != VK_SUCCESS) + { + ret = false; + goto end; + } + + if (!vulkan_find_extensions(exts, num_exts, properties, property_count)) + { + RARCH_ERR("[Vulkan]: Could not find instance extensions. Will attempt without them.\n"); + ret = false; + goto end; + } + +end: + free(properties); + return ret; +} + +static bool vulkan_find_device_extensions(VkPhysicalDevice gpu, const char **exts, unsigned num_exts) +{ + bool ret = true; + VkExtensionProperties *properties = NULL; + uint32_t property_count; + + if (VKFUNC(vkEnumerateDeviceExtensionProperties(gpu, NULL, &property_count, NULL)) != VK_SUCCESS) + return false; + + properties = (VkExtensionProperties*)malloc(property_count * sizeof(*properties)); + if (!properties) + { + ret = false; + goto end; + } + + if (VKFUNC(vkEnumerateDeviceExtensionProperties(gpu, NULL, &property_count, properties)) != VK_SUCCESS) + { + ret = false; + goto end; + } + + if (!vulkan_find_extensions(exts, num_exts, properties, property_count)) + { + RARCH_ERR("[Vulkan]: Could not find device extensions. Will attempt without them.\n"); + ret = false; + goto end; + } + +end: + free(properties); + return ret; +} + + bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, enum vulkan_wsi_type type) { @@ -1227,6 +1320,7 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, "VK_KHR_swapchain", }; static const char *instance_extensions[2]; + bool use_instance_ext, use_device_ext; instance_extensions[0] = "VK_KHR_surface"; @@ -1271,6 +1365,9 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, RARCH_LOG("Vulkan dynamic library loaded.\n"); VKSYM(vk, GetInstanceProcAddr); + VK_GET_INSTANCE_PROC_ADDR(EnumerateInstanceExtensionProperties); + + use_instance_ext = vulkan_find_instance_extensions(instance_extensions, ARRAY_SIZE(instance_extensions)); app.pApplicationName = "RetroArch"; app.applicationVersion = 0; @@ -1279,8 +1376,8 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, app.apiVersion = VK_MAKE_VERSION(1, 0, 6); info.pApplicationInfo = &app; - info.enabledExtensionCount = ARRAY_SIZE(instance_extensions); - info.ppEnabledExtensionNames = instance_extensions; + info.enabledExtensionCount = use_instance_ext ? ARRAY_SIZE(instance_extensions) : 0; + info.ppEnabledExtensionNames = use_instance_ext ? instance_extensions : NULL; if (cached_instance) { @@ -1382,14 +1479,16 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, return false; } + use_device_ext = vulkan_find_device_extensions(vk->context.gpu, device_extensions, ARRAY_SIZE(device_extensions)); + queue_info.queueFamilyIndex = vk->context.graphics_queue_index; queue_info.queueCount = 1; queue_info.pQueuePriorities = &one; device_info.queueCreateInfoCount = 1; device_info.pQueueCreateInfos = &queue_info; - device_info.enabledExtensionCount = ARRAY_SIZE(device_extensions); - device_info.ppEnabledExtensionNames = device_extensions; + device_info.enabledExtensionCount = use_device_ext ? ARRAY_SIZE(device_extensions) : 0; + device_info.ppEnabledExtensionNames = use_device_ext ? device_extensions : NULL; device_info.pEnabledFeatures = &features; if (cached_device) diff --git a/gfx/drivers_context/android_ctx.c b/gfx/drivers_context/android_ctx.c index 58cb47a57c..e6b7996d60 100644 --- a/gfx/drivers_context/android_ctx.c +++ b/gfx/drivers_context/android_ctx.c @@ -167,16 +167,6 @@ static void *android_gfx_ctx_init(void *video_driver) if (!egl_create_surface(&and->egl, android_app->window)) goto unlock_error; -#endif - break; - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - and->width = ANativeWindow_getWidth(android_app->window); - and->height = ANativeWindow_getHeight(android_app->window); - if (!vulkan_surface_create(&and->vk, VULKAN_WSI_ANDROID, - NULL, android_app->window, - and->width, and->height, and->swap_interval)) - goto error; #endif break; case GFX_CTX_NONE: @@ -243,6 +233,8 @@ static void android_gfx_ctx_check_window(void *data, bool *quit, /* Swapchains are recreated in set_resize as a * central place, so use that to trigger swapchain reinit. */ *resize = and->vk.need_new_swapchain; + new_width = and->width; + new_height = and->height; #endif break; case GFX_CTX_NONE: @@ -252,6 +244,9 @@ static void android_gfx_ctx_check_window(void *data, bool *quit, if (new_width != *width || new_height != *height) { + RARCH_LOG("[Android]: Resizing (%u x %u) -> (%u x %u).\n", + *width, *height, new_width, new_height); + *width = new_width; *height = new_height; *resize = true; @@ -265,10 +260,37 @@ static void android_gfx_ctx_check_window(void *data, bool *quit, static bool android_gfx_ctx_set_resize(void *data, unsigned width, unsigned height) { +#ifdef HAVE_VULKAN + android_ctx_data_t *and = (android_ctx_data_t*)data; + struct android_app *android_app = (struct android_app*)g_android; +#endif (void)data; (void)width; (void)height; + switch (android_api) + { + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + and->width = ANativeWindow_getWidth(android_app->window); + and->height = ANativeWindow_getHeight(android_app->window); + RARCH_LOG("[Android]: Native window size: %u x %u.\n", and->width, and->height); + if (!vulkan_create_swapchain(&and->vk, and->width, and->height, and->swap_interval)) + { + RARCH_ERR("[Android]: Failed to update swapchain.\n"); + return false; + } + + and->vk.context.invalid_swapchain = true; + and->vk.need_new_swapchain = false; +#endif + break; + + case GFX_CTX_NONE: + default: + break; + } + return false; } @@ -289,7 +311,8 @@ static bool android_gfx_ctx_set_video_mode(void *data, bool fullscreen) { #ifdef HAVE_VULKAN - android_ctx_data_t *and = (android_ctx_data_t*)data; + struct android_app *android_app = (struct android_app*)g_android; + android_ctx_data_t *and = (android_ctx_data_t*)data; #endif (void)width; @@ -300,10 +323,18 @@ static bool android_gfx_ctx_set_video_mode(void *data, { case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN - and->width = width; - and->height = height; + and->width = ANativeWindow_getWidth(android_app->window); + and->height = ANativeWindow_getHeight(android_app->window); + RARCH_LOG("[Android]: Native window size: %u x %u.\n", and->width, and->height); + if (!vulkan_surface_create(&and->vk, VULKAN_WSI_ANDROID, NULL, android_app->window, + and->width, and->height, and->swap_interval)) + { + RARCH_ERR("[Android]: Failed to create surface.\n"); + return false; + } #endif break; + case GFX_CTX_NONE: default: break; @@ -479,6 +510,7 @@ static void android_gfx_ctx_set_swap_interval(void *data, unsigned swap_interval #ifdef HAVE_VULKAN if (and->swap_interval != swap_interval) { + RARCH_LOG("[Vulkan]: Setting swap interval: %u.\n", swap_interval); and->swap_interval = swap_interval; if (and->vk.swapchain) and->vk.need_new_swapchain = true;