diff --git a/loader/extension_manual.c b/loader/extension_manual.c index de55a48fc..6b917fcd0 100644 --- a/loader/extension_manual.c +++ b/loader/extension_manual.c @@ -274,16 +274,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2E "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSurfacePresentModes2EXT"); abort(); } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->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]) { - 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); + 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); + } } return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, pSurfaceInfo, pPresentModeCount, pPresentModes); @@ -321,16 +323,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT( "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]"); abort(); /* Intentionally fail so user can correct issue. */ } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->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]) { - 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); + 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); + } } return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes); } diff --git a/loader/loader.rc b/loader/loader.rc index 04b283955..79ff27871 100644 --- a/loader/loader.rc +++ b/loader/loader.rc @@ -1,7 +1,7 @@ // -// Copyright (c) 2014-2024 The Khronos Group Inc. -// Copyright (c) 2014-2024 Valve Corporation -// Copyright (c) 2014-2024 LunarG, Inc. +// Copyright (c) 2014-2025 The Khronos Group Inc. +// Copyright (c) 2014-2025 Valve Corporation +// Copyright (c) 2014-2025 LunarG, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ #define VER_FILE_VERSION 1, 4, 304, 0 #define VER_FILE_DESCRIPTION_STR "1.4.304.Dev Build" #define VER_FILE_VERSION_STR "Vulkan Loader - Dev Build" -#define VER_COPYRIGHT_STR "Copyright (C) 2015-2024" +#define VER_COPYRIGHT_STR "Copyright (C) 2015-2025" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILE_VERSION diff --git a/loader/wsi.c b/loader/wsi.c index aae47b7ec..f30bcfa10 100644 --- a/loader/wsi.c +++ b/loader/wsi.c @@ -366,15 +366,16 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkP 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.GetPhysicalDeviceSurfaceFormatsKHR( - phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index], - pSurfaceFormatCount, pSurfaceFormats); + 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); + } } - return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount, pSurfaceFormats); } @@ -424,16 +425,17 @@ 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; - 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.GetPhysicalDeviceSurfacePresentModesKHR( - phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index], pPresentModeCount, - pPresentModes); + 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); + } } - return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(phys_dev_term->phys_dev, surface, pPresentModeCount, pPresentModes); } @@ -2497,7 +2499,10 @@ 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 = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface; + 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, @@ -2522,7 +2527,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K VkResult res = VK_SUCCESS; // Pass the call to the driver, possibly unwrapping the ICD surface - if (NULL != icd_term->surface_list.list && + 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; @@ -2549,8 +2554,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K icd_term->scanned_icd->lib_name); // Write to the VkSurfaceCapabilities2KHR struct - VkSurfaceKHR surface = pSurfaceInfo->surface; - if (NULL != icd_term->surface_list.list && + 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]; @@ -2600,11 +2605,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk return VK_SUCCESS; } - VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface); + VkIcdSurface *icd_surface = NULL; + if (VK_NULL_HANDLE != pSurfaceInfo->surface) { + icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface); + } if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) { // Pass the call to the driver, possibly unwrapping the ICD surface - if (NULL != icd_term->surface_list.list && + 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; @@ -2628,7 +2636,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk } VkSurfaceKHR surface = pSurfaceInfo->surface; - if (NULL != icd_term->surface_list.list && + 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]; diff --git a/scripts/loader_extension_generator.py b/scripts/loader_extension_generator.py index 5913c0d4c..2b77ba436 100644 --- a/scripts/loader_extension_generator.py +++ b/scripts/loader_extension_generator.py @@ -1277,8 +1277,11 @@ def CreateTrampTermFuncs(self): funcs += ' }\n' if has_surface == 1: - funcs += f' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)({surface_var_name});\n' - funcs += ' if (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 += ' 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' # 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: diff --git a/tests/framework/icd/test_icd.cpp b/tests/framework/icd/test_icd.cpp index f42012cdf..36504eb20 100644 --- a/tests/framework/icd/test_icd.cpp +++ b/tests/framework/icd/test_icd.cpp @@ -838,6 +838,11 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysi assert(false && "Surface not found during GetPhysicalDeviceSurfaceFormatsKHR query!"); return VK_ERROR_UNKNOWN; } + } else { + if (!IsInstanceExtensionEnabled(VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME)) { + assert(false && "Surface is NULL but VK_GOOGLE_surfaceless_query was not enabled!"); + return VK_ERROR_UNKNOWN; + } } FillCountPtr(icd.GetPhysDevice(physicalDevice).surface_formats, pSurfaceFormatCount, pSurfaceFormats); return VK_SUCCESS; @@ -852,11 +857,39 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfacePresentModesKHR(Vk assert(false && "Surface not found during GetPhysicalDeviceSurfacePresentModesKHR query!"); return VK_ERROR_UNKNOWN; } + } else { + if (!IsInstanceExtensionEnabled(VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME)) { + assert(false && "Surface is NULL but VK_GOOGLE_surfaceless_query was not enabled!"); + return VK_ERROR_UNKNOWN; + } } FillCountPtr(icd.GetPhysDevice(physicalDevice).surface_present_modes, pPresentModeCount, pPresentModes); return VK_SUCCESS; } +#if defined(WIN32) +VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfacePresentModes2EXT(VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, + uint32_t* pPresentModeCount, + VkPresentModeKHR* pPresentModes) { + if (pSurfaceInfo->surface != VK_NULL_HANDLE) { + uint64_t fake_surf_handle = (uint64_t)(pSurfaceInfo->surface); + auto found_iter = std::find(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle); + if (found_iter == icd.surface_handles.end()) { + assert(false && "Surface not found during GetPhysicalDeviceSurfacePresentModesKHR query!"); + return VK_ERROR_UNKNOWN; + } + } else { + if (!IsInstanceExtensionEnabled(VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME)) { + assert(false && "Surface is NULL but VK_GOOGLE_surfaceless_query was not enabled!"); + return VK_ERROR_UNKNOWN; + } + } + FillCountPtr(icd.GetPhysDevice(physicalDevice).surface_present_modes, pPresentModeCount, pPresentModes); + return VK_SUCCESS; +} +#endif + // VK_KHR_display VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, @@ -1310,6 +1343,12 @@ PFN_vkVoidFunction get_physical_device_func_wsi([[maybe_unused]] VkInstance inst if (string_eq(pName, "vkGetPhysicalDeviceSurfacePresentModesKHR")) return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfacePresentModesKHR); } +#if defined(WIN32) + if (IsInstanceExtensionEnabled("VK_EXT_full_screen_exclusive")) { + if (string_eq(pName, "vkGetPhysicalDeviceSurfacePresentModes2EXT")) + return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfacePresentModes2EXT); + } +#endif if (IsInstanceExtensionEnabled("VK_KHR_get_surface_capabilities2")) { if (string_eq(pName, "vkGetPhysicalDeviceSurfaceCapabilities2KHR")) return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfaceCapabilities2KHR); diff --git a/tests/framework/test_environment.cpp b/tests/framework/test_environment.cpp index efa4706fe..be8d63233 100644 --- a/tests/framework/test_environment.cpp +++ b/tests/framework/test_environment.cpp @@ -140,7 +140,6 @@ void init_vulkan_functions(VulkanFunctions& funcs) { funcs.vkCreateWin32SurfaceKHR = GPA(vkCreateWin32SurfaceKHR); funcs.vkGetPhysicalDeviceWin32PresentationSupportKHR = GPA(vkGetPhysicalDeviceWin32PresentationSupportKHR); #endif // VK_USE_PLATFORM_WIN32_KHR - funcs.vkDestroyDevice = GPA(vkDestroyDevice); funcs.vkGetDeviceQueue = GPA(vkGetDeviceQueue); #undef GPA diff --git a/tests/loader_wsi_tests.cpp b/tests/loader_wsi_tests.cpp index a33bee1a9..82a274352 100644 --- a/tests/loader_wsi_tests.cpp +++ b/tests/loader_wsi_tests.cpp @@ -758,6 +758,68 @@ TEST(WsiTests, WaylandGetPhysicalDeviceSurfaceSupportKHR) { } #endif +TEST(WsiTests, GoogleSurfaceslessQuery) { + std::vector present_modes{VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, + VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR}; + VkSurfaceFormatKHR surface_format = {VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR}; + FrameworkEnvironment env{}; + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) + .setup_WSI() + .add_instance_extension("VK_GOOGLE_surfaceless_query") + .add_instance_extension("VK_KHR_get_surface_capabilities2") + .add_physical_device(PhysicalDevice{} + .add_extension("VK_KHR_swapchain") +#if defined(WIN32) + .add_extension("VK_EXT_full_screen_exclusive") +#endif + .add_surface_format(surface_format) + .add_surface_present_modes(present_modes) + .finish()); + + InstWrapper inst{env.vulkan_functions}; + inst.create_info.add_extension("VK_KHR_surface"); + inst.create_info.add_extension("VK_GOOGLE_surfaceless_query"); + ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); + + VkPhysicalDevice physical_device = inst.GetPhysDev(); + + uint32_t present_mode_count = 4; + std::vector queried_present_modes{present_mode_count}; + inst->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, VK_NULL_HANDLE, &present_mode_count, + queried_present_modes.data()); + ASSERT_EQ(present_modes, queried_present_modes); + + uint32_t surface_format_count = 1; + std::vector queried_surface_formats{surface_format_count}; + inst->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, VK_NULL_HANDLE, &surface_format_count, + queried_surface_formats.data()); + ASSERT_EQ(std::vector{surface_format}, queried_surface_formats); + + uint32_t surface_format2_count = 1; + std::vector queried_surface_formats2{surface_format2_count}; + VkPhysicalDeviceSurfaceInfo2KHR surface_info{}; + surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; + surface_info.surface = VK_NULL_HANDLE; + inst->vkGetPhysicalDeviceSurfaceFormats2KHR(physical_device, &surface_info, &surface_format_count, + queried_surface_formats2.data()); + ASSERT_EQ(std::vector{surface_format}, queried_surface_formats2); + + VkSurfaceCapabilities2KHR surface_caps2{}; + surface_caps2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR; + + ASSERT_EQ(VK_SUCCESS, + env.vulkan_functions.vkGetPhysicalDeviceSurfaceCapabilities2KHR(physical_device, &surface_info, &surface_caps2)); + +#if defined(WIN32) + PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT pfn_vkGetPhysicalDeviceSurfacePresentModes2EXT = + inst.load("vkGetPhysicalDeviceSurfacePresentModes2EXT"); + ASSERT_EQ(VK_SUCCESS, pfn_vkGetPhysicalDeviceSurfacePresentModes2EXT(physical_device, &surface_info, &present_mode_count, + queried_present_modes.data())); + ASSERT_EQ(present_modes, queried_present_modes); + +#endif +} + TEST(WsiTests, ForgetEnableSurfaceExtensions) { FrameworkEnvironment env{}; env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))