Skip to content

Commit d8f3e89

Browse files
Support VK_GOOGLE_surfaceless_query
Requires bypassing the logic which dereferences VkSurfaceKHR in vkGetPhysicalDeviceSurfaceFormatsKHR and vkGetPhysicalDeviceSurfacePresentModesKHR. This should have been done closer to the release of VK_GOOGLE_surfaceless_query, but because that extension was meant for Android, which isn't supported by this loader, it was not done. That said, SwiftShader can support the extension, so support is now being added in this commit.
1 parent f51ed4e commit d8f3e89

File tree

6 files changed

+133
-49
lines changed

6 files changed

+133
-49
lines changed

loader/extension_manual.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -274,16 +274,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2E
274274
"ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSurfacePresentModes2EXT");
275275
abort();
276276
}
277-
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
278-
if (NULL != icd_term->surface_list.list &&
279-
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
280-
icd_term->surface_list.list[icd_surface->surface_index]) {
281-
VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
282-
surface_info_copy.sType = pSurfaceInfo->sType;
283-
surface_info_copy.pNext = pSurfaceInfo->pNext;
284-
surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
285-
return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy,
286-
pPresentModeCount, pPresentModes);
277+
if (VK_NULL_HANDLE != pSurfaceInfo->surface) {
278+
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
279+
if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
280+
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
281+
icd_term->surface_list.list[icd_surface->surface_index]) {
282+
VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
283+
surface_info_copy.sType = pSurfaceInfo->sType;
284+
surface_info_copy.pNext = pSurfaceInfo->pNext;
285+
surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
286+
return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy,
287+
pPresentModeCount, pPresentModes);
288+
}
287289
}
288290
return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, pSurfaceInfo, pPresentModeCount,
289291
pPresentModes);
@@ -321,16 +323,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(
321323
"[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]");
322324
abort(); /* Intentionally fail so user can correct issue. */
323325
}
324-
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
325-
if (NULL != icd_term->surface_list.list &&
326-
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
327-
icd_term->surface_list.list[icd_surface->surface_index]) {
328-
VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
329-
surface_info_copy.sType = pSurfaceInfo->sType;
330-
surface_info_copy.pNext = pSurfaceInfo->pNext;
331-
surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
332-
return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy,
333-
pModes);
326+
if (VK_NULL_HANDLE != pSurfaceInfo->surface) {
327+
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
328+
if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
329+
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
330+
icd_term->surface_list.list[icd_surface->surface_index]) {
331+
VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
332+
surface_info_copy.sType = pSurfaceInfo->sType;
333+
surface_info_copy.pNext = pSurfaceInfo->pNext;
334+
surface_info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
335+
return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(
336+
device, &surface_info_copy, pModes);
337+
}
334338
}
335339
return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
336340
}

loader/loader.rc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
2-
// Copyright (c) 2014-2024 The Khronos Group Inc.
3-
// Copyright (c) 2014-2024 Valve Corporation
4-
// Copyright (c) 2014-2024 LunarG, Inc.
2+
// Copyright (c) 2014-2025 The Khronos Group Inc.
3+
// Copyright (c) 2014-2025 Valve Corporation
4+
// Copyright (c) 2014-2025 LunarG, Inc.
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
2525
#define VER_FILE_VERSION 1, 4, 304, 0
2626
#define VER_FILE_DESCRIPTION_STR "1.4.304.Dev Build"
2727
#define VER_FILE_VERSION_STR "Vulkan Loader - Dev Build"
28-
#define VER_COPYRIGHT_STR "Copyright (C) 2015-2024"
28+
#define VER_COPYRIGHT_STR "Copyright (C) 2015-2025"
2929

3030
VS_VERSION_INFO VERSIONINFO
3131
FILEVERSION VER_FILE_VERSION

loader/wsi.c

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -366,15 +366,16 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkP
366366
return VK_SUCCESS;
367367
}
368368

