From bacdd2a0c94783781a79a113af3b1646ebccfb1b Mon Sep 17 00:00:00 2001 From: Daniel Rakos Date: Tue, 18 Feb 2025 17:30:28 +0100 Subject: [PATCH] loader: Lazily allocate ICD surface objects --- loader/allocation.h | 3 + loader/extension_manual.c | 61 +-- loader/generated/vk_loader_extensions.c | 28 +- loader/wsi.c | 650 ++++++++++++++---------- loader/wsi.h | 14 + scripts/loader_extension_generator.py | 21 +- tests/framework/test_environment.cpp | 55 +- 7 files changed, 480 insertions(+), 352 deletions(-) diff --git a/loader/allocation.h b/loader/allocation.h index e9c5bc59a..8cfb4986a 100644 --- a/loader/allocation.h +++ b/loader/allocation.h @@ -30,6 +30,9 @@ #include "loader_common.h" +// The loader always aligns memory allocations to the largest unit size which is the size of a uint64_t +#define loader_aligned_size(x) ((((x) + sizeof(uint64_t) - 1) / sizeof(uint64_t)) * sizeof(uint64_t)) + void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope allocation_scope); void *loader_instance_heap_calloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope allocation_scope); void loader_instance_heap_free(const struct loader_instance *instance, void *pMemory); diff --git a/loader/extension_manual.c b/loader/extension_manual.c index 6b917fcd0..5bc4e38e1 100644 --- a/loader/extension_manual.c +++ b/loader/extension_manual.c @@ -104,21 +104,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2E VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT *pSurfaceCapabilities) { struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; - - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface); - - // Unwrap the surface if needed - VkSurfaceKHR unwrapped_surface = surface; - 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]) { - unwrapped_surface = phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]; + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; } if (NULL != icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT) { // Pass the call to the driver - return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT(phys_dev_term->phys_dev, unwrapped_surface, - pSurfaceCapabilities); + return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT(phys_dev_term->phys_dev, surface, pSurfaceCapabilities); } else { // Emulate the call loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0, @@ -127,8 +120,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2E icd_term->scanned_icd->lib_name); VkSurfaceCapabilitiesKHR surface_caps; - VkResult res = - icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, unwrapped_surface, &surface_caps); + res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface, &surface_caps); pSurfaceCapabilities->minImageCount = surface_caps.minImageCount; pSurfaceCapabilities->maxImageCount = surface_caps.maxImageCount; pSurfaceCapabilities->currentExtent = surface_caps.currentExtent; @@ -274,21 +266,15 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2E "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSurfacePresentModes2EXT"); abort(); } - if (VK_NULL_HANDLE != pSurfaceInfo->surface) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface); - if (NULL != icd_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]) { - VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy; - surface_info_copy.sType = pSurfaceInfo->sType; - surface_info_copy.pNext = pSurfaceInfo->pNext; - surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index]; - return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy, - pPresentModeCount, pPresentModes); - } + + VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy = *pSurfaceInfo; + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface_info_copy.surface); + if (res != VK_SUCCESS) { + return res; } - return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, pSurfaceInfo, pPresentModeCount, - pPresentModes); + + return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy, + pPresentModeCount, pPresentModes); } VKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(VkDevice device, @@ -323,20 +309,15 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT( "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]"); abort(); /* Intentionally fail so user can correct issue. */ } - if (VK_NULL_HANDLE != pSurfaceInfo->surface) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface); - if (NULL != icd_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]) { - VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy; - surface_info_copy.sType = pSurfaceInfo->sType; - surface_info_copy.pNext = pSurfaceInfo->pNext; - surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index]; - return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT( - device, &surface_info_copy, pModes); - } + + VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy = *pSurfaceInfo; + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface_info_copy.surface); + if (res != VK_SUCCESS) { + return res; } - return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes); + + return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy, + pModes); } #endif // VK_USE_PLATFORM_WIN32_KHR diff --git a/loader/generated/vk_loader_extensions.c b/loader/generated/vk_loader_extensions.c index 5f909cb7a..63d24c294 100644 --- a/loader/generated/vk_loader_extensions.c +++ b/loader/generated/vk_loader_extensions.c @@ -5338,10 +5338,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectTagEXT( // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call. } else if (pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) { if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->object; - 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]) { - local_tag_info.object = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index]; + VkSurfaceKHR surface = (VkSurfaceKHR)(uintptr_t)pTagInfo->object; + if (wsi_unwrap_icd_surface(icd_term, &surface) == VK_SUCCESS) { + local_tag_info.object = (uint64_t)surface; } } // If this is an instance we have to replace it with the proper one for the next call. @@ -5397,10 +5396,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectNameEXT( // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call. } else if (pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) { if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->object; - 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]) { - local_name_info.object = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index]; + VkSurfaceKHR surface = (VkSurfaceKHR)(uintptr_t)pNameInfo->object; + if (wsi_unwrap_icd_surface(icd_term, &surface) == VK_SUCCESS) { + local_name_info.object = (uint64_t)surface; } } // If this is an instance we have to replace it with the proper one for the next call. @@ -6001,10 +5999,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectNameEXT( // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call. } else if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) { if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->objectHandle; - 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]) { - local_name_info.objectHandle = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index]; + VkSurfaceKHR surface = (VkSurfaceKHR)(uintptr_t)pNameInfo->objectHandle; + if (wsi_unwrap_icd_surface(icd_term, &surface) == VK_SUCCESS) { + local_name_info.objectHandle = (uint64_t)surface; } } // If this is an instance we have to replace it with the proper one for the next call. @@ -6064,10 +6061,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_SetDebugUtilsObjectTagEXT( // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call. } else if (pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) { if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->objectHandle; - 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]) { - local_tag_info.objectHandle = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index]; + VkSurfaceKHR surface = (VkSurfaceKHR)(uintptr_t)pTagInfo->objectHandle; + if (wsi_unwrap_icd_surface(icd_term, &surface) == VK_SUCCESS) { + local_tag_info.objectHandle = (uint64_t)surface; } } // If this is an instance we have to replace it with the proper one for the next call. diff --git a/loader/wsi.c b/loader/wsi.c index 0d841f724..ce6d3a0c1 100644 --- a/loader/wsi.c +++ b/loader/wsi.c @@ -39,6 +39,217 @@ // the ICDs. #define ICD_VER_SUPPORTS_ICD_SURFACE_KHR 3 +struct loader_struct_type_info { + VkStructureType stype; + size_t size; +}; + +// This function unwraps the application-provided surface handle into the ICD-specific surface handle +// corresponding to the specified physical device. If the ICD-specific surface handle does not exist +// yet, then this function also creates of the ICD-specific surface object. This enables lazy creation +// of ICD-specific surface objects and therefore avoids creating surfaces for ICDs that may not be able +// to or should not create the specific type of surface (one example is the VK_KHR_display extension +// where the VkDisplayModeKHR handles the surfaces are created from are physical-device-specific +// non-dispatchable handles and therefore they should not be passed down to a foreign ICD). +VkResult wsi_unwrap_icd_surface(struct loader_icd_term *icd_term, VkSurfaceKHR *surface) { + VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(*surface); + +#if defined(VK_USE_PLATFORM_ANDROID_KHR) + if (icd_surface->base.platform == VK_ICD_WSI_PLATFORM_ANDROID) { + // Android does not use ICD-created surfaces + // NOTE: This may be incorrect and in fact the legacy code could result in out-of-bounds + // accesses to VkIcdSurface::surface_index in case of Android, but we preserved the legacy + // behavior (while also eliminating the chance for out-of-bounds accesses). + return VK_SUCCESS; + } +#endif // VK_USE_PLATFORM_ANDROID_KHR +#if defined(VK_USE_PLATFORM_MACOS_MVK) + if (icd_surface->base.platform == VK_ICD_WSI_PLATFORM_IOS) { + // iOS does not use ICD-created surfaces (matching legacy behavior) + // NOTE: This may be incorrect and in fact the legacy code could result in out-of-bounds + // accesses to VkIcdSurface::surface_index in case of Android, but we preserved the legacy + // behavior (while also eliminating the chance for out-of-bounds accesses). + return VK_SUCCESS; + } +#endif // VK_USE_PLATFORM_MACOS_MVK + + if (NULL == icd_term->surface_list.list || + icd_term->surface_list.capacity <= icd_surface->surface_index * sizeof(VkSurfaceKHR)) { + // This surface handle is not one that was created by the loader, therefore we simply return + // the input surface handle unmodified. This matches legacy behavior. + return VK_SUCCESS; + } + + VkResult result = VK_SUCCESS; + if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { + if (VK_NULL_HANDLE == icd_term->surface_list.list[icd_surface->surface_index]) { + // If the surface does not exist yet for the target ICD, then create it lazily + switch (icd_surface->base.platform) { +#if defined(VK_USE_PLATFORM_WAYLAND_KHR) + case VK_ICD_WSI_PLATFORM_WAYLAND: + if (NULL != icd_term->dispatch.CreateWaylandSurfaceKHR) { + result = icd_term->dispatch.CreateWaylandSurfaceKHR( + icd_term->instance, (const VkWaylandSurfaceCreateInfoKHR *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_WAYLAND_KHR + +#if defined(VK_USE_PLATFORM_WIN32_KHR) + case VK_ICD_WSI_PLATFORM_WIN32: + if (NULL != icd_term->dispatch.CreateWin32SurfaceKHR) { + result = icd_term->dispatch.CreateWin32SurfaceKHR( + icd_term->instance, (const VkWin32SurfaceCreateInfoKHR *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_WIN32_KHR + +#if defined(VK_USE_PLATFORM_XCB_KHR) + case VK_ICD_WSI_PLATFORM_XCB: + if (NULL != icd_term->dispatch.CreateXcbSurfaceKHR) { + result = icd_term->dispatch.CreateXcbSurfaceKHR( + icd_term->instance, (const VkXcbSurfaceCreateInfoKHR *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_XCB_KHR + +#if defined(VK_USE_PLATFORM_XLIB_KHR) + case VK_ICD_WSI_PLATFORM_XLIB: + if (NULL != icd_term->dispatch.CreateXlibSurfaceKHR) { + result = icd_term->dispatch.CreateXlibSurfaceKHR( + icd_term->instance, (const VkXlibSurfaceCreateInfoKHR *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_XLIB_KHR + +#if defined(VK_USE_PLATFORM_MACOS_MVK) + case VK_ICD_WSI_PLATFORM_MACOS: + if (NULL != icd_term->dispatch.CreateMacOSSurfaceMVK) { + result = icd_term->dispatch.CreateMacOSSurfaceMVK( + icd_term->instance, (const VkMacOSSurfaceCreateInfoMVK *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_MACOS_MVK + + case VK_ICD_WSI_PLATFORM_DISPLAY: + if (NULL != icd_term->dispatch.CreateDisplayPlaneSurfaceKHR) { + result = icd_term->dispatch.CreateDisplayPlaneSurfaceKHR( + icd_term->instance, (const VkDisplaySurfaceCreateInfoKHR *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; + + case VK_ICD_WSI_PLATFORM_HEADLESS: + if (NULL != icd_term->dispatch.CreateHeadlessSurfaceEXT) { + result = icd_term->dispatch.CreateHeadlessSurfaceEXT( + icd_term->instance, (const VkHeadlessSurfaceCreateInfoEXT *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; + +#if defined(VK_USE_PLATFORM_METAL_EXT) + case VK_ICD_WSI_PLATFORM_METAL: + if (NULL != icd_term->dispatch.CreateMetalSurfaceEXT) { + result = icd_term->dispatch.CreateMetalSurfaceEXT( + icd_term->instance, (const VkMetalSurfaceCreateInfoEXT *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_METAL_EXT + +#if defined(VK_USE_PLATFORM_DIRECTFB_EXT) + case VK_ICD_WSI_PLATFORM_DIRECTFB: + if (NULL != icd_term->dispatch.CreateDirectFBSurfaceEXT) { + result = icd_term->dispatch.CreateDirectFBSurfaceEXT( + icd_term->instance, (const VkDirectFBSurfaceCreateInfoEXT *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_DIRECTFB_EXT + +#if defined(VK_USE_PLATFORM_VI_NN) + case VK_ICD_WSI_PLATFORM_VI: + if (NULL != icd_term->dispatch.CreateViSurfaceNN) { + result = icd_term->dispatch.CreateViSurfaceNN( + icd_term->instance, (const VkViSurfaceCreateInfoNN *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_VI_NN + +#if defined(VK_USE_PLATFORM_GGP) + case VK_ICD_WSI_PLATFORM_GGP: + if (NULL != icd_term->dispatch.CreateStreamDescriptorSurfaceGGP) { + result = icd_term->dispatch.CreateStreamDescriptorSurfaceGGP( + icd_term->instance, (const VkStreamDescriptorSurfaceCreateInfoGGP *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_GGP + +#if defined(VK_USE_PLATFORM_SCREEN_QNX) + case VK_ICD_WSI_PLATFORM_SCREEN: + if (NULL != icd_term->dispatch.CreateScreenSurfaceQNX) { + result = icd_term->dispatch.CreateScreenSurfaceQNX( + icd_term->instance, (const VkScreenSurfaceCreateInfoQNX *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_SCREEN_QNX + +#if defined(VK_USE_PLATFORM_FUCHSIA) + case VK_ICD_WSI_PLATFORM_FUCHSIA: + if (NULL != icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA) { + result = icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA( + icd_term->instance, (const VkImagePipeSurfaceCreateInfoFUCHSIA *)icd_surface->create_info, + &icd_term->this_instance->alloc_callbacks, &icd_term->surface_list.list[icd_surface->surface_index]); + } else { + result = VK_ERROR_EXTENSION_NOT_PRESENT; + } + break; +#endif // VK_USE_PLATFORM_FUCHSIA + + default: + // Not supported + result = VK_ERROR_EXTENSION_NOT_PRESENT; + break; + } + } + + *surface = icd_term->surface_list.list[icd_surface->surface_index]; + } + + return result; +} + void wsi_create_instance(struct loader_instance *loader_inst, const VkInstanceCreateInfo *pCreateInfo) { for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) { @@ -202,6 +413,9 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkS assert((VkSurfaceKHR)(uintptr_t)NULL == icd_term->surface_list.list[icd_surface->surface_index]); } } + if (NULL != icd_surface->create_info) { + loader_instance_heap_free(loader_inst, icd_surface->create_info); + } loader_release_object_from_list(&loader_inst->surfaces_list, icd_surface->surface_index); loader_instance_heap_free(loader_inst, (void *)(uintptr_t)surface); } @@ -253,12 +467,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceSupportKHR(VkP return VK_SUCCESS; } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; - 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]) { - return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR( - phys_dev_term->phys_dev, queueFamilyIndex, icd_term->surface_list.list[icd_surface->surface_index], pSupported); + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; } return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, surface, pSupported); @@ -308,13 +519,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilitiesKH return VK_SUCCESS; } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; - 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]) { - return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR( - phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index], - pSurfaceCapabilities); + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; } return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface, pSurfaceCapabilities); @@ -367,15 +574,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkP } if (VK_NULL_HANDLE != surface) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; - 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]) { - return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR( - phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index], - pSurfaceFormatCount, pSurfaceFormats); + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; } } + return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount, pSurfaceFormats); } @@ -425,17 +629,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKH "ICD for selected physical device does not export vkGetPhysicalDeviceSurfacePresentModesKHR!"); return VK_SUCCESS; } + if (VK_NULL_HANDLE != surface) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; - - if (icd_surface != NULL && 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]) { - return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR( - phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index], - pPresentModeCount, pPresentModes); + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; } } + return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(phys_dev_term->phys_dev, surface, pPresentModeCount, pPresentModes); } @@ -486,22 +687,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, co "extension enabled?"); return VK_SUCCESS; } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateInfo->surface; - 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]) { - // We found the ICD, and there is an ICD KHR surface - // associated with it, so copy the CreateInfo struct - // and point it at the ICD's surface. - VkSwapchainCreateInfoKHR *pCreateCopy = loader_stack_alloc(sizeof(VkSwapchainCreateInfoKHR)); - if (NULL == pCreateCopy) { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - memcpy(pCreateCopy, pCreateInfo, sizeof(VkSwapchainCreateInfoKHR)); - pCreateCopy->surface = icd_term->surface_list.list[icd_surface->surface_index]; - return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, pCreateCopy, pAllocator, pSwapchain); + + VkSwapchainCreateInfoKHR create_info_copy = *pCreateInfo; + VkResult res = wsi_unwrap_icd_surface(icd_term, &create_info_copy.surface); + if (res != VK_SUCCESS) { + return res; } - return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); + + return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, &create_info_copy, pAllocator, pSwapchain); } // This is the trampoline entrypoint for DestroySwapchainKHR @@ -573,6 +766,7 @@ VkResult allocate_icd_surface_struct(struct loader_instance *instance, size_t ba icd_surface->non_platform_offset = (uint32_t)((uint8_t *)(&icd_surface->base_size) - (uint8_t *)icd_surface); icd_surface->entire_size = sizeof(VkIcdSurface); icd_surface->surface_index = next_index; + icd_surface->create_info = NULL; for (struct loader_icd_term *icd_term = instance->icd_terms; icd_term != NULL; icd_term = icd_term->next) { if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { @@ -600,6 +794,54 @@ VkResult allocate_icd_surface_struct(struct loader_instance *instance, size_t ba return res; } +VkResult copy_surface_create_info(struct loader_instance *loader_inst, VkIcdSurface *icd_surface, const void *create_info, + size_t struct_type_info_count, const struct loader_struct_type_info *struct_type_info, + const char *base_struct_name) { + size_t create_info_total_size = 0; + const VkBaseInStructure *base = (const VkBaseInStructure *)create_info; + while (NULL != base) { + bool known_struct = false; + for (size_t i = 0; i < struct_type_info_count; ++i) { + if (base->sType == struct_type_info[i].stype) { + create_info_total_size += loader_aligned_size(struct_type_info[i].size); + base = base->pNext; + known_struct = true; + break; + } + } + if (!known_struct) { + loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, "Unsupported extension structure in %s pNext chain.", + base_struct_name); + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + } + + icd_surface->create_info = loader_instance_heap_alloc(loader_inst, create_info_total_size, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (NULL == icd_surface->create_info) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + uint8_t *dst = (uint8_t *)icd_surface->create_info; + VkBaseInStructure *prev_struct = NULL; + base = (const VkBaseInStructure *)create_info; + while (NULL != base) { + for (size_t i = 0; i < struct_type_info_count; ++i) { + if (base->sType == struct_type_info[i].stype) { + memcpy(dst, base, struct_type_info[i].size); + if (NULL != prev_struct) { + prev_struct->pNext = (const VkBaseInStructure *)dst; + } + prev_struct = (VkBaseInStructure *)dst; + dst += loader_aligned_size(struct_type_info[i].size); + base = base->pNext; + break; + } + } + } + + return VK_SUCCESS; +} + void cleanup_surface_creation(struct loader_instance *loader_inst, VkResult result, VkIcdSurface *icd_surface, const VkAllocationCallbacks *pAllocator) { if (VK_SUCCESS != result && NULL != icd_surface) { @@ -618,6 +860,9 @@ void cleanup_surface_creation(struct loader_instance *loader_inst, VkResult resu loader_inst->surfaces_list.list[icd_surface->surface_index].allocation_callbacks = *pAllocator; } } + if (NULL != icd_surface->create_info) { + loader_instance_heap_free(loader_inst, icd_surface->create_info); + } loader_instance_heap_free(loader_inst, icd_surface); } } @@ -669,18 +914,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance insta icd_surface->win_surf.hinstance = pCreateInfo->hinstance; icd_surface->win_surf.hwnd = pCreateInfo->hwnd; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateWin32SurfaceKHR) { - result = icd_term->dispatch.CreateWin32SurfaceKHR(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, sizeof(VkWin32SurfaceCreateInfoKHR)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkWin32SurfaceCreateInfoKHR"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -775,18 +1013,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(VkInstance ins icd_surface->wayland_surf.display = pCreateInfo->display; icd_surface->wayland_surf.surface = pCreateInfo->surface; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateWaylandSurfaceKHR) { - result = icd_term->dispatch.CreateWaylandSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, sizeof(VkWaylandSurfaceCreateInfoKHR)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkWaylandSurfaceCreateInfoKHR"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -885,18 +1116,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(VkInstance instanc icd_surface->xcb_surf.connection = pCreateInfo->connection; icd_surface->xcb_surf.window = pCreateInfo->window; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateXcbSurfaceKHR) { - result = icd_term->dispatch.CreateXcbSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, sizeof(VkXcbSurfaceCreateInfoKHR)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkXcbSurfaceCreateInfoKHR"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -998,18 +1222,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(VkInstance instan icd_surface->xlib_surf.dpy = pCreateInfo->dpy; icd_surface->xlib_surf.window = pCreateInfo->window; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateXlibSurfaceKHR) { - result = icd_term->dispatch.CreateXlibSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, sizeof(VkXlibSurfaceCreateInfoKHR)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkXlibSurfaceCreateInfoKHR"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -1110,18 +1327,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDirectFBSurfaceEXT(VkInstance in icd_surface->directfb_surf.dfb = pCreateInfo->dfb; icd_surface->directfb_surf.surface = pCreateInfo->surface; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateDirectFBSurfaceEXT) { - result = icd_term->dispatch.CreateDirectFBSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT, sizeof(VkDirectFBSurfaceCreateInfoEXT)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkDirectFBSurfaceCreateInfoEXT"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -1264,18 +1474,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateHeadlessSurfaceEXT(VkInstance in } icd_surface->headless_surf.base.platform = VK_ICD_WSI_PLATFORM_HEADLESS; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateHeadlessSurfaceEXT) { - result = icd_term->dispatch.CreateHeadlessSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT, sizeof(VkHeadlessSurfaceCreateInfoEXT)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkHeadlessSurfaceCreateInfoEXT"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -1357,18 +1561,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance insta icd_surface->macos_surf.base.platform = VK_ICD_WSI_PLATFORM_MACOS; icd_surface->macos_surf.pView = pCreateInfo->pView; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateMacOSSurfaceMVK) { - result = icd_term->dispatch.CreateMacOSSurfaceMVK(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, sizeof(VkMacOSSurfaceCreateInfoMVK)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkMacOSSurfaceCreateInfoMVK"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -1475,18 +1672,11 @@ terminator_CreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamD icd_surface->ggp_surf.base.platform = VK_ICD_WSI_PLATFORM_GGP; icd_surface->ggp_surf.streamDescriptor = pCreateInfo->streamDescriptor; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateStreamDescriptorSurfaceGGP) { - result = icd_term->dispatch.CreateStreamDescriptorSurfaceGGP( - icd_term->instance, pCreateInfo, pAllocator, &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP, sizeof(VkStreamDescriptorSurfaceCreateInfoGGP)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkStreamDescriptorSurfaceCreateInfoGGP"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -1537,18 +1727,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance insta icd_surface->metal_surf.base.platform = VK_ICD_WSI_PLATFORM_METAL; icd_surface->metal_surf.pLayer = pCreateInfo->pLayer; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateMetalSurfaceEXT) { - result = icd_term->dispatch.CreateMetalSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT, sizeof(VkMetalSurfaceCreateInfoEXT)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkMetalSurfaceCreateInfoEXT"); + *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; out: @@ -1604,18 +1788,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateScreenSurfaceQNX(VkInstance inst icd_surface->screen_surf.context = pCreateInfo->context; icd_surface->screen_surf.window = pCreateInfo->window; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateScreenSurfaceQNX) { - result = icd_term->dispatch.CreateScreenSurfaceQNX(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX, sizeof(VkScreenSurfaceCreateInfoQNX)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkScreenSurfaceCreateInfoQNX"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -1711,18 +1888,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateViSurfaceNN(VkInstance instance, icd_surface->vi_surf.base.platform = VK_ICD_WSI_PLATFORM_VI; icd_surface->vi_surf.window = pCreateInfo->window; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateViSurfaceNN) { - result = icd_term->dispatch.CreateViSurfaceNN(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN, sizeof(VkViSurfaceCreateInfoNN)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkViSurfaceCreateInfoNN"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -2031,18 +2201,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(VkInstanc icd_surface->display_surf.alphaMode = pCreateInfo->alphaMode; icd_surface->display_surf.imageExtent = pCreateInfo->imageExtent; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateDisplayPlaneSurfaceKHR) { - result = icd_term->dispatch.CreateDisplayPlaneSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, sizeof(VkDisplaySurfaceCreateInfoKHR)}, + {VK_STRUCTURE_TYPE_DISPLAY_SURFACE_STEREO_CREATE_INFO_NV, sizeof(VkDisplaySurfaceStereoCreateInfoNV)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkDisplaySurfaceCreateInfoKHR"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -2100,10 +2264,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSharedSwapchainsKHR(VkDevice dev } memcpy(pCreateCopy, pCreateInfos, sizeof(VkSwapchainCreateInfoKHR) * swapchainCount); for (uint32_t sc = 0; sc < swapchainCount; sc++) { - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateCopy[sc].surface; - if (icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && - icd_term->surface_list.list[icd_surface->surface_index]) { - pCreateCopy[sc].surface = icd_term->surface_list.list[icd_surface->surface_index]; + VkResult res = wsi_unwrap_icd_surface(icd_term, &pCreateCopy[sc].surface); + if (res != VK_SUCCESS) { + return res; } } return dev->loader_dispatch.extension_terminator_dispatch.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateCopy, @@ -2151,13 +2314,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModesKHR(V "extensions enabled when using Vulkan 1.0?"); return VK_SUCCESS; } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface; - 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]) { - return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModesKHR( - device, icd_term->surface_list.list[icd_surface->surface_index], pModes); + + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; } + return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes); } @@ -2190,13 +2352,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDevicePresentRectanglesKHR( } return VK_SUCCESS; } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface); - 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]) { - return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR( - phys_dev_term->phys_dev, icd_term->surface_list.list[icd_surface->surface_index], pRectCount, pRects); + + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; } + return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR(phys_dev_term->phys_dev, surface, pRectCount, pRects); } @@ -2470,18 +2631,11 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA(VkInstan icd_surface->imagepipe_surf.base.platform = VK_ICD_WSI_PLATFORM_FUCHSIA; - // 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) { - if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { - if (NULL != icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA) { - result = icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA(icd_term->instance, pCreateInfo, pAllocator, - &icd_term->surface_list.list[icd_surface->surface_index]); - if (VK_SUCCESS != result) { - goto out; - } - } - } - } + const struct loader_struct_type_info ci_types[] = { + {VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA, sizeof(VkImagePipeSurfaceCreateInfoFUCHSIA)}, + }; + copy_surface_create_info(loader_inst, icd_surface, pCreateInfo, sizeof(ci_types) / sizeof(ci_types[0]), ci_types, + "VkImagePipeSurfaceCreateInfoFUCHSIA"); *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface; @@ -2568,10 +2722,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance; - VkIcdSurface *icd_surface = NULL; - if (pSurfaceInfo->surface) { - icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface; - } if (!loader_inst->wsi_surface_enabled) { loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0, @@ -2579,6 +2729,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K return VK_SUCCESS; } + VkSurfaceKHR surface = pSurfaceInfo->surface; + if (VK_NULL_HANDLE != pSurfaceInfo->surface) { + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; + } + } + if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR != NULL) { void *pNext = pSurfaceCapabilities->pNext; while (pNext != NULL) { @@ -2593,20 +2751,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K pNext = pNext_out_structure.pNext; } - VkResult res = VK_SUCCESS; - // Pass the call to the driver, possibly unwrapping the ICD surface - if (NULL != icd_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]) { - VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo; - info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index]; - res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, &info_copy, - pSurfaceCapabilities); - } else { - res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, pSurfaceInfo, - pSurfaceCapabilities); - } + VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo; + info_copy.surface = surface; + + VkResult res = + icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, &info_copy, pSurfaceCapabilities); // Because VK_EXT_surface_maintenance1 is an instance extension, applications will use it to query info on drivers which do // not support the extension. Thus we need to emulate the driver filling out the structs in that case. @@ -2623,12 +2773,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K icd_term->scanned_icd->lib_name); // Write to the VkSurfaceCapabilities2KHR struct - VkSurfaceKHR surface = VK_NULL_HANDLE; - if (NULL != icd_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]) { - surface = icd_term->surface_list.list[icd_surface->surface_index]; - } // If the icd doesn't support VK_KHR_surface, then there are no capabilities if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR) { @@ -2674,24 +2818,21 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk return VK_SUCCESS; } - VkIcdSurface *icd_surface = NULL; + VkSurfaceKHR surface = pSurfaceInfo->surface; if (VK_NULL_HANDLE != pSurfaceInfo->surface) { - icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface); + VkResult res = wsi_unwrap_icd_surface(icd_term, &surface); + if (res != VK_SUCCESS) { + return res; + } } if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) { // Pass the call to the driver, possibly unwrapping the ICD surface - if (NULL != icd_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]) { - VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo; - info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index]; - return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, &info_copy, pSurfaceFormatCount, - pSurfaceFormats); - } else { - return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, pSurfaceInfo, - pSurfaceFormatCount, pSurfaceFormats); - } + VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo; + info_copy.surface = surface; + + return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, &info_copy, pSurfaceFormatCount, + pSurfaceFormats); } else { // Emulate the call loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0, @@ -2704,13 +2845,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk "- this struct will be ignored"); } - VkSurfaceKHR surface = pSurfaceInfo->surface; - if (NULL != icd_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]) { - surface = icd_term->surface_list.list[icd_surface->surface_index]; - } - // If the icd doesn't support VK_KHR_surface, then there are no formats if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR) { if (pSurfaceFormatCount) { diff --git a/loader/wsi.h b/loader/wsi.h index ee3f9c40a..b66c544ba 100644 --- a/loader/wsi.h +++ b/loader/wsi.h @@ -65,14 +65,28 @@ typedef struct { #endif // VK_USE_PLATFORM_VI_NN VkIcdSurfaceDisplay display_surf; VkIcdSurfaceHeadless headless_surf; + + // All of the specific ICD surface structures start with the base structure + VkIcdSurfaceBase base; }; uint32_t base_size; // Size of VkIcdSurfaceBase uint32_t platform_size; // Size of corresponding VkIcdSurfaceXXX uint32_t non_platform_offset; // Start offset to base_size uint32_t entire_size; // Size of entire VkIcdSurface uint32_t surface_index; // This surface's index into each drivers list of created surfaces + + // The create info parameters captured by the union in VkIcdSurface are insufficient, as they do not + // capture every single parameter from the create info (e.g. flags that did not have any flags defined + // at the time) and they also cannot capture extension structures, so we are including a separate + // pointer that will hold a copy of the original creation structure chain. This chain can only capture + // known extension structures and preferably should be auto-generated, but the list of extension + // structures is rather limited (there is only a single display surface creation structure extension + // at the time of writing). + uint8_t *create_info; } VkIcdSurface; +VkResult wsi_unwrap_icd_surface(struct loader_icd_term *icd_term, VkSurfaceKHR *surface); + bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr); void wsi_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo); diff --git a/scripts/loader_extension_generator.py b/scripts/loader_extension_generator.py index 2b77ba436..f79a7e343 100644 --- a/scripts/loader_extension_generator.py +++ b/scripts/loader_extension_generator.py @@ -1109,14 +1109,14 @@ def CreateTrampTermFuncs(self): requires_terminator = 1 always_use_param_name = False surface_type_to_replace = 'VkSurfaceKHR' - surface_name_replacement = 'icd_term->surface_list[icd_surface->surface_index]' + surface_name_replacement = 'unwrapped_surface' if param.type == 'VkPhysicalDeviceSurfaceInfo2KHR': has_surface = 1 surface_var_name = param.name + '->surface' requires_terminator = 1 update_structure_surface = 1 update_structure_string = ' VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;\n' - update_structure_string += ' info_copy.surface = icd_term->surface_list[icd_surface->surface_index];\n' + update_structure_string += ' info_copy.surface = unwrapped_surface;\n' always_use_param_name = False surface_type_to_replace = 'VkPhysicalDeviceSurfaceInfo2KHR' surface_name_replacement = '&info_copy' @@ -1277,11 +1277,9 @@ def CreateTrampTermFuncs(self): funcs += ' }\n' if has_surface == 1: - funcs += ' VkIcdSurface *icd_surface = NULL;\n' - funcs += f' if (NULL != {surface_var_name}) {{\n' - funcs += f' icd_surface = (VkIcdSurface *)(uintptr_t)({surface_var_name});\n' - funcs += ' }\n' - funcs += ' if (NULL != icd_surface && NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) && icd_term->surface_list[icd_surface->surface_index]) {\n' + funcs += f' VkSurfaceKHR unwrapped_surface = {surface_var_name};\n' + funcs += ' VkResult unwrap_res = wsi_unwrap_icd_surface(icd_term, &unwrapped_surface);\n' + funcs += ' if (unwrap_res == VK_SUCCESS) {\n' # If there's a structure with a surface, we need to update its internals with the correct surface for the ICD if update_structure_surface == 1: @@ -1363,10 +1361,9 @@ def CreateTrampTermFuncs(self): funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n' funcs += f' }} else if ({debug_struct_name}->objectType == {surf_check}) {{\n' funcs += ' if (NULL != dev && NULL != dev->loader_dispatch.core_dispatch.CreateSwapchainKHR) {\n' - funcs += f' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t){debug_struct_name}->{member_name};\n' - funcs += ' if (NULL != icd_term->surface_list.list && icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR)\n' - funcs += ' && icd_term->surface_list.list[icd_surface->surface_index]) {\n' - funcs += f' {local_struct}.{member_name} = (uint64_t)icd_term->surface_list.list[icd_surface->surface_index];\n' + funcs += f' VkSurfaceKHR surface = (VkSurfaceKHR)(uintptr_t){debug_struct_name}->{member_name};\n' + funcs += ' if (wsi_unwrap_icd_surface(icd_term, &surface) == VK_SUCCESS) {\n' + funcs += f' {local_struct}.{member_name} = (uint64_t)surface;\n' funcs += ' }\n' funcs += ' }\n' funcs += ' // If this is an instance we have to replace it with the proper one for the next call.\n' @@ -1398,7 +1395,7 @@ def CreateTrampTermFuncs(self): if param.type == 'VkPhysicalDevice': funcs += 'phys_dev_term->phys_dev' elif param.type == 'VkSurfaceKHR': - funcs += 'icd_term->surface_list[icd_surface->surface_index]' + funcs += 'unwrapped_surface' elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo': funcs += '&local_name_info' elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo': diff --git a/tests/framework/test_environment.cpp b/tests/framework/test_environment.cpp index be8d63233..e205a7c11 100644 --- a/tests/framework/test_environment.cpp +++ b/tests/framework/test_environment.cpp @@ -871,69 +871,72 @@ std::vector FrameworkEnvironment::GetLayerProperties(uint32_t } template -VkResult create_surface_helper(VulkanFunctions* functions, VkInstance inst, VkSurfaceKHR& surface, const char* load_func_name) { +VkResult create_surface_helper(VulkanFunctions* functions, VkInstance inst, VkSurfaceKHR& surface, const char* load_func_name, + VkStructureType stype) { CreationFunc pfn_CreateSurface = functions->load(inst, load_func_name); if (!pfn_CreateSurface) return VK_ERROR_EXTENSION_NOT_PRESENT; - CreateInfo surf_create_info{}; + CreateInfo surf_create_info{stype}; return pfn_CreateSurface(inst, &surf_create_info, nullptr, &surface); } VkResult create_surface(VulkanFunctions* functions, VkInstance inst, VkSurfaceKHR& surface, [[maybe_unused]] const char* api_selection) { #if defined(VK_USE_PLATFORM_ANDROID_KHR) - return create_surface_helper(functions, inst, surface, - "vkCreateAndroidSurfaceKHR"); + return create_surface_helper( + functions, inst, surface, "vkCreateAndroidSurfaceKHR", VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR); #elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) - return create_surface_helper(functions, inst, surface, - "vkCreateDirectFBSurfaceEXT"); + return create_surface_helper( + functions, inst, surface, "vkCreateDirectFBSurfaceEXT", VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT); #elif defined(VK_USE_PLATFORM_FUCHSIA) return create_surface_helper( - functions, inst, surface, "vkCreateImagePipeSurfaceFUCHSIA"); + functions, inst, surface, "vkCreateImagePipeSurfaceFUCHSIA", VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA); #elif defined(VK_USE_PLATFORM_GGP) return create_surface_helper( - functions, inst, surface, "vkCreateStreamDescriptorSurfaceGGP"); + functions, inst, surface, "vkCreateStreamDescriptorSurfaceGGP", + VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP); #elif defined(VK_USE_PLATFORM_IOS_MVK) - return create_surface_helper(functions, inst, surface, - "vkCreateIOSSurfaceMVK"); + return create_surface_helper( + functions, inst, surface, "vkCreateIOSSurfaceMVK", VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK); #elif defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT) #if defined(VK_USE_PLATFORM_MACOS_MVK) if (api_selection != nullptr && string_eq(api_selection, "VK_USE_PLATFORM_MACOS_MVK")) - return create_surface_helper(functions, inst, surface, - "vkCreateMacOSSurfaceMVK"); + return create_surface_helper( + functions, inst, surface, "vkCreateMacOSSurfaceMVK", VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK); #endif #if defined(VK_USE_PLATFORM_METAL_EXT) if (api_selection == nullptr || (api_selection != nullptr && string_eq(api_selection, "VK_USE_PLATFORM_METAL_EXT"))) - return create_surface_helper(functions, inst, surface, - "vkCreateMetalSurfaceEXT"); + return create_surface_helper( + functions, inst, surface, "vkCreateMetalSurfaceEXT", VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT); #endif return VK_ERROR_NOT_PERMITTED_KHR; #elif defined(VK_USE_PLATFORM_SCREEN_QNX) - return create_surface_helper(functions, inst, surface, - "vkCreateScreenSurfaceQNX"); + return create_surface_helper( + functions, inst, surface, "vkCreateScreenSurfaceQNX", VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX); #elif defined(VK_USE_PLATFORM_VI_NN) - return create_surface_helper(functions, inst, surface, "vkCreateViSurfaceNN"); + return create_surface_helper(functions, inst, surface, "vkCreateViSurfaceNN", + VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN); #elif defined(VK_USE_PLATFORM_WIN32_KHR) - return create_surface_helper(functions, inst, surface, - "vkCreateWin32SurfaceKHR"); + return create_surface_helper( + functions, inst, surface, "vkCreateWin32SurfaceKHR", VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR); #elif defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WAYLAND_KHR) #if defined(VK_USE_PLATFORM_XLIB_KHR) if (string_eq(api_selection, "VK_USE_PLATFORM_XLIB_KHR")) - return create_surface_helper(functions, inst, surface, - "vkCreateXlibSurfaceKHR"); + return create_surface_helper( + functions, inst, surface, "vkCreateXlibSurfaceKHR", VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR); #endif #if defined(VK_USE_PLATFORM_WAYLAND_KHR) if (string_eq(api_selection, "VK_USE_PLATFORM_WAYLAND_KHR")) - return create_surface_helper(functions, inst, surface, - "vkCreateWaylandSurfaceKHR"); + return create_surface_helper( + functions, inst, surface, "vkCreateWaylandSurfaceKHR", VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR); #endif #if defined(VK_USE_PLATFORM_XCB_KHR) if (api_selection == nullptr || string_eq(api_selection, "VK_USE_PLATFORM_XCB_KHR")) - return create_surface_helper(functions, inst, surface, - "vkCreateXcbSurfaceKHR"); + return create_surface_helper( + functions, inst, surface, "vkCreateXcbSurfaceKHR", VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR); #endif return VK_ERROR_NOT_PERMITTED_KHR; #else return create_surface_helper( - functions, inst, surface, "vkCreateDisplayPlaneSurfaceKHR"); + functions, inst, surface, "vkCreateDisplayPlaneSurfaceKHR", VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR); #endif } VkResult create_surface(InstWrapper& inst, VkSurfaceKHR& surface, const char* api_selection) {