1/*
2 * Copyright (c) 2021-2023 The Khronos Group Inc.
3 * Copyright (c) 2021-2023 Valve Corporation
4 * Copyright (c) 2021-2023 LunarG, Inc.
5 * Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
6 * Copyright (c) 2023-2023 RasterGrid Kft.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and/or associated documentation files (the "Materials"), to
10 * deal in the Materials without restriction, including without limitation the
11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Materials, and to permit persons to whom the Materials are
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice(s) and this permission notice shall be included in
16 * all copies or substantial portions of the Materials.
17 *
18 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 *
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
25 * USE OR OTHER DEALINGS IN THE MATERIALS.
26 *
27 * Author: Charles Giessen <charles@lunarg.com>
28 */
29
30#include "test_icd.h"
31
32// export vk_icdGetInstanceProcAddr
33#if !defined(TEST_ICD_EXPORT_ICD_GIPA)
34#define TEST_ICD_EXPORT_ICD_GIPA 0
35#endif
36
37// export vk_icdNegotiateLoaderICDInterfaceVersion
38#if !defined(TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION)
39#define TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION 0
40#endif
41
42// export vk_icdGetPhysicalDeviceProcAddr
43#if !defined(TEST_ICD_EXPORT_ICD_GPDPA)
44#define TEST_ICD_EXPORT_ICD_GPDPA 0
45#endif
46
47// export vk_icdEnumerateAdapterPhysicalDevices
48#if !defined(TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES)
49#define TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES 0
50#endif
51
52// expose vk_icdNegotiateLoaderICDInterfaceVersion, vk_icdEnumerateAdapterPhysicalDevices, and vk_icdGetPhysicalDeviceProcAddr
53// through vk_icdGetInstanceProcAddr or vkGetInstanceProcAddr
54#if !defined(TEST_ICD_EXPOSE_VERSION_7)
55#define TEST_ICD_EXPOSE_VERSION_7 0
56#endif
57
58TestICD icd;
59extern "C" {
60FRAMEWORK_EXPORT TestICD* get_test_icd_func() { return &icd; }
61FRAMEWORK_EXPORT TestICD* reset_icd_func() {
62    icd.~TestICD();
63    return new (&icd) TestICD();
64}
65}
66
67LayerDefinition& FindLayer(std::vector<LayerDefinition>& layers, std::string layerName) {
68    for (auto& layer : layers) {
69        if (layer.layerName == layerName) return layer;
70    }
71    assert(false && "Layer name not found!");
72    return layers[0];
73}
74bool CheckLayer(std::vector<LayerDefinition>& layers, std::string layerName) {
75    for (auto& layer : layers) {
76        if (layer.layerName == layerName) return true;
77    }
78    return false;
79}
80
81bool IsInstanceExtensionSupported(const char* extension_name) {
82    return icd.instance_extensions.end() !=
83           std::find_if(icd.instance_extensions.begin(), icd.instance_extensions.end(),
84                        [extension_name](Extension const& ext) { return string_eq(&ext.extensionName[0], extension_name); });
85}
86
87bool IsInstanceExtensionEnabled(const char* extension_name) {
88    return icd.enabled_instance_extensions.end() !=
89           std::find_if(icd.enabled_instance_extensions.begin(), icd.enabled_instance_extensions.end(),
90                        [extension_name](Extension const& ext) { return string_eq(&ext.extensionName[0], extension_name); });
91}
92
93bool IsPhysicalDeviceExtensionAvailable(const char* extension_name) {
94    for (auto& phys_dev : icd.physical_devices) {
95        if (phys_dev.extensions.end() !=
96            std::find_if(phys_dev.extensions.begin(), phys_dev.extensions.end(),
97                         [extension_name](Extension const& ext) { return ext.extensionName == extension_name; })) {
98            return true;
99        }
100    }
101    return false;
102}
103
104// typename T must have '.get()' function that returns a type U
105template <typename T, typename U>
106VkResult FillCountPtr(std::vector<T> const& data_vec, uint32_t* pCount, U* pData) {
107    if (pCount == nullptr) {
108        return VK_ERROR_OUT_OF_HOST_MEMORY;
109    }
110    if (pData == nullptr) {
111        *pCount = static_cast<uint32_t>(data_vec.size());
112        return VK_SUCCESS;
113    }
114    uint32_t amount_written = 0;
115    uint32_t amount_to_write = static_cast<uint32_t>(data_vec.size());
116    if (*pCount < data_vec.size()) {
117        amount_to_write = *pCount;
118    }
119    for (size_t i = 0; i < amount_to_write; i++) {
120        pData[i] = data_vec[i].get();
121        amount_written++;
122    }
123    if (*pCount < data_vec.size()) {
124        *pCount = amount_written;
125        return VK_INCOMPLETE;
126    }
127    *pCount = amount_written;
128    return VK_SUCCESS;
129}
130
131template <typename T>
132VkResult FillCountPtr(std::vector<T> const& data_vec, uint32_t* pCount, T* pData) {
133    if (pCount == nullptr) {
134        return VK_ERROR_OUT_OF_HOST_MEMORY;
135    }
136    if (pData == nullptr) {
137        *pCount = static_cast<uint32_t>(data_vec.size());
138        return VK_SUCCESS;
139    }
140    uint32_t amount_written = 0;
141    uint32_t amount_to_write = static_cast<uint32_t>(data_vec.size());
142    if (*pCount < data_vec.size()) {
143        amount_to_write = *pCount;
144    }
145    for (size_t i = 0; i < amount_to_write; i++) {
146        pData[i] = data_vec[i];
147        amount_written++;
148    }
149    if (*pCount < data_vec.size()) {
150        *pCount = amount_written;
151        return VK_INCOMPLETE;
152    }
153    *pCount = amount_written;
154    return VK_SUCCESS;
155}
156
157//// Instance Functions ////
158
159// VK_SUCCESS,VK_INCOMPLETE
160VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount,
161                                                                           VkExtensionProperties* pProperties) {
162    if (pLayerName != nullptr) {
163        auto& layer = FindLayer(icd.instance_layers, std::string(pLayerName));
164        return FillCountPtr(layer.extensions, pPropertyCount, pProperties);
165    } else {  // instance extensions
166        FillCountPtr(icd.instance_extensions, pPropertyCount, pProperties);
167    }
168
169    return VK_SUCCESS;
170}
171
172VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
173    return FillCountPtr(icd.instance_layers, pPropertyCount, pProperties);
174}
175
176VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
177    if (pApiVersion != nullptr) {
178        *pApiVersion = icd.icd_api_version;
179    }
180    return VK_SUCCESS;
181}
182
183VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
184                                                     [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
185                                                     VkInstance* pInstance) {
186    if (pCreateInfo == nullptr || pCreateInfo->pApplicationInfo == nullptr) {
187        return VK_ERROR_OUT_OF_HOST_MEMORY;
188    }
189
190    if (icd.icd_api_version < VK_API_VERSION_1_1) {
191        if (pCreateInfo->pApplicationInfo->apiVersion > VK_API_VERSION_1_0) {
192            return VK_ERROR_INCOMPATIBLE_DRIVER;
193        }
194    }
195
196    // Add to the list of enabled extensions only those that the ICD actively supports
197    for (uint32_t iii = 0; iii < pCreateInfo->enabledExtensionCount; ++iii) {
198        if (IsInstanceExtensionSupported(pCreateInfo->ppEnabledExtensionNames[iii])) {
199            icd.add_enabled_instance_extension({pCreateInfo->ppEnabledExtensionNames[iii]});
200        }
201    }
202
203    // VK_SUCCESS
204    *pInstance = icd.instance_handle.handle;
205
206    icd.passed_in_instance_create_flags = pCreateInfo->flags;
207
208    return VK_SUCCESS;
209}
210
211VKAPI_ATTR void VKAPI_CALL test_vkDestroyInstance([[maybe_unused]] VkInstance instance,
212                                                  [[maybe_unused]] const VkAllocationCallbacks* pAllocator) {}
213
214// VK_SUCCESS,VK_INCOMPLETE
215VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDevices([[maybe_unused]] VkInstance instance, uint32_t* pPhysicalDeviceCount,
216                                                               VkPhysicalDevice* pPhysicalDevices) {
217    if (pPhysicalDevices == nullptr) {
218        *pPhysicalDeviceCount = static_cast<uint32_t>(icd.physical_devices.size());
219    } else {
220        uint32_t handles_written = 0;
221        for (size_t i = 0; i < icd.physical_devices.size(); i++) {
222            if (i < *pPhysicalDeviceCount) {
223                handles_written++;
224                pPhysicalDevices[i] = icd.physical_devices[i].vk_physical_device.handle;
225            } else {
226                *pPhysicalDeviceCount = handles_written;
227                return VK_INCOMPLETE;
228            }
229        }
230        *pPhysicalDeviceCount = handles_written;
231    }
232    return VK_SUCCESS;
233}
234
235// VK_SUCCESS,VK_INCOMPLETE, VK_ERROR_INITIALIZATION_FAILED
236VKAPI_ATTR VkResult VKAPI_CALL
237test_vkEnumeratePhysicalDeviceGroups([[maybe_unused]] VkInstance instance, uint32_t* pPhysicalDeviceGroupCount,
238                                     VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
239    VkResult result = VK_SUCCESS;
240
241    if (pPhysicalDeviceGroupProperties == nullptr) {
242        if (0 == icd.physical_device_groups.size()) {
243            *pPhysicalDeviceGroupCount = static_cast<uint32_t>(icd.physical_devices.size());
244        } else {
245            *pPhysicalDeviceGroupCount = static_cast<uint32_t>(icd.physical_device_groups.size());
246        }
247    } else {
248        // NOTE: This is a fake struct to make sure the pNext chain is properly passed down to the ICD
249        //       vkEnumeratePhysicalDeviceGroups.
250        //       The two versions must match:
251        //           "FakePNext" test in loader_regresion_tests.cpp
252        //           "test_vkEnumeratePhysicalDeviceGroups" in test_icd.cpp
253        struct FakePnextSharedWithICD {
254            VkStructureType sType;
255            void* pNext;
256            uint32_t value;
257        };
258
259        uint32_t group_count = 0;
260        if (0 == icd.physical_device_groups.size()) {
261            group_count = static_cast<uint32_t>(icd.physical_devices.size());
262            for (size_t device_group = 0; device_group < icd.physical_devices.size(); device_group++) {
263                if (device_group >= *pPhysicalDeviceGroupCount) {
264                    group_count = *pPhysicalDeviceGroupCount;
265                    result = VK_INCOMPLETE;
266                    break;
267                }
268                pPhysicalDeviceGroupProperties[device_group].subsetAllocation = false;
269                pPhysicalDeviceGroupProperties[device_group].physicalDeviceCount = 1;
270                pPhysicalDeviceGroupProperties[device_group].physicalDevices[0] =
271                    icd.physical_devices[device_group].vk_physical_device.handle;
272                for (size_t i = 1; i < VK_MAX_DEVICE_GROUP_SIZE; i++) {
273                    pPhysicalDeviceGroupProperties[device_group].physicalDevices[i] = {};
274                }
275            }
276        } else {
277            group_count = static_cast<uint32_t>(icd.physical_device_groups.size());
278            for (size_t device_group = 0; device_group < icd.physical_device_groups.size(); device_group++) {
279                if (device_group >= *pPhysicalDeviceGroupCount) {
280                    group_count = *pPhysicalDeviceGroupCount;
281                    result = VK_INCOMPLETE;
282                    break;
283                }
284                pPhysicalDeviceGroupProperties[device_group].subsetAllocation =
285                    icd.physical_device_groups[device_group].subset_allocation;
286                uint32_t handles_written = 0;
287                for (size_t i = 0; i < icd.physical_device_groups[device_group].physical_device_handles.size(); i++) {
288                    handles_written++;
289                    pPhysicalDeviceGroupProperties[device_group].physicalDevices[i] =
290                        icd.physical_device_groups[device_group].physical_device_handles[i]->vk_physical_device.handle;
291                }
292                for (size_t i = handles_written; i < VK_MAX_DEVICE_GROUP_SIZE; i++) {
293                    pPhysicalDeviceGroupProperties[device_group].physicalDevices[i] = {};
294                }
295                pPhysicalDeviceGroupProperties[device_group].physicalDeviceCount = handles_written;
296            }
297        }
298        // NOTE: The following code is purely to test pNext passing in vkEnumeratePhysicalDevice groups
299        //       and includes normally invalid information.
300        for (size_t device_group = 0; device_group < group_count; device_group++) {
301            if (nullptr != pPhysicalDeviceGroupProperties[device_group].pNext) {
302                VkBaseInStructure* base = reinterpret_cast<VkBaseInStructure*>(pPhysicalDeviceGroupProperties[device_group].pNext);
303                if (base->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT) {
304                    FakePnextSharedWithICD* fake = reinterpret_cast<FakePnextSharedWithICD*>(base);
305                    fake->value = 0xDECAFBAD;
306                }
307            }
308        }
309        *pPhysicalDeviceGroupCount = static_cast<uint32_t>(group_count);
310    }
311    return result;
312}
313
314VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDebugUtilsMessengerEXT(
315    [[maybe_unused]] VkInstance instance, [[maybe_unused]] const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
316    [[maybe_unused]] const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger) {
317    if (nullptr != pMessenger) {
318        uint64_t fake_msgr_handle = reinterpret_cast<uint64_t>(new uint8_t);
319        icd.messenger_handles.push_back(fake_msgr_handle);
320#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || \
321    defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
322        *pMessenger = reinterpret_cast<VkDebugUtilsMessengerEXT>(fake_msgr_handle);
323#else
324        *pMessenger = fake_msgr_handle;
325#endif
326    }
327    return VK_SUCCESS;
328}
329
330VKAPI_ATTR void VKAPI_CALL test_vkDestroyDebugUtilsMessengerEXT([[maybe_unused]] VkInstance instance,
331                                                                VkDebugUtilsMessengerEXT messenger,
332                                                                [[maybe_unused]] const VkAllocationCallbacks* pAllocator) {
333    if (messenger != VK_NULL_HANDLE) {
334        uint64_t fake_msgr_handle = (uint64_t)(messenger);
335        auto found_iter = std::find(icd.messenger_handles.begin(), icd.messenger_handles.end(), fake_msgr_handle);
336        if (found_iter != icd.messenger_handles.end()) {
337            // Remove it from the list
338            icd.messenger_handles.erase(found_iter);
339            // Delete the handle
340            delete (uint8_t*)fake_msgr_handle;
341        } else {
342            assert(false && "Messenger not found during destroy!");
343        }
344    }
345}
346
347// Debug utils & debug marker ext stubs
348VKAPI_ATTR VkResult VKAPI_CALL test_vkDebugMarkerSetObjectTagEXT(VkDevice dev, const VkDebugMarkerObjectTagInfoEXT* pTagInfo) {
349    if (pTagInfo && pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
350        VkPhysicalDevice pd = (VkPhysicalDevice)(uintptr_t)(pTagInfo->object);
351        if (pd != icd.physical_devices.at(icd.lookup_device(dev).phys_dev_index).vk_physical_device.handle)
352            return VK_ERROR_DEVICE_LOST;
353    }
354    if (pTagInfo && pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
355        if (pTagInfo->object != icd.surface_handles.at(0)) return VK_ERROR_DEVICE_LOST;
356    }
357    if (pTagInfo && pTagInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT) {
358        if (pTagInfo->object != (uint64_t)(uintptr_t)icd.instance_handle.handle) return VK_ERROR_DEVICE_LOST;
359    }
360    return VK_SUCCESS;
361}
362VKAPI_ATTR VkResult VKAPI_CALL test_vkDebugMarkerSetObjectNameEXT(VkDevice dev, const VkDebugMarkerObjectNameInfoEXT* pNameInfo) {
363    if (pNameInfo && pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT) {
364        VkPhysicalDevice pd = (VkPhysicalDevice)(uintptr_t)(pNameInfo->object);
365        if (pd != icd.physical_devices.at(icd.lookup_device(dev).phys_dev_index).vk_physical_device.handle)
366            return VK_ERROR_DEVICE_LOST;
367    }
368    if (pNameInfo && pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT) {
369        if (pNameInfo->object != icd.surface_handles.at(0)) return VK_ERROR_DEVICE_LOST;
370    }
371    if (pNameInfo && pNameInfo->objectType == VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT) {
372        if (pNameInfo->object != (uint64_t)(uintptr_t)icd.instance_handle.handle) return VK_ERROR_DEVICE_LOST;
373    }
374    return VK_SUCCESS;
375}
376VKAPI_ATTR void VKAPI_CALL test_vkCmdDebugMarkerBeginEXT(VkCommandBuffer, const VkDebugMarkerMarkerInfoEXT*) {}
377VKAPI_ATTR void VKAPI_CALL test_vkCmdDebugMarkerEndEXT(VkCommandBuffer) {}
378VKAPI_ATTR void VKAPI_CALL test_vkCmdDebugMarkerInsertEXT(VkCommandBuffer, const VkDebugMarkerMarkerInfoEXT*) {}
379
380VKAPI_ATTR VkResult VKAPI_CALL test_vkSetDebugUtilsObjectNameEXT(VkDevice dev, const VkDebugUtilsObjectNameInfoEXT* pNameInfo) {
381    if (pNameInfo && pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
382        VkPhysicalDevice pd = (VkPhysicalDevice)(uintptr_t)(pNameInfo->objectHandle);
383        if (pd != icd.physical_devices.at(icd.lookup_device(dev).phys_dev_index).vk_physical_device.handle)
384            return VK_ERROR_DEVICE_LOST;
385    }
386    if (pNameInfo && pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
387        if (pNameInfo->objectHandle != icd.surface_handles.at(0)) return VK_ERROR_DEVICE_LOST;
388    }
389    if (pNameInfo && pNameInfo->objectType == VK_OBJECT_TYPE_INSTANCE) {
390        if (pNameInfo->objectHandle != (uint64_t)(uintptr_t)icd.instance_handle.handle) return VK_ERROR_DEVICE_LOST;
391    }
392    return VK_SUCCESS;
393}
394VKAPI_ATTR VkResult VKAPI_CALL test_vkSetDebugUtilsObjectTagEXT(VkDevice dev, const VkDebugUtilsObjectTagInfoEXT* pTagInfo) {
395    if (pTagInfo && pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
396        VkPhysicalDevice pd = (VkPhysicalDevice)(uintptr_t)(pTagInfo->objectHandle);
397        if (pd != icd.physical_devices.at(icd.lookup_device(dev).phys_dev_index).vk_physical_device.handle)
398            return VK_ERROR_DEVICE_LOST;
399    }
400    if (pTagInfo && pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
401        if (pTagInfo->objectHandle != icd.surface_handles.at(0)) return VK_ERROR_DEVICE_LOST;
402    }
403    if (pTagInfo && pTagInfo->objectType == VK_OBJECT_TYPE_INSTANCE) {
404        if (pTagInfo->objectHandle != (uint64_t)(uintptr_t)icd.instance_handle.handle) return VK_ERROR_DEVICE_LOST;
405    }
406    return VK_SUCCESS;
407}
408VKAPI_ATTR void VKAPI_CALL test_vkQueueBeginDebugUtilsLabelEXT(VkQueue, const VkDebugUtilsLabelEXT*) {}
409VKAPI_ATTR void VKAPI_CALL test_vkQueueEndDebugUtilsLabelEXT(VkQueue) {}
410VKAPI_ATTR void VKAPI_CALL test_vkQueueInsertDebugUtilsLabelEXT(VkQueue, const VkDebugUtilsLabelEXT*) {}
411VKAPI_ATTR void VKAPI_CALL test_vkCmdBeginDebugUtilsLabelEXT(VkCommandBuffer, const VkDebugUtilsLabelEXT*) {}
412VKAPI_ATTR void VKAPI_CALL test_vkCmdEndDebugUtilsLabelEXT(VkCommandBuffer) {}
413VKAPI_ATTR void VKAPI_CALL test_vkCmdInsertDebugUtilsLabelEXT(VkCommandBuffer, const VkDebugUtilsLabelEXT*) {}
414
415//// Physical Device functions ////
416
417// VK_SUCCESS,VK_INCOMPLETE
418VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceLayerProperties(VkPhysicalDevice, uint32_t*, VkLayerProperties*) {
419    assert(false && "ICD's don't contain layers???");
420    return VK_SUCCESS;
421}
422
423// VK_SUCCESS, VK_INCOMPLETE, VK_ERROR_LAYER_NOT_PRESENT
424VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName,
425                                                                         uint32_t* pPropertyCount,
426                                                                         VkExtensionProperties* pProperties) {
427    auto& phys_dev = icd.GetPhysDevice(physicalDevice);
428    if (pLayerName != nullptr) {
429        assert(false && "Drivers don't contain layers???");
430        return VK_SUCCESS;
431    } else {  // instance extensions
432        return FillCountPtr(phys_dev.extensions, pPropertyCount, pProperties);
433    }
434}
435
436VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
437                                                                         uint32_t* pQueueFamilyPropertyCount,
438                                                                         VkQueueFamilyProperties* pQueueFamilyProperties) {
439    auto& phys_dev = icd.GetPhysDevice(physicalDevice);
440    FillCountPtr(phys_dev.queue_family_properties, pQueueFamilyPropertyCount, pQueueFamilyProperties);
441}
442
443VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo,
444                                                   [[maybe_unused]] const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
445    // VK_SUCCESS
446    auto found = std::find_if(icd.physical_devices.begin(), icd.physical_devices.end(), [physicalDevice](PhysicalDevice& phys_dev) {
447        return phys_dev.vk_physical_device.handle == physicalDevice;
448    });
449    if (found == icd.physical_devices.end()) return VK_ERROR_INITIALIZATION_FAILED;
450    auto device_handle = DispatchableHandle<VkDevice>();
451    *pDevice = device_handle.handle;
452    found->device_handles.push_back(device_handle.handle);
453    found->device_create_infos.push_back(DeviceCreateInfo{pCreateInfo});
454    for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
455        found->queue_handles.emplace_back();
456    }
457    icd.device_handles.emplace_back(std::move(device_handle));
458
459    return VK_SUCCESS;
460}
461
462VKAPI_ATTR void VKAPI_CALL test_vkDestroyDevice(VkDevice device, [[maybe_unused]] const VkAllocationCallbacks* pAllocator) {
463    auto found = std::find(icd.device_handles.begin(), icd.device_handles.end(), device);
464    if (found != icd.device_handles.end()) icd.device_handles.erase(found);
465    auto fd = icd.lookup_device(device);
466    if (!fd.found) return;
467    auto& phys_dev = icd.physical_devices.at(fd.phys_dev_index);
468    phys_dev.device_handles.erase(phys_dev.device_handles.begin() + fd.dev_index);
469    phys_dev.device_create_infos.erase(phys_dev.device_create_infos.begin() + fd.dev_index);
470}
471
472VKAPI_ATTR VkResult VKAPI_CALL generic_tool_props_function([[maybe_unused]] VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
473                                                           VkPhysicalDeviceToolPropertiesEXT* pToolProperties) {
474    if (icd.tooling_properties.size() == 0) {
475        return VK_SUCCESS;
476    }
477    if (pToolProperties == nullptr && pToolCount != nullptr) {
478        *pToolCount = static_cast<uint32_t>(icd.tooling_properties.size());
479    } else if (pToolCount != nullptr) {
480        for (size_t i = 0; i < *pToolCount; i++) {
481            if (i >= icd.tooling_properties.size()) {
482                return VK_INCOMPLETE;
483            }
484            pToolProperties[i] = icd.tooling_properties[i];
485        }
486    }
487    return VK_SUCCESS;
488}
489
490VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
491                                                                         VkPhysicalDeviceToolPropertiesEXT* pToolProperties) {
492    return generic_tool_props_function(physicalDevice, pToolCount, pToolProperties);
493}
494
495VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice, uint32_t* pToolCount,
496                                                                      VkPhysicalDeviceToolPropertiesEXT* pToolProperties) {
497    return generic_tool_props_function(physicalDevice, pToolCount, pToolProperties);
498}
499
500template <typename T>
501T to_nondispatch_handle(uint64_t handle) {
502#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || \
503    defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
504    return reinterpret_cast<T>(handle);
505#else
506    return handle;
507#endif
508}
509
510template <typename T>
511uint64_t from_nondispatch_handle(T handle) {
512#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || \
513    defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
514    return reinterpret_cast<uint64_t>(handle);
515#else
516    return handle;
517#endif
518}
519
520//// WSI ////
521template <typename HandleType>
522void common_nondispatch_handle_creation(std::vector<uint64_t>& handles, HandleType* pHandle) {
523    if (nullptr != pHandle) {
524        if (handles.size() == 0)
525            handles.push_back(800851234);
526        else
527            handles.push_back(handles.back() + 102030);
528        *pHandle = to_nondispatch_handle<HandleType>(handles.back());
529    }
530}
531#if defined(VK_USE_PLATFORM_ANDROID_KHR)
532
533VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
534                                                              const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
535    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
536    return VK_SUCCESS;
537}
538#endif
539
540#if defined(VK_USE_PLATFORM_WIN32_KHR)
541VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateWin32SurfaceKHR([[maybe_unused]] VkInstance instance,
542                                                            [[maybe_unused]] const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
543                                                            [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
544                                                            VkSurfaceKHR* pSurface) {
545    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
546    return VK_SUCCESS;
547}
548
549VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice, uint32_t) { return VK_TRUE; }
550#endif  // VK_USE_PLATFORM_WIN32_KHR
551
552#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
553VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateWaylandSurfaceKHR([[maybe_unused]] VkInstance instance,
554                                                              [[maybe_unused]] const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
555                                                              [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
556                                                              VkSurfaceKHR* pSurface) {
557    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
558    return VK_SUCCESS;
559}
560
561VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice, uint32_t,
562                                                                                     struct wl_display*) {
563    return VK_TRUE;
564}
565#endif  // VK_USE_PLATFORM_WAYLAND_KHR
566#if defined(VK_USE_PLATFORM_XCB_KHR)
567VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateXcbSurfaceKHR([[maybe_unused]] VkInstance instance,
568                                                          [[maybe_unused]] const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
569                                                          [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
570                                                          VkSurfaceKHR* pSurface) {
571    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
572    return VK_SUCCESS;
573}
574
575VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice, uint32_t, xcb_connection_t*,
576                                                                                 xcb_visualid_t) {
577    return VK_TRUE;
578}
579#endif  // VK_USE_PLATFORM_XCB_KHR
580
581#if defined(VK_USE_PLATFORM_XLIB_KHR)
582VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateXlibSurfaceKHR([[maybe_unused]] VkInstance instance,
583                                                           [[maybe_unused]] const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
584                                                           [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
585                                                           VkSurfaceKHR* pSurface) {
586    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
587    return VK_SUCCESS;
588}
589
590VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice, uint32_t, Display*, VisualID) {
591    return VK_TRUE;
592}
593#endif  // VK_USE_PLATFORM_XLIB_KHR
594
595#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
596VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDirectFBSurfaceEXT(VkInstance instance,
597                                                               const VkDirectFBSurfaceCreateInfoEXT* pCreateInfo,
598                                                               const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
599    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
600    return VK_SUCCESS;
601}
602
603VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceDirectFBPresentationSupportEXT(VkPhysicalDevice physicalDevice,
604                                                                                      uint32_t queueFamilyIndex, IDirectFB* dfb) {
605    return VK_TRUE;
606}
607
608#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
609
610#if defined(VK_USE_PLATFORM_MACOS_MVK)
611VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateMacOSSurfaceMVK([[maybe_unused]] VkInstance instance,
612                                                            [[maybe_unused]] const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
613                                                            [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
614                                                            VkSurfaceKHR* pSurface) {
615    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
616    return VK_SUCCESS;
617}
618#endif  // VK_USE_PLATFORM_MACOS_MVK
619
620#if defined(VK_USE_PLATFORM_IOS_MVK)
621VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateIOSSurfaceMVK([[maybe_unused]] VkInstance instance,
622                                                          [[maybe_unused]] const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
623                                                          [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
624                                                          VkSurfaceKHR* pSurface) {
625    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
626    return VK_SUCCESS;
627}
628#endif  // VK_USE_PLATFORM_IOS_MVK
629
630#if defined(VK_USE_PLATFORM_GGP)
631VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateStreamDescriptorSurfaceGGP(VkInstance instance,
632                                                                       const VkStreamDescriptorSurfaceCreateInfoGGP* pCreateInfo,
633                                                                       const VkAllocationCallbacks* pAllocator,
634                                                                       VkSurfaceKHR* pSurface) {
635    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
636    return VK_SUCCESS;
637}
638#endif  // VK_USE_PLATFORM_GGP
639
640#if defined(VK_USE_PLATFORM_METAL_EXT)
641VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateMetalSurfaceEXT([[maybe_unused]] VkInstance instance,
642                                                            [[maybe_unused]] const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
643                                                            [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
644                                                            VkSurfaceKHR* pSurface) {
645    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
646    return VK_SUCCESS;
647}
648#endif  // VK_USE_PLATFORM_METAL_EXT
649
650#if defined(VK_USE_PLATFORM_SCREEN_QNX)
651VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateScreenSurfaceQNX(VkInstance instance, const VkScreenSurfaceCreateInfoQNX* pCreateInfo,
652                                                             const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
653    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
654    return VK_SUCCESS;
655}
656
657VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceScreenPresentationSupportQNX(VkPhysicalDevice physicalDevice,
658                                                                                    uint32_t queueFamilyIndex,
659                                                                                    struct _screen_window* window) {
660    return VK_TRUE;
661}
662#endif  // VK_USE_PLATFORM_SCREEN_QNX
663
664VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateHeadlessSurfaceEXT([[maybe_unused]] VkInstance instance,
665                                                               [[maybe_unused]] const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo,
666                                                               [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
667                                                               VkSurfaceKHR* pSurface) {
668    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
669    return VK_SUCCESS;
670}
671
672VKAPI_ATTR void VKAPI_CALL test_vkDestroySurfaceKHR([[maybe_unused]] VkInstance instance, VkSurfaceKHR surface,
673                                                    [[maybe_unused]] const VkAllocationCallbacks* pAllocator) {
674    if (surface != VK_NULL_HANDLE) {
675        uint64_t fake_surf_handle = from_nondispatch_handle(surface);
676        auto found_iter = std::find(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle);
677        if (found_iter != icd.surface_handles.end()) {
678            // Remove it from the list
679            icd.surface_handles.erase(found_iter);
680        } else {
681            assert(false && "Surface not found during destroy!");
682        }
683    }
684}
685// VK_KHR_swapchain
686VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateSwapchainKHR([[maybe_unused]] VkDevice device,
687                                                         [[maybe_unused]] const VkSwapchainCreateInfoKHR* pCreateInfo,
688                                                         [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
689                                                         VkSwapchainKHR* pSwapchain) {
690    common_nondispatch_handle_creation(icd.swapchain_handles, pSwapchain);
691    return VK_SUCCESS;
692}
693
694VKAPI_ATTR VkResult VKAPI_CALL test_vkGetSwapchainImagesKHR([[maybe_unused]] VkDevice device,
695                                                            [[maybe_unused]] VkSwapchainKHR swapchain,
696                                                            uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
697    std::vector<uint64_t> handles{123, 234, 345, 345, 456};
698    if (pSwapchainImages == nullptr) {
699        if (pSwapchainImageCount) *pSwapchainImageCount = static_cast<uint32_t>(handles.size());
700    } else if (pSwapchainImageCount) {
701        for (uint32_t i = 0; i < *pSwapchainImageCount && i < handles.size(); i++) {
702            pSwapchainImages[i] = to_nondispatch_handle<VkImage>(handles.back());
703        }
704        if (*pSwapchainImageCount < handles.size()) return VK_INCOMPLETE;
705    }
706    return VK_SUCCESS;
707}
708
709VKAPI_ATTR void VKAPI_CALL test_vkDestroySwapchainKHR([[maybe_unused]] VkDevice device, VkSwapchainKHR swapchain,
710                                                      [[maybe_unused]] const VkAllocationCallbacks* pAllocator) {
711    if (swapchain != VK_NULL_HANDLE) {
712        uint64_t fake_swapchain_handle = from_nondispatch_handle(swapchain);
713        auto found_iter = icd.swapchain_handles.erase(
714            std::remove(icd.swapchain_handles.begin(), icd.swapchain_handles.end(), fake_swapchain_handle),
715            icd.swapchain_handles.end());
716        if (!icd.swapchain_handles.empty() && found_iter == icd.swapchain_handles.end()) {
717            assert(false && "Swapchain not found during destroy!");
718        }
719    }
720}
721// VK_KHR_swapchain with 1.1
722VKAPI_ATTR VkResult VKAPI_CALL test_vkGetDeviceGroupSurfacePresentModesKHR([[maybe_unused]] VkDevice device,
723                                                                           [[maybe_unused]] VkSurfaceKHR surface,
724                                                                           VkDeviceGroupPresentModeFlagsKHR* pModes) {
725    if (!pModes) return VK_ERROR_INITIALIZATION_FAILED;
726    *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
727    return VK_SUCCESS;
728}
729
730// VK_KHR_surface
731VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
732                                                                         VkSurfaceKHR surface, VkBool32* pSupported) {
733    if (surface != VK_NULL_HANDLE) {
734        uint64_t fake_surf_handle = (uint64_t)(surface);
735        auto found_iter = std::find(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle);
736        if (found_iter == icd.surface_handles.end()) {
737            assert(false && "Surface not found during GetPhysicalDeviceSurfaceSupportKHR query!");
738            return VK_ERROR_UNKNOWN;
739        }
740    }
741    if (nullptr != pSupported) {
742        *pSupported = icd.GetPhysDevice(physicalDevice).queue_family_properties.at(queueFamilyIndex).support_present;
743    }
744    return VK_SUCCESS;
745}
746VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
747                                                                              VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
748    if (surface != VK_NULL_HANDLE) {
749        uint64_t fake_surf_handle = (uint64_t)(surface);
750        auto found_iter = std::find(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle);
751        if (found_iter == icd.surface_handles.end()) {
752            assert(false && "Surface not found during GetPhysicalDeviceSurfaceCapabilitiesKHR query!");
753            return VK_ERROR_UNKNOWN;
754        }
755    }
756    if (nullptr != pSurfaceCapabilities) {
757        *pSurfaceCapabilities = icd.GetPhysDevice(physicalDevice).surface_capabilities;
758    }
759    return VK_SUCCESS;
760}
761VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
762                                                                         uint32_t* pSurfaceFormatCount,
763                                                                         VkSurfaceFormatKHR* pSurfaceFormats) {
764    if (surface != VK_NULL_HANDLE) {
765        uint64_t fake_surf_handle = (uint64_t)(surface);
766        auto found_iter = std::find(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle);
767        if (found_iter == icd.surface_handles.end()) {
768            assert(false && "Surface not found during GetPhysicalDeviceSurfaceFormatsKHR query!");
769            return VK_ERROR_UNKNOWN;
770        }
771    }
772    FillCountPtr(icd.GetPhysDevice(physicalDevice).surface_formats, pSurfaceFormatCount, pSurfaceFormats);
773    return VK_SUCCESS;
774}
775VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
776                                                                              uint32_t* pPresentModeCount,
777                                                                              VkPresentModeKHR* pPresentModes) {
778    if (surface != VK_NULL_HANDLE) {
779        uint64_t fake_surf_handle = (uint64_t)(surface);
780        auto found_iter = std::find(icd.surface_handles.begin(), icd.surface_handles.end(), fake_surf_handle);
781        if (found_iter == icd.surface_handles.end()) {
782            assert(false && "Surface not found during GetPhysicalDeviceSurfacePresentModesKHR query!");
783            return VK_ERROR_UNKNOWN;
784        }
785    }
786    FillCountPtr(icd.GetPhysDevice(physicalDevice).surface_present_modes, pPresentModeCount, pPresentModes);
787    return VK_SUCCESS;
788}
789
790// VK_KHR_display
791VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
792                                                                            uint32_t* pPropertyCount,
793                                                                            VkDisplayPropertiesKHR* pProperties) {
794    FillCountPtr(icd.GetPhysDevice(physicalDevice).display_properties, pPropertyCount, pProperties);
795    return VK_SUCCESS;
796}
797VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,
798                                                                                 uint32_t* pPropertyCount,
799                                                                                 VkDisplayPlanePropertiesKHR* pProperties) {
800    FillCountPtr(icd.GetPhysDevice(physicalDevice).display_plane_properties, pPropertyCount, pProperties);
801    return VK_SUCCESS;
802}
803VKAPI_ATTR VkResult VKAPI_CALL test_vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
804                                                                          [[maybe_unused]] uint32_t planeIndex,
805                                                                          uint32_t* pDisplayCount, VkDisplayKHR* pDisplays) {
806    FillCountPtr(icd.GetPhysDevice(physicalDevice).displays, pDisplayCount, pDisplays);
807    return VK_SUCCESS;
808}
809VKAPI_ATTR VkResult VKAPI_CALL test_vkGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,
810                                                                  [[maybe_unused]] VkDisplayKHR display, uint32_t* pPropertyCount,
811                                                                  VkDisplayModePropertiesKHR* pProperties) {
812    FillCountPtr(icd.GetPhysDevice(physicalDevice).display_mode_properties, pPropertyCount, pProperties);
813    return VK_SUCCESS;
814}
815VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDisplayModeKHR(VkPhysicalDevice physicalDevice, [[maybe_unused]] VkDisplayKHR display,
816                                                           [[maybe_unused]] const VkDisplayModeCreateInfoKHR* pCreateInfo,
817                                                           [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
818                                                           VkDisplayModeKHR* pMode) {
819    if (nullptr != pMode) {
820        *pMode = icd.GetPhysDevice(physicalDevice).display_mode;
821    }
822    return VK_SUCCESS;
823}
824VKAPI_ATTR VkResult VKAPI_CALL test_vkGetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,
825                                                                     [[maybe_unused]] VkDisplayModeKHR mode,
826                                                                     [[maybe_unused]] uint32_t planeIndex,
827                                                                     VkDisplayPlaneCapabilitiesKHR* pCapabilities) {
828    if (nullptr != pCapabilities) {
829        *pCapabilities = icd.GetPhysDevice(physicalDevice).display_plane_capabilities;
830    }
831    return VK_SUCCESS;
832}
833VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDisplayPlaneSurfaceKHR(
834    [[maybe_unused]] VkInstance instance, [[maybe_unused]] const VkDisplaySurfaceCreateInfoKHR* pCreateInfo,
835    [[maybe_unused]] const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
836    common_nondispatch_handle_creation(icd.surface_handles, pSurface);
837    return VK_SUCCESS;
838}
839
840// VK_KHR_get_surface_capabilities2
841VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
842                                                                               const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
843                                                                               VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
844    if (nullptr != pSurfaceInfo && nullptr != pSurfaceCapabilities) {
845        return test_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, pSurfaceInfo->surface,
846                                                              &pSurfaceCapabilities->surfaceCapabilities);
847    }
848    return VK_SUCCESS;
849}
850VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
851                                                                          const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
852                                                                          uint32_t* pSurfaceFormatCount,
853                                                                          VkSurfaceFormat2KHR* pSurfaceFormats) {
854    if (nullptr != pSurfaceFormatCount) {
855        test_vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount, nullptr);
856        if (nullptr != pSurfaceFormats) {
857            auto& phys_dev = icd.GetPhysDevice(physicalDevice);
858            // Since the structures are different, we have to copy each item over seperately.  Since we have multiple, we
859            // have to manually copy the data here instead of calling the next function
860            for (uint32_t cnt = 0; cnt < *pSurfaceFormatCount; ++cnt) {
861                memcpy(&pSurfaceFormats[cnt].surfaceFormat, &phys_dev.surface_formats[cnt], sizeof(VkSurfaceFormatKHR));
862            }
863        }
864    }
865    return VK_SUCCESS;
866}
867// VK_KHR_display_swapchain
868VkResult test_vkCreateSharedSwapchainsKHR([[maybe_unused]] VkDevice device, uint32_t swapchainCount,
869                                          [[maybe_unused]] const VkSwapchainCreateInfoKHR* pCreateInfos,
870                                          [[maybe_unused]] const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains) {
871    for (uint32_t i = 0; i < swapchainCount; i++) {
872        common_nondispatch_handle_creation(icd.swapchain_handles, &pSwapchains[i]);
873    }
874    return VK_SUCCESS;
875}
876
877//// misc
878VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateCommandPool([[maybe_unused]] VkDevice device,
879                                                        [[maybe_unused]] const VkCommandPoolCreateInfo* pCreateInfo,
880                                                        [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
881                                                        VkCommandPool* pCommandPool) {
882    if (pCommandPool != nullptr) {
883        pCommandPool = reinterpret_cast<VkCommandPool*>(0xdeadbeefdeadbeef);
884    }
885    return VK_SUCCESS;
886}
887
888VKAPI_ATTR void VKAPI_CALL test_vkDestroyCommandPool(VkDevice, VkCommandPool, const VkAllocationCallbacks*) {
889    // do nothing, leak memory for now
890}
891VKAPI_ATTR VkResult VKAPI_CALL test_vkAllocateCommandBuffers([[maybe_unused]] VkDevice device,
892                                                             const VkCommandBufferAllocateInfo* pAllocateInfo,
893                                                             VkCommandBuffer* pCommandBuffers) {
894    if (pAllocateInfo != nullptr && pCommandBuffers != nullptr) {
895        for (size_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
896            icd.allocated_command_buffers.push_back({});
897            pCommandBuffers[i] = icd.allocated_command_buffers.back().handle;
898        }
899    }
900    return VK_SUCCESS;
901}
902
903VKAPI_ATTR void VKAPI_CALL test_vkGetDeviceQueue([[maybe_unused]] VkDevice device, [[maybe_unused]] uint32_t queueFamilyIndex,
904                                                 uint32_t queueIndex, VkQueue* pQueue) {
905    auto fd = icd.lookup_device(device);
906    if (fd.found) {
907        *pQueue = icd.physical_devices.at(fd.phys_dev_index).queue_handles[queueIndex].handle;
908    }
909}
910
911// VK_EXT_acquire_drm_display
912VKAPI_ATTR VkResult VKAPI_CALL test_vkAcquireDrmDisplayEXT(VkPhysicalDevice, int32_t, VkDisplayKHR) { return VK_SUCCESS; }
913
914VKAPI_ATTR VkResult VKAPI_CALL test_vkGetDrmDisplayEXT(VkPhysicalDevice physicalDevice, [[maybe_unused]] int32_t drmFd,
915                                                       [[maybe_unused]] uint32_t connectorId, VkDisplayKHR* display) {
916    if (nullptr != display && icd.GetPhysDevice(physicalDevice).displays.size() > 0) {
917        *display = icd.GetPhysDevice(physicalDevice).displays[0];
918    }
919    return VK_SUCCESS;
920}
921
922//// stubs
923// 1.0
924VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
925    if (nullptr != pFeatures) {
926        memcpy(pFeatures, &icd.GetPhysDevice(physicalDevice).features, sizeof(VkPhysicalDeviceFeatures));
927    }
928}
929VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
930                                                              VkPhysicalDeviceProperties* pProperties) {
931    if (nullptr != pProperties) {
932        auto& phys_dev = icd.GetPhysDevice(physicalDevice);
933        memcpy(pProperties, &phys_dev.properties, sizeof(VkPhysicalDeviceProperties));
934        size_t max_len = (phys_dev.deviceName.length() > VK_MAX_PHYSICAL_DEVICE_NAME_SIZE) ? VK_MAX_PHYSICAL_DEVICE_NAME_SIZE
935                                                                                           : phys_dev.deviceName.length();
936        std::copy(phys_dev.deviceName.c_str(), phys_dev.deviceName.c_str() + max_len, pProperties->deviceName);
937        pProperties->deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE - 1] = '\0';
938    }
939}
940VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
941                                                                    VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
942    if (nullptr != pMemoryProperties) {
943        memcpy(pMemoryProperties, &icd.GetPhysDevice(physicalDevice).memory_properties, sizeof(VkPhysicalDeviceMemoryProperties));
944    }
945}
946VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceSparseImageFormatProperties(
947    VkPhysicalDevice physicalDevice, [[maybe_unused]] VkFormat format, [[maybe_unused]] VkImageType type,
948    [[maybe_unused]] VkSampleCountFlagBits samples, [[maybe_unused]] VkImageUsageFlags usage, [[maybe_unused]] VkImageTiling tiling,
949    uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties) {
950    FillCountPtr(icd.GetPhysDevice(physicalDevice).sparse_image_format_properties, pPropertyCount, pProperties);
951}
952VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
953                                                                    VkFormatProperties* pFormatProperties) {
954    if (nullptr != pFormatProperties) {
955        memcpy(pFormatProperties, &icd.GetPhysDevice(physicalDevice).format_properties[static_cast<uint32_t>(format)],
956               sizeof(VkFormatProperties));
957    }
958}
959VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceImageFormatProperties(
960    VkPhysicalDevice physicalDevice, [[maybe_unused]] VkFormat format, [[maybe_unused]] VkImageType type,
961    [[maybe_unused]] VkImageTiling tiling, [[maybe_unused]] VkImageUsageFlags usage, [[maybe_unused]] VkImageCreateFlags flags,
962    VkImageFormatProperties* pImageFormatProperties) {
963    if (nullptr != pImageFormatProperties) {
964        memcpy(pImageFormatProperties, &icd.GetPhysDevice(physicalDevice).image_format_properties, sizeof(VkImageFormatProperties));
965    }
966    return VK_SUCCESS;
967}
968
969// 1.1
970VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
971                                                             VkPhysicalDeviceFeatures2* pFeatures) {
972    if (nullptr != pFeatures) {
973        test_vkGetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
974    }
975}
976VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
977                                                               VkPhysicalDeviceProperties2* pProperties) {
978    if (nullptr != pProperties) {
979        auto& phys_dev = icd.GetPhysDevice(physicalDevice);
980        test_vkGetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
981        VkBaseInStructure* pNext = reinterpret_cast<VkBaseInStructure*>(pProperties->pNext);
982        while (pNext) {
983            if (pNext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT) {
984                auto* bus_info = reinterpret_cast<VkPhysicalDevicePCIBusInfoPropertiesEXT*>(pNext);
985                bus_info->pciBus = phys_dev.pci_bus;
986            }
987            if (pNext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT) {
988                auto* layered_driver_props = reinterpret_cast<VkPhysicalDeviceLayeredDriverPropertiesMSFT*>(pNext);
989                layered_driver_props->underlyingAPI = phys_dev.layered_driver_underlying_api;
990            }
991            pNext = reinterpret_cast<VkBaseInStructure*>(const_cast<VkBaseInStructure*>(pNext->pNext));
992        }
993    }
994}
995VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
996                                                                     VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
997    if (nullptr != pMemoryProperties) {
998        test_vkGetPhysicalDeviceMemoryProperties(physicalDevice, &pMemoryProperties->memoryProperties);
999    }
1000}
1001VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
1002                                                                          uint32_t* pQueueFamilyPropertyCount,
1003                                                                          VkQueueFamilyProperties2* pQueueFamilyProperties) {
1004    if (nullptr != pQueueFamilyPropertyCount) {
1005        test_vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, nullptr);
1006        if (nullptr != pQueueFamilyProperties) {
1007            auto& phys_dev = icd.GetPhysDevice(physicalDevice);
1008            // Since the structures are different, we have to copy each item over seperately.  Since we have multiple, we
1009            // have to manually copy the data here instead of calling the next function
1010            for (uint32_t queue = 0; queue < *pQueueFamilyPropertyCount; ++queue) {
1011                memcpy(&pQueueFamilyProperties[queue].queueFamilyProperties, &phys_dev.queue_family_properties[queue].properties,
1012                       sizeof(VkQueueFamilyProperties));
1013            }
1014        }
1015    }
1016}
1017VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceSparseImageFormatProperties2(
1018    VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount,
1019    VkSparseImageFormatProperties2* pProperties) {
1020    if (nullptr != pPropertyCount) {
1021        test_vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type,
1022                                                            pFormatInfo->samples, pFormatInfo->usage, pFormatInfo->tiling,
1023                                                            pPropertyCount, nullptr);
1024        if (nullptr != pProperties) {
1025            auto& phys_dev = icd.GetPhysDevice(physicalDevice);
1026            // Since the structures are different, we have to copy each item over seperately.  Since we have multiple, we
1027            // have to manually copy the data here instead of calling the next function
1028            for (uint32_t cnt = 0; cnt < *pPropertyCount; ++cnt) {
1029                memcpy(&pProperties[cnt].properties, &phys_dev.sparse_image_format_properties[cnt],
1030                       sizeof(VkSparseImageFormatProperties));
1031            }
1032        }
1033    }
1034}
1035VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format,
1036                                                                     VkFormatProperties2* pFormatProperties) {
1037    if (nullptr != pFormatProperties) {
1038        test_vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &pFormatProperties->formatProperties);
1039    }
1040}
1041VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceImageFormatProperties2(
1042    VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
1043    VkImageFormatProperties2* pImageFormatProperties) {
1044    if (nullptr != pImageFormatInfo) {
1045        VkImageFormatProperties* ptr = nullptr;
1046        if (pImageFormatProperties) {
1047            ptr = &pImageFormatProperties->imageFormatProperties;
1048        }
1049        test_vkGetPhysicalDeviceImageFormatProperties(physicalDevice, pImageFormatInfo->format, pImageFormatInfo->type,
1050                                                      pImageFormatInfo->tiling, pImageFormatInfo->usage, pImageFormatInfo->flags,
1051                                                      ptr);
1052    }
1053    return VK_SUCCESS;
1054}
1055VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceExternalBufferProperties(
1056    VkPhysicalDevice physicalDevice, [[maybe_unused]] const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
1057    VkExternalBufferProperties* pExternalBufferProperties) {
1058    if (nullptr != pExternalBufferProperties) {
1059        auto& phys_dev = icd.GetPhysDevice(physicalDevice);
1060        memcpy(&pExternalBufferProperties->externalMemoryProperties, &phys_dev.external_memory_properties,
1061               sizeof(VkExternalMemoryProperties));
1062    }
1063}
1064VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceExternalSemaphoreProperties(
1065    VkPhysicalDevice physicalDevice, [[maybe_unused]] const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
1066    VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
1067    if (nullptr != pExternalSemaphoreProperties) {
1068        auto& phys_dev = icd.GetPhysDevice(physicalDevice);
1069        memcpy(pExternalSemaphoreProperties, &phys_dev.external_semaphore_properties, sizeof(VkExternalSemaphoreProperties));
1070    }
1071}
1072VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceExternalFenceProperties(
1073    VkPhysicalDevice physicalDevice, [[maybe_unused]] const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
1074    VkExternalFenceProperties* pExternalFenceProperties) {
1075    if (nullptr != pExternalFenceProperties) {
1076        auto& phys_dev = icd.GetPhysDevice(physicalDevice);
1077        memcpy(pExternalFenceProperties, &phys_dev.external_fence_properties, sizeof(VkExternalFenceProperties));
1078    }
1079}
1080// Entry-points associated with the VK_KHR_performance_query extension
1081VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
1082    VkPhysicalDevice, uint32_t, uint32_t*, VkPerformanceCounterKHR*, VkPerformanceCounterDescriptionKHR*) {
1083    return VK_SUCCESS;
1084}
1085VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(VkPhysicalDevice,
1086                                                                                        const VkQueryPoolPerformanceCreateInfoKHR*,
1087                                                                                        uint32_t*) {}
1088VKAPI_ATTR VkResult VKAPI_CALL test_vkAcquireProfilingLockKHR(VkDevice, const VkAcquireProfilingLockInfoKHR*) { return VK_SUCCESS; }
1089VKAPI_ATTR void VKAPI_CALL test_vkReleaseProfilingLockKHR(VkDevice) {}
1090// Entry-points associated with the VK_EXT_sample_locations extension
1091VKAPI_ATTR void VKAPI_CALL test_vkCmdSetSampleLocationsEXT(VkCommandBuffer, const VkSampleLocationsInfoEXT*) {}
1092VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceMultisamplePropertiesEXT(VkPhysicalDevice, VkSampleCountFlagBits,
1093                                                                            VkMultisamplePropertiesEXT*) {}
1094// Entry-points associated with the VK_EXT_calibrated_timestamps extension
1095VKAPI_ATTR VkResult VKAPI_CALL test_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice, uint32_t*, VkTimeDomainEXT*) {
1096    return VK_SUCCESS;
1097}
1098VKAPI_ATTR VkResult VKAPI_CALL test_vkGetCalibratedTimestampsEXT(VkDevice, uint32_t, const VkCalibratedTimestampInfoEXT*, uint64_t*,
1099                                                                 uint64_t*) {
1100    return VK_SUCCESS;
1101}
1102
1103#if defined(WIN32)
1104VKAPI_ATTR VkResult VKAPI_CALL test_vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID,
1105                                                                          uint32_t* pPhysicalDeviceCount,
1106                                                                          VkPhysicalDevice* pPhysicalDevices) {
1107    if (adapterLUID.LowPart != icd.adapterLUID.LowPart || adapterLUID.HighPart != icd.adapterLUID.HighPart) {
1108        *pPhysicalDeviceCount = 0;
1109        return VK_ERROR_INCOMPATIBLE_DRIVER;
1110    }
1111    icd.called_enumerate_adapter_physical_devices = true;
1112    VkResult res = test_vkEnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
1113    // For this testing, flip order intentionally
1114    if (nullptr != pPhysicalDevices) {
1115        std::reverse(pPhysicalDevices, pPhysicalDevices + *pPhysicalDeviceCount);
1116    }
1117    return res;
1118}
1119#endif  // defined(WIN32)
1120
1121VkResult test_vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
1122    if (icd.called_vk_icd_gipa == CalledICDGIPA::not_called &&
1123        icd.called_negotiate_interface == CalledNegotiateInterface::not_called)
1124        icd.called_negotiate_interface = CalledNegotiateInterface::vk_icd_negotiate;
1125    else if (icd.called_vk_icd_gipa != CalledICDGIPA::not_called)
1126        icd.called_negotiate_interface = CalledNegotiateInterface::vk_icd_gipa_first;
1127
1128    // loader puts the minimum it supports in pSupportedVersion, if that is lower than our minimum
1129    // If the ICD doesn't supports the interface version provided by the loader, report VK_ERROR_INCOMPATIBLE_DRIVER
1130    if (icd.min_icd_interface_version > *pSupportedVersion) {
1131        icd.interface_version_check = InterfaceVersionCheck::loader_version_too_old;
1132        *pSupportedVersion = icd.min_icd_interface_version;
1133        return VK_ERROR_INCOMPATIBLE_DRIVER;
1134    }
1135
1136    // the loader-provided interface version is newer than that supported by the ICD
1137    if (icd.max_icd_interface_version < *pSupportedVersion) {
1138        icd.interface_version_check = InterfaceVersionCheck::loader_version_too_new;
1139        *pSupportedVersion = icd.max_icd_interface_version;
1140    }
1141    // ICD interface version is greater than the loader's,  return the loader's version
1142    else if (icd.max_icd_interface_version > *pSupportedVersion) {
1143        icd.interface_version_check = InterfaceVersionCheck::icd_version_too_new;
1144        // don't change *pSupportedVersion
1145    } else {
1146        icd.interface_version_check = InterfaceVersionCheck::version_is_supported;
1147        *pSupportedVersion = icd.max_icd_interface_version;
1148    }
1149
1150    return VK_SUCCESS;
1151}
1152
1153// Forward declarations for trampolines
1154extern "C" {
1155#if TEST_ICD_EXPOSE_VERSION_7
1156FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
1157#if TEST_ICD_EXPORT_ICD_GPDPA
1158FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName);
1159#endif
1160#if defined(WIN32) && TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
1161FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID,
1162                                                                                      uint32_t* pPhysicalDeviceCount,
1163                                                                                      VkPhysicalDevice* pPhysicalDevices);
1164#endif
1165#endif
1166}
1167
1168//// trampolines
1169
1170PFN_vkVoidFunction get_instance_func_ver_1_1([[maybe_unused]] VkInstance instance, const char* pName) {
1171    if (icd.icd_api_version >= VK_API_VERSION_1_1) {
1172        if (string_eq(pName, "test_vkEnumerateInstanceVersion")) {
1173            return icd.can_query_vkEnumerateInstanceVersion ? to_vkVoidFunction(test_vkEnumerateInstanceVersion) : nullptr;
1174        }
1175        if (string_eq(pName, "vkEnumeratePhysicalDeviceGroups")) {
1176            return to_vkVoidFunction(test_vkEnumeratePhysicalDeviceGroups);
1177        }
1178    }
1179    return nullptr;
1180}
1181
1182PFN_vkVoidFunction get_physical_device_func_wsi([[maybe_unused]] VkInstance instance, const char* pName) {
1183    if (IsInstanceExtensionEnabled("VK_KHR_surface")) {
1184        if (string_eq(pName, "vkGetPhysicalDeviceSurfaceSupportKHR"))
1185            return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfaceSupportKHR);
1186        if (string_eq(pName, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"))
1187            return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
1188        if (string_eq(pName, "vkGetPhysicalDeviceSurfaceFormatsKHR"))
1189            return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfaceFormatsKHR);
1190        if (string_eq(pName, "vkGetPhysicalDeviceSurfacePresentModesKHR"))
1191            return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfacePresentModesKHR);
1192    }
1193    if (IsInstanceExtensionEnabled("VK_KHR_get_surface_capabilities2")) {
1194        if (string_eq(pName, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"))
1195            return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfaceCapabilities2KHR);
1196        if (string_eq(pName, "vkGetPhysicalDeviceSurfaceFormats2KHR"))
1197            return to_vkVoidFunction(test_vkGetPhysicalDeviceSurfaceFormats2KHR);
1198    }
1199    if (IsInstanceExtensionEnabled("VK_KHR_display")) {
1200        if (string_eq(pName, "vkGetPhysicalDeviceDisplayPropertiesKHR"))
1201            return to_vkVoidFunction(test_vkGetPhysicalDeviceDisplayPropertiesKHR);
1202        if (string_eq(pName, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"))
1203            return to_vkVoidFunction(test_vkGetPhysicalDeviceDisplayPlanePropertiesKHR);
1204        if (string_eq(pName, "vkGetDisplayPlaneSupportedDisplaysKHR"))
1205            return to_vkVoidFunction(test_vkGetDisplayPlaneSupportedDisplaysKHR);
1206        if (string_eq(pName, "vkGetDisplayModePropertiesKHR")) return to_vkVoidFunction(test_vkGetDisplayModePropertiesKHR);
1207        if (string_eq(pName, "vkCreateDisplayModeKHR")) return to_vkVoidFunction(test_vkCreateDisplayModeKHR);
1208        if (string_eq(pName, "vkGetDisplayPlaneCapabilitiesKHR")) return to_vkVoidFunction(test_vkGetDisplayPlaneCapabilitiesKHR);
1209        if (string_eq(pName, "vkCreateDisplayPlaneSurfaceKHR")) return to_vkVoidFunction(test_vkCreateDisplayPlaneSurfaceKHR);
1210    }
1211    if (IsInstanceExtensionEnabled("VK_EXT_acquire_drm_display")) {
1212        if (string_eq(pName, "vkAcquireDrmDisplayEXT")) return to_vkVoidFunction(test_vkAcquireDrmDisplayEXT);
1213        if (string_eq(pName, "vkGetDrmDisplayEXT")) return to_vkVoidFunction(test_vkGetDrmDisplayEXT);
1214    }
1215    return nullptr;
1216}
1217
1218PFN_vkVoidFunction get_instance_func_wsi(VkInstance instance, const char* pName) {
1219    if (icd.min_icd_interface_version >= 3 && icd.enable_icd_wsi == true) {
1220#if defined(VK_USE_PLATFORM_ANDROID_KHR)
1221        if (string_eq(pName, "vkCreateAndroidSurfaceKHR")) {
1222            icd.is_using_icd_wsi = true;
1223            return to_vkVoidFunction(test_vkCreateAndroidSurfaceKHR);
1224        }
1225#endif
1226#if defined(VK_USE_PLATFORM_METAL_EXT)
1227        if (string_eq(pName, "vkCreateMetalSurfaceEXT")) {
1228            return to_vkVoidFunction(test_vkCreateMetalSurfaceEXT);
1229        }
1230#endif
1231#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
1232        if (string_eq(pName, "vkCreateWaylandSurfaceKHR")) {
1233            return to_vkVoidFunction(test_vkCreateWaylandSurfaceKHR);
1234        }
1235        if (string_eq(pName, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")) {
1236            return to_vkVoidFunction(test_vkGetPhysicalDeviceWaylandPresentationSupportKHR);
1237        }
1238#endif
1239#if defined(VK_USE_PLATFORM_XCB_KHR)
1240        if (string_eq(pName, "vkCreateXcbSurfaceKHR")) {
1241            return to_vkVoidFunction(test_vkCreateXcbSurfaceKHR);
1242        }
1243        if (string_eq(pName, "vkGetPhysicalDeviceXcbPresentationSupportKHR")) {
1244            return to_vkVoidFunction(test_vkGetPhysicalDeviceXcbPresentationSupportKHR);
1245        }
1246#endif
1247#if defined(VK_USE_PLATFORM_XLIB_KHR)
1248        if (string_eq(pName, "vkCreateXlibSurfaceKHR")) {
1249            return to_vkVoidFunction(test_vkCreateXlibSurfaceKHR);
1250        }
1251        if (string_eq(pName, "vkGetPhysicalDeviceXlibPresentationSupportKHR")) {
1252            return to_vkVoidFunction(test_vkGetPhysicalDeviceXlibPresentationSupportKHR);
1253        }
1254#endif
1255#if defined(VK_USE_PLATFORM_WIN32_KHR)
1256        if (string_eq(pName, "vkCreateWin32SurfaceKHR")) {
1257            return to_vkVoidFunction(test_vkCreateWin32SurfaceKHR);
1258        }
1259        if (string_eq(pName, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) {
1260            return to_vkVoidFunction(test_vkGetPhysicalDeviceWin32PresentationSupportKHR);
1261        }
1262#endif
1263#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
1264        if (string_eq(pName, "vkCreateDirectFBSurfaceEXT")) {
1265            return to_vkVoidFunction(test_vkCreateDirectFBSurfaceEXT);
1266        }
1267        if (string_eq(pName, "vkGetPhysicalDeviceDirectFBPresentationSupportEXT")) {
1268            return to_vkVoidFunction(test_vkGetPhysicalDeviceDirectFBPresentationSupportEXT);
1269        }
1270#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
1271
1272#if defined(VK_USE_PLATFORM_MACOS_MVK)
1273        if (string_eq(pName, "vkCreateMacOSSurfaceMVK")) {
1274            return to_vkVoidFunction(test_vkCreateMacOSSurfaceMVK);
1275        }
1276#endif  // VK_USE_PLATFORM_MACOS_MVK
1277
1278#if defined(VK_USE_PLATFORM_IOS_MVK)
1279        if (string_eq(pName, "vkCreateIOSSurfaceMVK")) {
1280            return to_vkVoidFunction(test_vkCreateIOSSurfaceMVK);
1281        }
1282#endif  // VK_USE_PLATFORM_IOS_MVK
1283
1284#if defined(VK_USE_PLATFORM_GGP)
1285        if (string_eq(pName, "vkCreateStreamDescriptorSurfaceGGP")) {
1286            return to_vkVoidFunction(test_vkCreateStreamDescriptorSurfaceGGP);
1287        }
1288#endif  // VK_USE_PLATFORM_GGP
1289
1290#if defined(VK_USE_PLATFORM_SCREEN_QNX)
1291        if (string_eq(pName, "vkCreateScreenSurfaceQNX")) {
1292            return to_vkVoidFunction(test_vkCreateScreenSurfaceQNX);
1293        }
1294        if (string_eq(pName, "vkGetPhysicalDeviceScreenPresentationSupportQNX")) {
1295            return to_vkVoidFunction(test_vkGetPhysicalDeviceScreenPresentationSupportQNX);
1296        }
1297#endif  // VK_USE_PLATFORM_SCREEN_QNX
1298
1299        if (string_eq(pName, "vkCreateHeadlessSurfaceEXT")) {
1300            return to_vkVoidFunction(test_vkCreateHeadlessSurfaceEXT);
1301        }
1302
1303        if (string_eq(pName, "vkDestroySurfaceKHR")) {
1304            icd.is_using_icd_wsi = true;
1305            return to_vkVoidFunction(test_vkDestroySurfaceKHR);
1306        }
1307    }
1308    if (IsInstanceExtensionEnabled(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
1309        if (string_eq(pName, "vkCreateDebugUtilsMessengerEXT")) {
1310            return to_vkVoidFunction(test_vkCreateDebugUtilsMessengerEXT);
1311        }
1312        if (string_eq(pName, "vkDestroyDebugUtilsMessengerEXT")) {
1313            return to_vkVoidFunction(test_vkDestroyDebugUtilsMessengerEXT);
1314        }
1315    }
1316
1317    PFN_vkVoidFunction ret_phys_dev_wsi = get_physical_device_func_wsi(instance, pName);
1318    if (ret_phys_dev_wsi != nullptr) return ret_phys_dev_wsi;
1319    return nullptr;
1320}
1321PFN_vkVoidFunction get_physical_device_func([[maybe_unused]] VkInstance instance, const char* pName) {
1322    if (string_eq(pName, "vkEnumerateDeviceLayerProperties")) return to_vkVoidFunction(test_vkEnumerateDeviceLayerProperties);
1323    if (string_eq(pName, "vkEnumerateDeviceExtensionProperties"))
1324        return to_vkVoidFunction(test_vkEnumerateDeviceExtensionProperties);
1325    if (string_eq(pName, "vkGetPhysicalDeviceQueueFamilyProperties"))
1326        return to_vkVoidFunction(test_vkGetPhysicalDeviceQueueFamilyProperties);
1327    if (string_eq(pName, "vkCreateDevice")) return to_vkVoidFunction(test_vkCreateDevice);
1328
1329    if (string_eq(pName, "vkGetPhysicalDeviceFeatures"))
1330        return icd.can_query_GetPhysicalDeviceFuncs ? to_vkVoidFunction(test_vkGetPhysicalDeviceFeatures) : nullptr;
1331    if (string_eq(pName, "vkGetPhysicalDeviceProperties"))
1332        return icd.can_query_GetPhysicalDeviceFuncs ? to_vkVoidFunction(test_vkGetPhysicalDeviceProperties) : nullptr;
1333    if (string_eq(pName, "vkGetPhysicalDeviceMemoryProperties"))
1334        return icd.can_query_GetPhysicalDeviceFuncs ? to_vkVoidFunction(test_vkGetPhysicalDeviceMemoryProperties) : nullptr;
1335    if (string_eq(pName, "vkGetPhysicalDeviceSparseImageFormatProperties"))
1336        return icd.can_query_GetPhysicalDeviceFuncs ? to_vkVoidFunction(test_vkGetPhysicalDeviceSparseImageFormatProperties)
1337                                                    : nullptr;
1338    if (string_eq(pName, "vkGetPhysicalDeviceFormatProperties"))
1339        return icd.can_query_GetPhysicalDeviceFuncs ? to_vkVoidFunction(test_vkGetPhysicalDeviceFormatProperties) : nullptr;
1340    if (string_eq(pName, "vkGetPhysicalDeviceImageFormatProperties"))
1341        return icd.can_query_GetPhysicalDeviceFuncs ? to_vkVoidFunction(test_vkGetPhysicalDeviceImageFormatProperties) : nullptr;
1342
1343    if (IsInstanceExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1344        if (string_eq(pName, "vkGetPhysicalDeviceFeatures2KHR")) return to_vkVoidFunction(test_vkGetPhysicalDeviceFeatures2);
1345        if (string_eq(pName, "vkGetPhysicalDeviceProperties2KHR")) return to_vkVoidFunction(test_vkGetPhysicalDeviceProperties2);
1346        if (string_eq(pName, "vkGetPhysicalDeviceFormatProperties2KHR"))
1347            return to_vkVoidFunction(test_vkGetPhysicalDeviceFormatProperties2);
1348        if (string_eq(pName, "vkGetPhysicalDeviceMemoryProperties2KHR"))
1349            return to_vkVoidFunction(test_vkGetPhysicalDeviceMemoryProperties2);
1350
1351        if (string_eq(pName, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"))
1352            return to_vkVoidFunction(test_vkGetPhysicalDeviceQueueFamilyProperties2);
1353
1354        if (string_eq(pName, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR"))
1355            return to_vkVoidFunction(test_vkGetPhysicalDeviceSparseImageFormatProperties2);
1356
1357        if (string_eq(pName, "vkGetPhysicalDeviceImageFormatProperties2KHR")) {
1358            return to_vkVoidFunction(test_vkGetPhysicalDeviceImageFormatProperties2);
1359        }
1360    }
1361    if (IsInstanceExtensionEnabled(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
1362        if (string_eq(pName, "vkGetPhysicalDeviceExternalBufferPropertiesKHR"))
1363            return to_vkVoidFunction(test_vkGetPhysicalDeviceExternalBufferProperties);
1364    }
1365    if (IsInstanceExtensionEnabled(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME)) {
1366        if (string_eq(pName, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"))
1367            return to_vkVoidFunction(test_vkGetPhysicalDeviceExternalSemaphoreProperties);
1368    }
1369    if (IsInstanceExtensionEnabled(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME)) {
1370        if (string_eq(pName, "vkGetPhysicalDeviceExternalFencePropertiesKHR"))
1371            return to_vkVoidFunction(test_vkGetPhysicalDeviceExternalFenceProperties);
1372    }
1373
1374    // The following physical device extensions only need 1 device to support them for the ICD to export
1375    // them
1376    if (IsPhysicalDeviceExtensionAvailable(VK_KHR_PERFORMANCE_QUERY_EXTENSION_NAME)) {
1377        if (string_eq(pName, "vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR"))
1378            return to_vkVoidFunction(test_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR);
1379        if (string_eq(pName, "vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR"))
1380            return to_vkVoidFunction(test_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR);
1381        if (string_eq(pName, "vkAcquireProfilingLockKHR")) return to_vkVoidFunction(test_vkAcquireProfilingLockKHR);
1382        if (string_eq(pName, "vkReleaseProfilingLockKHR")) return to_vkVoidFunction(test_vkReleaseProfilingLockKHR);
1383    }
1384    if (IsPhysicalDeviceExtensionAvailable(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME)) {
1385        if (string_eq(pName, "vkCmdSetSampleLocationsEXT")) return to_vkVoidFunction(test_vkCmdSetSampleLocationsEXT);
1386        if (string_eq(pName, "vkGetPhysicalDeviceMultisamplePropertiesEXT"))
1387            return to_vkVoidFunction(test_vkGetPhysicalDeviceMultisamplePropertiesEXT);
1388    }
1389    if (IsPhysicalDeviceExtensionAvailable(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME)) {
1390        if (string_eq(pName, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT"))
1391            return to_vkVoidFunction(test_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT);
1392        if (string_eq(pName, "vkGetCalibratedTimestampsEXT")) return to_vkVoidFunction(test_vkGetCalibratedTimestampsEXT);
1393    }
1394
1395    if (icd.icd_api_version >= VK_MAKE_API_VERSION(0, 1, 1, 0)) {
1396        if (string_eq(pName, "vkGetPhysicalDeviceFeatures2")) return to_vkVoidFunction(test_vkGetPhysicalDeviceFeatures2);
1397        if (string_eq(pName, "vkGetPhysicalDeviceProperties2")) return to_vkVoidFunction(test_vkGetPhysicalDeviceProperties2);
1398        if (string_eq(pName, "vkGetPhysicalDeviceFormatProperties2"))
1399            return to_vkVoidFunction(test_vkGetPhysicalDeviceFormatProperties2);
1400        if (string_eq(pName, "vkGetPhysicalDeviceMemoryProperties2"))
1401            return to_vkVoidFunction(test_vkGetPhysicalDeviceMemoryProperties2);
1402
1403        if (string_eq(pName, "vkGetPhysicalDeviceQueueFamilyProperties2"))
1404            return to_vkVoidFunction(test_vkGetPhysicalDeviceQueueFamilyProperties2);
1405
1406        if (string_eq(pName, "vkGetPhysicalDeviceSparseImageFormatProperties2"))
1407            return to_vkVoidFunction(test_vkGetPhysicalDeviceSparseImageFormatProperties2);
1408
1409        if (string_eq(pName, "vkGetPhysicalDeviceImageFormatProperties2")) {
1410            return to_vkVoidFunction(test_vkGetPhysicalDeviceImageFormatProperties2);
1411        }
1412
1413        if (string_eq(pName, "vkGetPhysicalDeviceExternalBufferProperties"))
1414            return to_vkVoidFunction(test_vkGetPhysicalDeviceExternalBufferProperties);
1415        if (string_eq(pName, "vkGetPhysicalDeviceExternalSemaphoreProperties"))
1416            return to_vkVoidFunction(test_vkGetPhysicalDeviceExternalSemaphoreProperties);
1417        if (string_eq(pName, "vkGetPhysicalDeviceExternalFenceProperties"))
1418            return to_vkVoidFunction(test_vkGetPhysicalDeviceExternalFenceProperties);
1419    }
1420
1421    if (icd.supports_tooling_info_core) {
1422        if (string_eq(pName, "vkGetPhysicalDeviceToolProperties")) return to_vkVoidFunction(test_vkGetPhysicalDeviceToolProperties);
1423    }
1424    if (icd.supports_tooling_info_ext) {
1425        if (string_eq(pName, "vkGetPhysicalDeviceToolPropertiesEXT"))
1426            return to_vkVoidFunction(test_vkGetPhysicalDeviceToolPropertiesEXT);
1427    }
1428
1429    for (auto& phys_dev : icd.physical_devices) {
1430        for (auto& func : phys_dev.custom_physical_device_functions) {
1431            if (func.name == pName) {
1432                return to_vkVoidFunction(func.function);
1433            }
1434        }
1435    }
1436    return nullptr;
1437}
1438
1439PFN_vkVoidFunction get_instance_func(VkInstance instance, const char* pName) {
1440    if (string_eq(pName, "vkDestroyInstance")) return to_vkVoidFunction(test_vkDestroyInstance);
1441    if (string_eq(pName, "vkEnumeratePhysicalDevices")) return to_vkVoidFunction(test_vkEnumeratePhysicalDevices);
1442
1443    if (IsInstanceExtensionEnabled(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME)) {
1444        if (string_eq(pName, "vkEnumeratePhysicalDeviceGroupsKHR")) return to_vkVoidFunction(test_vkEnumeratePhysicalDeviceGroups);
1445    }
1446
1447    PFN_vkVoidFunction ret_phys_dev = get_physical_device_func(instance, pName);
1448    if (ret_phys_dev != nullptr) return ret_phys_dev;
1449
1450    PFN_vkVoidFunction ret_1_1 = get_instance_func_ver_1_1(instance, pName);
1451    if (ret_1_1 != nullptr) return ret_1_1;
1452
1453    PFN_vkVoidFunction ret_wsi = get_instance_func_wsi(instance, pName);
1454    if (ret_wsi != nullptr) return ret_wsi;
1455
1456    for (auto& func : icd.custom_instance_functions) {
1457        if (func.name == pName) {
1458            return to_vkVoidFunction(func.function);
1459        }
1460    }
1461
1462    return nullptr;
1463}
1464
1465bool should_check(std::vector<const char*> const& exts, VkDevice device, const char* ext_name) {
1466    if (device == NULL) return true;  // always look if device is NULL
1467    for (auto const& ext : exts) {
1468        if (string_eq(ext, ext_name)) {
1469            return true;
1470        }
1471    }
1472    return false;
1473}
1474
1475PFN_vkVoidFunction get_device_func(VkDevice device, const char* pName) {
1476    TestICD::FindDevice fd{};
1477    DeviceCreateInfo create_info{};
1478    if (device != nullptr) {
1479        fd = icd.lookup_device(device);
1480        if (!fd.found) return NULL;
1481        create_info = icd.physical_devices.at(fd.phys_dev_index).device_create_infos.at(fd.dev_index);
1482    }
1483    if (string_eq(pName, "vkCreateCommandPool")) return to_vkVoidFunction(test_vkCreateCommandPool);
1484    if (string_eq(pName, "vkAllocateCommandBuffers")) return to_vkVoidFunction(test_vkAllocateCommandBuffers);
1485    if (string_eq(pName, "vkDestroyCommandPool")) return to_vkVoidFunction(test_vkDestroyCommandPool);
1486    if (string_eq(pName, "vkGetDeviceQueue")) return to_vkVoidFunction(test_vkGetDeviceQueue);
1487    if (string_eq(pName, "vkDestroyDevice")) return to_vkVoidFunction(test_vkDestroyDevice);
1488    if (should_check(create_info.enabled_extensions, device, "VK_KHR_swapchain")) {
1489        if (string_eq(pName, "vkCreateSwapchainKHR")) return to_vkVoidFunction(test_vkCreateSwapchainKHR);
1490        if (string_eq(pName, "vkGetSwapchainImagesKHR")) return to_vkVoidFunction(test_vkGetSwapchainImagesKHR);
1491        if (string_eq(pName, "vkDestroySwapchainKHR")) return to_vkVoidFunction(test_vkDestroySwapchainKHR);
1492
1493        if (icd.icd_api_version >= VK_API_VERSION_1_1 && string_eq(pName, "vkGetDeviceGroupSurfacePresentModesKHR"))
1494            return to_vkVoidFunction(test_vkGetDeviceGroupSurfacePresentModesKHR);
1495    }
1496    if (should_check(create_info.enabled_extensions, device, "VK_KHR_display_swapchain")) {
1497        if (string_eq(pName, "vkCreateSharedSwapchainsKHR")) return to_vkVoidFunction(test_vkCreateSharedSwapchainsKHR);
1498    }
1499    if (should_check(create_info.enabled_extensions, device, "VK_KHR_device_group")) {
1500        if (string_eq(pName, "vkGetDeviceGroupSurfacePresentModesKHR"))
1501            return to_vkVoidFunction(test_vkGetDeviceGroupSurfacePresentModesKHR);
1502    }
1503    if (should_check(create_info.enabled_extensions, device, "VK_EXT_debug_marker")) {
1504        if (string_eq(pName, "vkDebugMarkerSetObjectTagEXT")) return to_vkVoidFunction(test_vkDebugMarkerSetObjectTagEXT);
1505        if (string_eq(pName, "vkDebugMarkerSetObjectNameEXT")) return to_vkVoidFunction(test_vkDebugMarkerSetObjectNameEXT);
1506        if (string_eq(pName, "vkCmdDebugMarkerBeginEXT")) return to_vkVoidFunction(test_vkCmdDebugMarkerBeginEXT);
1507        if (string_eq(pName, "vkCmdDebugMarkerEndEXT")) return to_vkVoidFunction(test_vkCmdDebugMarkerEndEXT);
1508        if (string_eq(pName, "vkCmdDebugMarkerInsertEXT")) return to_vkVoidFunction(test_vkCmdDebugMarkerInsertEXT);
1509    }
1510    if (IsInstanceExtensionEnabled("VK_EXT_debug_utils")) {
1511        if (string_eq(pName, "vkSetDebugUtilsObjectNameEXT")) return to_vkVoidFunction(test_vkSetDebugUtilsObjectNameEXT);
1512        if (string_eq(pName, "vkSetDebugUtilsObjectTagEXT")) return to_vkVoidFunction(test_vkSetDebugUtilsObjectTagEXT);
1513        if (string_eq(pName, "vkQueueBeginDebugUtilsLabelEXT")) return to_vkVoidFunction(test_vkQueueBeginDebugUtilsLabelEXT);
1514        if (string_eq(pName, "vkQueueEndDebugUtilsLabelEXT")) return to_vkVoidFunction(test_vkQueueEndDebugUtilsLabelEXT);
1515        if (string_eq(pName, "vkQueueInsertDebugUtilsLabelEXT")) return to_vkVoidFunction(test_vkQueueInsertDebugUtilsLabelEXT);
1516        if (string_eq(pName, "vkCmdBeginDebugUtilsLabelEXT")) return to_vkVoidFunction(test_vkCmdBeginDebugUtilsLabelEXT);
1517        if (string_eq(pName, "vkCmdEndDebugUtilsLabelEXT")) return to_vkVoidFunction(test_vkCmdEndDebugUtilsLabelEXT);
1518        if (string_eq(pName, "vkCmdInsertDebugUtilsLabelEXT")) return to_vkVoidFunction(test_vkCmdInsertDebugUtilsLabelEXT);
1519    }
1520    // look for device functions setup from a test
1521    for (const auto& phys_dev : icd.physical_devices) {
1522        for (const auto& function : phys_dev.known_device_functions) {
1523            if (function.name == pName) {
1524                return to_vkVoidFunction(function.function);
1525            }
1526        }
1527    }
1528    return nullptr;
1529}
1530
1531VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
1532    return get_instance_func(instance, pName);
1533}
1534
1535VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_vkGetDeviceProcAddr(VkDevice device, const char* pName) {
1536    return get_device_func(device, pName);
1537}
1538
1539PFN_vkVoidFunction base_get_instance_proc_addr(VkInstance instance, const char* pName) {
1540    if (pName == nullptr) return nullptr;
1541    if (instance == NULL) {
1542#if TEST_ICD_EXPOSE_VERSION_7
1543        if (string_eq(pName, "vk_icdNegotiateLoaderICDInterfaceVersion"))
1544            return icd.exposes_vk_icdNegotiateLoaderICDInterfaceVersion
1545                       ? to_vkVoidFunction(vk_icdNegotiateLoaderICDInterfaceVersion)
1546                       : NULL;
1547#if TEST_ICD_EXPORT_ICD_GPDPA
1548        if (string_eq(pName, "vk_icdGetPhysicalDeviceProcAddr"))
1549            return icd.exposes_vk_icdGetPhysicalDeviceProcAddr ? to_vkVoidFunction(vk_icdGetPhysicalDeviceProcAddr) : NULL;
1550#endif
1551#if defined(WIN32) && TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
1552        if (string_eq(pName, "vk_icdEnumerateAdapterPhysicalDevices"))
1553            return icd.exposes_vk_icdEnumerateAdapterPhysicalDevices ? to_vkVoidFunction(vk_icdEnumerateAdapterPhysicalDevices)
1554                                                                     : NULL;
1555#endif  // defined(WIN32)
1556#endif  // TEST_ICD_EXPOSE_VERSION_7
1557
1558        if (string_eq(pName, "vkGetInstanceProcAddr")) return to_vkVoidFunction(test_vkGetInstanceProcAddr);
1559        if (string_eq(pName, "vkEnumerateInstanceExtensionProperties"))
1560            return icd.exposes_vkEnumerateInstanceExtensionProperties
1561                       ? to_vkVoidFunction(test_vkEnumerateInstanceExtensionProperties)
1562                       : NULL;
1563        if (string_eq(pName, "vkEnumerateInstanceLayerProperties"))
1564            return to_vkVoidFunction(test_vkEnumerateInstanceLayerProperties);
1565        if (string_eq(pName, "vkEnumerateInstanceVersion"))
1566            return icd.can_query_vkEnumerateInstanceVersion ? to_vkVoidFunction(test_vkEnumerateInstanceVersion) : nullptr;
1567        if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_vkCreateInstance);
1568    }
1569    if (string_eq(pName, "vkGetDeviceProcAddr")) return to_vkVoidFunction(test_vkGetDeviceProcAddr);
1570
1571    auto instance_func_return = get_instance_func(instance, pName);
1572    if (instance_func_return != nullptr) return instance_func_return;
1573
1574    // Need to return function pointers for device extensions
1575    auto device_func_return = get_device_func(nullptr, pName);
1576    if (device_func_return != nullptr) return device_func_return;
1577    return nullptr;
1578}
1579
1580// Exported functions
1581extern "C" {
1582#if TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION
1583FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
1584    return test_vk_icdNegotiateLoaderICDInterfaceVersion(pSupportedVersion);
1585}
1586#endif  // TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION
1587
1588#if TEST_ICD_EXPORT_ICD_GPDPA
1589FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName) {
1590    return get_physical_device_func(instance, pName);
1591}
1592#endif  // TEST_ICD_EXPORT_ICD_GPDPA
1593
1594#if TEST_ICD_EXPORT_ICD_GIPA
1595FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName) {
1596    if (icd.called_vk_icd_gipa == CalledICDGIPA::not_called) icd.called_vk_icd_gipa = CalledICDGIPA::vk_icd_gipa;
1597    return base_get_instance_proc_addr(instance, pName);
1598}
1599#else   // !TEST_ICD_EXPORT_ICD_GIPA
1600FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
1601    if (icd.called_vk_icd_gipa == CalledICDGIPA::not_called) icd.called_vk_icd_gipa = CalledICDGIPA::vk_gipa;
1602    return base_get_instance_proc_addr(instance, pName);
1603}
1604FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
1605                                                                 const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
1606    return test_vkCreateInstance(pCreateInfo, pAllocator, pInstance);
1607}
1608FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char* pLayerName,
1609                                                                                       uint32_t* pPropertyCount,
1610                                                                                       VkExtensionProperties* pProperties) {
1611    return test_vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
1612}
1613#endif  // TEST_ICD_EXPORT_ICD_GIPA
1614
1615#if TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
1616#if defined(WIN32)
1617FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID,
1618                                                                                      uint32_t* pPhysicalDeviceCount,
1619                                                                                      VkPhysicalDevice* pPhysicalDevices) {
1620    return test_vk_icdEnumerateAdapterPhysicalDevices(instance, adapterLUID, pPhysicalDeviceCount, pPhysicalDevices);
1621}
1622#endif  // defined(WIN32)
1623#endif  // TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
1624
1625}  // extern "C"
1626