Skip to content

Commit

Permalink
Support VK_GOOGLE_surfaceless_query
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
charles-lunarg committed Jan 15, 2025
1 parent f51ed4e commit 360a77b
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 49 deletions.
44 changes: 24 additions & 20 deletions loader/extension_manual.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
8 changes: 4 additions & 4 deletions loader/loader.rc
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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
Expand Down
54 changes: 31 additions & 23 deletions loader/wsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand All @@ -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];
Expand Down Expand Up @@ -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;
Expand All @@ -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];
Expand Down
7 changes: 5 additions & 2 deletions scripts/loader_extension_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
10 changes: 10 additions & 0 deletions tests/framework/icd/test_icd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -852,6 +857,11 @@ 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;
Expand Down
59 changes: 59 additions & 0 deletions tests/loader_wsi_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,65 @@ TEST(WsiTests, WaylandGetPhysicalDeviceSurfaceSupportKHR) {
}
#endif

TEST(WsiTests, GoogleSurfaceslessQuery) {
std::vector<VkPresentModeKHR> 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_physical_device(PhysicalDevice{}
.add_extension("VK_KHR_swapchain")
.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<VkPresentModeKHR> 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<VkSurfaceFormatKHR> queried_surface_formats{surface_format_count};
inst->vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, VK_NULL_HANDLE, &surface_format_count,
queried_surface_formats.data());
ASSERT_EQ(std::vector<VkSurfaceFormatKHR>{surface_format}, queried_surface_formats);

uint32_t surface_format2_count = 1;
std::vector<VkSurfaceFormat2KHR> 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<VkSurfaceFormatKHR>{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_GetPhysicalDeviceSurfacePresentModes2EXT =
inst.load("vkGetPhysicalDeviceSurfacePresentModes2EXT");
ASSERT_EQ(VK_SUCCESS, pfn_GetPhysicalDeviceSurfacePresentModes2EXT(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))
Expand Down

0 comments on commit 360a77b

Please sign in to comment.