1/*
2 * Copyright (c) 2015-2022 Valve Corporation
3 * Copyright (c) 2015-2022 LunarG, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Author: Jon Ashburn <jon@lunarg.com>
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <ctype.h>
23#include <string>
24#include <algorithm>
25#include <assert.h>
26#include <unordered_map>
27#include <memory>
28#include <vector>
29
30#include "vulkan/vk_layer.h"
31#include "vk_dispatch_table_helper.h"
32#include "loader/vk_loader_layer.h"
33
34// Export full support of instance extension VK_EXT_direct_mode_display extension
35#if !defined(TEST_LAYER_EXPORT_DIRECT_DISP)
36#define TEST_LAYER_EXPORT_DIRECT_DISP 0
37#endif
38
39// Export full support of instance extension VK_EXT_display_surface_counter extension
40#if !defined(TEST_LAYER_EXPORT_DISP_SURF_COUNT)
41#define TEST_LAYER_EXPORT_DISP_SURF_COUNT 0
42#endif
43
44// Export full support of device extension VK_KHR_maintenance1 extension
45#if !defined(TEST_LAYER_EXPORT_MAINT_1)
46#define TEST_LAYER_EXPORT_MAINT_1 0
47#endif
48
49// Export full support of device extension VK_KHR_shared_presentable_image extension
50#if !defined(TEST_LAYER_EXPORT_PRESENT_IMAGE)
51#define TEST_LAYER_EXPORT_PRESENT_IMAGE 0
52#endif
53
54#if !defined(VK_LAYER_EXPORT)
55#if defined(__GNUC__) && __GNUC__ >= 4
56#define VK_LAYER_EXPORT __attribute__((visibility("default")))
57#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
58#define VK_LAYER_EXPORT __attribute__((visibility("default")))
59#else
60#define VK_LAYER_EXPORT
61#endif
62#endif
63
64struct wrapped_phys_dev_obj {
65    VkLayerInstanceDispatchTable *loader_disp;
66    struct wrapped_inst_obj *inst;  // parent instance object
67    void *obj;
68};
69
70struct wrapped_inst_obj {
71    VkLayerInstanceDispatchTable *loader_disp;
72    VkLayerInstanceDispatchTable layer_disp;  // this layer's dispatch table
73    PFN_vkSetInstanceLoaderData pfn_inst_init;
74    struct wrapped_phys_dev_obj *ptr_phys_devs;  // any enumerated phys devs
75    VkInstance obj;
76    bool layer_is_implicit;
77    bool direct_display_enabled;
78    bool display_surf_counter_enabled;
79    bool debug_utils_enabled;
80};
81
82struct wrapped_dev_obj {
83    VkLayerDispatchTable *loader_disp;
84    VkLayerDispatchTable disp;
85    PFN_vkSetDeviceLoaderData pfn_dev_init;
86    PFN_vkGetDeviceProcAddr pfn_get_dev_proc_addr;
87    VkDevice obj;
88    bool maintanence_1_enabled;
89    bool present_image_enabled;
90    bool debug_utils_enabled;
91    bool debug_report_enabled;
92    bool debug_marker_enabled;
93};
94
95struct wrapped_debug_util_mess_obj {
96    VkInstance inst;
97    VkDebugUtilsMessengerEXT obj;
98};
99
100struct saved_wrapped_handles_storage {
101    std::vector<wrapped_inst_obj *> instances;
102    std::vector<wrapped_phys_dev_obj *> physical_devices;
103    std::vector<wrapped_dev_obj *> devices;
104    std::vector<wrapped_debug_util_mess_obj *> debug_util_messengers;
105};
106
107saved_wrapped_handles_storage saved_wrapped_handles;
108
109VkInstance unwrap_instance(const VkInstance instance, wrapped_inst_obj **inst) {
110    *inst = reinterpret_cast<wrapped_inst_obj *>(instance);
111    auto it = std::find(saved_wrapped_handles.instances.begin(), saved_wrapped_handles.instances.end(), *inst);
112    return (it == saved_wrapped_handles.instances.end()) ? VK_NULL_HANDLE : (*inst)->obj;
113}
114
115VkPhysicalDevice unwrap_phys_dev(const VkPhysicalDevice physical_device, wrapped_phys_dev_obj **phys_dev) {
116    *phys_dev = reinterpret_cast<wrapped_phys_dev_obj *>(physical_device);
117    auto it = std::find(saved_wrapped_handles.physical_devices.begin(), saved_wrapped_handles.physical_devices.end(), *phys_dev);
118    return (it == saved_wrapped_handles.physical_devices.end()) ? VK_NULL_HANDLE
119                                                                : reinterpret_cast<VkPhysicalDevice>((*phys_dev)->obj);
120}
121
122VkDevice unwrap_device(const VkDevice device, wrapped_dev_obj **dev) {
123    *dev = reinterpret_cast<wrapped_dev_obj *>(device);
124    auto it = std::find(saved_wrapped_handles.devices.begin(), saved_wrapped_handles.devices.end(), *dev);
125    return (it == saved_wrapped_handles.devices.end()) ? VK_NULL_HANDLE : (*dev)->obj;
126}
127
128VkDebugUtilsMessengerEXT unwrap_debug_util_messenger(const VkDebugUtilsMessengerEXT messenger, wrapped_debug_util_mess_obj **mess) {
129    *mess = reinterpret_cast<wrapped_debug_util_mess_obj *>(messenger);
130    auto it =
131        std::find(saved_wrapped_handles.debug_util_messengers.begin(), saved_wrapped_handles.debug_util_messengers.end(), *mess);
132    return (it == saved_wrapped_handles.debug_util_messengers.end()) ? VK_NULL_HANDLE : (*mess)->obj;
133}
134
135VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) {
136    VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
137    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
138        chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
139    }
140    assert(chain_info != NULL);
141    return chain_info;
142}
143
144VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) {
145    VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
146    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
147        chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
148    }
149    assert(chain_info != NULL);
150    return chain_info;
151}
152
153namespace wrap_objects {
154
155const VkLayerProperties global_layer = {
156    "VK_LAYER_LUNARG_wrap_objects",
157    VK_HEADER_VERSION_COMPLETE,
158    1,
159    "LunarG Test Layer",
160};
161
162uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
163
164VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
165                                                     const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
166    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
167    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
168    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
169    if (fpCreateInstance == NULL) {
170        return VK_ERROR_INITIALIZATION_FAILED;
171    }
172    // Advance the link info for the next element on the chain
173    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
174    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
175    if (result != VK_SUCCESS) {
176        return result;
177    }
178    auto inst = new wrapped_inst_obj;
179    if (!inst) return VK_ERROR_OUT_OF_HOST_MEMORY;
180    saved_wrapped_handles.instances.push_back(inst);
181    memset(inst, 0, sizeof(*inst));
182    inst->obj = (*pInstance);
183    *pInstance = reinterpret_cast<VkInstance>(inst);
184    // store the loader callback for initializing created dispatchable objects
185    chain_info = get_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
186    if (chain_info) {
187        inst->pfn_inst_init = chain_info->u.pfnSetInstanceLoaderData;
188        result = inst->pfn_inst_init(inst->obj, reinterpret_cast<void *>(inst));
189        if (VK_SUCCESS != result) return result;
190    } else {
191        inst->pfn_inst_init = NULL;
192        inst->loader_disp = *(reinterpret_cast<VkLayerInstanceDispatchTable **>(inst->obj));
193    }
194    layer_init_instance_dispatch_table(inst->obj, &inst->layer_disp, fpGetInstanceProcAddr);
195    bool found = false;
196    for (uint32_t layer = 0; layer < pCreateInfo->enabledLayerCount; ++layer) {
197        std::string layer_name = pCreateInfo->ppEnabledLayerNames[layer];
198        std::transform(layer_name.begin(), layer_name.end(), layer_name.begin(),
199                       [](char c) { return static_cast<char>(::tolower(static_cast<char>(c))); });
200        if (layer_name.find("wrap") != std::string::npos && layer_name.find("obj") != std::string::npos) {
201            found = true;
202            break;
203        }
204    }
205    if (!found) {
206        inst->layer_is_implicit = true;
207    }
208
209    for (uint32_t ext = 0; ext < pCreateInfo->enabledExtensionCount; ++ext) {
210        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[ext], VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME)) {
211#if TEST_LAYER_EXPORT_DIRECT_DISP
212            inst->direct_display_enabled = true;
213#endif
214        }
215        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[ext], VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME)) {
216#if TEST_LAYER_EXPORT_DISP_SURF_COUNT
217            inst->display_surf_counter_enabled = true;
218#endif
219        }
220        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[ext], VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
221            inst->debug_utils_enabled = true;
222        }
223    }
224
225    return result;
226}
227
228VKAPI_ATTR void VKAPI_CALL wrap_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
229    wrapped_inst_obj *inst;
230    auto vk_inst = unwrap_instance(instance, &inst);
231    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
232    pDisp->DestroyInstance(vk_inst, pAllocator);
233    if (inst->ptr_phys_devs) delete[] inst->ptr_phys_devs;
234    delete inst;
235}
236
237VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateDebugUtilsMessengerEXT(VkInstance instance,
238                                                                   const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
239                                                                   const VkAllocationCallbacks *pAllocator,
240                                                                   VkDebugUtilsMessengerEXT *pMessenger) {
241    wrapped_inst_obj *inst;
242    auto vk_inst = unwrap_instance(instance, &inst);
243    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
244    VkResult result = pDisp->CreateDebugUtilsMessengerEXT(vk_inst, pCreateInfo, pAllocator, pMessenger);
245    auto mess = new wrapped_debug_util_mess_obj;
246    if (!mess) return VK_ERROR_OUT_OF_HOST_MEMORY;
247    saved_wrapped_handles.debug_util_messengers.push_back(mess);
248    memset(mess, 0, sizeof(*mess));
249    mess->obj = (*pMessenger);
250    *pMessenger = reinterpret_cast<VkDebugUtilsMessengerEXT>(mess);
251    return result;
252}
253
254VKAPI_ATTR void VKAPI_CALL wrap_vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
255                                                                const VkAllocationCallbacks *pAllocator) {
256    wrapped_inst_obj *inst;
257    auto vk_inst = unwrap_instance(instance, &inst);
258    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
259    wrapped_debug_util_mess_obj *mess;
260    auto vk_mess = unwrap_debug_util_messenger(messenger, &mess);
261    pDisp->DestroyDebugUtilsMessengerEXT(vk_inst, vk_mess, pAllocator);
262    delete mess;
263}
264
265VKAPI_ATTR void VKAPI_CALL wrap_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
266                                                    const VkAllocationCallbacks *pAllocator) {
267    wrapped_inst_obj *inst;
268    auto vk_inst = unwrap_instance(instance, &inst);
269    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
270    pDisp->DestroySurfaceKHR(vk_inst, surface, pAllocator);
271}
272#if defined(VK_USE_PLATFORM_ANDROID_KHR)
273VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
274                                                              const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
275    wrapped_inst_obj *inst;
276    auto vk_inst = unwrap_instance(instance, &inst);
277    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
278    return pDisp->CreateAndroidSurfaceKHR(vk_inst, pCreateInfo, pAllocator, pSurface);
279}
280#endif
281
282#if defined(VK_USE_PLATFORM_WIN32_KHR)
283VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
284                                                            const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
285    wrapped_inst_obj *inst;
286    auto vk_inst = unwrap_instance(instance, &inst);
287    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
288    return pDisp->CreateWin32SurfaceKHR(vk_inst, pCreateInfo, pAllocator, pSurface);
289}
290#endif  // VK_USE_PLATFORM_WIN32_KHR
291
292#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
293VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
294                                                              const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
295    wrapped_inst_obj *inst;
296    auto vk_inst = unwrap_instance(instance, &inst);
297    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
298    return pDisp->CreateWaylandSurfaceKHR(vk_inst, pCreateInfo, pAllocator, pSurface);
299}
300#endif  // VK_USE_PLATFORM_WAYLAND_KHR
301
302#if defined(VK_USE_PLATFORM_XCB_KHR)
303VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
304                                                          const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
305    wrapped_inst_obj *inst;
306    auto vk_inst = unwrap_instance(instance, &inst);
307    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
308    return pDisp->CreateXcbSurfaceKHR(vk_inst, pCreateInfo, pAllocator, pSurface);
309}
310#endif  // VK_USE_PLATFORM_XCB_KHR
311
312#if defined(VK_USE_PLATFORM_XLIB_KHR)
313VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
314                                                           const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
315    wrapped_inst_obj *inst;
316    auto vk_inst = unwrap_instance(instance, &inst);
317    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
318    return pDisp->CreateXlibSurfaceKHR(vk_inst, pCreateInfo, pAllocator, pSurface);
319}
320#endif  // VK_USE_PLATFORM_XLIB_KHR
321
322#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
323VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateDirectFBSurfaceEXT(VkInstance instance,
324                                                               const VkDirectFBSurfaceCreateInfoEXT *pCreateInfo,
325                                                               const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
326    wrapped_inst_obj *inst;
327    auto vk_inst = unwrap_instance(instance, &inst);
328    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
329    return pDisp->CreateDirectFBSurfaceEXT(vk_inst, pCreateInfo, pAllocator, pSurface);
330}
331#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
332
333#if defined(VK_USE_PLATFORM_MACOS_MVK)
334VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
335                                                            const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
336    wrapped_inst_obj *inst;
337    auto vk_inst = unwrap_instance(instance, &inst);
338    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
339    return pDisp->CreateMacOSSurfaceMVK(vk_inst, pCreateInfo, pAllocator, pSurface);
340}
341#endif  // VK_USE_PLATFORM_MACOS_MVK
342
343#if defined(VK_USE_PLATFORM_IOS_MVK)
344VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
345                                                          const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
346    wrapped_inst_obj *inst;
347    auto vk_inst = unwrap_instance(instance, &inst);
348    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
349    return pDisp->CreateIOSSurfaceMVK(vk_inst, pCreateInfo, pAllocator, pSurface);
350}
351#endif  // VK_USE_PLATFORM_IOS_MVK
352
353#if defined(VK_USE_PLATFORM_GGP)
354VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateStreamDescriptorSurfaceGGP(VkInstance instance,
355                                                                       const VkStreamDescriptorSurfaceCreateInfoGGP *pCreateInfo,
356                                                                       const VkAllocationCallbacks *pAllocator,
357                                                                       VkSurfaceKHR *pSurface) {
358    wrapped_inst_obj *inst;
359    auto vk_inst = unwrap_instance(instance, &inst);
360    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
361    return pDisp->CreateStreamDescriptorSurfaceGGP(vk_inst, pCreateInfo, pAllocator, pSurface);
362}
363#endif  // VK_USE_PLATFORM_GGP
364
365#if defined(VK_USE_PLATFORM_METAL_EXT)
366VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
367                                                            const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
368    wrapped_inst_obj *inst;
369    auto vk_inst = unwrap_instance(instance, &inst);
370    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
371    return pDisp->CreateMetalSurfaceEXT(vk_inst, pCreateInfo, pAllocator, pSurface);
372}
373#endif  // VK_USE_PLATFORM_METAL_EXT
374
375#if defined(VK_USE_PLATFORM_SCREEN_QNX)
376VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateScreenSurfaceQNX(VkInstance instance, const VkScreenSurfaceCreateInfoQNX *pCreateInfo,
377                                                             const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
378    wrapped_inst_obj *inst;
379    auto vk_inst = unwrap_instance(instance, &inst);
380    VkLayerInstanceDispatchTable *pDisp = &inst->layer_disp;
381    return pDisp->CreateScreenSurfaceQNX(vk_inst, pCreateInfo, pAllocator, pSurface);
382}
383#endif  // VK_USE_PLATFORM_SCREEN_QNX
384
385VKAPI_ATTR VkResult VKAPI_CALL wrap_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
386                                                               VkPhysicalDevice *pPhysicalDevices) {
387    wrapped_inst_obj *inst;
388    auto vk_inst = unwrap_instance(instance, &inst);
389    VkResult result = inst->layer_disp.EnumeratePhysicalDevices(vk_inst, pPhysicalDeviceCount, pPhysicalDevices);
390
391    if (VK_SUCCESS != result) return result;
392
393    if (pPhysicalDevices != NULL) {
394        assert(pPhysicalDeviceCount);
395        auto phys_devs = new wrapped_phys_dev_obj[*pPhysicalDeviceCount];
396        if (!phys_devs) return VK_ERROR_OUT_OF_HOST_MEMORY;
397        saved_wrapped_handles.physical_devices.push_back(phys_devs);
398        if (inst->ptr_phys_devs) delete[] inst->ptr_phys_devs;
399        inst->ptr_phys_devs = phys_devs;
400        for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
401            if (inst->pfn_inst_init == NULL) {
402                phys_devs[i].loader_disp = *(reinterpret_cast<VkLayerInstanceDispatchTable **>(pPhysicalDevices[i]));
403            } else {
404                result = inst->pfn_inst_init(vk_inst, reinterpret_cast<void *>(&phys_devs[i]));
405                if (VK_SUCCESS != result) return result;
406            }
407            phys_devs[i].obj = reinterpret_cast<void *>(pPhysicalDevices[i]);
408            phys_devs[i].inst = inst;
409            pPhysicalDevices[i] = reinterpret_cast<VkPhysicalDevice>(&phys_devs[i]);
410        }
411    }
412    return result;
413}
414
415VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
416    wrapped_phys_dev_obj *phys_dev;
417    auto vk_phys_dev = unwrap_phys_dev(physicalDevice, &phys_dev);
418    phys_dev->inst->layer_disp.GetPhysicalDeviceProperties(vk_phys_dev, pProperties);
419}
420
421VKAPI_ATTR void VKAPI_CALL wrap_vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
422                                                                         uint32_t *pQueueFamilyPropertyCount,
423                                                                         VkQueueFamilyProperties *pQueueFamilyProperties) {
424    wrapped_phys_dev_obj *phys_dev;
425    auto vk_phys_dev = unwrap_phys_dev(physicalDevice, &phys_dev);
426    phys_dev->inst->layer_disp.GetPhysicalDeviceQueueFamilyProperties(vk_phys_dev, pQueueFamilyPropertyCount,
427                                                                      pQueueFamilyProperties);
428}
429
430VKAPI_ATTR VkResult VKAPI_CALL wrap_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
431                                                                         uint32_t *pPropertyCount,
432                                                                         VkExtensionProperties *pProperties) {
433    VkResult result = VK_SUCCESS;
434    wrapped_phys_dev_obj *phys_dev;
435    auto vk_phys_dev = unwrap_phys_dev(physicalDevice, &phys_dev);
436
437    if (phys_dev->inst->layer_is_implicit || (pLayerName && !strcmp(pLayerName, global_layer.layerName))) {
438        uint32_t ext_count = 0;
439#if TEST_LAYER_EXPORT_MAINT_1
440        ext_count++;
441#endif
442#if TEST_LAYER_EXPORT_PRESENT_IMAGE
443        ext_count++;
444#endif
445        if (pPropertyCount) {
446            if (pProperties) {
447                [[maybe_unused]] uint32_t count = ext_count;
448                if (count > *pPropertyCount) {
449                    count = *pPropertyCount;
450                    result = VK_INCOMPLETE;
451                }
452
453                ext_count = 0;
454#if TEST_LAYER_EXPORT_MAINT_1
455                if (ext_count < count) {
456#if defined(_WIN32)
457                    strncpy_s(pProperties[ext_count].extensionName, VK_MAX_EXTENSION_NAME_SIZE, VK_KHR_MAINTENANCE1_EXTENSION_NAME,
458                              strlen(VK_KHR_MAINTENANCE1_EXTENSION_NAME) + 1);
459#else
460                    strncpy(pProperties[ext_count].extensionName, VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_MAX_EXTENSION_NAME_SIZE);
461#endif
462                    pProperties[ext_count].specVersion = 2;
463                    ext_count++;
464                }
465#endif
466#if TEST_LAYER_EXPORT_PRESENT_IMAGE
467                if (ext_count < count) {
468#if defined(_WIN32)
469                    strncpy_s(pProperties[ext_count].extensionName, VK_MAX_EXTENSION_NAME_SIZE,
470                              VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
471                              strlen(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME) + 1);
472#else
473                    strncpy(pProperties[ext_count].extensionName, VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
474                            VK_MAX_EXTENSION_NAME_SIZE);
475#endif
476                    pProperties[ext_count].specVersion = 1;
477                    ext_count++;
478                }
479#endif
480            }
481            *pPropertyCount = ext_count;
482        }
483        return result;
484    } else {
485        return phys_dev->inst->layer_disp.EnumerateDeviceExtensionProperties(vk_phys_dev, pLayerName, pPropertyCount, pProperties);
486    }
487}
488
489VKAPI_ATTR VkResult VKAPI_CALL wrap_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
490                                                   const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
491    wrapped_phys_dev_obj *phys_dev;
492    auto vk_phys_dev = unwrap_phys_dev(physicalDevice, &phys_dev);
493    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
494    PFN_vkGetInstanceProcAddr pfn_get_inst_proc_addr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
495    PFN_vkGetDeviceProcAddr pfn_get_dev_proc_addr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
496    PFN_vkCreateDevice pfn_create_device = (PFN_vkCreateDevice)pfn_get_inst_proc_addr(phys_dev->inst->obj, "vkCreateDevice");
497    if (pfn_create_device == NULL) {
498        return VK_ERROR_INITIALIZATION_FAILED;
499    }
500    // Advance the link info for the next element on the chain
501    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
502    VkResult result = pfn_create_device(vk_phys_dev, pCreateInfo, pAllocator, pDevice);
503    if (result != VK_SUCCESS) {
504        return result;
505    }
506    auto dev = new wrapped_dev_obj;
507    if (!dev) {
508        return VK_ERROR_OUT_OF_HOST_MEMORY;
509    }
510    saved_wrapped_handles.devices.push_back(dev);
511    memset(dev, 0, sizeof(*dev));
512    dev->obj = *pDevice;
513    dev->pfn_get_dev_proc_addr = pfn_get_dev_proc_addr;
514    *pDevice = reinterpret_cast<VkDevice>(dev);
515
516    // Store the loader callback for initializing created dispatchable objects
517    chain_info = get_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
518    if (chain_info) {
519        dev->pfn_dev_init = chain_info->u.pfnSetDeviceLoaderData;
520        result = dev->pfn_dev_init(dev->obj, reinterpret_cast<void *>(dev));
521        if (VK_SUCCESS != result) {
522            return result;
523        }
524    } else {
525        dev->pfn_dev_init = NULL;
526    }
527
528    // Initialize layer's dispatch table
529    layer_init_device_dispatch_table(dev->obj, &dev->disp, pfn_get_dev_proc_addr);
530
531    for (uint32_t ext = 0; ext < pCreateInfo->enabledExtensionCount; ++ext) {
532        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[ext], VK_KHR_MAINTENANCE1_EXTENSION_NAME)) {
533#if TEST_LAYER_EXPORT_MAINT_1
534            dev->maintanence_1_enabled = true;
535#endif
536        }
537        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[ext], VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME)) {
538#if TEST_LAYER_EXPORT_PRESENT_IMAGE
539            dev->present_image_enabled = true;
540#endif
541        }
542        if (!strcmp(pCreateInfo->ppEnabledExtensionNames[ext], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
543            dev->debug_marker_enabled = true;
544        }
545    }
546    dev->debug_utils_enabled = phys_dev->inst->debug_utils_enabled;
547
548    return result;
549}
550
551VKAPI_ATTR void VKAPI_CALL wrap_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
552    wrapped_dev_obj *dev;
553    auto vk_dev = unwrap_device(device, &dev);
554    dev->disp.DestroyDevice(vk_dev, pAllocator);
555    delete dev;
556}
557
558// Fake instance extension support
559VKAPI_ATTR VkResult VKAPI_CALL wrap_vkReleaseDisplayEXT(VkPhysicalDevice, VkDisplayKHR) { return VK_SUCCESS; }
560
561VKAPI_ATTR VkResult VKAPI_CALL wrap_vkGetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice, VkSurfaceKHR,
562                                                                               VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
563    if (nullptr != pSurfaceCapabilities) {
564        pSurfaceCapabilities->minImageCount = 7;
565        pSurfaceCapabilities->maxImageCount = 12;
566        pSurfaceCapabilities->maxImageArrayLayers = 365;
567    }
568    return VK_SUCCESS;
569}
570
571// Fake device extension support
572VKAPI_ATTR void VKAPI_CALL wrap_vkTrimCommandPoolKHR(VkDevice, VkCommandPool, VkCommandPoolTrimFlags) {}
573
574// Return an odd error so we can verify that this actually got called
575VKAPI_ATTR VkResult VKAPI_CALL wrap_vkGetSwapchainStatusKHR(VkDevice, VkSwapchainKHR) { return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; }
576
577// Debug utils & debug marker ext stubs
578VKAPI_ATTR VkResult VKAPI_CALL wrap_vkDebugMarkerSetObjectTagEXT(VkDevice device, const VkDebugMarkerObjectTagInfoEXT *pTagInfo) {
579    VkDebugMarkerObjectTagInfoEXT new_info = *pTagInfo;
580    wrapped_dev_obj *dev;
581    auto vk_dev = unwrap_device(device, &dev);
582    if (pTagInfo && pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
583        wrapped_phys_dev_obj *phys_dev;
584        auto vk_phys_dev = unwrap_phys_dev((VkPhysicalDevice)(uintptr_t)(pTagInfo->object), &phys_dev);
585        if (vk_phys_dev == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
586        new_info.object = (uint64_t)(uintptr_t)vk_phys_dev;
587    }
588    if (pTagInfo && pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
589        // TODO
590    }
591    if (pTagInfo && pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT) {
592        wrapped_inst_obj *inst;
593        auto instance = unwrap_instance((VkInstance)(uintptr_t)(pTagInfo->object), &inst);
594        if (instance == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
595        new_info.object = (uint64_t)(uintptr_t)instance;
596    }
597    return dev->disp.DebugMarkerSetObjectTagEXT(vk_dev, &new_info);
598}
599VKAPI_ATTR VkResult VKAPI_CALL wrap_vkDebugMarkerSetObjectNameEXT(VkDevice device,
600                                                                  const VkDebugMarkerObjectNameInfoEXT *pNameInfo) {
601    VkDebugMarkerObjectNameInfoEXT new_info = *pNameInfo;
602    wrapped_dev_obj *dev;
603    auto vk_dev = unwrap_device(device, &dev);
604    if (pNameInfo && pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
605        wrapped_phys_dev_obj *phys_dev;
606        auto vk_phys_dev = unwrap_phys_dev((VkPhysicalDevice)(uintptr_t)(pNameInfo->object), &phys_dev);
607        if (vk_phys_dev == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
608        new_info.object = (uint64_t)(uintptr_t)vk_phys_dev;
609    }
610    if (pNameInfo && pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
611        // TODO
612    }
613    if (pNameInfo && pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT) {
614        wrapped_inst_obj *inst;
615        auto instance = unwrap_instance((VkInstance)(uintptr_t)(pNameInfo->object), &inst);
616        if (instance == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
617        new_info.object = (uint64_t)(uintptr_t)instance;
618    }
619    return dev->disp.DebugMarkerSetObjectNameEXT(vk_dev, &new_info);
620}
621// Debug Marker functions that are not supported:
622// vkCmdDebugMarkerBeginEXT
623// vkCmdDebugMarkerEndEXT
624// vkCmdDebugMarkerInsertEXT
625
626VKAPI_ATTR VkResult VKAPI_CALL wrap_vkSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) {
627    VkDebugUtilsObjectNameInfoEXT new_info = *pNameInfo;
628    wrapped_dev_obj *dev;
629    auto vk_dev = unwrap_device(device, &dev);
630    if (pNameInfo && pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
631        wrapped_phys_dev_obj *phys_dev;
632        auto vk_phys_dev = unwrap_phys_dev((VkPhysicalDevice)(uintptr_t)(pNameInfo->objectHandle), &phys_dev);
633        if (vk_phys_dev == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
634        new_info.objectHandle = (uint64_t)(uintptr_t)vk_phys_dev;
635    }
636    if (pNameInfo && pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
637        // TODO
638    }
639    if (pNameInfo && pNameInfo->objectType == VK_OBJECT_TYPE_INSTANCE) {
640        wrapped_inst_obj *inst;
641        auto instance = unwrap_instance((VkInstance)(uintptr_t)(pNameInfo->objectHandle), &inst);
642        if (instance == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
643        new_info.objectHandle = (uint64_t)(uintptr_t)instance;
644    }
645    return dev->disp.SetDebugUtilsObjectNameEXT(vk_dev, &new_info);
646}
647VKAPI_ATTR VkResult VKAPI_CALL wrap_vkSetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) {
648    VkDebugUtilsObjectTagInfoEXT new_info = *pTagInfo;
649    wrapped_dev_obj *dev;
650    auto vk_dev = unwrap_device(device, &dev);
651    if (pTagInfo && pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
652        wrapped_phys_dev_obj *phys_dev;
653        auto vk_phys_dev = unwrap_phys_dev((VkPhysicalDevice)(uintptr_t)(pTagInfo->objectHandle), &phys_dev);
654        if (vk_phys_dev == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
655        new_info.objectHandle = (uint64_t)(uintptr_t)vk_phys_dev;
656    }
657    if (pTagInfo && pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
658        // TODO
659    }
660    if (pTagInfo && pTagInfo->objectType == VK_OBJECT_TYPE_INSTANCE) {
661        wrapped_inst_obj *inst;
662        auto instance = unwrap_instance((VkInstance)(uintptr_t)(pTagInfo->objectHandle), &inst);
663        if (instance == VK_NULL_HANDLE) return VK_ERROR_DEVICE_LOST;
664        new_info.objectHandle = (uint64_t)(uintptr_t)instance;
665    }
666    return dev->disp.SetDebugUtilsObjectTagEXT(vk_dev, &new_info);
667}
668// Debug utils functions that are not supported
669// vkQueueBeginDebugUtilsLabelEXT
670// vkQueueEndDebugUtilsLabelEXT
671// vkQueueInsertDebugUtilsLabelEXT
672// vkCmdBeginDebugUtilsLabelEXT
673// vkCmdEndDebugUtilsLabelEXT
674// vkCmdInsertDebugUtilsLabelEXT
675
676PFN_vkVoidFunction layer_intercept_device_proc(wrapped_dev_obj *dev, const char *name) {
677    if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
678
679    name += 2;
680    if (!strcmp(name, "CreateDevice")) return (PFN_vkVoidFunction)wrap_vkCreateDevice;
681    if (!strcmp(name, "DestroyDevice")) return (PFN_vkVoidFunction)wrap_vkDestroyDevice;
682
683    if (dev->maintanence_1_enabled && !strcmp(name, "TrimCommandPoolKHR")) return (PFN_vkVoidFunction)wrap_vkTrimCommandPoolKHR;
684    if (dev->present_image_enabled && !strcmp(name, "GetSwapchainStatusKHR"))
685        return (PFN_vkVoidFunction)wrap_vkGetSwapchainStatusKHR;
686
687    if (dev->debug_marker_enabled && !strcmp(name, "DebugMarkerSetObjectTagEXT"))
688        return (PFN_vkVoidFunction)wrap_vkDebugMarkerSetObjectTagEXT;
689    if (dev->debug_marker_enabled && !strcmp(name, "DebugMarkerSetObjectNameEXT"))
690        return (PFN_vkVoidFunction)wrap_vkDebugMarkerSetObjectNameEXT;
691    if (dev->debug_utils_enabled && !strcmp(name, "SetDebugUtilsObjectNameEXT"))
692        return (PFN_vkVoidFunction)wrap_vkSetDebugUtilsObjectNameEXT;
693    if (dev->debug_utils_enabled && !strcmp(name, "SetDebugUtilsObjectTagEXT"))
694        return (PFN_vkVoidFunction)wrap_vkSetDebugUtilsObjectTagEXT;
695
696    return NULL;
697}
698
699VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wrap_vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
700    PFN_vkVoidFunction addr;
701
702    if (!strcmp("vkGetDeviceProcAddr", funcName)) {
703        return (PFN_vkVoidFunction)wrap_vkGetDeviceProcAddr;
704    }
705
706    if (device == VK_NULL_HANDLE) {
707        return NULL;
708    }
709
710    wrapped_dev_obj *dev;
711    unwrap_device(device, &dev);
712
713    addr = layer_intercept_device_proc(dev, funcName);
714    if (addr) return addr;
715
716    return dev->pfn_get_dev_proc_addr(dev->obj, funcName);
717}
718
719PFN_vkVoidFunction layer_intercept_instance_proc(wrapped_inst_obj *inst, const char *name) {
720    if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
721
722    name += 2;
723    if (!strcmp(name, "DestroyInstance")) return (PFN_vkVoidFunction)wrap_vkDestroyInstance;
724    if (!strcmp(name, "CreateDevice")) return (PFN_vkVoidFunction)wrap_vkCreateDevice;
725    if (!strcmp(name, "EnumeratePhysicalDevices")) return (PFN_vkVoidFunction)wrap_vkEnumeratePhysicalDevices;
726
727    if (!strcmp(name, "EnumerateDeviceExtensionProperties")) return (PFN_vkVoidFunction)wrap_vkEnumerateDeviceExtensionProperties;
728
729    if (!strcmp(name, "CreateDebugUtilsMessengerEXT")) return (PFN_vkVoidFunction)wrap_vkCreateDebugUtilsMessengerEXT;
730    if (!strcmp(name, "DestroyDebugUtilsMessengerEXT")) return (PFN_vkVoidFunction)wrap_vkDestroyDebugUtilsMessengerEXT;
731
732    if (!strcmp(name, "GetPhysicalDeviceProperties")) return (PFN_vkVoidFunction)vkGetPhysicalDeviceProperties;
733    if (!strcmp(name, "GetPhysicalDeviceQueueFamilyProperties"))
734        return (PFN_vkVoidFunction)wrap_vkGetPhysicalDeviceQueueFamilyProperties;
735
736#if defined(VK_USE_PLATFORM_ANDROID_KHR)
737    if (!strcmp(name, "CreateAndroidSurfaceKHR")) return (PFN_vkVoidFunction)wrap_vkCreateAndroidSurfaceKHR;
738#endif  // VK_USE_PLATFORM_ANDROID_KHR
739
740#if defined(VK_USE_PLATFORM_WIN32_KHR)
741    if (!strcmp(name, "CreateWin32SurfaceKHR")) return (PFN_vkVoidFunction)wrap_vkCreateWin32SurfaceKHR;
742#endif  // VK_USE_PLATFORM_WIN32_KHR
743
744#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
745    if (!strcmp(name, "CreateWaylandSurfaceKHR")) return (PFN_vkVoidFunction)wrap_vkCreateWaylandSurfaceKHR;
746#endif  // VK_USE_PLATFORM_WAYLAND_KHR
747
748#if defined(VK_USE_PLATFORM_XCB_KHR)
749    if (!strcmp(name, "CreateXcbSurfaceKHR")) return (PFN_vkVoidFunction)wrap_vkCreateXcbSurfaceKHR;
750#endif  // VK_USE_PLATFORM_XCB_KHR
751
752#if defined(VK_USE_PLATFORM_XLIB_KHR)
753    if (!strcmp(name, "CreateXlibSurfaceKHR")) return (PFN_vkVoidFunction)wrap_vkCreateXlibSurfaceKHR;
754#endif  // VK_USE_PLATFORM_XLIB_KHR
755
756#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
757    if (!strcmp(name, "CreateDirectFBSurfaceEXT")) return (PFN_vkVoidFunction)wrap_vkCreateDirectFBSurfaceEXT;
758#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
759
760#if defined(VK_USE_PLATFORM_MACOS_MVK)
761    if (!strcmp(name, "CreateMacOSSurfaceMVK")) return (PFN_vkVoidFunction)wrap_vkCreateMacOSSurfaceMVK;
762#endif  // VK_USE_PLATFORM_MACOS_MVK
763
764#if defined(VK_USE_PLATFORM_IOS_MVK)
765    if (!strcmp(name, "CreateIOSSurfaceMVK")) return (PFN_vkVoidFunction)wrap_vkCreateIOSSurfaceMVK;
766#endif  // VK_USE_PLATFORM_IOS_MVK
767
768#if defined(VK_USE_PLATFORM_GGP)
769    if (!strcmp(name, "CreateStreamDescriptorSurfaceGGP")) return (PFN_vkVoidFunction)wrap_vkCreateStreamDescriptorSurfaceGGP;
770#endif  // VK_USE_PLATFORM_GGP
771
772#if defined(VK_USE_PLATFORM_METAL_EXT)
773    if (!strcmp(name, "CreateMetalSurfaceEXT")) return (PFN_vkVoidFunction)wrap_vkCreateMetalSurfaceEXT;
774#endif  // VK_USE_PLATFORM_METAL_EXT
775
776#if defined(VK_USE_PLATFORM_SCREEN_QNX)
777    if (!strcmp(name, "CreateScreenSurfaceQNX")) return (PFN_vkVoidFunction)wrap_vkCreateScreenSurfaceQNX;
778#endif  // VK_USE_PLATFORM_SCREEN_QNX
779    if (!strcmp(name, "DestroySurfaceKHR")) return (PFN_vkVoidFunction)wrap_vkDestroySurfaceKHR;
780
781    if (inst->direct_display_enabled && !strcmp(name, "ReleaseDisplayEXT")) return (PFN_vkVoidFunction)wrap_vkReleaseDisplayEXT;
782    if (inst->display_surf_counter_enabled && !strcmp(name, "GetPhysicalDeviceSurfaceCapabilities2EXT"))
783        return (PFN_vkVoidFunction)wrap_vkGetPhysicalDeviceSurfaceCapabilities2EXT;
784
785    // instance_proc needs to be able to query device commands even if the extension isn't enabled (because it isn't known at this
786    // time)
787    if (!strcmp(name, "TrimCommandPoolKHR")) return (PFN_vkVoidFunction)wrap_vkTrimCommandPoolKHR;
788    if (!strcmp(name, "GetSwapchainStatusKHR")) return (PFN_vkVoidFunction)wrap_vkGetSwapchainStatusKHR;
789
790    if (!strcmp(name, "DebugMarkerSetObjectTagEXT")) return (PFN_vkVoidFunction)wrap_vkDebugMarkerSetObjectTagEXT;
791    if (!strcmp(name, "DebugMarkerSetObjectNameEXT")) return (PFN_vkVoidFunction)wrap_vkDebugMarkerSetObjectNameEXT;
792    if (inst->debug_utils_enabled && !strcmp(name, "SetDebugUtilsObjectNameEXT"))
793        return (PFN_vkVoidFunction)wrap_vkSetDebugUtilsObjectNameEXT;
794    if (inst->debug_utils_enabled && !strcmp(name, "SetDebugUtilsObjectTagEXT"))
795        return (PFN_vkVoidFunction)wrap_vkSetDebugUtilsObjectTagEXT;
796
797    return NULL;
798}
799
800VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wrap_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
801    PFN_vkVoidFunction addr;
802
803    if (!strcmp(funcName, "vkGetInstanceProcAddr")) return (PFN_vkVoidFunction)wrap_vkGetInstanceProcAddr;
804    if (!strcmp(funcName, "vkCreateInstance")) return (PFN_vkVoidFunction)wrap_vkCreateInstance;
805
806    if (instance == VK_NULL_HANDLE) {
807        return NULL;
808    }
809
810    wrapped_inst_obj *inst;
811    unwrap_instance(instance, &inst);
812
813    addr = layer_intercept_instance_proc(inst, funcName);
814    if (addr) return addr;
815
816    VkLayerInstanceDispatchTable *pTable = &inst->layer_disp;
817
818    if (pTable->GetInstanceProcAddr == NULL) return NULL;
819    return pTable->GetInstanceProcAddr(inst->obj, funcName);
820}
821
822VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
823    assert(instance);
824
825    wrapped_inst_obj *inst;
826    unwrap_instance(instance, &inst);
827    VkLayerInstanceDispatchTable *pTable = &inst->layer_disp;
828
829    if (pTable->GetPhysicalDeviceProcAddr == NULL) return NULL;
830    return pTable->GetPhysicalDeviceProcAddr(inst->obj, funcName);
831}
832
833}  // namespace wrap_objects
834
835extern "C" {
836// loader-layer interface v0, just wrappers since there is only a layer
837VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
838    return wrap_objects::wrap_vkGetInstanceProcAddr(instance, funcName);
839}
840
841VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
842    return wrap_objects::wrap_vkGetDeviceProcAddr(device, funcName);
843}
844
845VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *, uint32_t *,
846                                                                                      VkExtensionProperties *) {
847    assert(0);  // TODO return wrap_objects::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
848    return VK_SUCCESS;
849}
850
851VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *, VkLayerProperties *) {
852    assert(0);  // TODO return wrap_objects::EnumerateInstanceLayerProperties(pCount, pProperties);
853    return VK_SUCCESS;
854}
855
856VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
857vkEnumerateDeviceExtensionProperties([[maybe_unused]] VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount,
858                                     VkExtensionProperties *pProperties) {
859    // the layer command handles VK_NULL_HANDLE just fine internally
860    assert(physicalDevice == VK_NULL_HANDLE);
861    return wrap_objects::wrap_vkEnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
862}
863
864VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(VkInstance instance,
865                                                              const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
866                                                              const VkAllocationCallbacks *pAllocator,
867                                                              VkDebugUtilsMessengerEXT *pMessenger) {
868    return wrap_objects::wrap_vkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
869}
870
871VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
872                                                           const VkAllocationCallbacks *pAllocator) {
873    return wrap_objects::wrap_vkDestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
874}
875
876VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
877    return wrap_objects::wrap_vkDestroySurfaceKHR(instance, surface, pAllocator);
878}
879
880#if defined(VK_USE_PLATFORM_ANDROID_KHR)
881VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
882                                                              const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
883    return wrap_objects::wrap_vkCreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
884}
885#endif  // VK_USE_PLATFORM_WIN32_KHR
886
887#if defined(VK_USE_PLATFORM_WIN32_KHR)
888VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
889                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
890    return wrap_objects::wrap_vkCreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
891}
892#endif  // VK_USE_PLATFORM_WIN32_KHR
893
894#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
895VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
896                                                         const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
897    return wrap_objects::wrap_vkCreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
898}
899#endif  // VK_USE_PLATFORM_WAYLAND_KHR
900
901#if defined(VK_USE_PLATFORM_XCB_KHR)
902VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
903                                                     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
904    return wrap_objects::wrap_vkCreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
905}
906#endif  // VK_USE_PLATFORM_XCB_KHR
907
908#if defined(VK_USE_PLATFORM_XLIB_KHR)
909VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
910                                                      const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
911    return wrap_objects::wrap_vkCreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
912}
913#endif  // VK_USE_PLATFORM_XLIB_KHR
914
915#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
916VKAPI_ATTR VkResult VKAPI_CALL vkCreateDirectFBSurfaceEXT(VkInstance instance, const VkDirectFBSurfaceCreateInfoEXT *pCreateInfo,
917                                                          const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
918    return wrap_objects::wrap_vkCreateDirectFBSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface);
919}
920#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
921
922#if defined(VK_USE_PLATFORM_MACOS_MVK)
923VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
924                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
925    return wrap_objects::wrap_vkCreateMacOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
926}
927#endif  // VK_USE_PLATFORM_MACOS_MVK
928
929#if defined(VK_USE_PLATFORM_IOS_MVK)
930VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
931                                                     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
932    return wrap_objects::wrap_vkCreateIOSSurfaceMVK(instance, pCreateInfo, pAllocator, pSurface);
933}
934#endif  // VK_USE_PLATFORM_IOS_MVK
935
936#if defined(VK_USE_PLATFORM_GGP)
937VKAPI_ATTR VkResult VKAPI_CALL vkCreateStreamDescriptorSurfaceGGP(VkInstance instance,
938                                                                  const VkStreamDescriptorSurfaceCreateInfoGGP *pCreateInfo,
939                                                                  const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
940    return wrap_objects::wrap_vkCreateStreamDescriptorSurfaceGGP(instance, pCreateInfo, pAllocator, pSurface);
941}
942#endif  // VK_USE_PLATFORM_GGP
943
944#if defined(VK_USE_PLATFORM_METAL_EXT)
945VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
946                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
947    return wrap_objects::wrap_vkCreateMetalSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface);
948}
949#endif  // VK_USE_PLATFORM_METAL_EXT
950
951#if defined(VK_USE_PLATFORM_SCREEN_QNX)
952VKAPI_ATTR VkResult VKAPI_CALL vkCreateScreenSurfaceQNX(VkInstance instance, const VkScreenSurfaceCreateInfoQNX *pCreateInfo,
953                                                        const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
954    return wrap_objects::wrap_vkCreateScreenSurfaceQNX(instance, pCreateInfo, pAllocator, pSurface);
955}
956#endif  // VK_USE_PLATFORM_SCREEN_QNX
957
958VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
959                                                                                           const char *funcName) {
960    return wrap_objects::GetPhysicalDeviceProcAddr(instance, funcName);
961}
962
963VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
964    assert(pVersionStruct != NULL);
965    assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
966
967    // Fill in the function pointers if our version is at least capable of having the structure contain them.
968    if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
969        pVersionStruct->pfnGetInstanceProcAddr = wrap_objects::wrap_vkGetInstanceProcAddr;
970        pVersionStruct->pfnGetDeviceProcAddr = wrap_objects::wrap_vkGetDeviceProcAddr;
971        pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
972    }
973
974    if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
975        wrap_objects::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion;
976    } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
977        pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
978    }
979
980    return VK_SUCCESS;
981}
982}
983