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