• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015-2022 The Khronos Group Inc.
3  * Copyright (c) 2015-2022 Valve Corporation
4  * Copyright (c) 2015-2022 LunarG, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Ian Elliott <ian@lunarg.com>
19  * Author: Jon Ashburn <jon@lunarg.com>
20  * Author: Ian Elliott <ianelliott@google.com>
21  * Author: Mark Lobodzinski <mark@lunarg.com>
22  * Author: Lenny Komow <lenny@lunarg.com>
23  * Author: Charles Giessen <charles@lunarg.com>
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 #include <vulkan/vk_icd.h>
30 
31 #include "allocation.h"
32 #include "loader.h"
33 #include "log.h"
34 #include "stack_allocation.h"
35 #include "vk_loader_platform.h"
36 #include "wsi.h"
37 
38 // The first ICD/Loader interface that support querying the SurfaceKHR from
39 // the ICDs.
40 #define ICD_VER_SUPPORTS_ICD_SURFACE_KHR 3
41 
wsi_create_instance(struct loader_instance * loader_inst,const VkInstanceCreateInfo * pCreateInfo)42 void wsi_create_instance(struct loader_instance *loader_inst, const VkInstanceCreateInfo *pCreateInfo) {
43     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
44         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
45             loader_inst->wsi_surface_enabled = true;
46             continue;
47         }
48 #if defined(VK_USE_PLATFORM_WIN32_KHR)
49         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
50             loader_inst->wsi_win32_surface_enabled = true;
51             continue;
52         }
53 #endif  // VK_USE_PLATFORM_WIN32_KHR
54 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
55         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
56             loader_inst->wsi_wayland_surface_enabled = true;
57             continue;
58         }
59 #endif  // VK_USE_PLATFORM_WAYLAND_KHR
60 #if defined(VK_USE_PLATFORM_XCB_KHR)
61         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
62             loader_inst->wsi_xcb_surface_enabled = true;
63             continue;
64         }
65 #endif  // VK_USE_PLATFORM_XCB_KHR
66 #if defined(VK_USE_PLATFORM_XLIB_KHR)
67         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
68             loader_inst->wsi_xlib_surface_enabled = true;
69             continue;
70         }
71 #endif  // VK_USE_PLATFORM_XLIB_KHR
72 #if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
73         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME) == 0) {
74             loader_inst->wsi_directfb_surface_enabled = true;
75             continue;
76         }
77 #endif  // VK_USE_PLATFORM_DIRECTFB_EXT
78 #if defined(VK_USE_PLATFORM_ANDROID_KHR)
79         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
80             loader_inst->wsi_android_surface_enabled = true;
81             continue;
82         }
83 #endif  // VK_USE_PLATFORM_ANDROID_KHR
84 #if defined(VK_USE_PLATFORM_OHOS)
85         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_OHOS_SURFACE_EXTENSION_NAME) == 0) {
86             loader_inst->wsi_ohos_surface_enabled = true;
87             continue;
88         }
89 #endif  // VK_USE_PLATFORM_OHOS
90 #if defined(VK_USE_PLATFORM_MACOS_MVK)
91         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_MVK_MACOS_SURFACE_EXTENSION_NAME) == 0) {
92             loader_inst->wsi_macos_surface_enabled = true;
93             continue;
94         }
95 #endif  // VK_USE_PLATFORM_MACOS_MVK
96 #if defined(VK_USE_PLATFORM_IOS_MVK)
97         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_MVK_IOS_SURFACE_EXTENSION_NAME) == 0) {
98             loader_inst->wsi_ios_surface_enabled = true;
99             continue;
100         }
101 #endif  // VK_USE_PLATFORM_IOS_MVK
102 #if defined(VK_USE_PLATFORM_GGP)
103         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME) == 0) {
104             loader_inst->wsi_ggp_surface_enabled = true;
105             continue;
106         }
107 #endif  // VK_USE_PLATFORM_GGP
108 #if defined(VK_USE_PLATFORM_FUCHSIA)
109         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME) == 0) {
110             loader_inst->wsi_imagepipe_surface_enabled = true;
111             continue;
112         }
113 #endif  // VK_USE_PLATFORM_FUCHSIA
114         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME) == 0) {
115             loader_inst->wsi_headless_surface_enabled = true;
116             continue;
117         }
118 #if defined(VK_USE_PLATFORM_METAL_EXT)
119         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_METAL_SURFACE_EXTENSION_NAME) == 0) {
120             loader_inst->wsi_metal_surface_enabled = true;
121             continue;
122         }
123 #endif
124 #if defined(VK_USE_PLATFORM_SCREEN_QNX)
125         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_QNX_SCREEN_SURFACE_EXTENSION_NAME) == 0) {
126             loader_inst->wsi_screen_surface_enabled = true;
127             continue;
128         }
129 #endif  // VK_USE_PLATFORM_SCREEN_QNX
130 #if defined(VK_USE_PLATFORM_VI_NN)
131         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NN_VI_SURFACE_EXTENSION_NAME) == 0) {
132             loader_inst->wsi_vi_surface_enabled = true;
133             continue;
134         }
135 #endif  // VK_USE_PLATFORM_VI_NN
136         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) {
137             loader_inst->wsi_display_enabled = true;
138             continue;
139         }
140         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME) == 0) {
141             loader_inst->wsi_display_props2_enabled = true;
142             continue;
143         }
144     }
145 }
146 
147 // Linux WSI surface extensions are not always compiled into the loader. (Assume
148 // for Windows the KHR_win32_surface is always compiled into loader). A given
149 // Linux build environment might not have the headers required for building one
150 // of the three extensions  (Xlib, Xcb, Wayland).  Thus, need to check if
151 // the built loader actually supports the particular Linux surface extension.
152 // If not supported by the built loader it will not be included in the list of
153 // enumerated instance extensions.  This solves the issue where an ICD or layer
154 // advertises support for a given Linux surface extension but the loader was not
155 // built to support the extension.
wsi_unsupported_instance_extension(const VkExtensionProperties * ext_prop)156 bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop) {
157 #if !defined(VK_USE_PLATFORM_WAYLAND_KHR)
158     if (!strcmp(ext_prop->extensionName, "VK_KHR_wayland_surface")) return true;
159 #endif  // VK_USE_PLATFORM_WAYLAND_KHR
160 #if !defined(VK_USE_PLATFORM_XCB_KHR)
161     if (!strcmp(ext_prop->extensionName, "VK_KHR_xcb_surface")) return true;
162 #endif  // VK_USE_PLATFORM_XCB_KHR
163 #if !defined(VK_USE_PLATFORM_XLIB_KHR)
164     if (!strcmp(ext_prop->extensionName, "VK_KHR_xlib_surface")) return true;
165 #endif  // VK_USE_PLATFORM_XLIB_KHR
166 #if !defined(VK_USE_PLATFORM_DIRECTFB_EXT)
167     if (!strcmp(ext_prop->extensionName, "VK_EXT_directfb_surface")) return true;
168 #endif  // VK_USE_PLATFORM_DIRECTFB_EXT
169 #if !defined(VK_USE_PLATFORM_SCREEN_QNX)
170     if (!strcmp(ext_prop->extensionName, "VK_QNX_screen_surface")) return true;
171 #endif  // VK_USE_PLATFORM_SCREEN_QNX
172 
173     return false;
174 }
175 
176 // Functions for the VK_KHR_surface extension:
177 
178 // This is the trampoline entrypoint for DestroySurfaceKHR
vkDestroySurfaceKHR(VkInstance instance,VkSurfaceKHR surface,const VkAllocationCallbacks * pAllocator)179 LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
180                                                              const VkAllocationCallbacks *pAllocator) {
181     struct loader_instance *loader_inst = loader_get_instance(instance);
182     if (NULL == loader_inst) {
183         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
184                    "vkDestroySurfaceKHR: Invalid instance [VUID-vkDestroySurfaceKHR-instance-parameter]");
185         abort(); /* Intentionally fail so user can correct issue. */
186     }
187     loader_inst->disp->layer_inst_disp.DestroySurfaceKHR(loader_inst->instance, surface, pAllocator);
188 }
189 
190 // This is the instance chain terminator function for DestroySurfaceKHR
terminator_DestroySurfaceKHR(VkInstance instance,VkSurfaceKHR surface,const VkAllocationCallbacks * pAllocator)191 VKAPI_ATTR void VKAPI_CALL terminator_DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
192                                                         const VkAllocationCallbacks *pAllocator) {
193     struct loader_instance *loader_inst = loader_get_instance(instance);
194 
195     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
196     if (NULL != icd_surface) {
197         for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
198             if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
199                 if (NULL != icd_term->dispatch.DestroySurfaceKHR && icd_term->surface_list.list[icd_surface->surface_index]) {
200                     icd_term->dispatch.DestroySurfaceKHR(icd_term->instance,
201                                                          icd_term->surface_list.list[icd_surface->surface_index], pAllocator);
202                     icd_term->surface_list.list[icd_surface->surface_index] = (VkSurfaceKHR)(uintptr_t)NULL;
203                 }
204             } else {
205                 // The real_icd_surface for any ICD not supporting the
206                 // proper interface version should be NULL.  If not, then
207                 // we have a problem.
208                 assert((VkSurfaceKHR)(uintptr_t)NULL == icd_term->surface_list.list[icd_surface->surface_index]);
209             }
210         }
211         loader_release_object_from_list(&loader_inst->surfaces_list, icd_surface->surface_index);
212         loader_instance_heap_free(loader_inst, (void *)(uintptr_t)surface);
213     }
214 }
215 
216 // This is the trampoline entrypoint for GetPhysicalDeviceSurfaceSupportKHR
vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,VkSurfaceKHR surface,VkBool32 * pSupported)217 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
218                                                                                   uint32_t queueFamilyIndex, VkSurfaceKHR surface,
219                                                                                   VkBool32 *pSupported) {
220     const VkLayerInstanceDispatchTable *disp;
221     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
222     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
223         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
224                    "vkGetPhysicalDeviceSurfaceSupportKHR: Invalid physicalDevice "
225                    "[VUID-vkGetPhysicalDeviceSurfaceSupportKHR-physicalDevice-parameter]");
226         abort(); /* Intentionally fail so user can correct issue. */
227     }
228     disp = loader_get_instance_layer_dispatch(physicalDevice);
229     return disp->GetPhysicalDeviceSurfaceSupportKHR(unwrapped_phys_dev, queueFamilyIndex, surface, pSupported);
230 }
231 
232 // This is the instance chain terminator function for
233 // GetPhysicalDeviceSurfaceSupportKHR
terminator_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,VkSurfaceKHR surface,VkBool32 * pSupported)234 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
235                                                                              uint32_t queueFamilyIndex, VkSurfaceKHR surface,
236                                                                              VkBool32 *pSupported) {
237     // First, check to ensure the appropriate extension was enabled:
238     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
239     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
240     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
241     if (!loader_inst->wsi_surface_enabled) {
242         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
243                    "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not executed!");
244         return VK_SUCCESS;
245     }
246 
247     if (NULL == pSupported) {
248         loader_log(loader_inst, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
249                    "NULL pointer passed into vkGetPhysicalDeviceSurfaceSupportKHR for pSupported!");
250         abort();
251     }
252     *pSupported = false;
253 
254     if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR) {
255         // set pSupported to false as this driver doesn't support WSI functionality
256         *pSupported = false;
257         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
258                    "ICD for selected physical device does not export vkGetPhysicalDeviceSurfaceSupportKHR!");
259         return VK_SUCCESS;
260     }
261 
262     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
263     if (NULL != icd_term->surface_list.list &&
264         icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
265         icd_term->surface_list.list[icd_surface->surface_index]) {
266         return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR(
267             phys_dev_term->phys_dev, queueFamilyIndex, icd_term->surface_list.list[icd_surface->surface_index], pSupported);
268     }
269 
270     return icd_term->dispatch.GetPhysicalDeviceSurfaceSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, surface, pSupported);
271 }
272 
273 // This is the trampoline entrypoint for GetPhysicalDeviceSurfaceCapabilitiesKHR
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)274 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
275     VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
276     const VkLayerInstanceDispatchTable *disp;
277     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
278     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
279         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
280                    "vkGetPhysicalDeviceSurfaceCapabilitiesKHR: Invalid physicalDevice "
281                    "[VUID-vkGetPhysicalDeviceSurfaceCapabilitiesKHR-physicalDevice-parameter]");
282         abort(); /* Intentionally fail so user can correct issue. */
283     }
284     disp = loader_get_instance_layer_dispatch(physicalDevice);
285     return disp->GetPhysicalDeviceSurfaceCapabilitiesKHR(unwrapped_phys_dev, surface, pSurfaceCapabilities);
286 }
287 
288 // This is the instance chain terminator function for
289 // GetPhysicalDeviceSurfaceCapabilitiesKHR
terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)290 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,
291                                                                                   VkSurfaceKHR surface,
292                                                                                   VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
293     // First, check to ensure the appropriate extension was enabled:
294     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
295     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
296     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
297     if (!loader_inst->wsi_surface_enabled) {
298         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
299                    "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed!");
300         return VK_SUCCESS;
301     }
302 
303     if (NULL == pSurfaceCapabilities) {
304         loader_log(loader_inst, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
305                    "NULL pointer passed into vkGetPhysicalDeviceSurfaceCapabilitiesKHR for pSurfaceCapabilities!");
306         abort();
307     }
308 
309     if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR) {
310         // Zero out the capabilities as this driver doesn't support WSI functionality
311         memset(pSurfaceCapabilities, 0, sizeof(VkSurfaceCapabilitiesKHR));
312         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
313                    "ICD for selected physical device does not export vkGetPhysicalDeviceSurfaceCapabilitiesKHR!");
314         return VK_SUCCESS;
315     }
316 
317     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
318     if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
319         phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
320         phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
321         return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(
322             phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
323             pSurfaceCapabilities);
324     }
325 
326     return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface, pSurfaceCapabilities);
327 }
328 
329 // This is the trampoline entrypoint for GetPhysicalDeviceSurfaceFormatsKHR
vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats)330 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
331                                                                                   VkSurfaceKHR surface,
332                                                                                   uint32_t *pSurfaceFormatCount,
333                                                                                   VkSurfaceFormatKHR *pSurfaceFormats) {
334     const VkLayerInstanceDispatchTable *disp;
335     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
336     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
337         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
338                    "vkGetPhysicalDeviceSurfaceFormatsKHR: Invalid physicalDevice "
339                    "[VUID-vkGetPhysicalDeviceSurfaceFormatsKHR-physicalDevice-parameter]");
340         abort(); /* Intentionally fail so user can correct issue. */
341     }
342     disp = loader_get_instance_layer_dispatch(physicalDevice);
343     return disp->GetPhysicalDeviceSurfaceFormatsKHR(unwrapped_phys_dev, surface, pSurfaceFormatCount, pSurfaceFormats);
344 }
345 
346 // This is the instance chain terminator function for
347 // GetPhysicalDeviceSurfaceFormatsKHR
terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats)348 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
349                                                                              uint32_t *pSurfaceFormatCount,
350                                                                              VkSurfaceFormatKHR *pSurfaceFormats) {
351     // First, check to ensure the appropriate extension was enabled:
352     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
353     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
354     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
355     if (!loader_inst->wsi_surface_enabled) {
356         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
357                    "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not executed!");
358         return VK_SUCCESS;
359     }
360 
361     if (NULL == pSurfaceFormatCount) {
362         loader_log(loader_inst, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
363                    "NULL pointer passed into vkGetPhysicalDeviceSurfaceFormatsKHR for pSurfaceFormatCount!");
364         abort();
365     }
366 
367     if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR) {
368         // Zero out the format count as this driver doesn't support WSI functionality
369         *pSurfaceFormatCount = 0;
370         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
371                    "ICD for selected physical device does not export vkGetPhysicalDeviceSurfaceFormatsKHR!");
372         return VK_SUCCESS;
373     }
374 
375     if (VK_NULL_HANDLE != surface) {
376         VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
377         if (NULL != phys_dev_term->this_icd_term->surface_list.list &&
378             phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
379             phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
380             return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(
381                 phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
382                 pSurfaceFormatCount, pSurfaceFormats);
383         }
384     }
385     return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount,
386                                                                  pSurfaceFormats);
387 }
388 
389 // This is the trampoline entrypoint for GetPhysicalDeviceSurfacePresentModesKHR
vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes)390 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
391                                                                                        VkSurfaceKHR surface,
392                                                                                        uint32_t *pPresentModeCount,
393                                                                                        VkPresentModeKHR *pPresentModes) {
394     const VkLayerInstanceDispatchTable *disp;
395     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
396     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
397         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
398                    "vkGetPhysicalDeviceSurfacePresentModesKHR: Invalid physicalDevice "
399                    "[VUID-vkGetPhysicalDeviceSurfacePresentModesKHR-physicalDevice-parameter]");
400         abort(); /* Intentionally fail so user can correct issue. */
401     }
402     disp = loader_get_instance_layer_dispatch(physicalDevice);
403     return disp->GetPhysicalDeviceSurfacePresentModesKHR(unwrapped_phys_dev, surface, pPresentModeCount, pPresentModes);
404 }
405 
406 // This is the instance chain terminator function for
407 // GetPhysicalDeviceSurfacePresentModesKHR
terminator_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes)408 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
409                                                                                   VkSurfaceKHR surface, uint32_t *pPresentModeCount,
410                                                                                   VkPresentModeKHR *pPresentModes) {
411     // First, check to ensure the appropriate extension was enabled:
412     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
413     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
414     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
415     if (!loader_inst->wsi_surface_enabled) {
416         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
417                    "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR not executed!");
418         return VK_SUCCESS;
419     }
420 
421     if (NULL == pPresentModeCount) {
422         loader_log(loader_inst, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
423                    "NULL pointer passed into vkGetPhysicalDeviceSurfacePresentModesKHR for pPresentModeCount!");
424         abort();
425     }
426 
427     if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR) {
428         // Zero out the present mode count as this driver doesn't support WSI functionality
429         *pPresentModeCount = 0;
430         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
431                    "ICD for selected physical device does not export vkGetPhysicalDeviceSurfacePresentModesKHR!");
432         return VK_SUCCESS;
433     }
434     if (VK_NULL_HANDLE != surface) {
435         VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
436 
437         if (icd_surface != NULL && NULL != phys_dev_term->this_icd_term->surface_list.list &&
438             phys_dev_term->this_icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
439             phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index]) {
440             return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(
441                 phys_dev_term->phys_dev, phys_dev_term->this_icd_term->surface_list.list[icd_surface->surface_index],
442                 pPresentModeCount, pPresentModes);
443         }
444     }
445     return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModesKHR(phys_dev_term->phys_dev, surface, pPresentModeCount,
446                                                                       pPresentModes);
447 }
448 
449 // Functions for the VK_KHR_swapchain extension:
450 
451 // This is the trampoline entrypoint for CreateSwapchainKHR
vkCreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchain)452 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
453                                                                   const VkAllocationCallbacks *pAllocator,
454                                                                   VkSwapchainKHR *pSwapchain) {
455     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
456     if (NULL == disp) {
457         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
458                    "vkCreateSwapchainKHR: Invalid device [VUID-vkCreateSwapchainKHR-device-parameter]");
459         abort(); /* Intentionally fail so user can correct issue. */
460     }
461     if (NULL == disp->CreateSwapchainKHR) {
462         struct loader_device *dev = *((struct loader_device **)device);
463         loader_log(NULL != dev ? dev->phys_dev_term->this_icd_term->this_instance : NULL,
464                    VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
465                    "vkCreateSwapchainKHR: Driver's function pointer was NULL, returning VK_SUCCESS. Was the VK_KHR_swapchain "
466                    "extension enabled?");
467         abort();
468     }
469     return disp->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
470 }
471 
terminator_CreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchain)472 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
473                                                              const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
474     struct loader_device *dev;
475     struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
476     if (NULL == icd_term || NULL == dev) {
477         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
478                    "vkCreateSwapchainKHR Terminator: device handle. This is likely the result of a "
479                    "layer wrapping device handles and failing to unwrap them in all functions. "
480                    "[VUID-vkCreateSwapchainKHR-device-parameter]");
481         abort(); /* Intentionally fail so user can correct issue. */
482     }
483     if (NULL == pCreateInfo) {
484         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
485                    "vkCreateSwapchainKHR: Invalid pCreateInfo pointer [VUID-vkCreateSwapchainKHR-pCreateInfo-parameter]");
486         abort(); /* Intentionally fail so user can correct issue. */
487     }
488     // Need to gracefully handle the function pointer not being found.
489     if (NULL == dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR) {
490         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
491                    "vkCreateSwapchainKHR: Driver's function pointer was NULL, returning VK_SUCCESS. Was the VK_KHR_swapchain "
492                    "extension enabled?");
493         return VK_SUCCESS;
494     }
495     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateInfo->surface;
496     if (NULL != icd_term->surface_list.list &&
497         icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
498         icd_term->surface_list.list[icd_surface->surface_index]) {
499         // We found the ICD, and there is an ICD KHR surface
500         // associated with it, so copy the CreateInfo struct
501         // and point it at the ICD's surface.
502         VkSwapchainCreateInfoKHR *pCreateCopy = loader_stack_alloc(sizeof(VkSwapchainCreateInfoKHR));
503         if (NULL == pCreateCopy) {
504             return VK_ERROR_OUT_OF_HOST_MEMORY;
505         }
506         memcpy(pCreateCopy, pCreateInfo, sizeof(VkSwapchainCreateInfoKHR));
507         pCreateCopy->surface = icd_term->surface_list.list[icd_surface->surface_index];
508         return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, pCreateCopy, pAllocator, pSwapchain);
509     }
510     return dev->loader_dispatch.extension_terminator_dispatch.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
511 }
512 
513 // This is the trampoline entrypoint for DestroySwapchainKHR
vkDestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain,const VkAllocationCallbacks * pAllocator)514 LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
515                                                                const VkAllocationCallbacks *pAllocator) {
516     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
517     if (NULL == disp) {
518         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
519                    "vkDestroySwapchainKHR: Invalid device [VUID-vkDestroySwapchainKHR-device-parameter]");
520         abort(); /* Intentionally fail so user can correct issue. */
521     }
522     disp->DestroySwapchainKHR(device, swapchain, pAllocator);
523 }
524 
525 // This is the trampoline entrypoint for GetSwapchainImagesKHR
vkGetSwapchainImagesKHR(VkDevice device,VkSwapchainKHR swapchain,uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages)526 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain,
527                                                                      uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
528     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
529     if (NULL == disp) {
530         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
531                    "vkGetSwapchainImagesKHR: Invalid device [VUID-vkGetSwapchainImagesKHR-device-parameter]");
532         abort(); /* Intentionally fail so user can correct issue. */
533     }
534     return disp->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
535 }
536 
537 // This is the trampoline entrypoint for AcquireNextImageKHR
vkAcquireNextImageKHR(VkDevice device,VkSwapchainKHR swapchain,uint64_t timeout,VkSemaphore semaphore,VkFence fence,uint32_t * pImageIndex)538 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
539                                                                    VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
540     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
541     if (NULL == disp) {
542         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
543                    "vkAcquireNextImageKHR: Invalid device [VUID-vkAcquireNextImageKHR-device-parameter]");
544         abort(); /* Intentionally fail so user can correct issue. */
545     }
546     return disp->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
547 }
548 
549 // This is the trampoline entrypoint for QueuePresentKHR
vkQueuePresentKHR(VkQueue queue,const VkPresentInfoKHR * pPresentInfo)550 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
551     const VkLayerDispatchTable *disp = loader_get_dispatch(queue);
552     if (NULL == disp) {
553         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
554                    "vkQueuePresentKHR: Invalid queue [VUID-vkQueuePresentKHR-queue-parameter]");
555         abort(); /* Intentionally fail so user can correct issue. */
556     }
557     return disp->QueuePresentKHR(queue, pPresentInfo);
558 }
559 
allocate_icd_surface_struct(struct loader_instance * instance,size_t base_size,size_t platform_size,const VkAllocationCallbacks * pAllocator,VkIcdSurface ** out_icd_surface)560 VkResult allocate_icd_surface_struct(struct loader_instance *instance, size_t base_size, size_t platform_size,
561                                      const VkAllocationCallbacks *pAllocator, VkIcdSurface **out_icd_surface) {
562     uint32_t next_index = 0;
563     VkIcdSurface *icd_surface = NULL;
564     VkResult res = loader_get_next_available_entry(instance, &instance->surfaces_list, &next_index, pAllocator);
565     if (res != VK_SUCCESS) {
566         goto out;
567     }
568 
569     // Next, if so, proceed with the implementation of this function:
570     icd_surface = loader_instance_heap_alloc(instance, sizeof(VkIcdSurface), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
571     if (icd_surface == NULL) {
572         res = VK_ERROR_OUT_OF_HOST_MEMORY;
573         goto out;
574     }
575     // Setup the new sizes and offsets so we can grow the structures in the
576     // future without having problems
577     icd_surface->base_size = (uint32_t)base_size;
578     icd_surface->platform_size = (uint32_t)platform_size;
579     icd_surface->non_platform_offset = (uint32_t)((uint8_t *)(&icd_surface->base_size) - (uint8_t *)icd_surface);
580     icd_surface->entire_size = sizeof(VkIcdSurface);
581     icd_surface->surface_index = next_index;
582 
583     for (struct loader_icd_term *icd_term = instance->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
584         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
585             if (icd_term->surface_list.list == NULL) {
586                 res =
587                     loader_init_generic_list(instance, (struct loader_generic_list *)&icd_term->surface_list, sizeof(VkSurfaceKHR));
588                 if (res != VK_SUCCESS) {
589                     goto out;
590                 }
591             } else if (icd_term->surface_list.capacity <= next_index * sizeof(VkSurfaceKHR)) {
592                 res = loader_resize_generic_list(instance, (struct loader_generic_list *)&icd_term->surface_list);
593                 if (res != VK_SUCCESS) {
594                     goto out;
595                 }
596             }
597         }
598     }
599 
600     *out_icd_surface = icd_surface;
601 out:
602     if (res != VK_SUCCESS) {
603         loader_instance_heap_free(instance, icd_surface);
604         // cleanup of icd_term->surface_list is done during instance destruction
605     }
606     return res;
607 }
608 
cleanup_surface_creation(struct loader_instance * loader_inst,VkResult result,VkIcdSurface * icd_surface,const VkAllocationCallbacks * pAllocator)609 void cleanup_surface_creation(struct loader_instance *loader_inst, VkResult result, VkIcdSurface *icd_surface,
610                               const VkAllocationCallbacks *pAllocator) {
611     if (VK_SUCCESS != result && NULL != icd_surface) {
612         for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
613             if (NULL != icd_term->surface_list.list &&
614                 icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
615                 icd_term->surface_list.list[icd_surface->surface_index] && NULL != icd_term->dispatch.DestroySurfaceKHR) {
616                 icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_term->surface_list.list[icd_surface->surface_index],
617                                                      pAllocator);
618             }
619         }
620         if (loader_inst->surfaces_list.list &&
621             loader_inst->surfaces_list.capacity > icd_surface->surface_index * sizeof(struct loader_used_object_status)) {
622             loader_inst->surfaces_list.list[icd_surface->surface_index].status = VK_FALSE;
623             if (NULL != pAllocator) {
624                 loader_inst->surfaces_list.list[icd_surface->surface_index].allocation_callbacks = *pAllocator;
625             }
626         }
627         loader_instance_heap_free(loader_inst, icd_surface);
628     }
629 }
630 
631 #if defined(VK_USE_PLATFORM_WIN32_KHR)
632 
633 // Functions for the VK_KHR_win32_surface extension:
634 
635 // This is the trampoline entrypoint for CreateWin32SurfaceKHR
vkCreateWin32SurfaceKHR(VkInstance instance,const VkWin32SurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)636 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(VkInstance instance,
637                                                                      const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
638                                                                      const VkAllocationCallbacks *pAllocator,
639                                                                      VkSurfaceKHR *pSurface) {
640     struct loader_instance *loader_inst = loader_get_instance(instance);
641     if (NULL == loader_inst) {
642         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
643                    "vkCreateWin32SurfaceKHR: Invalid instance [VUID-vkCreateWin32SurfaceKHR-instance-parameter]");
644         abort(); /* Intentionally fail so user can correct issue. */
645     }
646     return loader_inst->disp->layer_inst_disp.CreateWin32SurfaceKHR(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
647 }
648 
649 // This is the instance chain terminator function for CreateWin32SurfaceKHR
terminator_CreateWin32SurfaceKHR(VkInstance instance,const VkWin32SurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)650 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
651                                                                 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
652     VkResult result = VK_SUCCESS;
653     VkIcdSurface *icd_surface = NULL;
654     loader_platform_thread_lock_mutex(&loader_lock);
655 
656     // Initialize pSurface to NULL just to be safe.
657     *pSurface = VK_NULL_HANDLE;
658     // First, check to ensure the appropriate extension was enabled:
659     struct loader_instance *loader_inst = loader_get_instance(instance);
660     if (!loader_inst->wsi_win32_surface_enabled) {
661         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
662                    "VK_KHR_win32_surface extension not enabled. vkCreateWin32SurfaceKHR not executed!");
663         result = VK_ERROR_EXTENSION_NOT_PRESENT;
664         goto out;
665     }
666 
667     // Next, if so, proceed with the implementation of this function:
668     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->win_surf.base), sizeof(icd_surface->win_surf), pAllocator,
669                                          &icd_surface);
670     if (VK_SUCCESS != result) {
671         goto out;
672     }
673 
674     icd_surface->win_surf.base.platform = VK_ICD_WSI_PLATFORM_WIN32;
675     icd_surface->win_surf.hinstance = pCreateInfo->hinstance;
676     icd_surface->win_surf.hwnd = pCreateInfo->hwnd;
677 
678     // Loop through each ICD and determine if they need to create a surface
679     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
680         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
681             if (NULL != icd_term->dispatch.CreateWin32SurfaceKHR) {
682                 result = icd_term->dispatch.CreateWin32SurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
683                                                                   &icd_term->surface_list.list[icd_surface->surface_index]);
684                 if (VK_SUCCESS != result) {
685                     goto out;
686                 }
687             }
688         }
689     }
690 
691     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
692 
693 out:
694     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
695     loader_platform_thread_unlock_mutex(&loader_lock);
696     return result;
697 }
698 
699 // This is the trampoline entrypoint for
700 // GetPhysicalDeviceWin32PresentationSupportKHR
vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex)701 LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
702                                                                                             uint32_t queueFamilyIndex) {
703     const VkLayerInstanceDispatchTable *disp;
704     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
705     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
706         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
707                    "vkGetPhysicalDeviceWin32PresentationSupportKHR: Invalid physicalDevice "
708                    "[VUID-vkGetPhysicalDeviceWin32PresentationSupportKHR-physicalDevice-parameter]");
709         abort(); /* Intentionally fail so user can correct issue. */
710     }
711     disp = loader_get_instance_layer_dispatch(physicalDevice);
712     return disp->GetPhysicalDeviceWin32PresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex);
713 }
714 
715 // This is the instance chain terminator function for
716 // GetPhysicalDeviceWin32PresentationSupportKHR
terminator_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex)717 VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
718                                                                                        uint32_t queueFamilyIndex) {
719     // First, check to ensure the appropriate extension was enabled:
720     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
721     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
722     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
723     if (!loader_inst->wsi_win32_surface_enabled) {
724         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
725                    "VK_KHR_win32_surface extension not enabled. vkGetPhysicalDeviceWin32PresentationSupportKHR not executed!");
726         return VK_FALSE;
727     }
728 
729     if (NULL == icd_term->dispatch.GetPhysicalDeviceWin32PresentationSupportKHR) {
730         // return VK_FALSE as this driver doesn't support WSI functionality
731         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
732                    "ICD for selected physical device does not export vkGetPhysicalDeviceWin32PresentationSupportKHR!");
733         return VK_FALSE;
734     }
735 
736     return icd_term->dispatch.GetPhysicalDeviceWin32PresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex);
737 }
738 #endif  // VK_USE_PLATFORM_WIN32_KHR
739 
740 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
741 
742 // This is the trampoline entrypoint for CreateWaylandSurfaceKHR
vkCreateWaylandSurfaceKHR(VkInstance instance,const VkWaylandSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)743 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(VkInstance instance,
744                                                                        const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
745                                                                        const VkAllocationCallbacks *pAllocator,
746                                                                        VkSurfaceKHR *pSurface) {
747     struct loader_instance *loader_inst = loader_get_instance(instance);
748     if (NULL == loader_inst) {
749         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
750                    "vkCreateWaylandSurfaceKHR: Invalid instance [VUID-vkCreateWaylandSurfaceKHR-instance-parameter]");
751         abort(); /* Intentionally fail so user can correct issue. */
752     }
753     return loader_inst->disp->layer_inst_disp.CreateWaylandSurfaceKHR(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
754 }
755 
756 // This is the instance chain terminator function for CreateWaylandSurfaceKHR
terminator_CreateWaylandSurfaceKHR(VkInstance instance,const VkWaylandSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)757 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(VkInstance instance,
758                                                                   const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
759                                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
760     VkResult result = VK_SUCCESS;
761     VkIcdSurface *icd_surface = NULL;
762     loader_platform_thread_lock_mutex(&loader_lock);
763 
764     // First, check to ensure the appropriate extension was enabled:
765     struct loader_instance *loader_inst = loader_get_instance(instance);
766     if (!loader_inst->wsi_wayland_surface_enabled) {
767         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
768                    "VK_KHR_wayland_surface extension not enabled. vkCreateWaylandSurfaceKHR not executed!");
769         result = VK_ERROR_EXTENSION_NOT_PRESENT;
770         goto out;
771     }
772 
773     // Next, if so, proceed with the implementation of this function:
774     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->wayland_surf.base), sizeof(icd_surface->wayland_surf),
775                                          pAllocator, &icd_surface);
776     if (VK_SUCCESS != result) {
777         goto out;
778     }
779 
780     icd_surface->wayland_surf.base.platform = VK_ICD_WSI_PLATFORM_WAYLAND;
781     icd_surface->wayland_surf.display = pCreateInfo->display;
782     icd_surface->wayland_surf.surface = pCreateInfo->surface;
783 
784     // Loop through each ICD and determine if they need to create a surface
785     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
786         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
787             if (NULL != icd_term->dispatch.CreateWaylandSurfaceKHR) {
788                 result = icd_term->dispatch.CreateWaylandSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
789                                                                     &icd_term->surface_list.list[icd_surface->surface_index]);
790                 if (VK_SUCCESS != result) {
791                     goto out;
792                 }
793             }
794         }
795     }
796 
797     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
798 
799 out:
800     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
801     loader_platform_thread_unlock_mutex(&loader_lock);
802 
803     return result;
804 }
805 
806 // This is the trampoline entrypoint for
807 // GetPhysicalDeviceWaylandPresentationSupportKHR
vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,struct wl_display * display)808 LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
809                                                                                               uint32_t queueFamilyIndex,
810                                                                                               struct wl_display *display) {
811     const VkLayerInstanceDispatchTable *disp;
812     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
813     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
814         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
815                    "vkGetPhysicalDeviceWaylandPresentationSupportKHR: Invalid physicalDevice "
816                    "[VUID-vkGetPhysicalDeviceWaylandPresentationSupportKHR-physicalDevice-parameter]");
817         abort(); /* Intentionally fail so user can correct issue. */
818     }
819     disp = loader_get_instance_layer_dispatch(physicalDevice);
820     return disp->GetPhysicalDeviceWaylandPresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex, display);
821 }
822 
823 // This is the instance chain terminator function for
824 // GetPhysicalDeviceWaylandPresentationSupportKHR
terminator_GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,struct wl_display * display)825 VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
826                                                                                          uint32_t queueFamilyIndex,
827                                                                                          struct wl_display *display) {
828     // First, check to ensure the appropriate extension was enabled:
829     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
830     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
831     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
832     if (!loader_inst->wsi_wayland_surface_enabled) {
833         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
834                    "VK_KHR_wayland_surface extension not enabled. vkGetPhysicalDeviceWaylandPresentationSupportKHR not executed!");
835         return VK_FALSE;
836     }
837 
838     if (NULL == icd_term->dispatch.GetPhysicalDeviceWaylandPresentationSupportKHR) {
839         // return VK_FALSE as this driver doesn't support WSI functionality
840         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
841                    "ICD for selected physical device does not export vkGetPhysicalDeviceWaylandPresentationSupportKHR!");
842         return VK_FALSE;
843     }
844 
845     return icd_term->dispatch.GetPhysicalDeviceWaylandPresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, display);
846 }
847 #endif  // VK_USE_PLATFORM_WAYLAND_KHR
848 
849 #if defined(VK_USE_PLATFORM_XCB_KHR)
850 
851 // Functions for the VK_KHR_xcb_surface extension:
852 
853 // This is the trampoline entrypoint for CreateXcbSurfaceKHR
vkCreateXcbSurfaceKHR(VkInstance instance,const VkXcbSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)854 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(VkInstance instance,
855                                                                    const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
856                                                                    const VkAllocationCallbacks *pAllocator,
857                                                                    VkSurfaceKHR *pSurface) {
858     struct loader_instance *loader_inst = loader_get_instance(instance);
859     if (NULL == loader_inst) {
860         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
861                    "vkCreateXcbSurfaceKHR: Invalid instance [VUID-vkCreateXcbSurfaceKHR-instance-parameter]");
862         abort(); /* Intentionally fail so user can correct issue. */
863     }
864     return loader_inst->disp->layer_inst_disp.CreateXcbSurfaceKHR(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
865 }
866 
867 // This is the instance chain terminator function for CreateXcbSurfaceKHR
terminator_CreateXcbSurfaceKHR(VkInstance instance,const VkXcbSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)868 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
869                                                               const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
870     VkResult result = VK_SUCCESS;
871     VkIcdSurface *icd_surface = NULL;
872     loader_platform_thread_lock_mutex(&loader_lock);
873 
874     // First, check to ensure the appropriate extension was enabled:
875     struct loader_instance *loader_inst = loader_get_instance(instance);
876     if (!loader_inst->wsi_xcb_surface_enabled) {
877         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
878                    "VK_KHR_xcb_surface extension not enabled. vkCreateXcbSurfaceKHR not executed!");
879         result = VK_ERROR_EXTENSION_NOT_PRESENT;
880         goto out;
881     }
882 
883     // Next, if so, proceed with the implementation of this function:
884     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->xcb_surf.base), sizeof(icd_surface->xcb_surf), pAllocator,
885                                          &icd_surface);
886     if (VK_SUCCESS != result) {
887         goto out;
888     }
889 
890     icd_surface->xcb_surf.base.platform = VK_ICD_WSI_PLATFORM_XCB;
891     icd_surface->xcb_surf.connection = pCreateInfo->connection;
892     icd_surface->xcb_surf.window = pCreateInfo->window;
893 
894     // Loop through each ICD and determine if they need to create a surface
895     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
896         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
897             if (NULL != icd_term->dispatch.CreateXcbSurfaceKHR) {
898                 result = icd_term->dispatch.CreateXcbSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
899                                                                 &icd_term->surface_list.list[icd_surface->surface_index]);
900                 if (VK_SUCCESS != result) {
901                     goto out;
902                 }
903             }
904         }
905     }
906 
907     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
908 
909 out:
910     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
911     loader_platform_thread_unlock_mutex(&loader_lock);
912 
913     return result;
914 }
915 
916 // This is the trampoline entrypoint for
917 // GetPhysicalDeviceXcbPresentationSupportKHR
vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,xcb_connection_t * connection,xcb_visualid_t visual_id)918 LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
919                                                                                           uint32_t queueFamilyIndex,
920                                                                                           xcb_connection_t *connection,
921                                                                                           xcb_visualid_t visual_id) {
922     const VkLayerInstanceDispatchTable *disp;
923     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
924     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
925         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
926                    "vkGetPhysicalDeviceXcbPresentationSupportKHR: Invalid physicalDevice "
927                    "[VUID-vkGetPhysicalDeviceXcbPresentationSupportKHR-physicalDevice-parameter]");
928         abort(); /* Intentionally fail so user can correct issue. */
929     }
930     disp = loader_get_instance_layer_dispatch(physicalDevice);
931     return disp->GetPhysicalDeviceXcbPresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex, connection, visual_id);
932 }
933 
934 // This is the instance chain terminator function for
935 // GetPhysicalDeviceXcbPresentationSupportKHR
terminator_GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,xcb_connection_t * connection,xcb_visualid_t visual_id)936 VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
937                                                                                      uint32_t queueFamilyIndex,
938                                                                                      xcb_connection_t *connection,
939                                                                                      xcb_visualid_t visual_id) {
940     // First, check to ensure the appropriate extension was enabled:
941     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
942     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
943     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
944     if (!loader_inst->wsi_xcb_surface_enabled) {
945         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
946                    "VK_KHR_xcb_surface extension not enabled. vkGetPhysicalDeviceXcbPresentationSupportKHR not executed!");
947         return VK_FALSE;
948     }
949 
950     if (NULL == icd_term->dispatch.GetPhysicalDeviceXcbPresentationSupportKHR) {
951         // return VK_FALSE as this driver doesn't support WSI functionality
952         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
953                    "ICD for selected physical device does not export vkGetPhysicalDeviceXcbPresentationSupportKHR!");
954         return VK_FALSE;
955     }
956 
957     return icd_term->dispatch.GetPhysicalDeviceXcbPresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, connection,
958                                                                          visual_id);
959 }
960 #endif  // VK_USE_PLATFORM_XCB_KHR
961 
962 #if defined(VK_USE_PLATFORM_XLIB_KHR)
963 
964 // Functions for the VK_KHR_xlib_surface extension:
965 
966 // This is the trampoline entrypoint for CreateXlibSurfaceKHR
vkCreateXlibSurfaceKHR(VkInstance instance,const VkXlibSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)967 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(VkInstance instance,
968                                                                     const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
969                                                                     const VkAllocationCallbacks *pAllocator,
970                                                                     VkSurfaceKHR *pSurface) {
971     struct loader_instance *loader_inst = loader_get_instance(instance);
972     if (NULL == loader_inst) {
973         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
974                    "vkCreateXlibSurfaceKHR: Invalid instance [VUID-vkCreateXlibSurfaceKHR-instance-parameter]");
975         abort(); /* Intentionally fail so user can correct issue. */
976     }
977     return loader_inst->disp->layer_inst_disp.CreateXlibSurfaceKHR(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
978 }
979 
980 // This is the instance chain terminator function for CreateXlibSurfaceKHR
terminator_CreateXlibSurfaceKHR(VkInstance instance,const VkXlibSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)981 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
982                                                                const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
983     VkResult result = VK_SUCCESS;
984     VkIcdSurface *icd_surface = NULL;
985     loader_platform_thread_lock_mutex(&loader_lock);
986 
987     // First, check to ensure the appropriate extension was enabled:
988     struct loader_instance *loader_inst = loader_get_instance(instance);
989     if (!loader_inst->wsi_xlib_surface_enabled) {
990         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
991                    "VK_KHR_xlib_surface extension not enabled. vkCreateXlibSurfaceKHR not executed!");
992         result = VK_ERROR_EXTENSION_NOT_PRESENT;
993         goto out;
994     }
995 
996     // Next, if so, proceed with the implementation of this function:
997     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->xlib_surf.base), sizeof(icd_surface->xlib_surf),
998                                          pAllocator, &icd_surface);
999     if (VK_SUCCESS != result) {
1000         goto out;
1001     }
1002 
1003     icd_surface->xlib_surf.base.platform = VK_ICD_WSI_PLATFORM_XLIB;
1004     icd_surface->xlib_surf.dpy = pCreateInfo->dpy;
1005     icd_surface->xlib_surf.window = pCreateInfo->window;
1006 
1007     // Loop through each ICD and determine if they need to create a surface
1008     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1009         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1010             if (NULL != icd_term->dispatch.CreateXlibSurfaceKHR) {
1011                 result = icd_term->dispatch.CreateXlibSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
1012                                                                  &icd_term->surface_list.list[icd_surface->surface_index]);
1013                 if (VK_SUCCESS != result) {
1014                     goto out;
1015                 }
1016             }
1017         }
1018     }
1019 
1020     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1021 
1022 out:
1023     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1024     loader_platform_thread_unlock_mutex(&loader_lock);
1025 
1026     return result;
1027 }
1028 
1029 // This is the trampoline entrypoint for
1030 // GetPhysicalDeviceXlibPresentationSupportKHR
vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,Display * dpy,VisualID visualID)1031 LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
1032                                                                                            uint32_t queueFamilyIndex, Display *dpy,
1033                                                                                            VisualID visualID) {
1034     const VkLayerInstanceDispatchTable *disp;
1035     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1036     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1037         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1038                    "vkGetPhysicalDeviceXlibPresentationSupportKHR: Invalid physicalDevice "
1039                    "[VUID-vkGetPhysicalDeviceXlibPresentationSupportKHR-physicalDevice-parameter]");
1040         abort(); /* Intentionally fail so user can correct issue. */
1041     }
1042     disp = loader_get_instance_layer_dispatch(physicalDevice);
1043     return disp->GetPhysicalDeviceXlibPresentationSupportKHR(unwrapped_phys_dev, queueFamilyIndex, dpy, visualID);
1044 }
1045 
1046 // This is the instance chain terminator function for
1047 // GetPhysicalDeviceXlibPresentationSupportKHR
terminator_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,Display * dpy,VisualID visualID)1048 VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
1049                                                                                       uint32_t queueFamilyIndex, Display *dpy,
1050                                                                                       VisualID visualID) {
1051     // First, check to ensure the appropriate extension was enabled:
1052     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1053     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1054     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1055     if (!loader_inst->wsi_xlib_surface_enabled) {
1056         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1057                    "VK_KHR_xlib_surface extension not enabled. vkGetPhysicalDeviceXlibPresentationSupportKHR not executed!");
1058         return VK_FALSE;
1059     }
1060 
1061     if (NULL == icd_term->dispatch.GetPhysicalDeviceXlibPresentationSupportKHR) {
1062         // return VK_FALSE as this driver doesn't support WSI functionality
1063         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1064                    "ICD for selected physical device does not export vkGetPhysicalDeviceXlibPresentationSupportKHR!");
1065         return VK_FALSE;
1066     }
1067 
1068     return icd_term->dispatch.GetPhysicalDeviceXlibPresentationSupportKHR(phys_dev_term->phys_dev, queueFamilyIndex, dpy, visualID);
1069 }
1070 #endif  // VK_USE_PLATFORM_XLIB_KHR
1071 
1072 #if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
1073 
1074 // Functions for the VK_EXT_directfb_surface extension:
1075 
1076 // This is the trampoline entrypoint for CreateDirectFBSurfaceEXT
vkCreateDirectFBSurfaceEXT(VkInstance instance,const VkDirectFBSurfaceCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1077 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDirectFBSurfaceEXT(VkInstance instance,
1078                                                                         const VkDirectFBSurfaceCreateInfoEXT *pCreateInfo,
1079                                                                         const VkAllocationCallbacks *pAllocator,
1080                                                                         VkSurfaceKHR *pSurface) {
1081     struct loader_instance *loader_inst = loader_get_instance(instance);
1082     if (NULL == loader_inst) {
1083         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1084                    "vkCreateDirectFBSurfaceEXT: Invalid instance [VUID-vkCreateDirectFBSurfaceEXT-instance-parameter]");
1085         abort(); /* Intentionally fail so user can correct issue. */
1086     }
1087     return loader_inst->disp->layer_inst_disp.CreateDirectFBSurfaceEXT(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1088 }
1089 
1090 // This is the instance chain terminator function for CreateDirectFBSurfaceEXT
terminator_CreateDirectFBSurfaceEXT(VkInstance instance,const VkDirectFBSurfaceCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1091 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDirectFBSurfaceEXT(VkInstance instance,
1092                                                                    const VkDirectFBSurfaceCreateInfoEXT *pCreateInfo,
1093                                                                    const VkAllocationCallbacks *pAllocator,
1094                                                                    VkSurfaceKHR *pSurface) {
1095     VkResult result = VK_SUCCESS;
1096     VkIcdSurface *icd_surface = NULL;
1097     loader_platform_thread_lock_mutex(&loader_lock);
1098 
1099     // First, check to ensure the appropriate extension was enabled:
1100     struct loader_instance *loader_inst = loader_get_instance(instance);
1101     if (!loader_inst->wsi_directfb_surface_enabled) {
1102         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1103                    "VK_EXT_directfb_surface extension not enabled. vkCreateDirectFBSurfaceEXT not executed!");
1104         result = VK_ERROR_EXTENSION_NOT_PRESENT;
1105         goto out;
1106     }
1107 
1108     // Next, if so, proceed with the implementation of this function:
1109     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->directfb_surf.base), sizeof(icd_surface->directfb_surf),
1110                                          pAllocator, &icd_surface);
1111     if (VK_SUCCESS != result) {
1112         goto out;
1113     }
1114 
1115     icd_surface->directfb_surf.base.platform = VK_ICD_WSI_PLATFORM_DIRECTFB;
1116     icd_surface->directfb_surf.dfb = pCreateInfo->dfb;
1117     icd_surface->directfb_surf.surface = pCreateInfo->surface;
1118 
1119     // Loop through each ICD and determine if they need to create a surface
1120     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1121         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1122             if (NULL != icd_term->dispatch.CreateDirectFBSurfaceEXT) {
1123                 result = icd_term->dispatch.CreateDirectFBSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
1124                                                                      &icd_term->surface_list.list[icd_surface->surface_index]);
1125                 if (VK_SUCCESS != result) {
1126                     goto out;
1127                 }
1128             }
1129         }
1130     }
1131 
1132     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1133 
1134 out:
1135     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1136     loader_platform_thread_unlock_mutex(&loader_lock);
1137 
1138     return result;
1139 }
1140 
1141 // This is the trampoline entrypoint for
1142 // GetPhysicalDeviceDirectFBPresentationSupportEXT
vkGetPhysicalDeviceDirectFBPresentationSupportEXT(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,IDirectFB * dfb)1143 LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceDirectFBPresentationSupportEXT(VkPhysicalDevice physicalDevice,
1144                                                                                                uint32_t queueFamilyIndex,
1145                                                                                                IDirectFB *dfb) {
1146     const VkLayerInstanceDispatchTable *disp;
1147     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1148     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1149         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1150                    "vkGetPhysicalDeviceDirectFBPresentationSupportEXT: Invalid physicalDevice "
1151                    "[VUID-vkGetPhysicalDeviceDirectFBPresentationSupportEXT-physicalDevice-parameter]");
1152         abort(); /* Intentionally fail so user can correct issue. */
1153     }
1154     disp = loader_get_instance_layer_dispatch(physicalDevice);
1155     return disp->GetPhysicalDeviceDirectFBPresentationSupportEXT(unwrapped_phys_dev, queueFamilyIndex, dfb);
1156 }
1157 
1158 // This is the instance chain terminator function for
1159 // GetPhysicalDeviceDirectFBPresentationSupportEXT
terminator_GetPhysicalDeviceDirectFBPresentationSupportEXT(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,IDirectFB * dfb)1160 VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceDirectFBPresentationSupportEXT(VkPhysicalDevice physicalDevice,
1161                                                                                           uint32_t queueFamilyIndex,
1162                                                                                           IDirectFB *dfb) {
1163     // First, check to ensure the appropriate extension was enabled:
1164     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1165     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1166     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1167     if (!loader_inst->wsi_directfb_surface_enabled) {
1168         loader_log(
1169             loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1170             "VK_EXT_directfb_surface extension not enabled. vkGetPhysicalDeviceDirectFBPresentationSupportKHR not executed!");
1171         return VK_FALSE;
1172     }
1173 
1174     if (NULL == icd_term->dispatch.GetPhysicalDeviceDirectFBPresentationSupportEXT) {
1175         // return VK_FALSE as this driver doesn't support WSI functionality
1176         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1177                    "ICD for selected physical device does not export vkGetPhysicalDeviceDirectFBPresentationSupportEXT!");
1178         return VK_FALSE;
1179     }
1180 
1181     return icd_term->dispatch.GetPhysicalDeviceDirectFBPresentationSupportEXT(phys_dev_term->phys_dev, queueFamilyIndex, dfb);
1182 }
1183 
1184 #endif  // VK_USE_PLATFORM_DIRECTFB_EXT
1185 
1186 #if defined(VK_USE_PLATFORM_ANDROID_KHR)
1187 
1188 // Functions for the VK_KHR_android_surface extension:
1189 
1190 // This is the trampoline entrypoint for CreateAndroidSurfaceKHR
vkCreateAndroidSurfaceKHR(VkInstance instance,const VkAndroidSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1191 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(VkInstance instance,
1192                                                                        const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
1193                                                                        const VkAllocationCallbacks *pAllocator,
1194                                                                        VkSurfaceKHR *pSurface) {
1195     struct loader_instance *loader_inst = loader_get_instance(instance);
1196     if (NULL == loader_inst) {
1197         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1198                    "vkCreateAndroidSurfaceKHR: Invalid instance [VUID-vkCreateAndroidSurfaceKHR-instance-parameter]");
1199         abort(); /* Intentionally fail so user can correct issue. */
1200     }
1201     return loader_inst->disp->layer_inst_disp.CreateAndroidSurfaceKHR(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1202 }
1203 
1204 // This is the instance chain terminator function for CreateAndroidSurfaceKHR
terminator_CreateAndroidSurfaceKHR(VkInstance instance,const VkAndroidSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1205 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateAndroidSurfaceKHR(VkInstance instance,
1206                                                                   const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
1207                                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1208     // First, check to ensure the appropriate extension was enabled:
1209     struct loader_instance *loader_inst = loader_get_instance(instance);
1210     if (!loader_inst->wsi_display_enabled) {
1211         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1212                    "VK_KHR_display extension not enabled. vkCreateAndroidSurfaceKHR not executed!");
1213         return VK_ERROR_EXTENSION_NOT_PRESENT;
1214     }
1215 
1216     // Next, if so, proceed with the implementation of this function:
1217     VkIcdSurfaceAndroid *icd_surface =
1218         loader_instance_heap_alloc(loader_inst, sizeof(VkIcdSurfaceAndroid), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1219     if (icd_surface == NULL) {
1220         return VK_ERROR_OUT_OF_HOST_MEMORY;
1221     }
1222 
1223     icd_surface->base.platform = VK_ICD_WSI_PLATFORM_ANDROID;
1224     icd_surface->window = pCreateInfo->window;
1225 
1226     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1227 
1228     return VK_SUCCESS;
1229 }
1230 
1231 #endif  // VK_USE_PLATFORM_ANDROID_KHR
1232 
1233 #if defined(VK_USE_PLATFORM_OHOS)
1234 
1235 // Functions for the VK_OHOS_surface extension:
1236 
1237 // This is the trampoline entrypoint for CreateSurfaceOHOS
1238 
vkCreateSurfaceOHOS(VkInstance instance,const VkSurfaceCreateInfoOHOS * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1239 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSurfaceOHOS(VkInstance instance,
1240 																 const VkSurfaceCreateInfoOHOS *pCreateInfo,
1241                                                                  const VkAllocationCallbacks *pAllocator,
1242                                                                  VkSurfaceKHR *pSurface) {
1243     struct loader_instance *loader_inst = loader_get_instance(instance);
1244     if (NULL == loader_inst) {
1245         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1246                    "vkCreateSurfaceOHOS: Invalid instance [VUID-vkCreateSurfaceOHOS-instance-parameter]");
1247         abort(); /* Intentionally fail so user can correct issue. */
1248     }
1249     return loader_inst->disp->layer_inst_disp.CreateSurfaceOHOS(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1250 }
1251 
1252 // This is the instance chain terminator function for CreateSurfaceOHOS
terminator_CreateSurfaceOHOS(VkInstance instance,const VkSurfaceCreateInfoOHOS * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1253 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSurfaceOHOS(VkInstance instance,
1254                                                             const VkSurfaceCreateInfoOHOS *pCreateInfo,
1255                                                             const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1256     // First, check to ensure the appropriate extension was enabled:
1257     struct loader_instance *loader_inst = loader_get_instance(instance);
1258     if (!loader_inst->wsi_ohos_surface_enabled) {
1259         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1260                    "VK_OHOS_surface extension not enabled. vkCreateSurfaceOHOS not executed!\n");
1261         return VK_ERROR_EXTENSION_NOT_PRESENT;
1262     }
1263 
1264     // Next, if so, proceed with the implementation of this function:
1265     VkIcdSurfaceOHOS *pIcdSurface =
1266         loader_instance_heap_alloc(loader_inst, sizeof(VkIcdSurfaceOHOS), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1267     if (pIcdSurface == NULL) {
1268         return VK_ERROR_OUT_OF_HOST_MEMORY;
1269     }
1270 
1271     pIcdSurface->base.platform = VK_ICD_WSI_PLATFORM_OHOS;
1272     pIcdSurface->window = pCreateInfo->window;
1273 
1274     *pSurface = (VkSurfaceKHR)(uintptr_t)pIcdSurface;
1275 
1276     return VK_SUCCESS;
1277 }
1278 
1279 #endif  // VK_USE_PLATFORM_OHOS
1280 
1281 
1282 // Functions for the VK_EXT_headless_surface extension:
1283 
vkCreateHeadlessSurfaceEXT(VkInstance instance,const VkHeadlessSurfaceCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1284 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateHeadlessSurfaceEXT(VkInstance instance,
1285                                                                         const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
1286                                                                         const VkAllocationCallbacks *pAllocator,
1287                                                                         VkSurfaceKHR *pSurface) {
1288     struct loader_instance *loader_inst = loader_get_instance(instance);
1289     if (NULL == loader_inst) {
1290         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1291                    "vkCreateHeadlessSurfaceEXT: Invalid instance [VUID-vkCreateHeadlessSurfaceEXT-instance-parameter]");
1292         abort(); /* Intentionally fail so user can correct issue. */
1293     }
1294     return loader_inst->disp->layer_inst_disp.CreateHeadlessSurfaceEXT(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1295 }
1296 
terminator_CreateHeadlessSurfaceEXT(VkInstance instance,const VkHeadlessSurfaceCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1297 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateHeadlessSurfaceEXT(VkInstance instance,
1298                                                                    const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
1299                                                                    const VkAllocationCallbacks *pAllocator,
1300                                                                    VkSurfaceKHR *pSurface) {
1301     VkResult result = VK_SUCCESS;
1302     VkIcdSurface *icd_surface = NULL;
1303     loader_platform_thread_lock_mutex(&loader_lock);
1304 
1305     // First, check to ensure the appropriate extension was enabled:
1306     struct loader_instance *loader_inst = loader_get_instance(instance);
1307     if (!loader_inst->wsi_headless_surface_enabled) {
1308         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1309                    "VK_EXT_headless_surface extension not enabled.  "
1310                    "vkCreateHeadlessSurfaceEXT not executed!");
1311         return VK_SUCCESS;
1312     }
1313 
1314     // Next, if so, proceed with the implementation of this function:
1315     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->headless_surf.base), sizeof(icd_surface->headless_surf),
1316                                          pAllocator, &icd_surface);
1317     if (VK_SUCCESS != result) {
1318         goto out;
1319     }
1320 
1321     icd_surface->headless_surf.base.platform = VK_ICD_WSI_PLATFORM_HEADLESS;
1322     // Loop through each ICD and determine if they need to create a surface
1323     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1324         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1325             if (NULL != icd_term->dispatch.CreateHeadlessSurfaceEXT) {
1326                 result = icd_term->dispatch.CreateHeadlessSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
1327                                                                      &icd_term->surface_list.list[icd_surface->surface_index]);
1328                 if (VK_SUCCESS != result) {
1329                     goto out;
1330                 }
1331             }
1332         }
1333     }
1334 
1335     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1336 
1337 out:
1338     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1339     loader_platform_thread_unlock_mutex(&loader_lock);
1340 
1341     return result;
1342 }
1343 
1344 // Ensure we are properly setting VK_USE_PLATFORM_METAL_EXT, VK_USE_PLATFORM_IOS_MVK, and VK_USE_PLATFORM_MACOS_MVK.
1345 #if __APPLE__
1346 
1347 #ifndef VK_USE_PLATFORM_METAL_EXT
1348 #error "VK_USE_PLATFORM_METAL_EXT not defined!"
1349 #endif
1350 
1351 #include <TargetConditionals.h>
1352 
1353 #if TARGET_OS_IOS
1354 
1355 #ifndef VK_USE_PLATFORM_IOS_MVK
1356 #error "VK_USE_PLATFORM_IOS_MVK not defined!"
1357 #endif
1358 
1359 #endif  //  TARGET_OS_IOS
1360 
1361 #if TARGET_OS_OSX
1362 
1363 #ifndef VK_USE_PLATFORM_MACOS_MVK
1364 #error "VK_USE_PLATFORM_MACOS_MVK not defined!"
1365 #endif
1366 
1367 #endif  // TARGET_OS_OSX
1368 
1369 #endif  // __APPLE__
1370 
1371 #if defined(VK_USE_PLATFORM_MACOS_MVK)
1372 
1373 // Functions for the VK_MVK_macos_surface extension:
1374 
1375 // This is the trampoline entrypoint for CreateMacOSSurfaceMVK
vkCreateMacOSSurfaceMVK(VkInstance instance,const VkMacOSSurfaceCreateInfoMVK * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1376 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(VkInstance instance,
1377                                                                      const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
1378                                                                      const VkAllocationCallbacks *pAllocator,
1379                                                                      VkSurfaceKHR *pSurface) {
1380     struct loader_instance *loader_inst = loader_get_instance(instance);
1381     if (NULL == loader_inst) {
1382         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1383                    "vkCreateMacOSSurfaceMVK: Invalid instance [VUID-vkCreateMacOSSurfaceMVK-instance-parameter]");
1384         abort(); /* Intentionally fail so user can correct issue. */
1385     }
1386     return loader_inst->disp->layer_inst_disp.CreateMacOSSurfaceMVK(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1387 }
1388 
1389 // This is the instance chain terminator function for CreateMacOSSurfaceKHR
terminator_CreateMacOSSurfaceMVK(VkInstance instance,const VkMacOSSurfaceCreateInfoMVK * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1390 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
1391                                                                 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1392     VkResult result = VK_SUCCESS;
1393     VkIcdSurface *icd_surface = NULL;
1394     loader_platform_thread_lock_mutex(&loader_lock);
1395 
1396     // First, check to ensure the appropriate extension was enabled:
1397     struct loader_instance *loader_inst = loader_get_instance(instance);
1398     if (!loader_inst->wsi_macos_surface_enabled) {
1399         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1400                    "VK_MVK_macos_surface extension not enabled. vkCreateMacOSSurfaceMVK not executed!");
1401         result = VK_ERROR_EXTENSION_NOT_PRESENT;
1402         goto out;
1403     }
1404 
1405     // Next, if so, proceed with the implementation of this function:
1406     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->macos_surf.base), sizeof(icd_surface->macos_surf),
1407                                          pAllocator, &icd_surface);
1408     if (VK_SUCCESS != result) {
1409         goto out;
1410     }
1411 
1412     icd_surface->macos_surf.base.platform = VK_ICD_WSI_PLATFORM_MACOS;
1413     icd_surface->macos_surf.pView = pCreateInfo->pView;
1414 
1415     // Loop through each ICD and determine if they need to create a surface
1416     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1417         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1418             if (NULL != icd_term->dispatch.CreateMacOSSurfaceMVK) {
1419                 result = icd_term->dispatch.CreateMacOSSurfaceMVK(icd_term->instance, pCreateInfo, pAllocator,
1420                                                                   &icd_term->surface_list.list[icd_surface->surface_index]);
1421                 if (VK_SUCCESS != result) {
1422                     goto out;
1423                 }
1424             }
1425         }
1426     }
1427 
1428     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1429 
1430 out:
1431     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1432     loader_platform_thread_unlock_mutex(&loader_lock);
1433 
1434     return result;
1435 }
1436 
1437 #endif  // VK_USE_PLATFORM_MACOS_MVK
1438 
1439 #if defined(VK_USE_PLATFORM_IOS_MVK)
1440 
1441 // Functions for the VK_MVK_ios_surface extension:
1442 
1443 // This is the trampoline entrypoint for CreateIOSSurfaceMVK
vkCreateIOSSurfaceMVK(VkInstance instance,const VkIOSSurfaceCreateInfoMVK * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1444 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(VkInstance instance,
1445                                                                    const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
1446                                                                    const VkAllocationCallbacks *pAllocator,
1447                                                                    VkSurfaceKHR *pSurface) {
1448     struct loader_instance *loader_inst = loader_get_instance(instance);
1449     if (NULL == loader_inst) {
1450         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1451                    "vkCreateIOSSurfaceMVK: Invalid instance [VUID-vkCreateIOSSurfaceMVK-instance-parameter]");
1452         abort(); /* Intentionally fail so user can correct issue. */
1453     }
1454     return loader_inst->disp->layer_inst_disp.CreateIOSSurfaceMVK(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1455 }
1456 
1457 // This is the instance chain terminator function for CreateIOSSurfaceKHR
terminator_CreateIOSSurfaceMVK(VkInstance instance,const VkIOSSurfaceCreateInfoMVK * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1458 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
1459                                                               const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1460     (void)pAllocator;
1461 
1462     // First, check to ensure the appropriate extension was enabled:
1463     struct loader_instance *loader_inst = loader_get_instance(instance);
1464     if (!loader_inst->wsi_ios_surface_enabled) {
1465         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1466                    "VK_MVK_ios_surface extension not enabled. vkCreateIOSSurfaceMVK not executed!");
1467         return VK_ERROR_EXTENSION_NOT_PRESENT;
1468     }
1469 
1470     // Next, if so, proceed with the implementation of this function:
1471     VkIcdSurfaceIOS *icd_surface =
1472         loader_instance_heap_alloc(loader_inst, sizeof(VkIcdSurfaceIOS), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1473     if (icd_surface == NULL) {
1474         return VK_ERROR_OUT_OF_HOST_MEMORY;
1475     }
1476 
1477     icd_surface->base.platform = VK_ICD_WSI_PLATFORM_IOS;
1478     icd_surface->pView = pCreateInfo->pView;
1479 
1480     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1481 
1482     return VK_SUCCESS;
1483 }
1484 
1485 #endif  // VK_USE_PLATFORM_IOS_MVK
1486 
1487 #if defined(VK_USE_PLATFORM_GGP)
1488 
1489 // Functions for the VK_GGP_stream_descriptor_surface extension:
1490 
1491 // This is the trampoline entrypoint for CreateStreamDescriptorSurfaceGGP
1492 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateStreamDescriptorSurfaceGGP(VkInstance instance,const VkStreamDescriptorSurfaceCreateInfoGGP * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1493 vkCreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP *pCreateInfo,
1494                                    const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1495     struct loader_instance *loader_inst = loader_get_instance(instance);
1496     if (NULL == loader_inst) {
1497         loader_log(
1498             NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1499             "vkCreateStreamDescriptorSurfaceGGP: Invalid instance [VUID-vkCreateStreamDescriptorSurfaceGGP-instance-parameter]");
1500         abort(); /* Intentionally fail so user can correct issue. */
1501     }
1502     return loader_inst->disp->layer_inst_disp.CreateStreamDescriptorSurfaceGGP(loader_inst->instance, pCreateInfo, pAllocator,
1503                                                                                pSurface);
1504 }
1505 
1506 // This is the instance chain terminator function for CreateStreamDescriptorSurfaceGGP
1507 VKAPI_ATTR VkResult VKAPI_CALL
terminator_CreateStreamDescriptorSurfaceGGP(VkInstance instance,const VkStreamDescriptorSurfaceCreateInfoGGP * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1508 terminator_CreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP *pCreateInfo,
1509                                             const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1510     VkResult result = VK_SUCCESS;
1511     VkIcdSurface *icd_surface = NULL;
1512     loader_platform_thread_lock_mutex(&loader_lock);
1513 
1514     // First, check to ensure the appropriate extension was enabled:
1515     struct loader_instance *loader_inst = loader_get_instance(instance);
1516     if (!loader_inst->wsi_ggp_surface_enabled) {
1517         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1518                    "VK_GGP_stream_descriptor_surface extension not enabled. vkCreateStreamDescriptorSurfaceGGP not executed!");
1519         result = VK_ERROR_EXTENSION_NOT_PRESENT;
1520         goto out;
1521     }
1522 
1523     // Next, if so, proceed with the implementation of this function:
1524     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->ggp_surf.base), sizeof(icd_surface->ggp_surf), pAllocator,
1525                                          &icd_surface);
1526     if (VK_SUCCESS != result) {
1527         goto out;
1528     }
1529 
1530     icd_surface->ggp_surf.base.platform = VK_ICD_WSI_PLATFORM_GGP;
1531     icd_surface->ggp_surf.streamDescriptor = pCreateInfo->streamDescriptor;
1532 
1533     // Loop through each ICD and determine if they need to create a surface
1534     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1535         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1536             if (NULL != icd_term->dispatch.CreateStreamDescriptorSurfaceGGP) {
1537                 result = icd_term->dispatch.CreateStreamDescriptorSurfaceGGP(
1538                     icd_term->instance, pCreateInfo, pAllocator, &icd_term->surface_list.list[icd_surface->surface_index]);
1539                 if (VK_SUCCESS != result) {
1540                     goto out;
1541                 }
1542             }
1543         }
1544     }
1545 
1546     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1547 
1548 out:
1549     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1550     loader_platform_thread_unlock_mutex(&loader_lock);
1551 
1552     return result;
1553 }
1554 
1555 #endif  // VK_USE_PLATFORM_GGP
1556 
1557 #if defined(VK_USE_PLATFORM_METAL_EXT)
1558 
vkCreateMetalSurfaceEXT(VkInstance instance,const VkMetalSurfaceCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1559 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT(VkInstance instance,
1560                                                                      const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
1561                                                                      const VkAllocationCallbacks *pAllocator,
1562                                                                      VkSurfaceKHR *pSurface) {
1563     struct loader_instance *loader_inst = loader_get_instance(instance);
1564     if (NULL == loader_inst) {
1565         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1566                    "vkCreateMetalSurfaceEXT: Invalid instance [VUID-vkCreateMetalSurfaceEXT-instance-parameter]");
1567         abort(); /* Intentionally fail so user can correct issue. */
1568     }
1569     return loader_inst->disp->layer_inst_disp.CreateMetalSurfaceEXT(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1570 }
1571 
terminator_CreateMetalSurfaceEXT(VkInstance instance,const VkMetalSurfaceCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1572 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
1573                                                                 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1574     VkResult result = VK_SUCCESS;
1575     VkIcdSurface *icd_surface = NULL;
1576     loader_platform_thread_lock_mutex(&loader_lock);
1577 
1578     // First, check to ensure the appropriate extension was enabled:
1579     struct loader_instance *loader_inst = loader_get_instance(instance);
1580     if (!loader_inst->wsi_metal_surface_enabled) {
1581         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1582                    "VK_EXT_metal_surface extension not enabled. vkCreateMetalSurfaceEXT will not be executed.");
1583     }
1584 
1585     // Next, if so, proceed with the implementation of this function:
1586     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->metal_surf.base), sizeof(icd_surface->metal_surf),
1587                                          pAllocator, &icd_surface);
1588     if (VK_SUCCESS != result) {
1589         goto out;
1590     }
1591 
1592     icd_surface->metal_surf.base.platform = VK_ICD_WSI_PLATFORM_METAL;
1593     icd_surface->metal_surf.pLayer = pCreateInfo->pLayer;
1594 
1595     // Loop through each ICD and determine if they need to create a surface
1596     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1597         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1598             if (NULL != icd_term->dispatch.CreateMetalSurfaceEXT) {
1599                 result = icd_term->dispatch.CreateMetalSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator,
1600                                                                   &icd_term->surface_list.list[icd_surface->surface_index]);
1601                 if (VK_SUCCESS != result) {
1602                     goto out;
1603                 }
1604             }
1605         }
1606     }
1607     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1608 
1609 out:
1610     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1611     loader_platform_thread_unlock_mutex(&loader_lock);
1612 
1613     return result;
1614 }
1615 
1616 #endif  // VK_USE_PLATFORM_METAL_EXT
1617 
1618 #if defined(VK_USE_PLATFORM_SCREEN_QNX)
1619 
1620 // This is the trampoline entrypoint for CreateScreenSurfaceQNX
vkCreateScreenSurfaceQNX(VkInstance instance,const VkScreenSurfaceCreateInfoQNX * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1621 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateScreenSurfaceQNX(VkInstance instance,
1622                                                                       const VkScreenSurfaceCreateInfoQNX *pCreateInfo,
1623                                                                       const VkAllocationCallbacks *pAllocator,
1624                                                                       VkSurfaceKHR *pSurface) {
1625     struct loader_instance *loader_inst = loader_get_instance(instance);
1626     if (NULL == loader_inst) {
1627         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1628                    "vkCreateScreenSurfaceQNX: Invalid instance [VUID-vkCreateScreenSurfaceQNX-instance-parameter]");
1629         abort(); /* Intentionally fail so user can correct issue. */
1630     }
1631     return loader_inst->disp->layer_inst_disp.CreateScreenSurfaceQNX(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1632 }
1633 
1634 // This is the instance chain terminator function for CreateScreenSurfaceQNX
terminator_CreateScreenSurfaceQNX(VkInstance instance,const VkScreenSurfaceCreateInfoQNX * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1635 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateScreenSurfaceQNX(VkInstance instance,
1636                                                                  const VkScreenSurfaceCreateInfoQNX *pCreateInfo,
1637                                                                  const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1638     VkResult result = VK_SUCCESS;
1639     VkIcdSurface *icd_surface = NULL;
1640     loader_platform_thread_lock_mutex(&loader_lock);
1641 
1642     // First, check to ensure the appropriate extension was enabled:
1643     struct loader_instance *loader_inst = loader_get_instance(instance);
1644     if (!loader_inst->wsi_screen_surface_enabled) {
1645         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1646                    "VK_QNX_screen_surface extension not enabled. vkCreateScreenSurfaceQNX not executed!");
1647         result = VK_ERROR_EXTENSION_NOT_PRESENT;
1648         goto out;
1649     }
1650 
1651     // Next, if so, proceed with the implementation of this function:
1652     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->screen_surf.base), sizeof(icd_surface->screen_surf),
1653                                          pAllocator, &icd_surface);
1654     if (VK_SUCCESS != result) {
1655         goto out;
1656     }
1657 
1658     icd_surface->screen_surf.base.platform = VK_ICD_WSI_PLATFORM_SCREEN;
1659     icd_surface->screen_surf.context = pCreateInfo->context;
1660     icd_surface->screen_surf.window = pCreateInfo->window;
1661 
1662     // Loop through each ICD and determine if they need to create a surface
1663     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1664         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1665             if (NULL != icd_term->dispatch.CreateScreenSurfaceQNX) {
1666                 result = icd_term->dispatch.CreateScreenSurfaceQNX(icd_term->instance, pCreateInfo, pAllocator,
1667                                                                    &icd_term->surface_list.list[icd_surface->surface_index]);
1668                 if (VK_SUCCESS != result) {
1669                     goto out;
1670                 }
1671             }
1672         }
1673     }
1674 
1675     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1676 
1677 out:
1678     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1679     loader_platform_thread_unlock_mutex(&loader_lock);
1680 
1681     return result;
1682 }
1683 
1684 // This is the trampoline entrypoint for
1685 // GetPhysicalDeviceScreenPresentationSupportQNX
vkGetPhysicalDeviceScreenPresentationSupportQNX(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,struct _screen_window * window)1686 LOADER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceScreenPresentationSupportQNX(VkPhysicalDevice physicalDevice,
1687                                                                                              uint32_t queueFamilyIndex,
1688                                                                                              struct _screen_window *window) {
1689     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1690     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1691         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1692                    "vkGetPhysicalDeviceScreenPresentationSupportQNX: Invalid physicalDevice "
1693                    "[VUID-vkGetPhysicalDeviceScreenPresentationSupportQNX-physicalDevice-parameter]");
1694         abort(); /* Intentionally fail so user can correct issue. */
1695     }
1696     const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(physicalDevice);
1697     VkBool32 res = disp->GetPhysicalDeviceScreenPresentationSupportQNX(unwrapped_phys_dev, queueFamilyIndex, window);
1698     return res;
1699 }
1700 
1701 // This is the instance chain terminator function for
1702 // GetPhysicalDeviceScreenPresentationSupportQNX
terminator_GetPhysicalDeviceScreenPresentationSupportQNX(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,struct _screen_window * window)1703 VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceScreenPresentationSupportQNX(VkPhysicalDevice physicalDevice,
1704                                                                                         uint32_t queueFamilyIndex,
1705                                                                                         struct _screen_window *window) {
1706     // First, check to ensure the appropriate extension was enabled:
1707     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1708     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1709     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1710     if (!loader_inst->wsi_screen_surface_enabled) {
1711         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1712                    "VK_QNX_screen_surface extension not enabled. vkGetPhysicalDeviceScreenPresentationSupportQNX not executed!");
1713         return VK_FALSE;
1714     }
1715 
1716     if (NULL == icd_term->dispatch.GetPhysicalDeviceScreenPresentationSupportQNX) {
1717         // return VK_FALSE as this driver doesn't support WSI functionality
1718         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1719                    "ICD for selected physical device does not export vkGetPhysicalDeviceScreenPresentationSupportQNX!");
1720         return VK_FALSE;
1721     }
1722 
1723     return icd_term->dispatch.GetPhysicalDeviceScreenPresentationSupportQNX(phys_dev_term->phys_dev, queueFamilyIndex, window);
1724 }
1725 #endif  // VK_USE_PLATFORM_SCREEN_QNX
1726 
1727 #if defined(VK_USE_PLATFORM_VI_NN)
1728 
1729 // Functions for the VK_NN_vi_surface extension:
1730 
1731 // This is the trampoline entrypoint for CreateViSurfaceNN
vkCreateViSurfaceNN(VkInstance instance,const VkViSurfaceCreateInfoNN * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1732 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(VkInstance instance, const VkViSurfaceCreateInfoNN *pCreateInfo,
1733                                                                  const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1734     struct loader_instance *loader_inst = loader_get_instance(instance);
1735     if (NULL == loader_inst) {
1736         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1737                    "vkCreateViSurfaceNN: Invalid instance [VUID-vkCreateViSurfaceNN-instance-parameter]");
1738         abort(); /* Intentionally fail so user can correct issue. */
1739     }
1740     return loader_inst->disp->layer_inst_disp.CreateViSurfaceNN(loader_inst->instance, pCreateInfo, pAllocator, pSurface);
1741 }
1742 
1743 // This is the instance chain terminator function for CreateViSurfaceNN
terminator_CreateViSurfaceNN(VkInstance instance,const VkViSurfaceCreateInfoNN * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)1744 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateViSurfaceNN(VkInstance instance, const VkViSurfaceCreateInfoNN *pCreateInfo,
1745                                                             const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
1746     VkResult result = VK_SUCCESS;
1747     VkIcdSurface *icd_surface = NULL;
1748     loader_platform_thread_lock_mutex(&loader_lock);
1749 
1750     // First, check to ensure the appropriate extension was enabled:
1751     struct loader_instance *loader_inst = loader_get_instance(instance);
1752     if (!loader_inst->wsi_vi_surface_enabled) {
1753         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1754                    "VK_NN_vi_surface extension not enabled. vkCreateViSurfaceNN not executed!");
1755         result = VK_ERROR_EXTENSION_NOT_PRESENT;
1756         goto out;
1757     }
1758 
1759     // Next, if so, proceed with the implementation of this function:
1760     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->vi_surf.base), sizeof(icd_surface->vi_surf), pAllocator,
1761                                          &icd_surface);
1762     if (VK_SUCCESS != result) {
1763         goto out;
1764     }
1765 
1766     icd_surface->vi_surf.base.platform = VK_ICD_WSI_PLATFORM_VI;
1767     icd_surface->vi_surf.window = pCreateInfo->window;
1768 
1769     // Loop through each ICD and determine if they need to create a surface
1770     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
1771         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
1772             if (NULL != icd_term->dispatch.CreateViSurfaceNN) {
1773                 result = icd_term->dispatch.CreateViSurfaceNN(icd_term->instance, pCreateInfo, pAllocator,
1774                                                               &icd_term->surface_list.list[icd_surface->surface_index]);
1775                 if (VK_SUCCESS != result) {
1776                     goto out;
1777                 }
1778             }
1779         }
1780     }
1781 
1782     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
1783 
1784 out:
1785     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
1786     loader_platform_thread_unlock_mutex(&loader_lock);
1787 
1788     return result;
1789 }
1790 
1791 #endif  // VK_USE_PLATFORM_VI_NN
1792 
1793 // Functions for the VK_KHR_display instance extension:
vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPropertiesKHR * pProperties)1794 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
1795                                                                                      uint32_t *pPropertyCount,
1796                                                                                      VkDisplayPropertiesKHR *pProperties) {
1797     const VkLayerInstanceDispatchTable *disp;
1798     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1799     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1800         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1801                    "vkGetPhysicalDeviceDisplayPropertiesKHR: Invalid physicalDevice "
1802                    "[VUID-vkGetPhysicalDeviceDisplayPropertiesKHR-physicalDevice-parameter]");
1803         abort(); /* Intentionally fail so user can correct issue. */
1804     }
1805     disp = loader_get_instance_layer_dispatch(physicalDevice);
1806     VkResult res = disp->GetPhysicalDeviceDisplayPropertiesKHR(unwrapped_phys_dev, pPropertyCount, pProperties);
1807     return res;
1808 }
1809 
terminator_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPropertiesKHR * pProperties)1810 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
1811                                                                                 uint32_t *pPropertyCount,
1812                                                                                 VkDisplayPropertiesKHR *pProperties) {
1813     // First, check to ensure the appropriate extension was enabled:
1814     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1815     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1816     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1817     if (!loader_inst->wsi_display_enabled) {
1818         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1819                    "VK_KHR_display extension not enabled. vkGetPhysicalDeviceDisplayPropertiesKHR not executed!");
1820         return VK_SUCCESS;
1821     }
1822 
1823     if (NULL == icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR) {
1824         loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0,
1825                    "ICD for selected physical device does not export vkGetPhysicalDeviceDisplayPropertiesKHR!");
1826         // return 0 for property count as this driver doesn't support WSI functionality
1827         if (pPropertyCount) {
1828             *pPropertyCount = 0;
1829         }
1830         return VK_SUCCESS;
1831     }
1832 
1833     return icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
1834 }
1835 
vkGetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPlanePropertiesKHR * pProperties)1836 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
1837     VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties) {
1838     const VkLayerInstanceDispatchTable *disp;
1839     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1840     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1841         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1842                    "vkGetPhysicalDeviceDisplayPlanePropertiesKHR: Invalid physicalDevice "
1843                    "[VUID-vkGetPhysicalDeviceDisplayPlanePropertiesKHR-physicalDevice-parameter]");
1844         abort(); /* Intentionally fail so user can correct issue. */
1845     }
1846     disp = loader_get_instance_layer_dispatch(physicalDevice);
1847     VkResult res = disp->GetPhysicalDeviceDisplayPlanePropertiesKHR(unwrapped_phys_dev, pPropertyCount, pProperties);
1848     return res;
1849 }
1850 
terminator_GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPlanePropertiesKHR * pProperties)1851 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,
1852                                                                                      uint32_t *pPropertyCount,
1853                                                                                      VkDisplayPlanePropertiesKHR *pProperties) {
1854     // First, check to ensure the appropriate extension was enabled:
1855     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1856     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1857     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1858     if (!loader_inst->wsi_display_enabled) {
1859         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1860                    "VK_KHR_display extension not enabled. vkGetPhysicalDeviceDisplayPlanePropertiesKHR not executed!");
1861         return VK_SUCCESS;
1862     }
1863 
1864     if (NULL == icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR) {
1865         loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0,
1866                    "ICD for selected physical device does not export vkGetPhysicalDeviceDisplayPlanePropertiesKHR!");
1867         // return 0 for property count as this driver doesn't support WSI functionality
1868         if (pPropertyCount) {
1869             *pPropertyCount = 0;
1870         }
1871         return VK_SUCCESS;
1872     }
1873 
1874     return icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
1875 }
1876 
vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,uint32_t planeIndex,uint32_t * pDisplayCount,VkDisplayKHR * pDisplays)1877 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
1878                                                                                    uint32_t planeIndex, uint32_t *pDisplayCount,
1879                                                                                    VkDisplayKHR *pDisplays) {
1880     const VkLayerInstanceDispatchTable *disp;
1881     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1882     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1883         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1884                    "vkGetDisplayPlaneSupportedDisplaysKHR: Invalid physicalDevice "
1885                    "[VUID-vkGetDisplayPlaneSupportedDisplaysKHR-physicalDevice-parameter]");
1886         abort(); /* Intentionally fail so user can correct issue. */
1887     }
1888     disp = loader_get_instance_layer_dispatch(physicalDevice);
1889     VkResult res = disp->GetDisplayPlaneSupportedDisplaysKHR(unwrapped_phys_dev, planeIndex, pDisplayCount, pDisplays);
1890     return res;
1891 }
1892 
terminator_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,uint32_t planeIndex,uint32_t * pDisplayCount,VkDisplayKHR * pDisplays)1893 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
1894                                                                               uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
1895     // First, check to ensure the appropriate extension was enabled:
1896     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1897     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1898     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1899     if (!loader_inst->wsi_display_enabled) {
1900         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1901                    "VK_KHR_display extension not enabled. vkGetDisplayPlaneSupportedDisplaysKHR not executed!");
1902         return VK_SUCCESS;
1903     }
1904 
1905     if (NULL == icd_term->dispatch.GetDisplayPlaneSupportedDisplaysKHR) {
1906         loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0,
1907                    "ICD for selected physical device does not export vkGetDisplayPlaneSupportedDisplaysKHR!");
1908         // return 0 for property count as this driver doesn't support WSI functionality
1909         if (pDisplayCount) {
1910             *pDisplayCount = 0;
1911         }
1912         return VK_SUCCESS;
1913     }
1914 
1915     return icd_term->dispatch.GetDisplayPlaneSupportedDisplaysKHR(phys_dev_term->phys_dev, planeIndex, pDisplayCount, pDisplays);
1916 }
1917 
vkGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModePropertiesKHR * pProperties)1918 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
1919                                                                            uint32_t *pPropertyCount,
1920                                                                            VkDisplayModePropertiesKHR *pProperties) {
1921     const VkLayerInstanceDispatchTable *disp;
1922     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1923     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1924         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1925                    "vkGetDisplayModePropertiesKHR: Invalid physicalDevice "
1926                    "[VUID-vkGetDisplayModePropertiesKHR-physicalDevice-parameter]");
1927         abort(); /* Intentionally fail so user can correct issue. */
1928     }
1929     disp = loader_get_instance_layer_dispatch(physicalDevice);
1930     VkResult res = disp->GetDisplayModePropertiesKHR(unwrapped_phys_dev, display, pPropertyCount, pProperties);
1931     return res;
1932 }
1933 
terminator_GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModePropertiesKHR * pProperties)1934 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
1935                                                                       uint32_t *pPropertyCount,
1936                                                                       VkDisplayModePropertiesKHR *pProperties) {
1937     // First, check to ensure the appropriate extension was enabled:
1938     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1939     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1940     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1941     if (!loader_inst->wsi_display_enabled) {
1942         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1943                    "VK_KHR_display extension not enabled. vkGetDisplayModePropertiesKHR not executed!");
1944         return VK_SUCCESS;
1945     }
1946 
1947     if (NULL == icd_term->dispatch.GetDisplayModePropertiesKHR) {
1948         loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0,
1949                    "ICD for selected physical device does not export vkGetDisplayModePropertiesKHR!");
1950         // return 0 for property count as this driver doesn't support WSI functionality
1951         if (pPropertyCount) {
1952             *pPropertyCount = 0;
1953         }
1954         return VK_SUCCESS;
1955     }
1956 
1957     return icd_term->dispatch.GetDisplayModePropertiesKHR(phys_dev_term->phys_dev, display, pPropertyCount, pProperties);
1958 }
1959 
vkCreateDisplayModeKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,const VkDisplayModeCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDisplayModeKHR * pMode)1960 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
1961                                                                     const VkDisplayModeCreateInfoKHR *pCreateInfo,
1962                                                                     const VkAllocationCallbacks *pAllocator,
1963                                                                     VkDisplayModeKHR *pMode) {
1964     const VkLayerInstanceDispatchTable *disp;
1965     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1966     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1967         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1968                    "vkCreateDisplayModeKHR: Invalid physicalDevice "
1969                    "[VUID-vkCreateDisplayModeKHR-physicalDevice-parameter]");
1970         abort(); /* Intentionally fail so user can correct issue. */
1971     }
1972     disp = loader_get_instance_layer_dispatch(physicalDevice);
1973     VkResult res = disp->CreateDisplayModeKHR(unwrapped_phys_dev, display, pCreateInfo, pAllocator, pMode);
1974     return res;
1975 }
1976 
terminator_CreateDisplayModeKHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,const VkDisplayModeCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDisplayModeKHR * pMode)1977 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
1978                                                                const VkDisplayModeCreateInfoKHR *pCreateInfo,
1979                                                                const VkAllocationCallbacks *pAllocator, VkDisplayModeKHR *pMode) {
1980     // First, check to ensure the appropriate extension was enabled:
1981     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1982     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1983     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
1984     if (!loader_inst->wsi_display_enabled) {
1985         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1986                    "VK_KHR_display extension not enabled. vkCreateDisplayModeKHR not executed!");
1987         return VK_ERROR_EXTENSION_NOT_PRESENT;
1988     }
1989 
1990     if (NULL == icd_term->dispatch.CreateDisplayModeKHR) {
1991         // Can't emulate, so return an appropriate error
1992         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
1993                    "ICD for selected physical device does not export vkCreateDisplayModeKHR!");
1994         return VK_ERROR_INITIALIZATION_FAILED;
1995     }
1996 
1997     return icd_term->dispatch.CreateDisplayModeKHR(phys_dev_term->phys_dev, display, pCreateInfo, pAllocator, pMode);
1998 }
1999 
vkGetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkDisplayModeKHR mode,uint32_t planeIndex,VkDisplayPlaneCapabilitiesKHR * pCapabilities)2000 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,
2001                                                                               VkDisplayModeKHR mode, uint32_t planeIndex,
2002                                                                               VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
2003     const VkLayerInstanceDispatchTable *disp;
2004     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2005     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2006         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2007                    "vkGetDisplayPlaneCapabilitiesKHR: Invalid physicalDevice "
2008                    "[VUID-vkGetDisplayPlaneCapabilitiesKHR-physicalDevice-parameter]");
2009         abort(); /* Intentionally fail so user can correct issue. */
2010     }
2011     disp = loader_get_instance_layer_dispatch(physicalDevice);
2012     VkResult res = disp->GetDisplayPlaneCapabilitiesKHR(unwrapped_phys_dev, mode, planeIndex, pCapabilities);
2013     return res;
2014 }
2015 
terminator_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkDisplayModeKHR mode,uint32_t planeIndex,VkDisplayPlaneCapabilitiesKHR * pCapabilities)2016 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode,
2017                                                                          uint32_t planeIndex,
2018                                                                          VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
2019     // First, check to ensure the appropriate extension was enabled:
2020     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2021     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2022     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
2023     if (!loader_inst->wsi_display_enabled) {
2024         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
2025                    "VK_KHR_display extension not enabled. vkGetDisplayPlaneCapabilitiesKHR not executed!");
2026         return VK_SUCCESS;
2027     }
2028 
2029     if (NULL == icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR) {
2030         // Emulate support
2031         loader_log(loader_inst, VULKAN_LOADER_WARN_BIT, 0,
2032                    "ICD for selected physical device does not export vkGetDisplayPlaneCapabilitiesKHR!");
2033         if (pCapabilities) {
2034             memset(pCapabilities, 0, sizeof(VkDisplayPlaneCapabilitiesKHR));
2035         }
2036         return VK_SUCCESS;
2037     }
2038 
2039     return icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR(phys_dev_term->phys_dev, mode, planeIndex, pCapabilities);
2040 }
2041 
vkCreateDisplayPlaneSurfaceKHR(VkInstance instance,const VkDisplaySurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)2042 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(VkInstance instance,
2043                                                                             const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
2044                                                                             const VkAllocationCallbacks *pAllocator,
2045                                                                             VkSurfaceKHR *pSurface) {
2046     struct loader_instance *loader_inst = loader_get_instance(instance);
2047     if (NULL == loader_inst) {
2048         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2049                    "vkCreateDisplayPlaneSurfaceKHR: Invalid instance [VUID-vkCreateDisplayPlaneSurfaceKHR-instance-parameter]");
2050         abort(); /* Intentionally fail so user can correct issue. */
2051     }
2052     return loader_inst->disp->layer_inst_disp.CreateDisplayPlaneSurfaceKHR(loader_inst->instance, pCreateInfo, pAllocator,
2053                                                                            pSurface);
2054 }
2055 
terminator_CreateDisplayPlaneSurfaceKHR(VkInstance instance,const VkDisplaySurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)2056 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(VkInstance instance,
2057                                                                        const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
2058                                                                        const VkAllocationCallbacks *pAllocator,
2059                                                                        VkSurfaceKHR *pSurface) {
2060     VkResult result = VK_SUCCESS;
2061     VkIcdSurface *icd_surface = NULL;
2062     loader_platform_thread_lock_mutex(&loader_lock);
2063 
2064     // First, check to ensure the appropriate extension was enabled:
2065     struct loader_instance *loader_inst = loader_get_instance(instance);
2066     if (!loader_inst->wsi_display_enabled) {
2067         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
2068                    "VK_KHR_surface extension not enabled. vkCreateDisplayPlaneSurfaceKHR not executed!");
2069         result = VK_ERROR_EXTENSION_NOT_PRESENT;
2070         goto out;
2071     }
2072 
2073     // Next, if so, proceed with the implementation of this function:
2074     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->display_surf.base), sizeof(icd_surface->display_surf),
2075                                          pAllocator, &icd_surface);
2076     if (VK_SUCCESS != result) {
2077         goto out;
2078     }
2079 
2080     icd_surface->display_surf.base.platform = VK_ICD_WSI_PLATFORM_DISPLAY;
2081     icd_surface->display_surf.displayMode = pCreateInfo->displayMode;
2082     icd_surface->display_surf.planeIndex = pCreateInfo->planeIndex;
2083     icd_surface->display_surf.planeStackIndex = pCreateInfo->planeStackIndex;
2084     icd_surface->display_surf.transform = pCreateInfo->transform;
2085     icd_surface->display_surf.globalAlpha = pCreateInfo->globalAlpha;
2086     icd_surface->display_surf.alphaMode = pCreateInfo->alphaMode;
2087     icd_surface->display_surf.imageExtent = pCreateInfo->imageExtent;
2088 
2089     // Loop through each ICD and determine if they need to create a surface
2090     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
2091         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
2092             if (NULL != icd_term->dispatch.CreateDisplayPlaneSurfaceKHR) {
2093                 result = icd_term->dispatch.CreateDisplayPlaneSurfaceKHR(icd_term->instance, pCreateInfo, pAllocator,
2094                                                                          &icd_term->surface_list.list[icd_surface->surface_index]);
2095                 if (VK_SUCCESS != result) {
2096                     goto out;
2097                 }
2098             }
2099         }
2100     }
2101 
2102     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
2103 
2104 out:
2105     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
2106     loader_platform_thread_unlock_mutex(&loader_lock);
2107 
2108     return result;
2109 }
2110 
2111 // EXT_display_swapchain Extension command
2112 
vkCreateSharedSwapchainsKHR(VkDevice device,uint32_t swapchainCount,const VkSwapchainCreateInfoKHR * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchains)2113 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
2114                                                                          const VkSwapchainCreateInfoKHR *pCreateInfos,
2115                                                                          const VkAllocationCallbacks *pAllocator,
2116                                                                          VkSwapchainKHR *pSwapchains) {
2117     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
2118     if (NULL == disp) {
2119         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2120                    "vkCreateSharedSwapchainsKHR: Invalid device [VUID-vkCreateSharedSwapchainsKHR-device-parameter]");
2121         abort(); /* Intentionally fail so user can correct issue. */
2122     }
2123     return disp->CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
2124 }
2125 
terminator_CreateSharedSwapchainsKHR(VkDevice device,uint32_t swapchainCount,const VkSwapchainCreateInfoKHR * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchains)2126 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
2127                                                                     const VkSwapchainCreateInfoKHR *pCreateInfos,
2128                                                                     const VkAllocationCallbacks *pAllocator,
2129                                                                     VkSwapchainKHR *pSwapchains) {
2130     struct loader_device *dev;
2131     struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
2132     if (NULL == icd_term || NULL == dev) {
2133         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2134                    "vkCreateSharedSwapchainsKHR Terminator: Invalid device handle. This is likely the result of a "
2135                    "layer wrapping device handles and failing to unwrap them in all functions. "
2136                    "[VUID-vkCreateSharedSwapchainsKHR-device-parameter]");
2137         abort(); /* Intentionally fail so user can correct issue. */
2138     }
2139     if (NULL != icd_term->surface_list.list) {
2140         loader_log(NULL, VULKAN_LOADER_ERROR_BIT, 0,
2141                    "vkCreateSharedSwapchainsKHR Terminator: No VkSurfaceKHR objects were created, indicating an application "
2142                    "bug. Returning VK_SUCCESS. ");
2143         return VK_SUCCESS;
2144     }
2145     if (NULL == dev->loader_dispatch.extension_terminator_dispatch.CreateSharedSwapchainsKHR) {
2146         loader_log(NULL, VULKAN_LOADER_ERROR_BIT, 0,
2147                    "vkCreateSharedSwapchainsKHR Terminator: Driver's function pointer was NULL, returning VK_SUCCESS. Was the "
2148                    "VK_KHR_display_swapchain extension enabled?");
2149         return VK_SUCCESS;
2150     }
2151 
2152     VkSwapchainCreateInfoKHR *pCreateCopy = loader_stack_alloc(sizeof(VkSwapchainCreateInfoKHR) * swapchainCount);
2153     if (NULL == pCreateCopy) {
2154         return VK_ERROR_OUT_OF_HOST_MEMORY;
2155     }
2156     memcpy(pCreateCopy, pCreateInfos, sizeof(VkSwapchainCreateInfoKHR) * swapchainCount);
2157     for (uint32_t sc = 0; sc < swapchainCount; sc++) {
2158         VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pCreateCopy[sc].surface;
2159         if (icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
2160             icd_term->surface_list.list[icd_surface->surface_index]) {
2161             pCreateCopy[sc].surface = icd_term->surface_list.list[icd_surface->surface_index];
2162         }
2163     }
2164     return dev->loader_dispatch.extension_terminator_dispatch.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateCopy,
2165                                                                                         pAllocator, pSwapchains);
2166 }
2167 
2168 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkGetDeviceGroupPresentCapabilitiesKHR(VkDevice device,VkDeviceGroupPresentCapabilitiesKHR * pDeviceGroupPresentCapabilities)2169 vkGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities) {
2170     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
2171     if (NULL == disp) {
2172         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2173                    "vkGetDeviceGroupPresentCapabilitiesKHR: Invalid device "
2174                    "[VUID-vkGetDeviceGroupPresentCapabilitiesKHR-device-parameter]");
2175         abort(); /* Intentionally fail so user can correct issue. */
2176     }
2177     return disp->GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
2178 }
2179 
vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device,VkSurfaceKHR surface,VkDeviceGroupPresentModeFlagsKHR * pModes)2180 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface,
2181                                                                                     VkDeviceGroupPresentModeFlagsKHR *pModes) {
2182     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
2183     if (NULL == disp) {
2184         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2185                    "vkGetDeviceGroupSurfacePresentModesKHR: Invalid device "
2186                    "[VUID-vkGetDeviceGroupSurfacePresentModesKHR-device-parameter]");
2187         abort(); /* Intentionally fail so user can correct issue. */
2188     }
2189     return disp->GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
2190 }
2191 
terminator_GetDeviceGroupSurfacePresentModesKHR(VkDevice device,VkSurfaceKHR surface,VkDeviceGroupPresentModeFlagsKHR * pModes)2192 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface,
2193                                                                                VkDeviceGroupPresentModeFlagsKHR *pModes) {
2194     struct loader_device *dev;
2195     struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev);
2196     if (NULL == icd_term || NULL == dev) {
2197         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2198                    "vkGetDeviceGroupSurfacePresentModesKHR: Invalid device "
2199                    "[VUID-vkGetDeviceGroupSurfacePresentModesKHR-device-parameter]");
2200         abort(); /* Intentionally fail so user can correct issue. */
2201     }
2202     if (NULL == dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModesKHR) {
2203         loader_log(NULL, VULKAN_LOADER_ERROR_BIT, 0,
2204                    "vkGetDeviceGroupSurfacePresentModesKHR: Driver's function pointer was NULL, returning VK_SUCCESS. Was either "
2205                    "Vulkan 1.1 and VK_KHR_swapchain enabled or both the VK_KHR_device_group and VK_KHR_surface "
2206                    "extensions enabled when using Vulkan 1.0?");
2207         return VK_SUCCESS;
2208     }
2209     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)surface;
2210     if (NULL != icd_term->surface_list.list &&
2211         icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
2212         icd_term->surface_list.list[icd_surface->surface_index]) {
2213         return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModesKHR(
2214             device, icd_term->surface_list.list[icd_surface->surface_index], pModes);
2215     }
2216     return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
2217 }
2218 
vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pRectCount,VkRect2D * pRects)2219 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
2220                                                                                      VkSurfaceKHR surface, uint32_t *pRectCount,
2221                                                                                      VkRect2D *pRects) {
2222     const VkLayerInstanceDispatchTable *disp;
2223     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2224     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2225         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2226                    "vkGetPhysicalDevicePresentRectanglesKHR: Invalid physicalDevice "
2227                    "[VUID-vkGetPhysicalDevicePresentRectanglesKHR-physicalDevice-parameter]");
2228         abort(); /* Intentionally fail so user can correct issue. */
2229     }
2230     disp = loader_get_instance_layer_dispatch(physicalDevice);
2231     return disp->GetPhysicalDevicePresentRectanglesKHR(unwrapped_phys_dev, surface, pRectCount, pRects);
2232 }
2233 
terminator_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pRectCount,VkRect2D * pRects)2234 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
2235                                                                                 VkSurfaceKHR surface, uint32_t *pRectCount,
2236                                                                                 VkRect2D *pRects) {
2237     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2238     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2239     if (NULL == icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR) {
2240         loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
2241                    "ICD associated with VkPhysicalDevice does not support GetPhysicalDevicePresentRectanglesKHX");
2242         // return as this driver doesn't support WSI functionality
2243         if (pRectCount) {
2244             *pRectCount = 0;
2245         }
2246         return VK_SUCCESS;
2247     }
2248     VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
2249     if (NULL != icd_term->surface_list.list &&
2250         icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
2251         icd_term->surface_list.list[icd_surface->surface_index]) {
2252         return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR(
2253             phys_dev_term->phys_dev, icd_term->surface_list.list[icd_surface->surface_index], pRectCount, pRects);
2254     }
2255     return icd_term->dispatch.GetPhysicalDevicePresentRectanglesKHR(phys_dev_term->phys_dev, surface, pRectCount, pRects);
2256 }
2257 
vkAcquireNextImage2KHR(VkDevice device,const VkAcquireNextImageInfoKHR * pAcquireInfo,uint32_t * pImageIndex)2258 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo,
2259                                                                     uint32_t *pImageIndex) {
2260     const VkLayerDispatchTable *disp = loader_get_dispatch(device);
2261     if (NULL == disp) {
2262         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2263                    "vkAcquireNextImage2KHR: Invalid device [VUID-vkAcquireNextImage2KHR-device-parameter]");
2264         abort(); /* Intentionally fail so user can correct issue. */
2265     }
2266     return disp->AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
2267 }
2268 
2269 // ---- VK_KHR_get_display_properties2 extension trampoline/terminators
2270 
vkGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayProperties2KHR * pProperties)2271 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
2272                                                                                       uint32_t *pPropertyCount,
2273                                                                                       VkDisplayProperties2KHR *pProperties) {
2274     const VkLayerInstanceDispatchTable *disp;
2275     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2276     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2277         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2278                    "vkGetPhysicalDeviceDisplayProperties2KHR: Invalid physicalDevice "
2279                    "[VUID-vkGetPhysicalDeviceDisplayProperties2KHR-physicalDevice-parameter]");
2280         abort(); /* Intentionally fail so user can correct issue. */
2281     }
2282     disp = loader_get_instance_layer_dispatch(physicalDevice);
2283     return disp->GetPhysicalDeviceDisplayProperties2KHR(unwrapped_phys_dev, pPropertyCount, pProperties);
2284 }
2285 
terminator_GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayProperties2KHR * pProperties)2286 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
2287                                                                                  uint32_t *pPropertyCount,
2288                                                                                  VkDisplayProperties2KHR *pProperties) {
2289     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2290     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2291 
2292     // If the function is available in the driver, just call into it
2293     if (icd_term->dispatch.GetPhysicalDeviceDisplayProperties2KHR != NULL) {
2294         return icd_term->dispatch.GetPhysicalDeviceDisplayProperties2KHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
2295     }
2296 
2297     // We have to emulate the function.
2298     loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
2299                "vkGetPhysicalDeviceDisplayProperties2KHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
2300 
2301     // If the icd doesn't support VK_KHR_display, then no properties are available
2302     if (icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR == NULL) {
2303         *pPropertyCount = 0;
2304         return VK_SUCCESS;
2305     }
2306 
2307     // If we aren't writing to pProperties, then emulation is straightforward
2308     if (pProperties == NULL || *pPropertyCount == 0) {
2309         return icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, NULL);
2310     }
2311 
2312     // If we do have to write to pProperties, then we need to write to a temporary array of VkDisplayPropertiesKHR and copy it
2313     VkDisplayPropertiesKHR *properties = loader_stack_alloc(*pPropertyCount * sizeof(VkDisplayPropertiesKHR));
2314     if (properties == NULL) {
2315         return VK_ERROR_OUT_OF_HOST_MEMORY;
2316     }
2317     VkResult res = icd_term->dispatch.GetPhysicalDeviceDisplayPropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, properties);
2318     if (res < 0) {
2319         return res;
2320     }
2321     for (uint32_t i = 0; i < *pPropertyCount; ++i) {
2322         memcpy(&pProperties[i].displayProperties, &properties[i], sizeof(VkDisplayPropertiesKHR));
2323     }
2324     return res;
2325 }
2326 
vkGetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPlaneProperties2KHR * pProperties)2327 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlaneProperties2KHR(
2328     VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlaneProperties2KHR *pProperties) {
2329     const VkLayerInstanceDispatchTable *disp;
2330     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2331     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2332         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2333                    "vkGetPhysicalDeviceDisplayPlaneProperties2KHR: Invalid physicalDevice "
2334                    "[VUID-vkGetPhysicalDeviceDisplayPlaneProperties2KHR-physicalDevice-parameter]");
2335         abort(); /* Intentionally fail so user can correct issue. */
2336     }
2337     disp = loader_get_instance_layer_dispatch(physicalDevice);
2338     return disp->GetPhysicalDeviceDisplayPlaneProperties2KHR(unwrapped_phys_dev, pPropertyCount, pProperties);
2339 }
2340 
terminator_GetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkDisplayPlaneProperties2KHR * pProperties)2341 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,
2342                                                                                       uint32_t *pPropertyCount,
2343                                                                                       VkDisplayPlaneProperties2KHR *pProperties) {
2344     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2345     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2346 
2347     // If the function is available in the driver, just call into it
2348     if (icd_term->dispatch.GetPhysicalDeviceDisplayPlaneProperties2KHR != NULL) {
2349         return icd_term->dispatch.GetPhysicalDeviceDisplayPlaneProperties2KHR(phys_dev_term->phys_dev, pPropertyCount, pProperties);
2350     }
2351 
2352     // We have to emulate the function.
2353     loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
2354                "vkGetPhysicalDeviceDisplayPlaneProperties2KHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
2355 
2356     // If the icd doesn't support VK_KHR_display, then no properties are available
2357     if (icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR == NULL) {
2358         *pPropertyCount = 0;
2359         return VK_SUCCESS;
2360     }
2361 
2362     // If we aren't writing to pProperties, then emulation is straightforward
2363     if (pProperties == NULL || *pPropertyCount == 0) {
2364         return icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, NULL);
2365     }
2366 
2367     // If we do have to write to pProperties, then we need to write to a temporary array of VkDisplayPlanePropertiesKHR and copy it
2368     VkDisplayPlanePropertiesKHR *properties = loader_stack_alloc(*pPropertyCount * sizeof(VkDisplayPlanePropertiesKHR));
2369     if (properties == NULL) {
2370         return VK_ERROR_OUT_OF_HOST_MEMORY;
2371     }
2372     VkResult res =
2373         icd_term->dispatch.GetPhysicalDeviceDisplayPlanePropertiesKHR(phys_dev_term->phys_dev, pPropertyCount, properties);
2374     if (res < 0) {
2375         return res;
2376     }
2377     for (uint32_t i = 0; i < *pPropertyCount; ++i) {
2378         memcpy(&pProperties[i].displayPlaneProperties, &properties[i], sizeof(VkDisplayPlanePropertiesKHR));
2379     }
2380     return res;
2381 }
2382 
vkGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModeProperties2KHR * pProperties)2383 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
2384                                                                             uint32_t *pPropertyCount,
2385                                                                             VkDisplayModeProperties2KHR *pProperties) {
2386     const VkLayerInstanceDispatchTable *disp;
2387     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2388     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2389         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2390                    "vkGetDisplayModeProperties2KHR: Invalid physicalDevice "
2391                    "[VUID-vkGetDisplayModeProperties2KHR-physicalDevice-parameter]");
2392         abort(); /* Intentionally fail so user can correct issue. */
2393     }
2394     disp = loader_get_instance_layer_dispatch(physicalDevice);
2395     return disp->GetDisplayModeProperties2KHR(unwrapped_phys_dev, display, pPropertyCount, pProperties);
2396 }
2397 
terminator_GetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t * pPropertyCount,VkDisplayModeProperties2KHR * pProperties)2398 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
2399                                                                        uint32_t *pPropertyCount,
2400                                                                        VkDisplayModeProperties2KHR *pProperties) {
2401     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2402     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2403 
2404     // If the function is available in the driver, just call into it
2405     if (icd_term->dispatch.GetDisplayModeProperties2KHR != NULL) {
2406         return icd_term->dispatch.GetDisplayModeProperties2KHR(phys_dev_term->phys_dev, display, pPropertyCount, pProperties);
2407     }
2408 
2409     // We have to emulate the function.
2410     loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0, "vkGetDisplayModeProperties2KHR: Emulating call in ICD \"%s\"",
2411                icd_term->scanned_icd->lib_name);
2412 
2413     // If the icd doesn't support VK_KHR_display, then no properties are available
2414     if (icd_term->dispatch.GetDisplayModePropertiesKHR == NULL) {
2415         *pPropertyCount = 0;
2416         return VK_SUCCESS;
2417     }
2418 
2419     // If we aren't writing to pProperties, then emulation is straightforward
2420     if (pProperties == NULL || *pPropertyCount == 0) {
2421         return icd_term->dispatch.GetDisplayModePropertiesKHR(phys_dev_term->phys_dev, display, pPropertyCount, NULL);
2422     }
2423 
2424     // If we do have to write to pProperties, then we need to write to a temporary array of VkDisplayModePropertiesKHR and copy it
2425     VkDisplayModePropertiesKHR *properties = loader_stack_alloc(*pPropertyCount * sizeof(VkDisplayModePropertiesKHR));
2426     if (properties == NULL) {
2427         return VK_ERROR_OUT_OF_HOST_MEMORY;
2428     }
2429     VkResult res = icd_term->dispatch.GetDisplayModePropertiesKHR(phys_dev_term->phys_dev, display, pPropertyCount, properties);
2430     if (res < 0) {
2431         return res;
2432     }
2433     for (uint32_t i = 0; i < *pPropertyCount; ++i) {
2434         memcpy(&pProperties[i].displayModeProperties, &properties[i], sizeof(VkDisplayModePropertiesKHR));
2435     }
2436     return res;
2437 }
2438 
vkGetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,const VkDisplayPlaneInfo2KHR * pDisplayPlaneInfo,VkDisplayPlaneCapabilities2KHR * pCapabilities)2439 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
2440                                                                                const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
2441                                                                                VkDisplayPlaneCapabilities2KHR *pCapabilities) {
2442     const VkLayerInstanceDispatchTable *disp;
2443     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2444     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2445         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2446                    "vkGetDisplayPlaneCapabilities2KHR: Invalid physicalDevice "
2447                    "[VUID-vkGetDisplayPlaneCapabilities2KHR-physicalDevice-parameter]");
2448         abort(); /* Intentionally fail so user can correct issue. */
2449     }
2450     disp = loader_get_instance_layer_dispatch(physicalDevice);
2451     return disp->GetDisplayPlaneCapabilities2KHR(unwrapped_phys_dev, pDisplayPlaneInfo, pCapabilities);
2452 }
2453 
terminator_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,const VkDisplayPlaneInfo2KHR * pDisplayPlaneInfo,VkDisplayPlaneCapabilities2KHR * pCapabilities)2454 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
2455                                                                           const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
2456                                                                           VkDisplayPlaneCapabilities2KHR *pCapabilities) {
2457     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2458     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2459 
2460     // If the function is available in the driver, just call into it
2461     if (icd_term->dispatch.GetDisplayPlaneCapabilities2KHR != NULL) {
2462         return icd_term->dispatch.GetDisplayPlaneCapabilities2KHR(phys_dev_term->phys_dev, pDisplayPlaneInfo, pCapabilities);
2463     }
2464 
2465     // We have to emulate the function.
2466     loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
2467                "vkGetDisplayPlaneCapabilities2KHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
2468 
2469     // If the icd doesn't support VK_KHR_display, then there are no capabilities
2470     if (NULL == icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR) {
2471         if (pCapabilities) {
2472             memset(&pCapabilities->capabilities, 0, sizeof(VkDisplayPlaneCapabilitiesKHR));
2473         }
2474         return VK_SUCCESS;
2475     }
2476 
2477     // Just call into the old version of the function.
2478     return icd_term->dispatch.GetDisplayPlaneCapabilitiesKHR(phys_dev_term->phys_dev, pDisplayPlaneInfo->mode,
2479                                                              pDisplayPlaneInfo->planeIndex, &pCapabilities->capabilities);
2480 }
2481 
2482 #if defined(VK_USE_PLATFORM_FUCHSIA)
2483 
2484 // This is the trampoline entrypoint for CreateImagePipeSurfaceFUCHSIA
vkCreateImagePipeSurfaceFUCHSIA(VkInstance instance,const VkImagePipeSurfaceCreateInfoFUCHSIA * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)2485 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA(VkInstance instance,
2486                                                                              const VkImagePipeSurfaceCreateInfoFUCHSIA *pCreateInfo,
2487                                                                              const VkAllocationCallbacks *pAllocator,
2488                                                                              VkSurfaceKHR *pSurface) {
2489     struct loader_instance *loader_inst = loader_get_instance(instance);
2490     if (NULL == loader_inst) {
2491         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2492                    "vkCreateImagePipeSurfaceFUCHSIA: Invalid instance [VUID-vkCreateImagePipeSurfaceFUCHSIA-instance-parameter]");
2493         abort(); /* Intentionally fail so user can correct issue. */
2494     }
2495     return loader_inst->disp->layer_inst_disp.CreateImagePipeSurfaceFUCHSIA(loader_inst->instance, pCreateInfo, pAllocator,
2496                                                                             pSurface);
2497 }
2498 
2499 // This is the instance chain terminator function for CreateImagePipeSurfaceFUCHSIA
terminator_CreateImagePipeSurfaceFUCHSIA(VkInstance instance,const VkImagePipeSurfaceCreateInfoFUCHSIA * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)2500 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA(VkInstance instance,
2501                                                                         const VkImagePipeSurfaceCreateInfoFUCHSIA *pCreateInfo,
2502                                                                         const VkAllocationCallbacks *pAllocator,
2503                                                                         VkSurfaceKHR *pSurface) {
2504     VkResult result = VK_SUCCESS;
2505     VkIcdSurface *icd_surface = NULL;
2506 
2507     // Initialize pSurface to NULL just to be safe.
2508     *pSurface = VK_NULL_HANDLE;
2509     // First, check to ensure the appropriate extension was enabled:
2510     struct loader_instance *loader_inst = loader_get_instance(instance);
2511     if (!loader_inst->wsi_imagepipe_surface_enabled) {
2512         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
2513                    "VK_FUCHSIA_imagepipe_surface extension not enabled.  "
2514                    "vkCreateImagePipeSurfaceFUCHSIA not executed!");
2515         result = VK_ERROR_EXTENSION_NOT_PRESENT;
2516         goto out;
2517     }
2518 
2519     // Next, if so, proceed with the implementation of this function:
2520     result = allocate_icd_surface_struct(loader_inst, sizeof(icd_surface->imagepipe_surf.base), sizeof(icd_surface->imagepipe_surf),
2521                                          pAllocator, &icd_surface);
2522     if (VK_SUCCESS != result) {
2523         goto out;
2524     }
2525 
2526     icd_surface->imagepipe_surf.base.platform = VK_ICD_WSI_PLATFORM_FUCHSIA;
2527 
2528     // Loop through each ICD and determine if they need to create a surface
2529     for (struct loader_icd_term *icd_term = loader_inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
2530         if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) {
2531             if (NULL != icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA) {
2532                 result = icd_term->dispatch.CreateImagePipeSurfaceFUCHSIA(icd_term->instance, pCreateInfo, pAllocator,
2533                                                                           &icd_term->surface_list.list[icd_surface->surface_index]);
2534                 if (VK_SUCCESS != result) {
2535                     goto out;
2536                 }
2537             }
2538         }
2539     }
2540 
2541     *pSurface = (VkSurfaceKHR)(uintptr_t)icd_surface;
2542 
2543 out:
2544     cleanup_surface_creation(loader_inst, result, icd_surface, pAllocator);
2545 
2546     return result;
2547 }
2548 #endif  // VK_USE_PLATFORM_FUCHSIA
2549 
2550 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkSurfaceCapabilities2KHR * pSurfaceCapabilities)2551 vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
2552                                            VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
2553     const VkLayerInstanceDispatchTable *disp;
2554     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2555     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2556         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2557                    "vkGetPhysicalDeviceSurfaceCapabilities2KHR: Invalid physicalDevice "
2558                    "[VUID-vkGetPhysicalDeviceSurfaceCapabilities2KHR-physicalDevice-parameter]");
2559         abort(); /* Intentionally fail so user can correct issue. */
2560     }
2561     disp = loader_get_instance_layer_dispatch(physicalDevice);
2562     return disp->GetPhysicalDeviceSurfaceCapabilities2KHR(unwrapped_phys_dev, pSurfaceInfo, pSurfaceCapabilities);
2563 }
2564 
emulate_VK_EXT_surface_maintenance1(struct loader_icd_term * icd_term,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkSurfaceCapabilities2KHR * pSurfaceCapabilities)2565 void emulate_VK_EXT_surface_maintenance1(struct loader_icd_term *icd_term, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
2566                                          VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
2567     // Because VK_EXT_surface_maintenance1 is an instance extension, applications will use it to query info on drivers which do
2568     // not support the extension. Thus we need to emulate the driver filling out the structs in that case.
2569     if (!icd_term->supports_ext_surface_maintenance_1) {
2570         VkPresentModeKHR present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR;
2571         const void *void_pNext = pSurfaceInfo->pNext;
2572         while (void_pNext) {
2573             VkBaseOutStructure out_structure = {0};
2574             memcpy(&out_structure, void_pNext, sizeof(VkBaseOutStructure));
2575             if (out_structure.sType == VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT) {
2576                 VkSurfacePresentModeEXT *surface_present_mode = (VkSurfacePresentModeEXT *)void_pNext;
2577                 present_mode = surface_present_mode->presentMode;
2578             }
2579             void_pNext = out_structure.pNext;
2580         }
2581         // If no VkSurfacePresentModeEXT was present, return
2582         if (present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR) {
2583             return;
2584         }
2585 
2586         void_pNext = pSurfaceCapabilities->pNext;
2587         while (void_pNext) {
2588             VkBaseOutStructure out_structure = {0};
2589             memcpy(&out_structure, void_pNext, sizeof(VkBaseOutStructure));
2590             if (out_structure.sType == VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT) {
2591                 VkSurfacePresentModeCompatibilityEXT *surface_present_mode_compatibility =
2592                     (VkSurfacePresentModeCompatibilityEXT *)void_pNext;
2593                 if (surface_present_mode_compatibility->pPresentModes) {
2594                     if (surface_present_mode_compatibility->presentModeCount != 0) {
2595                         surface_present_mode_compatibility->pPresentModes[0] = present_mode;
2596                         surface_present_mode_compatibility->presentModeCount = 1;
2597                     }
2598                 } else {
2599                     surface_present_mode_compatibility->presentModeCount = 1;
2600                 }
2601 
2602             } else if (out_structure.sType == VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT) {
2603                 // Because there is no way to fill out the information faithfully, set scaled max/min image extent to the
2604                 // surface capabilities max/min extent and the rest to zero.
2605                 VkSurfacePresentScalingCapabilitiesEXT *surface_present_scaling_capabilities =
2606                     (VkSurfacePresentScalingCapabilitiesEXT *)void_pNext;
2607                 surface_present_scaling_capabilities->supportedPresentScaling = 0;
2608                 surface_present_scaling_capabilities->supportedPresentGravityX = 0;
2609                 surface_present_scaling_capabilities->supportedPresentGravityY = 0;
2610                 surface_present_scaling_capabilities->maxScaledImageExtent =
2611                     pSurfaceCapabilities->surfaceCapabilities.maxImageExtent;
2612                 surface_present_scaling_capabilities->minScaledImageExtent =
2613                     pSurfaceCapabilities->surfaceCapabilities.minImageExtent;
2614             }
2615             void_pNext = out_structure.pNext;
2616         }
2617     }
2618 }
2619 
terminator_GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkSurfaceCapabilities2KHR * pSurfaceCapabilities)2620 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2KHR(
2621     VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
2622     VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
2623     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2624     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2625     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
2626     VkIcdSurface *icd_surface = NULL;
2627     if (pSurfaceInfo->surface) {
2628         icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
2629     }
2630 
2631     if (!loader_inst->wsi_surface_enabled) {
2632         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
2633                    "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceCapabilities2KHR not executed!");
2634         return VK_SUCCESS;
2635     }
2636 
2637     if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR != NULL) {
2638         void *pNext = pSurfaceCapabilities->pNext;
2639         while (pNext != NULL) {
2640             VkBaseOutStructure pNext_out_structure = {0};
2641             memcpy(&pNext_out_structure, pNext, sizeof(VkBaseOutStructure));
2642             if (pNext_out_structure.sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR) {
2643                 // Not all ICDs may be supporting VK_KHR_surface_protected_capabilities
2644                 // Initialize VkSurfaceProtectedCapabilitiesKHR.supportsProtected to false and
2645                 // if an ICD supports protected surfaces, it will reset it to true accordingly.
2646                 ((VkSurfaceProtectedCapabilitiesKHR *)pNext)->supportsProtected = VK_FALSE;
2647             }
2648             pNext = pNext_out_structure.pNext;
2649         }
2650 
2651         VkResult res = VK_SUCCESS;
2652 
2653         // Pass the call to the driver, possibly unwrapping the ICD surface
2654         if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
2655             icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
2656             icd_term->surface_list.list[icd_surface->surface_index]) {
2657             VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
2658             info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
2659             res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, &info_copy,
2660                                                                               pSurfaceCapabilities);
2661         } else {
2662             res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, pSurfaceInfo,
2663                                                                               pSurfaceCapabilities);
2664         }
2665 
2666         // Because VK_EXT_surface_maintenance1 is an instance extension, applications will use it to query info on drivers which do
2667         // not support the extension. Thus we need to emulate the driver filling out the structs in that case.
2668         if (!icd_term->supports_ext_surface_maintenance_1) {
2669             emulate_VK_EXT_surface_maintenance1(icd_term, pSurfaceInfo, pSurfaceCapabilities);
2670         }
2671 
2672         return res;
2673     } else {
2674         // Emulate the call
2675         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
2676                    "vkGetPhysicalDeviceSurfaceCapabilities2KHR: Emulating call in ICD \"%s\" using "
2677                    "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
2678                    icd_term->scanned_icd->lib_name);
2679 
2680         // Write to the VkSurfaceCapabilities2KHR struct
2681         VkSurfaceKHR surface = VK_NULL_HANDLE;
2682         if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
2683             icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
2684             icd_term->surface_list.list[icd_surface->surface_index]) {
2685             surface = icd_term->surface_list.list[icd_surface->surface_index];
2686         }
2687 
2688         // If the icd doesn't support VK_KHR_surface, then there are no capabilities
2689         if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR) {
2690             if (pSurfaceCapabilities) {
2691                 memset(&pSurfaceCapabilities->surfaceCapabilities, 0, sizeof(VkSurfaceCapabilitiesKHR));
2692             }
2693             return VK_SUCCESS;
2694         }
2695         VkResult res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface,
2696                                                                                   &pSurfaceCapabilities->surfaceCapabilities);
2697 
2698         emulate_VK_EXT_surface_maintenance1(icd_term, pSurfaceInfo, pSurfaceCapabilities);
2699         return res;
2700     }
2701 }
2702 
2703 LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,uint32_t * pSurfaceFormatCount,VkSurfaceFormat2KHR * pSurfaceFormats)2704 vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
2705                                       uint32_t *pSurfaceFormatCount, VkSurfaceFormat2KHR *pSurfaceFormats) {
2706     const VkLayerInstanceDispatchTable *disp;
2707     VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2708     if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2709         loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2710                    "vkGetPhysicalDeviceSurfaceFormats2KHR: Invalid physicalDevice "
2711                    "[VUID-vkGetPhysicalDeviceSurfaceFormats2KHR-physicalDevice-parameter]");
2712         abort(); /* Intentionally fail so user can correct issue. */
2713     }
2714     disp = loader_get_instance_layer_dispatch(physicalDevice);
2715     return disp->GetPhysicalDeviceSurfaceFormats2KHR(unwrapped_phys_dev, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats);
2716 }
2717 
terminator_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,uint32_t * pSurfaceFormatCount,VkSurfaceFormat2KHR * pSurfaceFormats)2718 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
2719                                                                               const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
2720                                                                               uint32_t *pSurfaceFormatCount,
2721                                                                               VkSurfaceFormat2KHR *pSurfaceFormats) {
2722     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2723     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2724     struct loader_instance *loader_inst = (struct loader_instance *)icd_term->this_instance;
2725 
2726     if (!loader_inst->wsi_surface_enabled) {
2727         loader_log(loader_inst, VULKAN_LOADER_ERROR_BIT, 0,
2728                    "VK_KHR_surface extension not enabled. vkGetPhysicalDeviceSurfaceFormats2KHR not executed!");
2729         return VK_SUCCESS;
2730     }
2731 
2732     VkIcdSurface *icd_surface = NULL;
2733     if (VK_NULL_HANDLE != pSurfaceInfo->surface) {
2734         icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
2735     }
2736 
2737     if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) {
2738         // Pass the call to the driver, possibly unwrapping the ICD surface
2739         if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
2740             icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
2741             icd_term->surface_list.list[icd_surface->surface_index]) {
2742             VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo;
2743             info_copy.surface = icd_term->surface_list.list[icd_surface->surface_index];
2744             return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, &info_copy, pSurfaceFormatCount,
2745                                                                           pSurfaceFormats);
2746         } else {
2747             return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, pSurfaceInfo,
2748                                                                           pSurfaceFormatCount, pSurfaceFormats);
2749         }
2750     } else {
2751         // Emulate the call
2752         loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
2753                    "vkGetPhysicalDeviceSurfaceFormats2KHR: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceSurfaceFormatsKHR",
2754                    icd_term->scanned_icd->lib_name);
2755 
2756         if (pSurfaceInfo->pNext != NULL) {
2757             loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
2758                        "vkGetPhysicalDeviceSurfaceFormats2KHR: Emulation found unrecognized structure type in pSurfaceInfo->pNext "
2759                        "- this struct will be ignored");
2760         }
2761 
2762         VkSurfaceKHR surface = pSurfaceInfo->surface;
2763         if (NULL != icd_surface && NULL != icd_term->surface_list.list &&
2764             icd_term->surface_list.capacity > icd_surface->surface_index * sizeof(VkSurfaceKHR) &&
2765             icd_term->surface_list.list[icd_surface->surface_index]) {
2766             surface = icd_term->surface_list.list[icd_surface->surface_index];
2767         }
2768 
2769         // If the icd doesn't support VK_KHR_surface, then there are no formats
2770         if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR) {
2771             if (pSurfaceFormatCount) {
2772                 *pSurfaceFormatCount = 0;
2773             }
2774             return VK_SUCCESS;
2775         }
2776 
2777         if (*pSurfaceFormatCount == 0 || pSurfaceFormats == NULL) {
2778             // Write to pSurfaceFormatCount
2779             return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount,
2780                                                                          NULL);
2781         } else {
2782             // Allocate a temporary array for the output of the old function
2783             VkSurfaceFormatKHR *formats = loader_stack_alloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
2784             if (formats == NULL) {
2785                 return VK_ERROR_OUT_OF_HOST_MEMORY;
2786             }
2787 
2788             VkResult res = icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface,
2789                                                                                  pSurfaceFormatCount, formats);
2790             for (uint32_t i = 0; i < *pSurfaceFormatCount; ++i) {
2791                 pSurfaceFormats[i].surfaceFormat = formats[i];
2792                 if (pSurfaceFormats[i].pNext != NULL) {
2793                     loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
2794                                "vkGetPhysicalDeviceSurfaceFormats2KHR: Emulation found unrecognized structure type in "
2795                                "pSurfaceFormats[%d].pNext - this struct will be ignored",
2796                                i);
2797                 }
2798             }
2799             return res;
2800         }
2801     }
2802 }
2803 
wsi_swapchain_instance_gpa(struct loader_instance * loader_inst,const char * name,void ** addr)2804 bool wsi_swapchain_instance_gpa(struct loader_instance *loader_inst, const char *name, void **addr) {
2805     *addr = NULL;
2806 
2807     // Functions for the VK_KHR_surface extension:
2808     if (!strcmp("vkDestroySurfaceKHR", name)) {
2809         *addr = loader_inst->wsi_surface_enabled ? (void *)vkDestroySurfaceKHR : NULL;
2810         return true;
2811     }
2812     if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", name)) {
2813         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceSupportKHR : NULL;
2814         return true;
2815     }
2816     if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", name)) {
2817         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceCapabilitiesKHR : NULL;
2818         return true;
2819     }
2820     if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", name)) {
2821         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceFormatsKHR : NULL;
2822         return true;
2823     }
2824     if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", name)) {
2825         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfacePresentModesKHR : NULL;
2826         return true;
2827     }
2828 
2829     if (!strcmp("vkGetDeviceGroupPresentCapabilitiesKHR", name)) {
2830         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetDeviceGroupPresentCapabilitiesKHR : NULL;
2831         return true;
2832     }
2833 
2834     if (!strcmp("vkGetDeviceGroupSurfacePresentModesKHR", name)) {
2835         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetDeviceGroupSurfacePresentModesKHR : NULL;
2836         return true;
2837     }
2838 
2839     if (!strcmp("vkGetPhysicalDevicePresentRectanglesKHR", name)) {
2840         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetPhysicalDevicePresentRectanglesKHR : NULL;
2841         return true;
2842     }
2843 
2844     // Functions for VK_KHR_get_surface_capabilities2 extension:
2845     if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilities2KHR", name)) {
2846         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceCapabilities2KHR : NULL;
2847         return true;
2848     }
2849 
2850     if (!strcmp("vkGetPhysicalDeviceSurfaceFormats2KHR", name)) {
2851         *addr = loader_inst->wsi_surface_enabled ? (void *)vkGetPhysicalDeviceSurfaceFormats2KHR : NULL;
2852         return true;
2853     }
2854 
2855     // Functions for the VK_KHR_swapchain extension:
2856 
2857     // Note: This is a device extension, and its functions are statically
2858     // exported from the loader.  Per Khronos decisions, the loader's GIPA
2859     // function will return the trampoline function for such device-extension
2860     // functions, regardless of whether the extension has been enabled.
2861     if (!strcmp("vkCreateSwapchainKHR", name)) {
2862         *addr = (void *)vkCreateSwapchainKHR;
2863         return true;
2864     }
2865     if (!strcmp("vkDestroySwapchainKHR", name)) {
2866         *addr = (void *)vkDestroySwapchainKHR;
2867         return true;
2868     }
2869     if (!strcmp("vkGetSwapchainImagesKHR", name)) {
2870         *addr = (void *)vkGetSwapchainImagesKHR;
2871         return true;
2872     }
2873     if (!strcmp("vkAcquireNextImageKHR", name)) {
2874         *addr = (void *)vkAcquireNextImageKHR;
2875         return true;
2876     }
2877     if (!strcmp("vkQueuePresentKHR", name)) {
2878         *addr = (void *)vkQueuePresentKHR;
2879         return true;
2880     }
2881     if (!strcmp("vkAcquireNextImage2KHR", name)) {
2882         *addr = (void *)vkAcquireNextImage2KHR;
2883         return true;
2884     }
2885 
2886 #if defined(VK_USE_PLATFORM_WIN32_KHR)
2887 
2888     // Functions for the VK_KHR_win32_surface extension:
2889     if (!strcmp("vkCreateWin32SurfaceKHR", name)) {
2890         *addr = loader_inst->wsi_win32_surface_enabled ? (void *)vkCreateWin32SurfaceKHR : NULL;
2891         return true;
2892     }
2893     if (!strcmp("vkGetPhysicalDeviceWin32PresentationSupportKHR", name)) {
2894         *addr = loader_inst->wsi_win32_surface_enabled ? (void *)vkGetPhysicalDeviceWin32PresentationSupportKHR : NULL;
2895         return true;
2896     }
2897 #endif  // VK_USE_PLATFORM_WIN32_KHR
2898 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
2899 
2900     // Functions for the VK_KHR_wayland_surface extension:
2901     if (!strcmp("vkCreateWaylandSurfaceKHR", name)) {
2902         *addr = loader_inst->wsi_wayland_surface_enabled ? (void *)vkCreateWaylandSurfaceKHR : NULL;
2903         return true;
2904     }
2905     if (!strcmp("vkGetPhysicalDeviceWaylandPresentationSupportKHR", name)) {
2906         *addr = loader_inst->wsi_wayland_surface_enabled ? (void *)vkGetPhysicalDeviceWaylandPresentationSupportKHR : NULL;
2907         return true;
2908     }
2909 #endif  // VK_USE_PLATFORM_WAYLAND_KHR
2910 #if defined(VK_USE_PLATFORM_XCB_KHR)
2911 
2912     // Functions for the VK_KHR_xcb_surface extension:
2913     if (!strcmp("vkCreateXcbSurfaceKHR", name)) {
2914         *addr = loader_inst->wsi_xcb_surface_enabled ? (void *)vkCreateXcbSurfaceKHR : NULL;
2915         return true;
2916     }
2917     if (!strcmp("vkGetPhysicalDeviceXcbPresentationSupportKHR", name)) {
2918         *addr = loader_inst->wsi_xcb_surface_enabled ? (void *)vkGetPhysicalDeviceXcbPresentationSupportKHR : NULL;
2919         return true;
2920     }
2921 #endif  // VK_USE_PLATFORM_XCB_KHR
2922 #if defined(VK_USE_PLATFORM_XLIB_KHR)
2923 
2924     // Functions for the VK_KHR_xlib_surface extension:
2925     if (!strcmp("vkCreateXlibSurfaceKHR", name)) {
2926         *addr = loader_inst->wsi_xlib_surface_enabled ? (void *)vkCreateXlibSurfaceKHR : NULL;
2927         return true;
2928     }
2929     if (!strcmp("vkGetPhysicalDeviceXlibPresentationSupportKHR", name)) {
2930         *addr = loader_inst->wsi_xlib_surface_enabled ? (void *)vkGetPhysicalDeviceXlibPresentationSupportKHR : NULL;
2931         return true;
2932     }
2933 #endif  // VK_USE_PLATFORM_XLIB_KHR
2934 #if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
2935 
2936     // Functions for the VK_EXT_directfb_surface extension:
2937     if (!strcmp("vkCreateDirectFBSurfaceEXT", name)) {
2938         *addr = loader_inst->wsi_directfb_surface_enabled ? (void *)vkCreateDirectFBSurfaceEXT : NULL;
2939         return true;
2940     }
2941     if (!strcmp("vkGetPhysicalDeviceDirectFBPresentationSupportEXT", name)) {
2942         *addr = loader_inst->wsi_directfb_surface_enabled ? (void *)vkGetPhysicalDeviceDirectFBPresentationSupportEXT : NULL;
2943         return true;
2944     }
2945 #endif  // VK_USE_PLATFORM_DIRECTFB_EXT
2946 #if defined(VK_USE_PLATFORM_ANDROID_KHR)
2947 
2948     // Functions for the VK_KHR_android_surface extension:
2949     if (!strcmp("vkCreateAndroidSurfaceKHR", name)) {
2950         *addr = loader_inst->wsi_android_surface_enabled ? (void *)vkCreateAndroidSurfaceKHR : NULL;
2951         return true;
2952     }
2953 #endif  // VK_USE_PLATFORM_ANDROID_KHR
2954 #if defined(VK_USE_PLATFORM_OHOS)
2955 
2956     // Functions for the VK_OHOS_surface extension:
2957     if (!strcmp("vkCreateSurfaceOHOS", name)) {
2958         *addr = loader_inst->wsi_ohos_surface_enabled ? (void *)vkCreateSurfaceOHOS : NULL;
2959         return true;
2960     }
2961 #endif  // VK_USE_PLATFORM_OHOS
2962 
2963 #if defined(VK_USE_PLATFORM_MACOS_MVK)
2964 
2965     // Functions for the VK_MVK_macos_surface extension:
2966     if (!strcmp("vkCreateMacOSSurfaceMVK", name)) {
2967         *addr = loader_inst->wsi_macos_surface_enabled ? (void *)vkCreateMacOSSurfaceMVK : NULL;
2968         return true;
2969     }
2970 #endif  // VK_USE_PLATFORM_MACOS_MVK
2971 #if defined(VK_USE_PLATFORM_IOS_MVK)
2972 
2973     // Functions for the VK_MVK_ios_surface extension:
2974     if (!strcmp("vkCreateIOSSurfaceMVK", name)) {
2975         *addr = loader_inst->wsi_ios_surface_enabled ? (void *)vkCreateIOSSurfaceMVK : NULL;
2976         return true;
2977     }
2978 #endif  // VK_USE_PLATFORM_IOS_MVK
2979 #if defined(VK_USE_PLATFORM_GGP)
2980 
2981     // Functions for the VK_GGP_stream_descriptor_surface extension:
2982     if (!strcmp("vkCreateStreamDescriptorSurfaceGGP", name)) {
2983         *addr = loader_inst->wsi_ggp_surface_enabled ? (void *)vkCreateStreamDescriptorSurfaceGGP : NULL;
2984         return true;
2985     }
2986 #endif  // VK_USE_PLATFORM_GGP
2987 #if defined(VK_USE_PLATFORM_FUCHSIA)
2988 
2989     // Functions for the VK_FUCHSIA_imagepipe_surface extension:
2990     if (!strcmp("vkCreateImagePipeSurfaceFUCHSIA", name)) {
2991         *addr = loader_inst->wsi_imagepipe_surface_enabled ? (void *)vkCreateImagePipeSurfaceFUCHSIA : NULL;
2992         return true;
2993     }
2994 
2995 #endif  // VK_USE_PLATFORM_FUCHSIA
2996 
2997     // Functions for the VK_EXT_headless_surface extension:
2998     if (!strcmp("vkCreateHeadlessSurfaceEXT", name)) {
2999         *addr = loader_inst->wsi_headless_surface_enabled ? (void *)vkCreateHeadlessSurfaceEXT : NULL;
3000         return true;
3001     }
3002 
3003 #if defined(VK_USE_PLATFORM_METAL_EXT)
3004     // Functions for the VK_MVK_macos_surface extension:
3005     if (!strcmp("vkCreateMetalSurfaceEXT", name)) {
3006         *addr = loader_inst->wsi_metal_surface_enabled ? (void *)vkCreateMetalSurfaceEXT : NULL;
3007         return true;
3008     }
3009 #endif  // VK_USE_PLATFORM_METAL_EXT
3010 
3011 #if defined(VK_USE_PLATFORM_SCREEN_QNX)
3012 
3013     // Functions for the VK_QNX_screen_surface extension:
3014     if (!strcmp("vkCreateScreenSurfaceQNX", name)) {
3015         *addr = loader_inst->wsi_screen_surface_enabled ? (void *)vkCreateScreenSurfaceQNX : NULL;
3016         return true;
3017     }
3018     if (!strcmp("vkGetPhysicalDeviceScreenPresentationSupportQNX", name)) {
3019         *addr = loader_inst->wsi_screen_surface_enabled ? (void *)vkGetPhysicalDeviceScreenPresentationSupportQNX : NULL;
3020         return true;
3021     }
3022 #endif  // VK_USE_PLATFORM_SCREEN_QNX
3023 
3024 #if defined(VK_USE_PLATFORM_VI_NN)
3025 
3026     // Functions for the VK_NN_vi_surface extension:
3027     if (!strcmp("vkCreateViSurfaceNN", name)) {
3028         *addr = loader_inst->wsi_vi_surface_enabled ? (void *)vkCreateViSurfaceNN : NULL;
3029         return true;
3030     }
3031 #endif  // VK_USE_PLATFORM_VI_NN
3032 
3033     // Functions for VK_KHR_display extension:
3034     if (!strcmp("vkGetPhysicalDeviceDisplayPropertiesKHR", name)) {
3035         *addr = loader_inst->wsi_display_enabled ? (void *)vkGetPhysicalDeviceDisplayPropertiesKHR : NULL;
3036         return true;
3037     }
3038     if (!strcmp("vkGetPhysicalDeviceDisplayPlanePropertiesKHR", name)) {
3039         *addr = loader_inst->wsi_display_enabled ? (void *)vkGetPhysicalDeviceDisplayPlanePropertiesKHR : NULL;
3040         return true;
3041     }
3042     if (!strcmp("vkGetDisplayPlaneSupportedDisplaysKHR", name)) {
3043         *addr = loader_inst->wsi_display_enabled ? (void *)vkGetDisplayPlaneSupportedDisplaysKHR : NULL;
3044         return true;
3045     }
3046     if (!strcmp("vkGetDisplayModePropertiesKHR", name)) {
3047         *addr = loader_inst->wsi_display_enabled ? (void *)vkGetDisplayModePropertiesKHR : NULL;
3048         return true;
3049     }
3050     if (!strcmp("vkCreateDisplayModeKHR", name)) {
3051         *addr = loader_inst->wsi_display_enabled ? (void *)vkCreateDisplayModeKHR : NULL;
3052         return true;
3053     }
3054     if (!strcmp("vkGetDisplayPlaneCapabilitiesKHR", name)) {
3055         *addr = loader_inst->wsi_display_enabled ? (void *)vkGetDisplayPlaneCapabilitiesKHR : NULL;
3056         return true;
3057     }
3058     if (!strcmp("vkCreateDisplayPlaneSurfaceKHR", name)) {
3059         *addr = loader_inst->wsi_display_enabled ? (void *)vkCreateDisplayPlaneSurfaceKHR : NULL;
3060         return true;
3061     }
3062 
3063     // Functions for KHR_display_swapchain extension:
3064     if (!strcmp("vkCreateSharedSwapchainsKHR", name)) {
3065         *addr = (void *)vkCreateSharedSwapchainsKHR;
3066         return true;
3067     }
3068 
3069     // Functions for KHR_get_display_properties2
3070     if (!strcmp("vkGetPhysicalDeviceDisplayProperties2KHR", name)) {
3071         *addr = loader_inst->wsi_display_props2_enabled ? (void *)vkGetPhysicalDeviceDisplayProperties2KHR : NULL;
3072         return true;
3073     }
3074     if (!strcmp("vkGetPhysicalDeviceDisplayPlaneProperties2KHR", name)) {
3075         *addr = loader_inst->wsi_display_props2_enabled ? (void *)vkGetPhysicalDeviceDisplayPlaneProperties2KHR : NULL;
3076         return true;
3077     }
3078     if (!strcmp("vkGetDisplayModeProperties2KHR", name)) {
3079         *addr = loader_inst->wsi_display_props2_enabled ? (void *)vkGetDisplayModeProperties2KHR : NULL;
3080         return true;
3081     }
3082     if (!strcmp("vkGetDisplayPlaneCapabilities2KHR", name)) {
3083         *addr = loader_inst->wsi_display_props2_enabled ? (void *)vkGetDisplayPlaneCapabilities2KHR : NULL;
3084         return true;
3085     }
3086 
3087     return false;
3088 }
3089