369-
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
370-
if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
371-
phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
372-
phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
373-
return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(
374-
phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
375-
pSurfaceFormatCount, pSurfaceFormats);
369+
if (VK_NULL_HANDLE != surface) {
370+
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
371+
if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
372+
phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
373+
phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
374+
return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(
375+
phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
376+
pSurfaceFormatCount, pSurfaceFormats);
377+
}
376378
}
377-
378379
return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount,
379380
pSurfaceFormats);
380381
}
@@ -424,16 +425,17 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKH
424425
"ICD for selected physical device does not export vkGetPhysicalDeviceSurfacePresentModesKHR!");
425426
return VK_SUCCESS;
426427
}
428+
if (VK_NULL_HANDLE != surface) {
429+
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
427430

428-
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
429-
if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
430-
phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
431-
phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
432-
return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(
433-
phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index], pPresentModeCount,
434-
pPresentModes);
431+
if (icd_surface != NULL && NULL != phys_dev_term->this_icd_term->surface_list.list &&
432+
phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
433+
phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
434+
return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(
435+
phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
436+
pPresentModeCount, pPresentModes);
437+
}
435438
}
436-
437439
return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(phys_dev_term->phys_dev, surface, pPresentModeCount,
438440
pPresentModes);
439441
}
@@ -2497,7 +2499,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K
24972499
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
24982500
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
24992501
struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
2500-
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
2502+
VkIcdSurface *icd_surface = NULL;
2503+
if (pSurfaceInfo->surface) {
2504+
icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
2505+
}
25012506

25022507
if (!loader_inst->wsi_surface_enabled) {
25032508
loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
@@ -2522,7 +2527,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K
25222527
VkResult res = VK_SUCCESS;
25232528

25242529
// Pass the call to the driver, possibly unwrapping the ICD surface
2525-
if (NULL != icd_term->surface_list.list &&
2530+
if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
25262531
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
25272532
icd_term->surface_list.list[icd_surface->surface_index]) {
25282533
VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
@@ -2549,8 +2554,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K
25492554
icd_term->scanned_icd->lib_name);
25502555

25512556
// Write to the VkSurfaceCapabilities2KHR struct
2552-
VkSurfaceKHR surface = pSurfaceInfo->surface;
2553-
if (NULL != icd_term->surface_list.list &&
2557+
VkSurfaceKHR surface = VK_NULL_HANDLE;
2558+
if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
25542559
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
25552560
icd_term->surface_list.list[icd_surface->surface_index]) {
25562561
surface = icd_term->surface_list.list[icd_surface->surface_index];
@@ -2600,11 +2605,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk
26002605
return VK_SUCCESS;
26012606
}
26022607

2603-
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
2608+
VkIcdSurface *icd_surface = NULL;
2609+
if (VK_NULL_HANDLE != pSurfaceInfo->surface) {
2610+
icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
2611+
}
26042612

26052613
if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) {
26062614
// Pass the call to the driver, possibly unwrapping the ICD surface
2607-
if (NULL != icd_term->surface_list.list &&
2615+
if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
26082616
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
26092617
icd_term->surface_list.list[icd_surface->surface_index]) {
26102618
VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
@@ -2628,7 +2636,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(Vk
26282636
}
26292637

26302638
VkSurfaceKHR surface = pSurfaceInfo->surface;
2631-
if (NULL != icd_term->surface_list.list &&
2639+
if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
26322640
icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
26332641
icd_term->surface_list.list[icd_surface->surface_index]) {
26342642
surface = icd_term->surface_list.list[icd_surface->surface_index];

scripts/loader_extension_generator.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,8 +1277,11 @@ def CreateTrampTermFuncs(self):
12771277
funcs += ' }\n'
12781278

12791279
if has_surface == 1:
1280-
funcs += f' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)({surface_var_name});\n'
1281-
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'
1280+
funcs += ' VkIcdSurface *icd_surface = NULL;\n'
1281+
funcs += f' if (NULL != {surface_var_name}) {{\n'
1282+
funcs += f' icd_surface = (VkIcdSurface *)(uintptr_t)({surface_var_name});\n'
1283+
funcs += ' }\n'
1284+
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'
12821285

12831286
# If there's a structure with a surface, we need to update its internals with the correct surface for the ICD
12841287
if update_structure_surface == 1:

tests/framework/icd/test_icd.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,11 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysi
838838
assert(false && "Surface not found during GetPhysicalDeviceSurfaceFormatsKHR query!");
839839
return VK_ERROR_UNKNOWN;
840840
}
841+
} else {
842+
if (!IsInstanceExtensionEnabled(VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME)) {
843+
assert(false && "Surface is NULL but VK_GOOGLE_surfaceless_query was not enabled!");
844+
return VK_ERROR_UNKNOWN;
845+
}
841846
}
842847
FillCountPtr(icd.GetPhysDevice(physicalDevice).surface_formats, pSurfaceFormatCount, pSurfaceFormats);
843848
return VK_SUCCESS;
@@ -852,6 +857,11 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfacePresentModesKHR(Vk
852857
assert(false && "Surface not found during GetPhysicalDeviceSurfacePresentModesKHR query!");
853858
return VK_ERROR_UNKNOWN;
854859
}
860+
} else {
861+
if (!IsInstanceExtensionEnabled(VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME)) {
862+
assert(false && "Surface is NULL but VK_GOOGLE_surfaceless_query was not enabled!");
863+
return VK_ERROR_UNKNOWN;
864+
}
855865
}
856866
FillCountPtr(icd.GetPhysDevice(physicalDevice).surface_present_modes, pPresentModeCount, pPresentModes);
857867
return VK_SUCCESS;

