From d34e39292be0e355bd00f731303dd100f224c9b6 Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Tue, 29 Oct 2024 12:52:26 -0500 Subject: [PATCH] Track the extension used to create each VkSurfaceKHR The Vulkan-Loader now doesn't call into drivers if they do not support the extension that was used to create the VkSurfaceKHR handle. This prevents crashes from occuring where a driver is called using a surface that it does not know about, due to the driver not supporting the surface extension. Because the specification requires that VkSurfaceKHR must be a valid handle, the loader should not allow calls down into drivers which cannot know about the surface. Instead it should "emulate" the call as appropriate, returning 0 for counts and setting to 0 any structures that were passed in. --- loader/generated/vk_loader_extensions.c | 71 +++++++++++ loader/generated/vk_loader_extensions.h | 2 + loader/wsi.c | 150 +++++++++++++++++++++++- loader/wsi.h | 3 + scripts/loader_extension_generator.py | 18 +++ 5 files changed, 242 insertions(+), 2 deletions(-) diff --git a/loader/generated/vk_loader_extensions.c b/loader/generated/vk_loader_extensions.c index a10c91079..a155a484c 100644 --- a/loader/generated/vk_loader_extensions.c +++ b/loader/generated/vk_loader_extensions.c @@ -12241,6 +12241,77 @@ void fill_out_enabled_instance_extensions(uint32_t extension_count, const char * } }; +bool check_if_instance_extension_is_available(const struct loader_instance_extension_enables* enabled, const struct loader_instance_extension_enables* desired) { + if (desired->khr_surface && !enabled->khr_surface) return false; + if (desired->khr_display && !enabled->khr_display) return false; +#if defined(VK_USE_PLATFORM_XLIB_KHR) + if (desired->khr_xlib_surface && !enabled->khr_xlib_surface) return false; +#endif // defined(VK_USE_PLATFORM_XLIB_KHR) +#if defined(VK_USE_PLATFORM_XCB_KHR) + if (desired->khr_xcb_surface && !enabled->khr_xcb_surface) return false; +#endif // defined(VK_USE_PLATFORM_XCB_KHR) +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) + if (desired->khr_wayland_surface && !enabled->khr_wayland_surface) return false; +#endif // defined(VK_USE_PLATFORM_WAYLAND_KHR) +#if defined(VK_USE_PLATFORM_ANDROID_KHR) + if (desired->khr_android_surface && !enabled->khr_android_surface) return false; +#endif // defined(VK_USE_PLATFORM_ANDROID_KHR) +#if defined(VK_USE_PLATFORM_WIN32_KHR) + if (desired->khr_win32_surface && !enabled->khr_win32_surface) return false; +#endif // defined(VK_USE_PLATFORM_WIN32_KHR) + if (desired->khr_get_physical_device_properties2 && !enabled->khr_get_physical_device_properties2) return false; + if (desired->khr_device_group_creation && !enabled->khr_device_group_creation) return false; + if (desired->khr_external_memory_capabilities && !enabled->khr_external_memory_capabilities) return false; + if (desired->khr_external_semaphore_capabilities && !enabled->khr_external_semaphore_capabilities) return false; + if (desired->khr_external_fence_capabilities && !enabled->khr_external_fence_capabilities) return false; + if (desired->khr_get_surface_capabilities2 && !enabled->khr_get_surface_capabilities2) return false; + if (desired->khr_get_display_properties2 && !enabled->khr_get_display_properties2) return false; + if (desired->khr_surface_protected_capabilities && !enabled->khr_surface_protected_capabilities) return false; + if (desired->khr_portability_enumeration && !enabled->khr_portability_enumeration) return false; + if (desired->ext_debug_report && !enabled->ext_debug_report) return false; +#if defined(VK_USE_PLATFORM_GGP) + if (desired->ggp_stream_descriptor_surface && !enabled->ggp_stream_descriptor_surface) return false; +#endif // defined(VK_USE_PLATFORM_GGP) + if (desired->nv_external_memory_capabilities && !enabled->nv_external_memory_capabilities) return false; + if (desired->ext_validation_flags && !enabled->ext_validation_flags) return false; +#if defined(VK_USE_PLATFORM_VI_NN) + if (desired->nn_vi_surface && !enabled->nn_vi_surface) return false; +#endif // defined(VK_USE_PLATFORM_VI_NN) + if (desired->ext_direct_mode_display && !enabled->ext_direct_mode_display) return false; +#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT) + if (desired->ext_acquire_xlib_display && !enabled->ext_acquire_xlib_display) return false; +#endif // defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT) + if (desired->ext_display_surface_counter && !enabled->ext_display_surface_counter) return false; + if (desired->ext_swapchain_colorspace && !enabled->ext_swapchain_colorspace) return false; +#if defined(VK_USE_PLATFORM_IOS_MVK) + if (desired->mvk_ios_surface && !enabled->mvk_ios_surface) return false; +#endif // defined(VK_USE_PLATFORM_IOS_MVK) +#if defined(VK_USE_PLATFORM_MACOS_MVK) + if (desired->mvk_macos_surface && !enabled->mvk_macos_surface) return false; +#endif // defined(VK_USE_PLATFORM_MACOS_MVK) + if (desired->ext_debug_utils && !enabled->ext_debug_utils) return false; +#if defined(VK_USE_PLATFORM_FUCHSIA) + if (desired->fuchsia_imagepipe_surface && !enabled->fuchsia_imagepipe_surface) return false; +#endif // defined(VK_USE_PLATFORM_FUCHSIA) +#if defined(VK_USE_PLATFORM_METAL_EXT) + if (desired->ext_metal_surface && !enabled->ext_metal_surface) return false; +#endif // defined(VK_USE_PLATFORM_METAL_EXT) + if (desired->ext_validation_features && !enabled->ext_validation_features) return false; + if (desired->ext_headless_surface && !enabled->ext_headless_surface) return false; + if (desired->ext_surface_maintenance1 && !enabled->ext_surface_maintenance1) return false; + if (desired->ext_acquire_drm_display && !enabled->ext_acquire_drm_display) return false; +#if defined(VK_USE_PLATFORM_DIRECTFB_EXT) + if (desired->ext_directfb_surface && !enabled->ext_directfb_surface) return false; +#endif // defined(VK_USE_PLATFORM_DIRECTFB_EXT) +#if defined(VK_USE_PLATFORM_SCREEN_QNX) + if (desired->qnx_screen_surface && !enabled->qnx_screen_surface) return false; +#endif // defined(VK_USE_PLATFORM_SCREEN_QNX) + if (desired->google_surfaceless_query && !enabled->google_surfaceless_query) return false; + if (desired->lunarg_direct_driver_loading && !enabled->lunarg_direct_driver_loading) return false; + if (desired->ext_layer_settings && !enabled->ext_layer_settings) return false; + return true; +}; + // Some device commands still need a terminator because the loader needs to unwrap something about them. // In many cases, the item needing unwrapping is a VkPhysicalDevice or VkSurfaceKHR object. But there may be other items // in the future. diff --git a/loader/generated/vk_loader_extensions.h b/loader/generated/vk_loader_extensions.h index 4a15fc54a..7b601d1a6 100644 --- a/loader/generated/vk_loader_extensions.h +++ b/loader/generated/vk_loader_extensions.h @@ -53,6 +53,8 @@ struct loader_instance_extension_enables; // Forward declaration void fill_out_enabled_instance_extensions(uint32_t extension_count, const char *const * extension_list, struct loader_instance_extension_enables* enables); +bool check_if_instance_extension_is_available(const struct loader_instance_extension_enables* enabled, const struct loader_instance_extension_enables* desired); + // Extension interception for vkGetDeviceProcAddr function, so we can return // an appropriate terminator if this is one of those few device commands requiring // a terminator. diff --git a/loader/wsi.c b/loader/wsi.c index 693640cb0..27b4b8ac7 100644 --- a/loader/wsi.c +++ b/loader/wsi.c @@ -156,6 +156,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceSupportKHR(VkP } VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; + + // Set pSupported to false if the instance extension used to create the VkSurfaceKHR isn't supported by the ICD + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + *pSupported = VK_FALSE; + return VK_SUCCESS; + } + if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && icd_term->surface_list.list[icd_surface->surface_index]) { @@ -211,6 +218,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilitiesKH } VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; + + // Return if the instance extension used to create the VkSurfaceKHR isn't supported by the ICD + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + // Application shouldn't query the surface capabilities if the VkPhysicalDevice doesn't support the VkSurfaceKHR + memset(pSurfaceCapabilities, 0, sizeof(VkSurfaceCapabilitiesKHR)); + return VK_SUCCESS; + } + if (NULL != phys_dev_term->this_icd_term->surface_list.list && phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) { @@ -269,6 +284,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkP } VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; + + // Return if the instance extension used to create the VkSurfaceKHR isn't supported by the ICD + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + // Application shouldn't query the surface formats if the VkPhysicalDevice doesn't support the VkSurfaceKHR + *pSurfaceFormatCount = 0; + return VK_SUCCESS; + } + if (NULL != phys_dev_term->this_icd_term->surface_list.list && phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) { @@ -328,6 +351,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKH } VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; + + // Return if the instance extension used to create the VkSurfaceKHR isn't supported by the ICD + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + // Application shouldn't query the surface present modes if the VkPhysicalDevice doesn't support the VkSurfaceKHR + *pPresentModeCount = 0; + return VK_SUCCESS; + } + if (NULL != phys_dev_term->this_icd_term->surface_list.list && phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) { @@ -386,7 +417,19 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, co "extension enabled?"); return VK_SUCCESS; } + VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateInfo->surface; + + // Return if the instance extension used to create the VkSurfaceKHR isn't supported by the ICD + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + // Application shouldn't try to create a swapchain if the VkPhysicalDevice doesn't support the VkSurfaceKHR + // Return VK_ERROR_INITIALIZATION_FAILED to indicate that the swapchain is not valid and zero out the swapchain handle + if (pSwapchain) { + *pSwapchain = VK_NULL_HANDLE; + } + return VK_ERROR_INITIALIZATION_FAILED; + } + if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && icd_term->surface_list.list[icd_surface->surface_index]) { @@ -461,7 +504,7 @@ VkResult allocate_icd_surface_struct(struct loader_instance *instance, const VkA } // Next, if so, proceed with the implementation of this function: - icd_surface = loader_instance_heap_alloc(instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + icd_surface = loader_instance_heap_calloc(instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (icd_surface == NULL) { res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; @@ -503,7 +546,9 @@ void cleanup_surface_creation(struct loader_instance *loader_inst, VkResult resu for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { if (icd_term->enabled_instance_extensions.khr_surface && NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && - icd_term->surface_list.list[icd_surface->surface_index] && NULL != icd_term->dispatch.DestroySurfaceKHR) { + icd_term->surface_list.list[icd_surface->surface_index] && NULL != icd_term->dispatch.DestroySurfaceKHR && + check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, + &icd_surface->wsi_extension_used)) { icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_term->surface_list.list[icd_surface->surface_index], pAllocator); } @@ -560,6 +605,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance insta if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.khr_win32_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -661,6 +707,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(VkInstance ins if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.khr_wayland_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -766,6 +813,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(VkInstance instanc if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.khr_xcb_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -874,6 +922,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(VkInstance instan if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.khr_xlib_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -981,6 +1030,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDirectFBSurfaceEXT(VkInstance in if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.ext_directfb_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -1133,6 +1183,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateHeadlessSurfaceEXT(VkInstance in if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.ext_headless_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -1222,6 +1273,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance insta if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.mvk_macos_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -1336,6 +1388,7 @@ terminator_CreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamD if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.ggp_stream_descriptor_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -1394,6 +1447,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance insta if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.ext_metal_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -1456,6 +1510,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateScreenSurfaceQNX(VkInstance inst if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.qnx_screen_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -1559,6 +1614,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateViSurfaceNN(VkInstance instance, if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.nn_vi_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -1655,6 +1711,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPlanePropertie return VK_SUCCESS; } + struct loader_instance_extension_enables display_enabled = {0}; + display_enabled.khr_display = 1; + + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &display_enabled)) { + // return 0 for property count as this driver doesn't support WSI functionality + if (pPropertyCount) { + *pPropertyCount = 0; + } + loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, "ICD for selected physical device does not support VK_KHR_display!"); + return VK_SUCCESS; + } + if (NULL == icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR) { loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0, "ICD for selected physical device does not export vkGetPhysicalDeviceDisplayPlanePropertiesKHR!"); @@ -1696,6 +1764,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneSupportedDisplaysKHR(Vk return VK_SUCCESS; } + struct loader_instance_extension_enables display_enabled = {0}; + display_enabled.khr_display = 1; + + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &display_enabled)) { + // return 0 for property count as this driver doesn't support WSI functionality + if (pDisplayCount) { + *pDisplayCount = 0; + } + loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, "ICD for selected physical device does not support VK_KHR_display!"); + return VK_SUCCESS; + } + if (NULL == icd_term->dispatch.GetDisplayPlaneSupportedDisplaysKHR) { loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0, "ICD for selected physical device does not export vkGetDisplayPlaneSupportedDisplaysKHR!"); @@ -1738,6 +1818,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModePropertiesKHR(VkPhysical return VK_SUCCESS; } + struct loader_instance_extension_enables display_enabled = {0}; + display_enabled.khr_display = 1; + + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &display_enabled)) { + // return 0 for property count as this driver doesn't support WSI functionality + if (pPropertyCount) { + *pPropertyCount = 0; + } + loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, "ICD for selected physical device does not support VK_KHR_display!"); + return VK_SUCCESS; + } + if (NULL == icd_term->dispatch.GetDisplayModePropertiesKHR) { loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0, "ICD for selected physical device does not export vkGetDisplayModePropertiesKHR!"); @@ -1781,6 +1873,15 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayModeKHR(VkPhysicalDevice return VK_ERROR_EXTENSION_NOT_PRESENT; } + struct loader_instance_extension_enables display_enabled = {0}; + display_enabled.khr_display = 1; + + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &display_enabled)) { + // Can't emulate, so return an appropriate error + loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, "ICD for selected physical device does not support VK_KHR_display!"); + return VK_ERROR_INITIALIZATION_FAILED; + } + if (NULL == icd_term->dispatch.CreateDisplayModeKHR) { // Can't emulate, so return an appropriate error loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, @@ -1820,6 +1921,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilitiesKHR(VkPhysi return VK_SUCCESS; } + struct loader_instance_extension_enables display_enabled = {0}; + display_enabled.khr_display = 1; + + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &display_enabled)) { + // Emulate support + if (pCapabilities) { + memset(pCapabilities, 0, sizeof(VkDisplayPlaneCapabilitiesKHR)); + } + loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, "ICD for selected physical device does not support VK_KHR_display!"); + return VK_SUCCESS; + } + if (NULL == icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR) { // Emulate support loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0, @@ -1869,6 +1982,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(VkInstanc if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.khr_display = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -2030,6 +2144,15 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDevicePresentRectanglesKHR( return VK_SUCCESS; } VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface); + + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + // return as this driver doesn't support WSI functionality + if (pRectCount) { + *pRectCount = 0; + } + return VK_SUCCESS; + } + if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && icd_term->surface_list.list[icd_surface->surface_index]) { @@ -2305,6 +2428,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA(VkInstan if (VK_SUCCESS != result) { goto out; } + icd_surface->wsi_extension_used.fuchsia_imagepipe_surface = 1; // Loop through each ICD and determine if they need to create a surface for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { @@ -2474,6 +2598,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K } return VK_SUCCESS; } + // If the ICD doesn't support the surface extension used to create the VkSurfaceKHR, then there are no capabilities + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + if (pSurfaceCapabilities) { + memset(&pSurfaceCapabilities->surfaceCapabilities, 0, sizeof(VkSurfaceCapabilitiesKHR)); + } + return VK_SUCCESS; + } VkResult res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface, &pSurfaceCapabilities->surfaceCapabilities); @@ -2514,6 +2645,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface); if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) { + // If the ICD doesn't support the surface extension used to create the VkSurfaceKHR, then there are no formats + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + if (pSurfaceFormatCount) { + *pSurfaceFormatCount = 0; + } + return VK_SUCCESS; + } + // Pass the call to the driver, possibly unwrapping the ICD surface if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && @@ -2552,6 +2691,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk } return VK_SUCCESS; } + // If the ICD doesn't support the surface extension used to create the VkSurfaceKHR, then there are no formats + if (!check_if_instance_extension_is_available(&icd_term->enabled_instance_extensions, &icd_surface->wsi_extension_used)) { + if (pSurfaceFormatCount) { + *pSurfaceFormatCount = 0; + } + return VK_SUCCESS; + } if (*pSurfaceFormatCount == 0 || pSurfaceFormats == NULL) { // Write to pSurfaceFormatCount diff --git a/loader/wsi.h b/loader/wsi.h index 90de00123..ddbc1a4a1 100644 --- a/loader/wsi.h +++ b/loader/wsi.h @@ -26,6 +26,9 @@ typedef struct { uint32_t surface_index; // This surface's index into each drivers list of created surfaces + + // Defines the 'active' WSI extension used - only one member should be true + struct loader_instance_extension_enables wsi_extension_used; } VkIcdSurface; bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr); diff --git a/scripts/loader_extension_generator.py b/scripts/loader_extension_generator.py index e9b513c01..a9706b99f 100644 --- a/scripts/loader_extension_generator.py +++ b/scripts/loader_extension_generator.py @@ -284,6 +284,7 @@ def endFile(self): file_data += self.CreateTrampTermFuncs() file_data += self.InstExtensionGPA() file_data += self.OutputInstanceExtensionEnableStructDefinition() + file_data += self.OutputCheckInstanceExtensionIsEnabledFunc() file_data += self.DeviceExtensionGetTerminator() file_data += self.InitInstLoaderExtensionDispatchTable() file_data += self.OutputInstantExtensionWhitelistArray() @@ -508,6 +509,8 @@ def OutputPrototypesInHeader(self): protos += '// about.\n' protos += 'void fill_out_enabled_instance_extensions(uint32_t extension_count, const char *const * extension_list, struct loader_instance_extension_enables* enables);\n\n' protos += '\n' + protos += 'bool check_if_instance_extension_is_available(const struct loader_instance_extension_enables* enabled, const struct loader_instance_extension_enables* desired);\n' + protos += '\n' protos += '// Extension interception for vkGetDeviceProcAddr function, so we can return\n' protos += '// an appropriate terminator if this is one of those few device commands requiring\n' protos += '// a terminator.\n' @@ -812,6 +815,21 @@ def OutputInstanceExtensionEnableStructDefinition(self): return out + def OutputCheckInstanceExtensionIsEnabledFunc(self): + out = 'bool check_if_instance_extension_is_available(const struct loader_instance_extension_enables* enabled, const struct loader_instance_extension_enables* desired) {\n' + for ext in self.extensions: + if self.getAPIVersion(ext.name) or ext.type == 'device': + continue + if ext.protect is not None: + out += f'#if defined({ext.protect})\n' + out += f' if (desired->{ext.name[3:].lower()} && !enabled->{ext.name[3:].lower()}) return false;\n' + if ext.protect is not None: + out += f'#endif // defined({ext.protect})\n' + out += ' return true;\n' + out += '};\n\n' + + return out + # # Creates the prototypes for the loader's core instance command terminators def OutputLoaderTerminators(self):