15db71995Sopenharmony_ci/*
25db71995Sopenharmony_ci * Copyright (c) 2015-2022 The Khronos Group Inc.
35db71995Sopenharmony_ci * Copyright (c) 2015-2022 Valve Corporation
45db71995Sopenharmony_ci * Copyright (c) 2015-2022 LunarG, Inc.
55db71995Sopenharmony_ci *
65db71995Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
75db71995Sopenharmony_ci * you may not use this file except in compliance with the License.
85db71995Sopenharmony_ci * You may obtain a copy of the License at
95db71995Sopenharmony_ci *
105db71995Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
115db71995Sopenharmony_ci *
125db71995Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
135db71995Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
145db71995Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
155db71995Sopenharmony_ci * See the License for the specific language governing permissions and
165db71995Sopenharmony_ci * limitations under the License.
175db71995Sopenharmony_ci *
185db71995Sopenharmony_ci * Author: Mark Young <marky@lunarg.com>
195db71995Sopenharmony_ci * Author: Lenny Komow <lenny@lunarg.com>
205db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com>
215db71995Sopenharmony_ci */
225db71995Sopenharmony_ci
235db71995Sopenharmony_ci#include "extension_manual.h"
245db71995Sopenharmony_ci
255db71995Sopenharmony_ci#include <stdio.h>
265db71995Sopenharmony_ci#include <stdlib.h>
275db71995Sopenharmony_ci#include <string.h>
285db71995Sopenharmony_ci
295db71995Sopenharmony_ci#include "allocation.h"
305db71995Sopenharmony_ci#include "debug_utils.h"
315db71995Sopenharmony_ci#include "loader.h"
325db71995Sopenharmony_ci#include "log.h"
335db71995Sopenharmony_ci#include "wsi.h"
345db71995Sopenharmony_ci
355db71995Sopenharmony_ci// ---- Manually added trampoline/terminator functions
365db71995Sopenharmony_ci
375db71995Sopenharmony_ci// These functions, for whatever reason, require more complex changes than
385db71995Sopenharmony_ci// can easily be automatically generated.
395db71995Sopenharmony_ci
405db71995Sopenharmony_ci// ---- VK_NV_external_memory_capabilities extension trampoline/terminators
415db71995Sopenharmony_ci
425db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceExternalImageFormatPropertiesNV(
435db71995Sopenharmony_ci    VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage,
445db71995Sopenharmony_ci    VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType,
455db71995Sopenharmony_ci    VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
465db71995Sopenharmony_ci    const VkLayerInstanceDispatchTable *disp;
475db71995Sopenharmony_ci    VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
485db71995Sopenharmony_ci    if (VK_NULL_HANDLE == unwrapped_phys_dev) {
495db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
505db71995Sopenharmony_ci                   "vkGetPhysicalDeviceExternalImageFormatPropertiesNV: Invalid physicalDevice "
515db71995Sopenharmony_ci                   "[VUID-vkGetPhysicalDeviceExternalImageFormatPropertiesNV-physicalDevice-parameter]");
525db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
535db71995Sopenharmony_ci    }
545db71995Sopenharmony_ci    disp = loader_get_instance_layer_dispatch(physicalDevice);
555db71995Sopenharmony_ci
565db71995Sopenharmony_ci    return disp->GetPhysicalDeviceExternalImageFormatPropertiesNV(unwrapped_phys_dev, format, type, tiling, usage, flags,
575db71995Sopenharmony_ci                                                                  externalHandleType, pExternalImageFormatProperties);
585db71995Sopenharmony_ci}
595db71995Sopenharmony_ci
605db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
615db71995Sopenharmony_ci    VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage,
625db71995Sopenharmony_ci    VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType,
635db71995Sopenharmony_ci    VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
645db71995Sopenharmony_ci    struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
655db71995Sopenharmony_ci    struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
665db71995Sopenharmony_ci
675db71995Sopenharmony_ci    if (!icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV) {
685db71995Sopenharmony_ci        if (externalHandleType) {
695db71995Sopenharmony_ci            return VK_ERROR_FORMAT_NOT_SUPPORTED;
705db71995Sopenharmony_ci        }
715db71995Sopenharmony_ci
725db71995Sopenharmony_ci        if (!icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) {
735db71995Sopenharmony_ci            return VK_ERROR_INITIALIZATION_FAILED;
745db71995Sopenharmony_ci        }
755db71995Sopenharmony_ci
765db71995Sopenharmony_ci        pExternalImageFormatProperties->externalMemoryFeatures = 0;
775db71995Sopenharmony_ci        pExternalImageFormatProperties->exportFromImportedHandleTypes = 0;
785db71995Sopenharmony_ci        pExternalImageFormatProperties->compatibleHandleTypes = 0;
795db71995Sopenharmony_ci
805db71995Sopenharmony_ci        return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(
815db71995Sopenharmony_ci            phys_dev_term->phys_dev, format, type, tiling, usage, flags, &pExternalImageFormatProperties->imageFormatProperties);
825db71995Sopenharmony_ci    }
835db71995Sopenharmony_ci
845db71995Sopenharmony_ci    return icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV(
855db71995Sopenharmony_ci        phys_dev_term->phys_dev, format, type, tiling, usage, flags, externalHandleType, pExternalImageFormatProperties);
865db71995Sopenharmony_ci}
875db71995Sopenharmony_ci
885db71995Sopenharmony_ci// ---- VK_EXT_display_surface_counter extension trampoline/terminators
895db71995Sopenharmony_ci
905db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
915db71995Sopenharmony_ci                                                                        VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
925db71995Sopenharmony_ci    const VkLayerInstanceDispatchTable *disp;
935db71995Sopenharmony_ci    VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
945db71995Sopenharmony_ci    if (VK_NULL_HANDLE == unwrapped_phys_dev) {
955db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
965db71995Sopenharmony_ci                   "vkGetPhysicalDeviceExternalImageFormatPropertiesNV: Invalid physicalDevice "
975db71995Sopenharmony_ci                   "[VUID-vkGetPhysicalDeviceSurfaceCapabilities2EXT-physicalDevice-parameter]");
985db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
995db71995Sopenharmony_ci    }
1005db71995Sopenharmony_ci    disp = loader_get_instance_layer_dispatch(physicalDevice);
1015db71995Sopenharmony_ci    return disp->GetPhysicalDeviceSurfaceCapabilities2EXT(unwrapped_phys_dev, surface, pSurfaceCapabilities);
1025db71995Sopenharmony_ci}
1035db71995Sopenharmony_ci
1045db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(
1055db71995Sopenharmony_ci    VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
1065db71995Sopenharmony_ci    struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1075db71995Sopenharmony_ci    struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1085db71995Sopenharmony_ci
1095db71995Sopenharmony_ci    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(surface);
1105db71995Sopenharmony_ci    uint8_t icd_index = phys_dev_term->icd_index;
1115db71995Sopenharmony_ci
1125db71995Sopenharmony_ci    // Unwrap the surface if needed
1135db71995Sopenharmony_ci    VkSurfaceKHR unwrapped_surface = surface;
1145db71995Sopenharmony_ci    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)(icd_surface->real_icd_surfaces[icd_index])) {
1155db71995Sopenharmony_ci        unwrapped_surface = icd_surface->real_icd_surfaces[icd_index];
1165db71995Sopenharmony_ci    }
1175db71995Sopenharmony_ci
1185db71995Sopenharmony_ci    if (NULL != icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT) {
1195db71995Sopenharmony_ci        // Pass the call to the driver
1205db71995Sopenharmony_ci        return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT(phys_dev_term->phys_dev, unwrapped_surface,
1215db71995Sopenharmony_ci                                                                           pSurfaceCapabilities);
1225db71995Sopenharmony_ci    } else {
1235db71995Sopenharmony_ci        // Emulate the call
1245db71995Sopenharmony_ci        loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
1255db71995Sopenharmony_ci                   "vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulating call in ICD \"%s\" using "
1265db71995Sopenharmony_ci                   "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
1275db71995Sopenharmony_ci                   icd_term->scanned_icd->lib_name);
1285db71995Sopenharmony_ci
1295db71995Sopenharmony_ci        VkSurfaceCapabilitiesKHR surface_caps;
1305db71995Sopenharmony_ci        VkResult res =
1315db71995Sopenharmony_ci            icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, unwrapped_surface, &surface_caps);
1325db71995Sopenharmony_ci        pSurfaceCapabilities->minImageCount = surface_caps.minImageCount;
1335db71995Sopenharmony_ci        pSurfaceCapabilities->maxImageCount = surface_caps.maxImageCount;
1345db71995Sopenharmony_ci        pSurfaceCapabilities->currentExtent = surface_caps.currentExtent;
1355db71995Sopenharmony_ci        pSurfaceCapabilities->minImageExtent = surface_caps.minImageExtent;
1365db71995Sopenharmony_ci        pSurfaceCapabilities->maxImageExtent = surface_caps.maxImageExtent;
1375db71995Sopenharmony_ci        pSurfaceCapabilities->maxImageArrayLayers = surface_caps.maxImageArrayLayers;
1385db71995Sopenharmony_ci        pSurfaceCapabilities->supportedTransforms = surface_caps.supportedTransforms;
1395db71995Sopenharmony_ci        pSurfaceCapabilities->currentTransform = surface_caps.currentTransform;
1405db71995Sopenharmony_ci        pSurfaceCapabilities->supportedCompositeAlpha = surface_caps.supportedCompositeAlpha;
1415db71995Sopenharmony_ci        pSurfaceCapabilities->supportedUsageFlags = surface_caps.supportedUsageFlags;
1425db71995Sopenharmony_ci        pSurfaceCapabilities->supportedSurfaceCounters = 0;
1435db71995Sopenharmony_ci
1445db71995Sopenharmony_ci        if (pSurfaceCapabilities->pNext != NULL) {
1455db71995Sopenharmony_ci            loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0,
1465db71995Sopenharmony_ci                       "vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulation found unrecognized structure type in "
1475db71995Sopenharmony_ci                       "pSurfaceCapabilities->pNext - this struct will be ignored");
1485db71995Sopenharmony_ci        }
1495db71995Sopenharmony_ci
1505db71995Sopenharmony_ci        return res;
1515db71995Sopenharmony_ci    }
1525db71995Sopenharmony_ci}
1535db71995Sopenharmony_ci
1545db71995Sopenharmony_ci// ---- VK_EXT_direct_mode_display extension trampoline/terminators
1555db71995Sopenharmony_ci
1565db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
1575db71995Sopenharmony_ci    const VkLayerInstanceDispatchTable *disp;
1585db71995Sopenharmony_ci    VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1595db71995Sopenharmony_ci    if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1605db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1615db71995Sopenharmony_ci                   "vkReleaseDisplayEXT: Invalid physicalDevice [VUID-vkReleaseDisplayEXT-physicalDevice-parameter]");
1625db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
1635db71995Sopenharmony_ci    }
1645db71995Sopenharmony_ci    disp = loader_get_instance_layer_dispatch(physicalDevice);
1655db71995Sopenharmony_ci    return disp->ReleaseDisplayEXT(unwrapped_phys_dev, display);
1665db71995Sopenharmony_ci}
1675db71995Sopenharmony_ci
1685db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
1695db71995Sopenharmony_ci    struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
1705db71995Sopenharmony_ci    struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
1715db71995Sopenharmony_ci
1725db71995Sopenharmony_ci    if (icd_term->dispatch.ReleaseDisplayEXT == NULL) {
1735db71995Sopenharmony_ci        loader_log(icd_term->this_instance, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
1745db71995Sopenharmony_ci                   "ICD \"%s\" associated with VkPhysicalDevice does not support vkReleaseDisplayEXT - Consequently, the call is "
1755db71995Sopenharmony_ci                   "invalid because it should not be possible to acquire a display on this device",
1765db71995Sopenharmony_ci                   icd_term->scanned_icd->lib_name);
1775db71995Sopenharmony_ci        abort();
1785db71995Sopenharmony_ci    }
1795db71995Sopenharmony_ci    return icd_term->dispatch.ReleaseDisplayEXT(phys_dev_term->phys_dev, display);
1805db71995Sopenharmony_ci}
1815db71995Sopenharmony_ci
1825db71995Sopenharmony_ci// ---- VK_EXT_acquire_xlib_display extension trampoline/terminators
1835db71995Sopenharmony_ci
1845db71995Sopenharmony_ci#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
1855db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display) {
1865db71995Sopenharmony_ci    const VkLayerInstanceDispatchTable *disp;
1875db71995Sopenharmony_ci    VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
1885db71995Sopenharmony_ci    if (VK_NULL_HANDLE == unwrapped_phys_dev) {
1895db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
1905db71995Sopenharmony_ci                   "vkAcquireXlibDisplayEXT: Invalid physicalDevice [VUID-vkAcquireXlibDisplayEXT-physicalDevice-parameter]");
1915db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
1925db71995Sopenharmony_ci    }
1935db71995Sopenharmony_ci    disp = loader_get_instance_layer_dispatch(physicalDevice);
1945db71995Sopenharmony_ci    return disp->AcquireXlibDisplayEXT(unwrapped_phys_dev, dpy, display);
1955db71995Sopenharmony_ci}
1965db71995Sopenharmony_ci
1975db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy,
1985db71995Sopenharmony_ci                                                                VkDisplayKHR display) {
1995db71995Sopenharmony_ci    struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2005db71995Sopenharmony_ci    struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2015db71995Sopenharmony_ci
2025db71995Sopenharmony_ci    if (icd_term->dispatch.AcquireXlibDisplayEXT != NULL) {
2035db71995Sopenharmony_ci        // Pass the call to the driver
2045db71995Sopenharmony_ci        return icd_term->dispatch.AcquireXlibDisplayEXT(phys_dev_term->phys_dev, dpy, display);
2055db71995Sopenharmony_ci    } else {
2065db71995Sopenharmony_ci        // Emulate the call
2075db71995Sopenharmony_ci        loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
2085db71995Sopenharmony_ci                   "vkAcquireXLibDisplayEXT: Emulating call in ICD \"%s\" by returning error", icd_term->scanned_icd->lib_name);
2095db71995Sopenharmony_ci
2105db71995Sopenharmony_ci        // Fail for the unsupported command
2115db71995Sopenharmony_ci        return VK_ERROR_INITIALIZATION_FAILED;
2125db71995Sopenharmony_ci    }
2135db71995Sopenharmony_ci}
2145db71995Sopenharmony_ci
2155db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
2165db71995Sopenharmony_ci                                                        VkDisplayKHR *pDisplay) {
2175db71995Sopenharmony_ci    const VkLayerInstanceDispatchTable *disp;
2185db71995Sopenharmony_ci    VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2195db71995Sopenharmony_ci    if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2205db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2215db71995Sopenharmony_ci                   "vkGetRandROutputDisplayEXT: Invalid physicalDevice [VUID-vkGetRandROutputDisplayEXT-physicalDevice-parameter]");
2225db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
2235db71995Sopenharmony_ci    }
2245db71995Sopenharmony_ci    disp = loader_get_instance_layer_dispatch(physicalDevice);
2255db71995Sopenharmony_ci    return disp->GetRandROutputDisplayEXT(unwrapped_phys_dev, dpy, rrOutput, pDisplay);
2265db71995Sopenharmony_ci}
2275db71995Sopenharmony_ci
2285db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
2295db71995Sopenharmony_ci                                                                   VkDisplayKHR *pDisplay) {
2305db71995Sopenharmony_ci    struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2315db71995Sopenharmony_ci    struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2325db71995Sopenharmony_ci
2335db71995Sopenharmony_ci    if (icd_term->dispatch.GetRandROutputDisplayEXT != NULL) {
2345db71995Sopenharmony_ci        // Pass the call to the driver
2355db71995Sopenharmony_ci        return icd_term->dispatch.GetRandROutputDisplayEXT(phys_dev_term->phys_dev, dpy, rrOutput, pDisplay);
2365db71995Sopenharmony_ci    } else {
2375db71995Sopenharmony_ci        // Emulate the call
2385db71995Sopenharmony_ci        loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0,
2395db71995Sopenharmony_ci                   "vkGetRandROutputDisplayEXT: Emulating call in ICD \"%s\" by returning null display",
2405db71995Sopenharmony_ci                   icd_term->scanned_icd->lib_name);
2415db71995Sopenharmony_ci
2425db71995Sopenharmony_ci        // Return a null handle to indicate this can't be done
2435db71995Sopenharmony_ci        *pDisplay = VK_NULL_HANDLE;
2445db71995Sopenharmony_ci        return VK_SUCCESS;
2455db71995Sopenharmony_ci    }
2465db71995Sopenharmony_ci}
2475db71995Sopenharmony_ci
2485db71995Sopenharmony_ci#endif  // VK_USE_PLATFORM_XLIB_XRANDR_EXT
2495db71995Sopenharmony_ci
2505db71995Sopenharmony_ci#if defined(VK_USE_PLATFORM_WIN32_KHR)
2515db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModes2EXT(VkPhysicalDevice physicalDevice,
2525db71995Sopenharmony_ci                                                                        const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
2535db71995Sopenharmony_ci                                                                        uint32_t *pPresentModeCount,
2545db71995Sopenharmony_ci                                                                        VkPresentModeKHR *pPresentModes) {
2555db71995Sopenharmony_ci    const VkLayerInstanceDispatchTable *disp;
2565db71995Sopenharmony_ci    VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
2575db71995Sopenharmony_ci    if (VK_NULL_HANDLE == unwrapped_phys_dev) {
2585db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2595db71995Sopenharmony_ci                   "vkGetPhysicalDeviceSurfacePresentModes2EXT: Invalid physicalDevice "
2605db71995Sopenharmony_ci                   "[VUID-vkGetPhysicalDeviceSurfacePresentModes2EXT-physicalDevice-parameter]");
2615db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
2625db71995Sopenharmony_ci    }
2635db71995Sopenharmony_ci    disp = loader_get_instance_layer_dispatch(physicalDevice);
2645db71995Sopenharmony_ci    return disp->GetPhysicalDeviceSurfacePresentModes2EXT(unwrapped_phys_dev, pSurfaceInfo, pPresentModeCount, pPresentModes);
2655db71995Sopenharmony_ci}
2665db71995Sopenharmony_ci
2675db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2EXT(
2685db71995Sopenharmony_ci    VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, uint32_t *pPresentModeCount,
2695db71995Sopenharmony_ci    VkPresentModeKHR *pPresentModes) {
2705db71995Sopenharmony_ci    struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
2715db71995Sopenharmony_ci    struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
2725db71995Sopenharmony_ci    if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT) {
2735db71995Sopenharmony_ci        loader_log(icd_term->this_instance, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
2745db71995Sopenharmony_ci                   "ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSurfacePresentModes2EXT");
2755db71995Sopenharmony_ci        abort();
2765db71995Sopenharmony_ci    }
2775db71995Sopenharmony_ci    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)(pSurfaceInfo->surface);
2785db71995Sopenharmony_ci    uint8_t icd_index = phys_dev_term->icd_index;
2795db71995Sopenharmony_ci    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
2805db71995Sopenharmony_ci        VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
2815db71995Sopenharmony_ci        surface_info_copy.sType = pSurfaceInfo->sType;
2825db71995Sopenharmony_ci        surface_info_copy.pNext = pSurfaceInfo->pNext;
2835db71995Sopenharmony_ci        surface_info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
2845db71995Sopenharmony_ci        return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, &surface_info_copy,
2855db71995Sopenharmony_ci                                                                           pPresentModeCount, pPresentModes);
2865db71995Sopenharmony_ci    }
2875db71995Sopenharmony_ci    return icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT(phys_dev_term->phys_dev, pSurfaceInfo, pPresentModeCount,
2885db71995Sopenharmony_ci                                                                       pPresentModes);
2895db71995Sopenharmony_ci}
2905db71995Sopenharmony_ci
2915db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,
2925db71995Sopenharmony_ci                                                                     const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
2935db71995Sopenharmony_ci                                                                     VkDeviceGroupPresentModeFlagsKHR *pModes) {
2945db71995Sopenharmony_ci    const VkLayerDispatchTable *disp = loader_get_dispatch(device);
2955db71995Sopenharmony_ci    if (NULL == disp) {
2965db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
2975db71995Sopenharmony_ci                   "vkGetDeviceGroupSurfacePresentModes2EXT: Invalid device "
2985db71995Sopenharmony_ci                   "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-device-parameter]");
2995db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
3005db71995Sopenharmony_ci    }
3015db71995Sopenharmony_ci    return disp->GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
3025db71995Sopenharmony_ci}
3035db71995Sopenharmony_ci
3045db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(VkDevice device,
3055db71995Sopenharmony_ci                                                                                const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
3065db71995Sopenharmony_ci                                                                                VkDeviceGroupPresentModeFlagsKHR *pModes) {
3075db71995Sopenharmony_ci    uint32_t icd_index = 0;
3085db71995Sopenharmony_ci    struct loader_device *dev;
3095db71995Sopenharmony_ci    struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
3105db71995Sopenharmony_ci    if (NULL == icd_term || NULL == dev ||
3115db71995Sopenharmony_ci        NULL == dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT) {
3125db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
3135db71995Sopenharmony_ci                   "vkGetDeviceGroupSurfacePresentModes2EXT Terminator: Invalid device handle. This is likely the result of a "
3145db71995Sopenharmony_ci                   "layer wrapping device handles and failing to unwrap them in all functions. "
3155db71995Sopenharmony_ci                   "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-device-parameter]");
3165db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
3175db71995Sopenharmony_ci    }
3185db71995Sopenharmony_ci    if (NULL == pSurfaceInfo) {
3195db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
3205db71995Sopenharmony_ci                   "vkGetDeviceGroupSurfacePresentModes2EXT: Invalid pSurfaceInfo pointer "
3215db71995Sopenharmony_ci                   "[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]");
3225db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
3235db71995Sopenharmony_ci    }
3245db71995Sopenharmony_ci    VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
3255db71995Sopenharmony_ci    if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
3265db71995Sopenharmony_ci        VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
3275db71995Sopenharmony_ci        surface_info_copy.sType = pSurfaceInfo->sType;
3285db71995Sopenharmony_ci        surface_info_copy.pNext = pSurfaceInfo->pNext;
3295db71995Sopenharmony_ci        surface_info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
3305db71995Sopenharmony_ci        return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy,
3315db71995Sopenharmony_ci                                                                                                        pModes);
3325db71995Sopenharmony_ci    }
3335db71995Sopenharmony_ci    return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
3345db71995Sopenharmony_ci}
3355db71995Sopenharmony_ci
3365db71995Sopenharmony_ci#endif  // VK_USE_PLATFORM_WIN32_KHR
3375db71995Sopenharmony_ci
3385db71995Sopenharmony_ci// ---- VK_EXT_tooling_info extension trampoline/terminators
3395db71995Sopenharmony_ci
3405db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice, uint32_t *pToolCount,
3415db71995Sopenharmony_ci                                                                  VkPhysicalDeviceToolPropertiesEXT *pToolProperties) {
3425db71995Sopenharmony_ci    const VkLayerInstanceDispatchTable *disp;
3435db71995Sopenharmony_ci    VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
3445db71995Sopenharmony_ci    if (VK_NULL_HANDLE == unwrapped_phys_dev) {
3455db71995Sopenharmony_ci        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
3465db71995Sopenharmony_ci                   "vkGetPhysicalDeviceToolPropertiesEXT: Invalid physicalDevice "
3475db71995Sopenharmony_ci                   "[VUID-vkGetPhysicalDeviceToolPropertiesEXT-physicalDevice-parameter]");
3485db71995Sopenharmony_ci        abort(); /* Intentionally fail so user can correct issue. */
3495db71995Sopenharmony_ci    }
3505db71995Sopenharmony_ci    disp = loader_get_instance_layer_dispatch(physicalDevice);
3515db71995Sopenharmony_ci    return disp->GetPhysicalDeviceToolPropertiesEXT(unwrapped_phys_dev, pToolCount, pToolProperties);
3525db71995Sopenharmony_ci}
3535db71995Sopenharmony_ci
3545db71995Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice, uint32_t *pToolCount,
3555db71995Sopenharmony_ci                                                                             VkPhysicalDeviceToolPropertiesEXT *pToolProperties) {
3565db71995Sopenharmony_ci    struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
3575db71995Sopenharmony_ci    struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
3585db71995Sopenharmony_ci
3595db71995Sopenharmony_ci    bool tooling_info_supported = false;
3605db71995Sopenharmony_ci    uint32_t ext_count = 0;
3615db71995Sopenharmony_ci    VkExtensionProperties *ext_props = NULL;
3625db71995Sopenharmony_ci    VkResult res = VK_SUCCESS;
3635db71995Sopenharmony_ci    VkResult enumerate_res = VK_SUCCESS;
3645db71995Sopenharmony_ci
3655db71995Sopenharmony_ci    enumerate_res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &ext_count, NULL);
3665db71995Sopenharmony_ci    if (enumerate_res != VK_SUCCESS) {
3675db71995Sopenharmony_ci        goto out;
3685db71995Sopenharmony_ci    }
3695db71995Sopenharmony_ci
3705db71995Sopenharmony_ci    ext_props = loader_instance_heap_alloc(icd_term->this_instance, sizeof(VkExtensionProperties) * ext_count,
3715db71995Sopenharmony_ci                                           VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
3725db71995Sopenharmony_ci    if (!ext_props) {
3735db71995Sopenharmony_ci        res = VK_ERROR_OUT_OF_HOST_MEMORY;
3745db71995Sopenharmony_ci        goto out;
3755db71995Sopenharmony_ci    }
3765db71995Sopenharmony_ci
3775db71995Sopenharmony_ci    enumerate_res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &ext_count, ext_props);
3785db71995Sopenharmony_ci    if (enumerate_res != VK_SUCCESS) {
3795db71995Sopenharmony_ci        goto out;
3805db71995Sopenharmony_ci    }
3815db71995Sopenharmony_ci
3825db71995Sopenharmony_ci    for (uint32_t i = 0; i < ext_count; i++) {
3835db71995Sopenharmony_ci        if (strncmp(ext_props[i].extensionName, VK_EXT_TOOLING_INFO_EXTENSION_NAME, VK_MAX_EXTENSION_NAME_SIZE) == 0) {
3845db71995Sopenharmony_ci            tooling_info_supported = true;
3855db71995Sopenharmony_ci            break;
3865db71995Sopenharmony_ci        }
3875db71995Sopenharmony_ci    }
3885db71995Sopenharmony_ci
3895db71995Sopenharmony_ci    if (tooling_info_supported && icd_term->dispatch.GetPhysicalDeviceToolPropertiesEXT) {
3905db71995Sopenharmony_ci        res = icd_term->dispatch.GetPhysicalDeviceToolPropertiesEXT(phys_dev_term->phys_dev, pToolCount, pToolProperties);
3915db71995Sopenharmony_ci    }
3925db71995Sopenharmony_ci
3935db71995Sopenharmony_ciout:
3945db71995Sopenharmony_ci    // In the case the driver didn't support the extension, make sure that the first layer doesn't find the count uninitialized
3955db71995Sopenharmony_ci    if (!tooling_info_supported || !icd_term->dispatch.GetPhysicalDeviceToolPropertiesEXT) {
3965db71995Sopenharmony_ci        *pToolCount = 0;
3975db71995Sopenharmony_ci    }
3985db71995Sopenharmony_ci
3995db71995Sopenharmony_ci    loader_instance_heap_free(icd_term->this_instance, ext_props);
4005db71995Sopenharmony_ci
4015db71995Sopenharmony_ci    return res;
4025db71995Sopenharmony_ci}
403