tests/loader_wsi_tests.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,65 @@ TEST(WsiTests, WaylandGetPhysicalDeviceSurfaceSupportKHR) {
758758
}
759759
#endif
760760

761+
TEST(WsiTests, GoogleSurfaceslessQuery) {
762+
std::vector<VkPresentModeKHR> present_modes{VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR,
763+
VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR};
764+
VkSurfaceFormatKHR surface_format = {VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR};
765+
FrameworkEnvironment env{};
766+
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))
767+
.setup_WSI()
768+
.add_instance_extension("VK_GOOGLE_surfaceless_query")
769+
.add_physical_device(PhysicalDevice{}
770+
.add_extension("VK_KHR_swapchain")
771+
.add_surface_format(surface_format)
772+
.add_surface_present_modes(present_modes)
773+
.finish());
774+
775+
InstWrapper inst{env.vulkan_functions};
776+
inst.create_info.add_extension("VK_KHR_surface");
777+
inst.create_info.add_extension("VK_GOOGLE_surfaceless_query");
778+
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
779+
780+
VkPhysicalDevice physical_device = inst.GetPhysDev();
781+
782+
uint32_t present_mode_count = 4;
783+
std::vector<VkPresentModeKHR> queried_present_modes{present_mode_count};
784+
inst->vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, VK_NULL_HANDLE, &present_mode_count,
785+
queried_present_modes.data());
786+
ASSERT_EQ(present_modes, queried_present_modes);
787+
788+
uint32_t surface_format_count = 1;
789+
std::vector<VkSurfaceFormatKHR> queried_surface_formats{surface_format_count};
790+
inst->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, VK_NULL_HANDLE, &surface_format_count,
791+
queried_surface_formats.data());
792+
ASSERT_EQ(std::vector<VkSurfaceFormatKHR>{surface_format}, queried_surface_formats);
793+
794+
uint32_t surface_format2_count = 1;
795+
std::vector<VkSurfaceFormat2KHR> queried_surface_formats2{surface_format2_count};
796+
VkPhysicalDeviceSurfaceInfo2KHR surface_info{};
797+
surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
798+
surface_info.surface = VK_NULL_HANDLE;
799+
inst->vkGetPhysicalDeviceSurfaceFormats2KHR(physical_device, &surface_info, &surface_format_count,
800+
queried_surface_formats2.data());
801+
ASSERT_EQ(std::vector<VkSurfaceFormatKHR>{surface_format}, queried_surface_formats2);
802+
803+
VkSurfaceCapabilities2KHR surface_caps2{};
804+
surface_caps2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
805+
806+
ASSERT_EQ(VK_SUCCESS,
807+
env.vulkan_functions.vkGetPhysicalDeviceSurfaceCapabilities2KHR(physical_device, &surface_info, &surface_caps2));
808+
809+
#if defined(WIN32)
810+
811+
PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT pfn_GetPhysicalDeviceSurfacePresentModes2EXT =
812+
instance.load("vkGetPhysicalDeviceSurfacePresentModes2EXT");
813+
ASSERT_EQ(VK_SUCCESS, pfn_GetPhysicalDeviceSurfacePresentModes2EXT(physical_device, &surface_info, &present_mode_count,
814+
queried_present_modes.data()));
815+
ASSERT_EQ(present_modes, queried_present_modes);
816+
817+
#endif
818+
}
819+
761820
TEST(WsiTests, ForgetEnableSurfaceExtensions) {
762821
FrameworkEnvironment env{};
763822
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2))

0 commit comments

Comments
 (0)