Home | History | Annotate | Download | only in loader
      1 /*
      2  *
      3  * Copyright (c) 2014-2018 The Khronos Group Inc.
      4  * Copyright (c) 2014-2018 Valve Corporation
      5  * Copyright (c) 2014-2018 LunarG, Inc.
      6  * Copyright (C) 2015 Google Inc.
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *     http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19 
     20  *
     21  * Author: Jon Ashburn <jon (at) lunarg.com>
     22  * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com>
     23  * Author: Mark Young <marky (at) lunarg.com>
     24  * Author: Lenny Komow <lenny (at) lunarg.com>
     25  *
     26  */
     27 
     28 #define _GNU_SOURCE
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <stdarg.h>
     32 #include <stdbool.h>
     33 #include <string.h>
     34 #include <stddef.h>
     35 
     36 #include <sys/types.h>
     37 #if defined(_WIN32)
     38 #include "dirent_on_windows.h"
     39 #else  // _WIN32
     40 #include <dirent.h>
     41 #endif  // _WIN32
     42 #include "vk_loader_platform.h"
     43 #include "loader.h"
     44 #include "gpa_helper.h"
     45 #include "debug_report.h"
     46 #include "wsi.h"
     47 #include "vulkan/vk_icd.h"
     48 #include "cJSON.h"
     49 #include "murmurhash.h"
     50 
     51 #if defined(_WIN32)
     52 #include <Cfgmgr32.h>
     53 #include <initguid.h>
     54 #include <Devpkey.h>
     55 #endif
     56 
     57 // This is a CMake generated file with #defines for any functions/includes
     58 // that it found present.  This is currently necessary to properly determine
     59 // if secure_getenv or __secure_getenv are present
     60 #if !defined(VULKAN_NON_CMAKE_BUILD)
     61 #include "loader_cmake_config.h"
     62 #endif  // !defined(VULKAN_NON_CMAKE_BUILD)
     63 
     64 // Generated file containing all the extension data
     65 #include "vk_loader_extensions.c"
     66 
     67 struct loader_struct loader = {0};
     68 // TLS for instance for alloc/free callbacks
     69 THREAD_LOCAL_DECL struct loader_instance *tls_instance;
     70 
     71 static size_t loader_platform_combine_path(char *dest, size_t len, ...);
     72 
     73 struct loader_phys_dev_per_icd {
     74     uint32_t count;
     75     VkPhysicalDevice *phys_devs;
     76     struct loader_icd_term *this_icd_term;
     77 };
     78 
     79 enum loader_debug {
     80     LOADER_INFO_BIT = 0x01,
     81     LOADER_WARN_BIT = 0x02,
     82     LOADER_PERF_BIT = 0x04,
     83     LOADER_ERROR_BIT = 0x08,
     84     LOADER_DEBUG_BIT = 0x10,
     85 };
     86 
     87 uint32_t g_loader_debug = 0;
     88 uint32_t g_loader_log_msgs = 0;
     89 
     90 // thread safety lock for accessing global data structures such as "loader"
     91 // all entrypoints on the instance chain need to be locked except GPA
     92 // additionally CreateDevice and DestroyDevice needs to be locked
     93 loader_platform_thread_mutex loader_lock;
     94 loader_platform_thread_mutex loader_json_lock;
     95 
     96 LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
     97 
     98 void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope alloc_scope) {
     99     void *pMemory = NULL;
    100 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    101     {
    102 #else
    103     if (instance && instance->alloc_callbacks.pfnAllocation) {
    104         // These are internal structures, so it's best to align everything to
    105         // the largest unit size which is the size of a uint64_t.
    106         pMemory = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, sizeof(uint64_t), alloc_scope);
    107     } else {
    108 #endif
    109         pMemory = malloc(size);
    110     }
    111 
    112     return pMemory;
    113 }
    114 
    115 void loader_instance_heap_free(const struct loader_instance *instance, void *pMemory) {
    116     if (pMemory != NULL) {
    117 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    118         {
    119 #else
    120         if (instance && instance->alloc_callbacks.pfnFree) {
    121             instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
    122         } else {
    123 #endif
    124             free(pMemory);
    125         }
    126     }
    127 }
    128 
    129 void *loader_instance_heap_realloc(const struct loader_instance *instance, void *pMemory, size_t orig_size, size_t size,
    130                                    VkSystemAllocationScope alloc_scope) {
    131     void *pNewMem = NULL;
    132     if (pMemory == NULL || orig_size == 0) {
    133         pNewMem = loader_instance_heap_alloc(instance, size, alloc_scope);
    134     } else if (size == 0) {
    135         loader_instance_heap_free(instance, pMemory);
    136 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    137 #else
    138     } else if (instance && instance->alloc_callbacks.pfnReallocation) {
    139         // These are internal structures, so it's best to align everything to
    140         // the largest unit size which is the size of a uint64_t.
    141         pNewMem = instance->alloc_callbacks.pfnReallocation(instance->alloc_callbacks.pUserData, pMemory, size, sizeof(uint64_t),
    142                                                             alloc_scope);
    143 #endif
    144     } else {
    145         pNewMem = realloc(pMemory, size);
    146     }
    147     return pNewMem;
    148 }
    149 
    150 void *loader_instance_tls_heap_alloc(size_t size) {
    151     return loader_instance_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    152 }
    153 
    154 void loader_instance_tls_heap_free(void *pMemory) { loader_instance_heap_free(tls_instance, pMemory); }
    155 
    156 void *loader_device_heap_alloc(const struct loader_device *device, size_t size, VkSystemAllocationScope alloc_scope) {
    157     void *pMemory = NULL;
    158 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    159     {
    160 #else
    161     if (device && device->alloc_callbacks.pfnAllocation) {
    162         // These are internal structures, so it's best to align everything to
    163         // the largest unit size which is the size of a uint64_t.
    164         pMemory = device->alloc_callbacks.pfnAllocation(device->alloc_callbacks.pUserData, size, sizeof(uint64_t), alloc_scope);
    165     } else {
    166 #endif
    167         pMemory = malloc(size);
    168     }
    169     return pMemory;
    170 }
    171 
    172 void loader_device_heap_free(const struct loader_device *device, void *pMemory) {
    173     if (pMemory != NULL) {
    174 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    175         {
    176 #else
    177         if (device && device->alloc_callbacks.pfnFree) {
    178             device->alloc_callbacks.pfnFree(device->alloc_callbacks.pUserData, pMemory);
    179         } else {
    180 #endif
    181             free(pMemory);
    182         }
    183     }
    184 }
    185 
    186 void *loader_device_heap_realloc(const struct loader_device *device, void *pMemory, size_t orig_size, size_t size,
    187                                  VkSystemAllocationScope alloc_scope) {
    188     void *pNewMem = NULL;
    189     if (pMemory == NULL || orig_size == 0) {
    190         pNewMem = loader_device_heap_alloc(device, size, alloc_scope);
    191     } else if (size == 0) {
    192         loader_device_heap_free(device, pMemory);
    193 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    194 #else
    195     } else if (device && device->alloc_callbacks.pfnReallocation) {
    196         // These are internal structures, so it's best to align everything to
    197         // the largest unit size which is the size of a uint64_t.
    198         pNewMem = device->alloc_callbacks.pfnReallocation(device->alloc_callbacks.pUserData, pMemory, size, sizeof(uint64_t),
    199                                                           alloc_scope);
    200 #endif
    201     } else {
    202         pNewMem = realloc(pMemory, size);
    203     }
    204     return pNewMem;
    205 }
    206 
    207 // Environment variables
    208 #if defined(__linux__)
    209 
    210 static inline char *loader_getenv(const char *name, const struct loader_instance *inst) {
    211     // No allocation of memory necessary for Linux, but we should at least touch
    212     // the inst pointer to get rid of compiler warnings.
    213     (void)inst;
    214     return getenv(name);
    215 }
    216 
    217 static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
    218     // No allocation of memory necessary for Linux, but we should at least touch
    219     // the inst pointer to get rid of compiler warnings.
    220     (void)inst;
    221 
    222 #ifdef HAVE_SECURE_GETENV
    223     return secure_getenv(name);
    224 #elif defined(HAVE___SECURE_GETENV)
    225     return __secure_getenv(name);
    226 #else
    227 #pragma message(                                                                       \
    228     "Warning:  Falling back to non-secure getenv for environmental lookups!  Consider" \
    229     " updating to a different libc.")
    230     return loader_getenv(name, inst);
    231 #endif
    232 }
    233 
    234 static inline void loader_free_getenv(char *val, const struct loader_instance *inst) {
    235     // No freeing of memory necessary for Linux, but we should at least touch
    236     // the val and inst pointers to get rid of compiler warnings.
    237     (void)val;
    238     (void)inst;
    239 }
    240 
    241 #elif defined(WIN32)
    242 
    243 static inline char *loader_getenv(const char *name, const struct loader_instance *inst) {
    244     char *retVal;
    245     DWORD valSize;
    246 
    247     valSize = GetEnvironmentVariableA(name, NULL, 0);
    248 
    249     // valSize DOES include the null terminator, so for any set variable
    250     // will always be at least 1. If it's 0, the variable wasn't set.
    251     if (valSize == 0) return NULL;
    252 
    253     // Allocate the space necessary for the registry entry
    254     if (NULL != inst && NULL != inst->alloc_callbacks.pfnAllocation) {
    255         retVal = (char *)inst->alloc_callbacks.pfnAllocation(inst->alloc_callbacks.pUserData, valSize, sizeof(char *),
    256                                                              VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    257     } else {
    258         retVal = (char *)malloc(valSize);
    259     }
    260 
    261     if (NULL != retVal) {
    262         GetEnvironmentVariableA(name, retVal, valSize);
    263     }
    264 
    265     return retVal;
    266 }
    267 
    268 static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
    269     // No secure version for Windows as far as I know
    270     return loader_getenv(name, inst);
    271 }
    272 
    273 static inline void loader_free_getenv(char *val, const struct loader_instance *inst) {
    274     if (NULL != inst && NULL != inst->alloc_callbacks.pfnFree) {
    275         inst->alloc_callbacks.pfnFree(inst->alloc_callbacks.pUserData, val);
    276     } else {
    277         free((void *)val);
    278     }
    279 }
    280 
    281 #else
    282 
    283 static inline char *loader_getenv(const char *name, const struct loader_instance *inst) {
    284     // stub func
    285     (void)inst;
    286     (void)name;
    287     return NULL;
    288 }
    289 static inline void loader_free_getenv(char *val, const struct loader_instance *inst) {
    290     // stub func
    291     (void)val;
    292     (void)inst;
    293 }
    294 
    295 #endif
    296 
    297 void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...) {
    298     char msg[512];
    299     char cmd_line_msg[512];
    300     size_t cmd_line_size = sizeof(cmd_line_msg);
    301     va_list ap;
    302     int ret;
    303 
    304     va_start(ap, format);
    305     ret = vsnprintf(msg, sizeof(msg), format, ap);
    306     if ((ret >= (int)sizeof(msg)) || ret < 0) {
    307         msg[sizeof(msg) - 1] = '\0';
    308     }
    309     va_end(ap);
    310 
    311     if (inst) {
    312         util_DebugReportMessage(inst, msg_type, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(uintptr_t)inst, 0, msg_code,
    313                                 "loader", msg);
    314     }
    315 
    316     if (!(msg_type & g_loader_log_msgs)) {
    317         return;
    318     }
    319 
    320     cmd_line_msg[0] = '\0';
    321     cmd_line_size -= 1;
    322     size_t original_size = cmd_line_size;
    323 
    324     va_start(ap, format);
    325     if ((msg_type & LOADER_INFO_BIT) != 0) {
    326         strncat(cmd_line_msg, "INFO", cmd_line_size);
    327         cmd_line_size -= 4;
    328     }
    329     if ((msg_type & LOADER_WARN_BIT) != 0) {
    330         if (cmd_line_size != original_size) {
    331             strncat(cmd_line_msg, " | ", cmd_line_size);
    332             cmd_line_size -= 3;
    333         }
    334         strncat(cmd_line_msg, "WARNING", cmd_line_size);
    335         cmd_line_size -= 7;
    336     }
    337     if ((msg_type & LOADER_PERF_BIT) != 0) {
    338         if (cmd_line_size != original_size) {
    339             strncat(cmd_line_msg, " | ", cmd_line_size);
    340             cmd_line_size -= 3;
    341         }
    342         strncat(cmd_line_msg, "PERF", cmd_line_size);
    343         cmd_line_size -= 4;
    344     }
    345     if ((msg_type & LOADER_ERROR_BIT) != 0) {
    346         if (cmd_line_size != original_size) {
    347             strncat(cmd_line_msg, " | ", cmd_line_size);
    348             cmd_line_size -= 3;
    349         }
    350         strncat(cmd_line_msg, "ERROR", cmd_line_size);
    351         cmd_line_size -= 5;
    352     }
    353     if ((msg_type & LOADER_DEBUG_BIT) != 0) {
    354         if (cmd_line_size != original_size) {
    355             strncat(cmd_line_msg, " | ", cmd_line_size);
    356             cmd_line_size -= 3;
    357         }
    358         strncat(cmd_line_msg, "DEBUG", cmd_line_size);
    359         cmd_line_size -= 5;
    360     }
    361     if (cmd_line_size != original_size) {
    362         strncat(cmd_line_msg, ": ", cmd_line_size);
    363         cmd_line_size -= 2;
    364     }
    365 
    366     if (0 < cmd_line_size) {
    367         // If the message is too long, trim it down
    368         if (strlen(msg) > cmd_line_size) {
    369             msg[cmd_line_size - 1] = '\0';
    370         }
    371         strncat(cmd_line_msg, msg, cmd_line_size);
    372     } else {
    373         // Shouldn't get here, but check to make sure if we've already overrun
    374         // the string boundary
    375         assert(false);
    376     }
    377 
    378 #if defined(WIN32)
    379     OutputDebugString(cmd_line_msg);
    380     OutputDebugString("\n");
    381 #endif
    382 
    383     fputs(cmd_line_msg, stderr);
    384     fputc('\n', stderr);
    385 }
    386 
    387 VKAPI_ATTR VkResult VKAPI_CALL vkSetInstanceDispatch(VkInstance instance, void *object) {
    388     struct loader_instance *inst = loader_get_instance(instance);
    389     if (!inst) {
    390         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    391                    "vkSetInstanceDispatch: Can not retrieve Instance "
    392                    "dispatch table.");
    393         return VK_ERROR_INITIALIZATION_FAILED;
    394     }
    395     loader_set_dispatch(object, inst->disp);
    396     return VK_SUCCESS;
    397 }
    398 
    399 VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceDispatch(VkDevice device, void *object) {
    400     struct loader_device *dev;
    401     struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
    402 
    403     if (NULL == icd_term) {
    404         return VK_ERROR_INITIALIZATION_FAILED;
    405     }
    406     loader_set_dispatch(object, &dev->loader_dispatch);
    407     return VK_SUCCESS;
    408 }
    409 
    410 #if defined(_WIN32)
    411 
    412 // Append the JSON path data to the list and allocate/grow the list if it's not large enough.
    413 // Function returns true if filename was appended to reg_data list.
    414 // Caller should free reg_data.
    415 static bool loaderAddJsonEntry(const struct loader_instance *inst,
    416                                char **reg_data,    // list of JSON files
    417                                PDWORD total_size,  // size of reg_data
    418                                LPCTSTR key_name,   // key name - used for debug prints - i.e. VulkanDriverName
    419                                DWORD key_type,     // key data type
    420                                LPSTR json_path,    // JSON string to add to the list reg_data
    421                                DWORD json_size,    // size in bytes of json_path
    422                                VkResult *result) {
    423     if (NULL == *reg_data) {
    424         *reg_data = loader_instance_heap_alloc(inst, *total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    425         if (NULL == *reg_data) {
    426             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    427                        "loaderAddJsonEntry: Failed to allocate space for registry data for key %s", json_path);
    428             *result = VK_ERROR_OUT_OF_HOST_MEMORY;
    429             return false;
    430         }
    431         *reg_data[0] = '\0';
    432     } else if (strlen(*reg_data) + json_size + 1 > *total_size) {
    433         void *new_ptr =
    434             loader_instance_heap_realloc(inst, *reg_data, *total_size, *total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    435         if (NULL == new_ptr) {
    436             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    437                        "loaderAddJsonEntry: Failed to reallocate space for registry value of size %d for key %s", *total_size * 2,
    438                        json_path);
    439             *result = VK_ERROR_OUT_OF_HOST_MEMORY;
    440             return false;
    441         }
    442         *reg_data = new_ptr;
    443         *total_size *= 2;
    444     }
    445 
    446     for (char *curr_filename = json_path; curr_filename[0] != '\0'; curr_filename += strlen(curr_filename) + 1) {
    447         if (strlen(*reg_data) == 0) {
    448             (void)snprintf(*reg_data, json_size + 1, "%s", curr_filename);
    449         } else {
    450             (void)snprintf(*reg_data + strlen(*reg_data), json_size + 2, "%c%s", PATH_SEPARATOR, curr_filename);
    451         }
    452         loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "%s: Located json file \"%s\" from PnP registry: %s", __FUNCTION__,
    453                    curr_filename, key_name);
    454 
    455         if (key_type == REG_SZ) {
    456             break;
    457         }
    458     }
    459     return true;
    460 }
    461 
    462 // Find the list of registry files (names VulkanDriverName/VulkanDriverNameWow) in hkr.
    463 //
    464 // This function looks for filename in given device handle, filename is then added to return list
    465 // function return true if filename was appended to reg_data list
    466 // If error occures result is updated with failure reason
    467 bool loaderGetDeviceRegistryEntry(const struct loader_instance *inst, char **reg_data, PDWORD total_size, DEVINST dev_id, LPCTSTR value_name, VkResult *result)
    468 {
    469     HKEY hkrKey = INVALID_HANDLE_VALUE;
    470     DWORD requiredSize, data_type;
    471     char *manifest_path = NULL;
    472     bool found = false;
    473 
    474     if (NULL == total_size || NULL == reg_data) {
    475         *result = VK_ERROR_INITIALIZATION_FAILED;
    476         return false;
    477     }
    478 
    479     CONFIGRET status = CM_Open_DevNode_Key(dev_id, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hkrKey, CM_REGISTRY_SOFTWARE);
    480     if (status != CR_SUCCESS) {
    481         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
    482             "loaderGetDeviceRegistryEntry: Failed to open registry key for DeviceID(%d)", dev_id);
    483         *result = VK_ERROR_INITIALIZATION_FAILED;
    484         return false;
    485     }
    486 
    487     // query value
    488     LSTATUS ret = RegQueryValueEx(
    489         hkrKey,
    490         value_name,
    491         NULL,
    492         NULL,
    493         NULL,
    494         &requiredSize);
    495 
    496     if (ret != ERROR_SUCCESS) {
    497         if (ret == ERROR_FILE_NOT_FOUND) {
    498             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
    499                 "loaderGetDeviceRegistryEntry: Device ID(%d) Does not contain a value for \"%s\"", dev_id, value_name);
    500         } else {
    501             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
    502                 "loaderGetDeviceRegistryEntry: DeviceID(%d) Failed to obtain %s size", dev_id, value_name);
    503         }
    504         goto out;
    505     }
    506 
    507     manifest_path = loader_instance_heap_alloc(inst, requiredSize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    508     if (manifest_path == NULL) {
    509         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    510             "loaderGetDeviceRegistryEntry: Failed to allocate space for DriverName.");
    511         *result = VK_ERROR_OUT_OF_HOST_MEMORY;
    512         goto out;
    513     }
    514 
    515     ret = RegQueryValueEx(
    516         hkrKey,
    517         value_name,
    518         NULL,
    519         &data_type,
    520         (BYTE *)manifest_path,
    521         &requiredSize
    522     );
    523 
    524     if (ret != ERROR_SUCCESS) {
    525         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    526             "loaderGetDeviceRegistryEntry: DeviceID(%d) Failed to obtain %s", value_name);
    527 
    528         *result = VK_ERROR_INITIALIZATION_FAILED;
    529         goto out;
    530     }
    531 
    532     if (data_type != REG_SZ && data_type != REG_MULTI_SZ) {
    533         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    534             "loaderGetDeviceRegistryEntry: Invalid %s data type. Expected REG_SZ or REG_MULTI_SZ.", value_name);
    535         *result = VK_ERROR_INITIALIZATION_FAILED;
    536         goto out;
    537     }
    538 
    539     found = loaderAddJsonEntry(inst, reg_data, total_size, value_name, data_type, manifest_path, requiredSize, result);
    540 
    541 out:
    542     if (manifest_path != NULL) {
    543         loader_instance_heap_free(inst, manifest_path);
    544     }
    545     RegCloseKey(hkrKey);
    546     return found;
    547 }
    548 
    549 // Find the list of registry files (names VulkanDriverName/VulkanDriverNameWow) in hkr .
    550 //
    551 // This function looks for display devices and childish software components
    552 // for a list of files which are added to a returned list (function return
    553 // value).
    554 // Function return is a string with a ';'  separated list of filenames.
    555 // Function return is NULL if no valid name/value pairs  are found in the key,
    556 // or the key is not found.
    557 //
    558 // *reg_data contains a string list of filenames as pointer.
    559 // When done using the returned string list, the caller should free the pointer.
    560 VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char **reg_data, PDWORD reg_data_size, LPCTSTR value_name) {
    561     static const wchar_t *softwareComponentGUID = L"{5c4c3332-344d-483c-8739-259e934c9cc8}";
    562     static const wchar_t *displayGUID = L"{4d36e968-e325-11ce-bfc1-08002be10318}";
    563     const ULONG flags = CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT;
    564 
    565     wchar_t childGuid[MAX_GUID_STRING_LEN + 2];  // +2 for brackets {}
    566     ULONG childGuidSize = sizeof(childGuid);
    567 
    568     DEVINST devID = 0, childID = 0;
    569     wchar_t *pDeviceNames = NULL;
    570     ULONG deviceNamesSize = 0;
    571     VkResult result = VK_SUCCESS;
    572     bool found = false;
    573 
    574     if (NULL == reg_data) {
    575         result = VK_ERROR_INITIALIZATION_FAILED;
    576         return result;
    577     }
    578 
    579     // if after obtaining the DeviceNameSize, new device is added start over
    580     do {
    581         CM_Get_Device_ID_List_SizeW(&deviceNamesSize, displayGUID, flags);
    582 
    583         if (pDeviceNames != NULL) {
    584             loader_instance_heap_free(inst, pDeviceNames);
    585         }
    586 
    587         pDeviceNames = loader_instance_heap_alloc(inst, deviceNamesSize * sizeof(wchar_t), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    588         if (pDeviceNames == NULL) {
    589             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    590                 "loaderGetDeviceRegistryFiles: Failed to allocate space for display device names.");
    591             result = VK_ERROR_OUT_OF_HOST_MEMORY;
    592             return result;
    593         }
    594     } while (CM_Get_Device_ID_ListW(displayGUID, pDeviceNames, deviceNamesSize, flags) == CR_BUFFER_SMALL);
    595 
    596     if (pDeviceNames) {
    597         for (wchar_t *deviceName = pDeviceNames; *deviceName; deviceName += wcslen(deviceName) + 1) {
    598             CONFIGRET status = CM_Locate_DevNodeW(&devID, deviceName, CM_LOCATE_DEVNODE_NORMAL);
    599             if (CR_SUCCESS != status) {
    600                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to open DevNode %s",
    601                            deviceName);
    602                 continue;
    603             }
    604             ULONG ulStatus, ulProblem;
    605             status = CM_Get_DevNode_Status(&ulStatus, &ulProblem, devID, 0);
    606 
    607             if (CR_SUCCESS != status)
    608             {
    609                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to probe device status %s",
    610                            deviceName);
    611                 continue;
    612             }
    613             if ((ulStatus & DN_HAS_PROBLEM) && (ulProblem == CM_PROB_NEED_RESTART || ulProblem == DN_NEED_RESTART))
    614             {
    615                 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
    616                            "loaderGetDeviceRegistryFiles: device %s is pending reboot, skipping ...", deviceName);
    617                 continue;
    618             }
    619 
    620             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: opening device %s", deviceName);
    621 
    622             if (loaderGetDeviceRegistryEntry(inst, reg_data, reg_data_size, devID, value_name, &result)) {
    623                 found = true;
    624                 continue;
    625             }
    626             else if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
    627                 break;
    628             }
    629 
    630             status = CM_Get_Child(&childID, devID, 0);
    631             if (status != CR_SUCCESS) {
    632                 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
    633                            "loaderGetDeviceRegistryFiles: unable to open child-device error:%d", status);
    634                 continue;
    635             }
    636 
    637             do {
    638                 wchar_t buffer[MAX_DEVICE_ID_LEN];
    639                 CM_Get_Device_IDW(childID, buffer, MAX_DEVICE_ID_LEN, 0);
    640 
    641                 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
    642                            "loaderGetDeviceRegistryFiles: Opening child device %d - %s", childID, buffer);
    643 
    644                 status = CM_Get_DevNode_Registry_PropertyW(childID, CM_DRP_CLASSGUID, NULL, &childGuid, &childGuidSize, 0);
    645                 if (status != CR_SUCCESS) {
    646                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    647                                "loaderGetDeviceRegistryFiles: unable to obtain GUID for:%d error:%d", childID, status);
    648 
    649                     result = VK_ERROR_INITIALIZATION_FAILED;
    650                     continue;
    651                 }
    652 
    653                 if (wcscmp(childGuid, softwareComponentGUID) != 0) {
    654                     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
    655                                "loaderGetDeviceRegistryFiles: GUID for %d is not SoftwareComponent skipping", childID);
    656                     continue;
    657                 }
    658 
    659                 if (loaderGetDeviceRegistryEntry(inst, reg_data, reg_data_size, childID, value_name, &result)) {
    660                     found = true;
    661                     break; // check next-display-device
    662                 }
    663 
    664             } while (CM_Get_Sibling(&childID, childID, 0) == CR_SUCCESS);
    665         }
    666 
    667         loader_instance_heap_free(inst, pDeviceNames);
    668     }
    669 
    670     if (!found && result != VK_ERROR_OUT_OF_HOST_MEMORY) {
    671         result = VK_ERROR_INITIALIZATION_FAILED;
    672     }
    673 
    674     return result;
    675 }
    676 
    677 static char *loader_get_next_path(char *path);
    678 
    679 // Find the list of registry files (names within a key) in key "location".
    680 //
    681 // This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as
    682 // given in "location"
    683 // for a list or name/values which are added to a returned list (function return
    684 // value).
    685 // The DWORD values within the key must be 0 or they are skipped.
    686 // Function return is a string with a ';'  separated list of filenames.
    687 // Function return is NULL if no valid name/value pairs  are found in the key,
    688 // or the key is not found.
    689 //
    690 // *reg_data contains a string list of filenames as pointer.
    691 // When done using the returned string list, the caller should free the pointer.
    692 VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *location, bool use_secondary_hive, char **reg_data, PDWORD reg_data_size) {
    693     LONG rtn_value;
    694     HKEY hive = DEFAULT_VK_REGISTRY_HIVE, key;
    695     DWORD access_flags;
    696     char name[2048];
    697     char *loc = location;
    698     char *next;
    699     DWORD idx;
    700     DWORD name_size = sizeof(name);
    701     DWORD value;
    702     DWORD value_size = sizeof(value);
    703     VkResult result = VK_SUCCESS;
    704     bool found = false;
    705 
    706     if (NULL == reg_data) {
    707         result = VK_ERROR_INITIALIZATION_FAILED;
    708         goto out;
    709     }
    710 
    711     while (*loc) {
    712         next = loader_get_next_path(loc);
    713         access_flags = KEY_QUERY_VALUE;
    714         rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
    715         if (ERROR_SUCCESS == rtn_value) {
    716             idx = 0;
    717             while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE)&value, &value_size)) ==
    718                    ERROR_SUCCESS) {
    719                 if (value_size == sizeof(value) && value == 0) {
    720                     if (NULL == *reg_data) {
    721                         *reg_data = loader_instance_heap_alloc(inst, *reg_data_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    722                         if (NULL == *reg_data) {
    723                             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    724                                        "loaderGetRegistryFiles: Failed to allocate space for registry data for key %s", name);
    725                             RegCloseKey(key);
    726                             result = VK_ERROR_OUT_OF_HOST_MEMORY;
    727                             goto out;
    728                         }
    729                         *reg_data[0] = '\0';
    730                     } else if (strlen(*reg_data) + name_size + 1 > *reg_data_size) {
    731                         void *new_ptr = loader_instance_heap_realloc(inst, *reg_data, *reg_data_size, *reg_data_size * 2,
    732                                                                      VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    733                         if (NULL == new_ptr) {
    734                             loader_log(
    735                                 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    736                                 "loaderGetRegistryFiles: Failed to reallocate space for registry value of size %d for key %s",
    737                                 *reg_data_size * 2, name);
    738                             RegCloseKey(key);
    739                             result = VK_ERROR_OUT_OF_HOST_MEMORY;
    740                             goto out;
    741                         }
    742                         *reg_data = new_ptr;
    743                         *reg_data_size *= 2;
    744                     }
    745                     loader_log(
    746                         inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Located json file \"%s\" from registry \"%s\\%s\"", name,
    747                         hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR, location);
    748                     if (strlen(*reg_data) == 0) {
    749                         // The list is emtpy. Add the first entry.
    750                         (void)snprintf(*reg_data, name_size + 1, "%s", name);
    751                         found = true;
    752                     } else {
    753                         // At this point the reg_data variable contains other JSON paths, likely from the PNP/device section
    754                         // of the registry that we want to have precendence over this non-device specific section of the registry.
    755                         // To make sure we avoid enumerating old JSON files/drivers that might be present in the non-device specific
    756                         // area of the registry when a newer device specific JSON file is present, do a check before adding.
    757                         // Find the file name, without path, of the JSON file found in the non-device specific registry location.
    758                         // If the same JSON file name is already found in the list, don't add it again.
    759                         bool foundDuplicate = false;
    760                         char *pLastSlashName = strrchr(name, '\\');
    761                         if (pLastSlashName != NULL) {
    762                             char *foundMatch = strstr(*reg_data, pLastSlashName + 1);
    763                             if (foundMatch != NULL) {
    764                                 foundDuplicate = true;
    765                             }
    766                         }
    767 
    768                         if (foundDuplicate == false) {
    769                             // Add the new entry to the list.
    770                             (void)snprintf(*reg_data + strlen(*reg_data), name_size + 2, "%c%s", PATH_SEPARATOR, name);
    771                             found = true;
    772                         } else {
    773                             loader_log(
    774                                 inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
    775                                 "Skipping adding of json file \"%s\" from registry \"%s\\%s\" to the list due to duplication", name,
    776                                 hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR,
    777                                 location);
    778                         }
    779                     }
    780                 }
    781                 name_size = 2048;
    782             }
    783             RegCloseKey(key);
    784         }
    785 
    786         // Advance the location - if the next location is in the secondary hive, then reset the locations and advance the hive
    787         if (use_secondary_hive && (hive == DEFAULT_VK_REGISTRY_HIVE) && (*next == '\0')) {
    788             loc = location;
    789             hive = SECONDARY_VK_REGISTRY_HIVE;
    790         } else {
    791             loc = next;
    792         }
    793     }
    794 
    795     if (!found && result != VK_ERROR_OUT_OF_HOST_MEMORY) {
    796         result = VK_ERROR_INITIALIZATION_FAILED;
    797     }
    798 
    799 out:
    800 
    801     return result;
    802 }
    803 
    804 #endif  // WIN32
    805 
    806 // Combine path elements, separating each element with the platform-specific
    807 // directory separator, and save the combined string to a destination buffer,
    808 // not exceeding the given length. Path elements are given as variable args,
    809 // with a NULL element terminating the list.
    810 //
    811 // \returns the total length of the combined string, not including an ASCII
    812 // NUL termination character. This length may exceed the available storage:
    813 // in this case, the written string will be truncated to avoid a buffer
    814 // overrun, and the return value will greater than or equal to the storage
    815 // size. A NULL argument may be provided as the destination buffer in order
    816 // to determine the required string length without actually writing a string.
    817 static size_t loader_platform_combine_path(char *dest, size_t len, ...) {
    818     size_t required_len = 0;
    819     va_list ap;
    820     const char *component;
    821 
    822     va_start(ap, len);
    823 
    824     while ((component = va_arg(ap, const char *))) {
    825         if (required_len > 0) {
    826             // This path element is not the first non-empty element; prepend
    827             // a directory separator if space allows
    828             if (dest && required_len + 1 < len) {
    829                 (void)snprintf(dest + required_len, len - required_len, "%c", DIRECTORY_SYMBOL);
    830             }
    831             required_len++;
    832         }
    833 
    834         if (dest && required_len < len) {
    835             strncpy(dest + required_len, component, len - required_len);
    836         }
    837         required_len += strlen(component);
    838     }
    839 
    840     va_end(ap);
    841 
    842     // strncpy(3) won't add a NUL terminating byte in the event of truncation.
    843     if (dest && required_len >= len) {
    844         dest[len - 1] = '\0';
    845     }
    846 
    847     return required_len;
    848 }
    849 
    850 // Given string of three part form "maj.min.pat" convert to a vulkan version number.
    851 static uint32_t loader_make_version(char *vers_str) {
    852     uint32_t vers = 0, major = 0, minor = 0, patch = 0;
    853     char *vers_tok;
    854 
    855     if (!vers_str) {
    856         return vers;
    857     }
    858 
    859     vers_tok = strtok(vers_str, ".\"\n\r");
    860     if (NULL != vers_tok) {
    861         major = (uint16_t)atoi(vers_tok);
    862         vers_tok = strtok(NULL, ".\"\n\r");
    863         if (NULL != vers_tok) {
    864             minor = (uint16_t)atoi(vers_tok);
    865             vers_tok = strtok(NULL, ".\"\n\r");
    866             if (NULL != vers_tok) {
    867                 patch = (uint16_t)atoi(vers_tok);
    868             }
    869         }
    870     }
    871 
    872     return VK_MAKE_VERSION(major, minor, patch);
    873 }
    874 
    875 bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) {
    876     return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
    877 }
    878 
    879 // Search the given ext_array for an extension matching the given vk_ext_prop
    880 bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count,
    881                                      const VkExtensionProperties *ext_array) {
    882     for (uint32_t i = 0; i < count; i++) {
    883         if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) return true;
    884     }
    885     return false;
    886 }
    887 
    888 // Search the given ext_list for an extension matching the given vk_ext_prop
    889 bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) {
    890     for (uint32_t i = 0; i < ext_list->count; i++) {
    891         if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true;
    892     }
    893     return false;
    894 }
    895 
    896 // Search the given ext_list for a device extension matching the given ext_prop
    897 bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) {
    898     for (uint32_t i = 0; i < ext_list->count; i++) {
    899         if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true;
    900     }
    901     return false;
    902 }
    903 
    904 // Search the given layer list for a layer matching the given layer name
    905 static struct loader_layer_properties *loader_get_layer_property(const char *name, const struct loader_layer_list *layer_list) {
    906     for (uint32_t i = 0; i < layer_list->count; i++) {
    907         const VkLayerProperties *item = &layer_list->list[i].info;
    908         if (strcmp(name, item->layerName) == 0) return &layer_list->list[i];
    909     }
    910     return NULL;
    911 }
    912 
    913 // Get the next unused layer property in the list. Init the property to zero.
    914 static struct loader_layer_properties *loader_get_next_layer_property(const struct loader_instance *inst,
    915                                                                       struct loader_layer_list *layer_list) {
    916     if (layer_list->capacity == 0) {
    917         layer_list->list =
    918             loader_instance_heap_alloc(inst, sizeof(struct loader_layer_properties) * 64, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    919         if (layer_list->list == NULL) {
    920             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    921                        "loader_get_next_layer_property: Out of memory can "
    922                        "not add any layer properties to list");
    923             return NULL;
    924         }
    925         memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
    926         layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
    927     }
    928 
    929     // Ensure enough room to add an entry
    930     if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) {
    931         void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2,
    932                                                      VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    933         if (NULL == new_ptr) {
    934             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_next_layer_property: realloc failed for layer list");
    935             return NULL;
    936         }
    937         layer_list->list = new_ptr;
    938         layer_list->capacity *= 2;
    939     }
    940 
    941     layer_list->count++;
    942     return &(layer_list->list[layer_list->count - 1]);
    943 }
    944 
    945 // Remove all layer properties entries from the list
    946 void loader_delete_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
    947     uint32_t i, j, k;
    948     struct loader_device_extension_list *dev_ext_list;
    949     struct loader_dev_ext_props *ext_props;
    950     if (!layer_list) return;
    951 
    952     for (i = 0; i < layer_list->count; i++) {
    953         if (NULL != layer_list->list[i].component_layer_names) {
    954             loader_instance_heap_free(inst, layer_list->list[i].component_layer_names);
    955             layer_list->list[i].component_layer_names = NULL;
    956         }
    957         loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_list->list[i].instance_extension_list);
    958         dev_ext_list = &layer_list->list[i].device_extension_list;
    959         if (dev_ext_list->capacity > 0 && NULL != dev_ext_list->list) {
    960             for (j = 0; j < dev_ext_list->count; j++) {
    961                 ext_props = &dev_ext_list->list[j];
    962                 if (ext_props->entrypoint_count > 0) {
    963                     for (k = 0; k < ext_props->entrypoint_count; k++) {
    964                         loader_instance_heap_free(inst, ext_props->entrypoints[k]);
    965                     }
    966                     loader_instance_heap_free(inst, ext_props->entrypoints);
    967                 }
    968             }
    969         }
    970         loader_destroy_generic_list(inst, (struct loader_generic_list *)dev_ext_list);
    971     }
    972     layer_list->count = 0;
    973 
    974     if (layer_list->capacity > 0) {
    975         layer_list->capacity = 0;
    976         loader_instance_heap_free(inst, layer_list->list);
    977     }
    978 }
    979 
    980 static VkResult loader_add_instance_extensions(const struct loader_instance *inst,
    981                                                const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, const char *lib_name,
    982                                                struct loader_extension_list *ext_list) {
    983     uint32_t i, count = 0;
    984     VkExtensionProperties *ext_props;
    985     VkResult res = VK_SUCCESS;
    986 
    987     if (!fp_get_props) {
    988         // No EnumerateInstanceExtensionProperties defined
    989         goto out;
    990     }
    991 
    992     res = fp_get_props(NULL, &count, NULL);
    993     if (res != VK_SUCCESS) {
    994         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    995                    "loader_add_instance_extensions: Error getting Instance "
    996                    "extension count from %s",
    997                    lib_name);
    998         goto out;
    999     }
   1000 
   1001     if (count == 0) {
   1002         // No ExtensionProperties to report
   1003         goto out;
   1004     }
   1005 
   1006     ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
   1007     if (NULL == ext_props) {
   1008         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   1009         goto out;
   1010     }
   1011 
   1012     res = fp_get_props(NULL, &count, ext_props);
   1013     if (res != VK_SUCCESS) {
   1014         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1015                    "loader_add_instance_extensions: Error getting Instance "
   1016                    "extensions from %s",
   1017                    lib_name);
   1018         goto out;
   1019     }
   1020 
   1021     for (i = 0; i < count; i++) {
   1022         char spec_version[64];
   1023 
   1024         bool ext_unsupported = wsi_unsupported_instance_extension(&ext_props[i]);
   1025         if (!ext_unsupported) {
   1026             (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion),
   1027                            VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion));
   1028             loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Instance Extension: %s (%s) version %s", ext_props[i].extensionName,
   1029                        lib_name, spec_version);
   1030 
   1031             res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
   1032             if (res != VK_SUCCESS) {
   1033                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1034                            "loader_add_instance_extensions: Failed to add %s "
   1035                            "to Instance extension list",
   1036                            lib_name);
   1037                 goto out;
   1038             }
   1039         }
   1040     }
   1041 
   1042 out:
   1043     return res;
   1044 }
   1045 
   1046 // Initialize ext_list with the physical device extensions.
   1047 // The extension properties are passed as inputs in count and ext_props.
   1048 static VkResult loader_init_device_extensions(const struct loader_instance *inst, struct loader_physical_device_term *phys_dev_term,
   1049                                               uint32_t count, VkExtensionProperties *ext_props,
   1050                                               struct loader_extension_list *ext_list) {
   1051     VkResult res;
   1052     uint32_t i;
   1053 
   1054     res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
   1055     if (VK_SUCCESS != res) {
   1056         return res;
   1057     }
   1058 
   1059     for (i = 0; i < count; i++) {
   1060         char spec_version[64];
   1061         (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion),
   1062                        VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion));
   1063         loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName,
   1064                    phys_dev_term->this_icd_term->scanned_icd->lib_name, spec_version);
   1065         res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
   1066         if (res != VK_SUCCESS) return res;
   1067     }
   1068 
   1069     return VK_SUCCESS;
   1070 }
   1071 
   1072 VkResult loader_add_device_extensions(const struct loader_instance *inst,
   1073                                       PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties,
   1074                                       VkPhysicalDevice physical_device, const char *lib_name,
   1075                                       struct loader_extension_list *ext_list) {
   1076     uint32_t i, count;
   1077     VkResult res;
   1078     VkExtensionProperties *ext_props;
   1079 
   1080     res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
   1081     if (res == VK_SUCCESS && count > 0) {
   1082         ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
   1083         if (!ext_props) {
   1084             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1085                        "loader_add_device_extensions: Failed to allocate space"
   1086                        " for device extension properties.");
   1087             return VK_ERROR_OUT_OF_HOST_MEMORY;
   1088         }
   1089         res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
   1090         if (res != VK_SUCCESS) {
   1091             return res;
   1092         }
   1093         for (i = 0; i < count; i++) {
   1094             char spec_version[64];
   1095             (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion),
   1096                            VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion));
   1097             loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName,
   1098                        lib_name, spec_version);
   1099             res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
   1100             if (res != VK_SUCCESS) {
   1101                 return res;
   1102             }
   1103         }
   1104     } else {
   1105         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1106                    "loader_add_device_extensions: Error getting physical "
   1107                    "device extension info count from library %s",
   1108                    lib_name);
   1109         return res;
   1110     }
   1111 
   1112     return VK_SUCCESS;
   1113 }
   1114 
   1115 VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) {
   1116     size_t capacity = 32 * element_size;
   1117     list_info->count = 0;
   1118     list_info->capacity = 0;
   1119     list_info->list = loader_instance_heap_alloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1120     if (list_info->list == NULL) {
   1121         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1122                    "loader_init_generic_list: Failed to allocate space "
   1123                    "for generic list");
   1124         return VK_ERROR_OUT_OF_HOST_MEMORY;
   1125     }
   1126     memset(list_info->list, 0, capacity);
   1127     list_info->capacity = capacity;
   1128     return VK_SUCCESS;
   1129 }
   1130 
   1131 void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
   1132     loader_instance_heap_free(inst, list->list);
   1133     list->count = 0;
   1134     list->capacity = 0;
   1135 }
   1136 
   1137 // Append non-duplicate extension properties defined in props to the given ext_list.
   1138 // Return - Vk_SUCCESS on success
   1139 VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list,
   1140                                 uint32_t prop_list_count, const VkExtensionProperties *props) {
   1141     uint32_t i;
   1142     const VkExtensionProperties *cur_ext;
   1143 
   1144     if (ext_list->list == NULL || ext_list->capacity == 0) {
   1145         VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
   1146         if (VK_SUCCESS != res) {
   1147             return res;
   1148         }
   1149     }
   1150 
   1151     for (i = 0; i < prop_list_count; i++) {
   1152         cur_ext = &props[i];
   1153 
   1154         // look for duplicates
   1155         if (has_vk_extension_property(cur_ext, ext_list)) {
   1156             continue;
   1157         }
   1158 
   1159         // add to list at end
   1160         // check for enough capacity
   1161         if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) {
   1162             void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
   1163                                                          VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1164             if (new_ptr == NULL) {
   1165                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1166                            "loader_add_to_ext_list: Failed to reallocate "
   1167                            "space for extension list");
   1168                 return VK_ERROR_OUT_OF_HOST_MEMORY;
   1169             }
   1170             ext_list->list = new_ptr;
   1171 
   1172             // double capacity
   1173             ext_list->capacity *= 2;
   1174         }
   1175 
   1176         memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
   1177         ext_list->count++;
   1178     }
   1179     return VK_SUCCESS;
   1180 }
   1181 
   1182 // Append one extension property defined in props with entrypoints defined in entries to the given
   1183 // ext_list. Do not append if a duplicate.
   1184 // Return - Vk_SUCCESS on success
   1185 VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list,
   1186                                     const VkExtensionProperties *props, uint32_t entry_count, char **entrys) {
   1187     uint32_t idx;
   1188     if (ext_list->list == NULL || ext_list->capacity == 0) {
   1189         VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props));
   1190         if (VK_SUCCESS != res) {
   1191             return res;
   1192         }
   1193     }
   1194 
   1195     // look for duplicates
   1196     if (has_vk_dev_ext_property(props, ext_list)) {
   1197         return VK_SUCCESS;
   1198     }
   1199 
   1200     idx = ext_list->count;
   1201     // add to list at end
   1202     // check for enough capacity
   1203     if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
   1204         void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
   1205                                                      VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1206 
   1207         if (NULL == new_ptr) {
   1208             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1209                        "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list");
   1210             return VK_ERROR_OUT_OF_HOST_MEMORY;
   1211         }
   1212         ext_list->list = new_ptr;
   1213 
   1214         // double capacity
   1215         ext_list->capacity *= 2;
   1216     }
   1217 
   1218     memcpy(&ext_list->list[idx].props, props, sizeof(*props));
   1219     ext_list->list[idx].entrypoint_count = entry_count;
   1220     if (entry_count == 0) {
   1221         ext_list->list[idx].entrypoints = NULL;
   1222     } else {
   1223         ext_list->list[idx].entrypoints =
   1224             loader_instance_heap_alloc(inst, sizeof(char *) * entry_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1225         if (ext_list->list[idx].entrypoints == NULL) {
   1226             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1227                        "loader_add_to_dev_ext_list: Failed to allocate space "
   1228                        "for device extension entrypoint list in list %d",
   1229                        idx);
   1230             ext_list->list[idx].entrypoint_count = 0;
   1231             return VK_ERROR_OUT_OF_HOST_MEMORY;
   1232         }
   1233         for (uint32_t i = 0; i < entry_count; i++) {
   1234             ext_list->list[idx].entrypoints[i] =
   1235                 loader_instance_heap_alloc(inst, strlen(entrys[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1236             if (ext_list->list[idx].entrypoints[i] == NULL) {
   1237                 for (uint32_t j = 0; j < i; j++) {
   1238                     loader_instance_heap_free(inst, ext_list->list[idx].entrypoints[j]);
   1239                 }
   1240                 loader_instance_heap_free(inst, ext_list->list[idx].entrypoints);
   1241                 ext_list->list[idx].entrypoint_count = 0;
   1242                 ext_list->list[idx].entrypoints = NULL;
   1243                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1244                            "loader_add_to_dev_ext_list: Failed to allocate space "
   1245                            "for device extension entrypoint %d name",
   1246                            i);
   1247                 return VK_ERROR_OUT_OF_HOST_MEMORY;
   1248             }
   1249             strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
   1250         }
   1251     }
   1252     ext_list->count++;
   1253 
   1254     return VK_SUCCESS;
   1255 }
   1256 
   1257 // Prototype of loader_add_meta_layer function since we use it in the loader_add_implicit_layer, but can also
   1258 // call loader_add_implicit_layer from loader_add_meta_layer.
   1259 bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
   1260                            struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
   1261                            const struct loader_layer_list *source_list);
   1262 
   1263 // Search the given layer list for a list matching the given VkLayerProperties
   1264 bool has_vk_layer_property(const VkLayerProperties *vk_layer_prop, const struct loader_layer_list *list) {
   1265     for (uint32_t i = 0; i < list->count; i++) {
   1266         if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) return true;
   1267     }
   1268     return false;
   1269 }
   1270 
   1271 // Search the given layer list for a layer matching the given name
   1272 bool has_layer_name(const char *name, const struct loader_layer_list *list) {
   1273     for (uint32_t i = 0; i < list->count; i++) {
   1274         if (strcmp(name, list->list[i].info.layerName) == 0) return true;
   1275     }
   1276     return false;
   1277 }
   1278 
   1279 // Search the given search_list for any layers in the props list.  Add these to the
   1280 // output layer_list.  Don't add duplicates to the output layer_list.
   1281 static VkResult loader_add_layer_names_to_list(const struct loader_instance *inst, struct loader_layer_list *output_list,
   1282                                                struct loader_layer_list *expanded_output_list, uint32_t name_count,
   1283                                                const char *const *names, const struct loader_layer_list *source_list) {
   1284     struct loader_layer_properties *layer_prop;
   1285     VkResult err = VK_SUCCESS;
   1286 
   1287     for (uint32_t i = 0; i < name_count; i++) {
   1288         const char *source_name = names[i];
   1289         layer_prop = loader_get_layer_property(source_name, source_list);
   1290         if (NULL == layer_prop) {
   1291             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1292                        "loader_add_layer_names_to_list: Unable to find layer"
   1293                        " %s",
   1294                        source_name);
   1295             err = VK_ERROR_LAYER_NOT_PRESENT;
   1296             continue;
   1297         }
   1298 
   1299         // If not a meta-layer, simply add it.
   1300         if (0 == (layer_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
   1301             if (!has_vk_layer_property(&layer_prop->info, output_list)) {
   1302                 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
   1303             }
   1304             if (!has_vk_layer_property(&layer_prop->info, expanded_output_list)) {
   1305                 loader_add_to_layer_list(inst, expanded_output_list, 1, layer_prop);
   1306             }
   1307         } else {
   1308             if (!has_vk_layer_property(&layer_prop->info, output_list) ||
   1309                 !has_vk_layer_property(&layer_prop->info, expanded_output_list)) {
   1310                 loader_add_meta_layer(inst, layer_prop, output_list, expanded_output_list, source_list);
   1311             }
   1312         }
   1313     }
   1314 
   1315     return err;
   1316 }
   1317 
   1318 // Manage lists of VkLayerProperties
   1319 static bool loader_init_layer_list(const struct loader_instance *inst, struct loader_layer_list *list) {
   1320     list->capacity = 32 * sizeof(struct loader_layer_properties);
   1321     list->list = loader_instance_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1322     if (list->list == NULL) {
   1323         return false;
   1324     }
   1325     memset(list->list, 0, list->capacity);
   1326     list->count = 0;
   1327     return true;
   1328 }
   1329 
   1330 void loader_destroy_layer_list(const struct loader_instance *inst, struct loader_device *device,
   1331                                struct loader_layer_list *layer_list) {
   1332     if (device) {
   1333         loader_device_heap_free(device, layer_list->list);
   1334     } else {
   1335         loader_instance_heap_free(inst, layer_list->list);
   1336     }
   1337     layer_list->count = 0;
   1338     layer_list->capacity = 0;
   1339 }
   1340 
   1341 // Append non-duplicate layer properties defined in prop_list to the given layer_info list
   1342 VkResult loader_add_to_layer_list(const struct loader_instance *inst, struct loader_layer_list *list, uint32_t prop_list_count,
   1343                                   const struct loader_layer_properties *props) {
   1344     uint32_t i;
   1345     struct loader_layer_properties *layer;
   1346 
   1347     if (list->list == NULL || list->capacity == 0) {
   1348         loader_init_layer_list(inst, list);
   1349     }
   1350 
   1351     if (list->list == NULL) return VK_SUCCESS;
   1352 
   1353     for (i = 0; i < prop_list_count; i++) {
   1354         layer = (struct loader_layer_properties *)&props[i];
   1355 
   1356         // Look for duplicates, and skip
   1357         if (has_vk_layer_property(&layer->info, list)) {
   1358             continue;
   1359         }
   1360 
   1361         // Check for enough capacity
   1362         if (((list->count + 1) * sizeof(struct loader_layer_properties)) >= list->capacity) {
   1363             size_t new_capacity = list->capacity * 2;
   1364             void *new_ptr =
   1365                 loader_instance_heap_realloc(inst, list->list, list->capacity, new_capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1366             if (NULL == new_ptr) {
   1367                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1368                            "loader_add_to_layer_list: Realloc failed for when attempting to add new layer");
   1369                 return VK_ERROR_OUT_OF_HOST_MEMORY;
   1370             }
   1371             list->list = new_ptr;
   1372             list->capacity = new_capacity;
   1373         }
   1374 
   1375         memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
   1376         list->count++;
   1377     }
   1378 
   1379     return VK_SUCCESS;
   1380 }
   1381 
   1382 // Check the individual implicit layer for the enable/disable environment variable settings.  Only add it after
   1383 // every check has passed indicating it should be used.
   1384 static void loader_add_implicit_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
   1385                                       struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
   1386                                       const struct loader_layer_list *source_list) {
   1387     bool enable = loader_is_implicit_layer_enabled(inst, prop);
   1388     if (enable) {
   1389         if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
   1390             if (NULL != target_list && !has_vk_layer_property(&prop->info, target_list)) {
   1391                 loader_add_to_layer_list(inst, target_list, 1, prop);
   1392             }
   1393             if (NULL != expanded_target_list && !has_vk_layer_property(&prop->info, expanded_target_list)) {
   1394                 loader_add_to_layer_list(inst, expanded_target_list, 1, prop);
   1395             }
   1396         } else {
   1397             if (!has_vk_layer_property(&prop->info, target_list) ||
   1398                 (NULL != expanded_target_list && !has_vk_layer_property(&prop->info, expanded_target_list))) {
   1399                 loader_add_meta_layer(inst, prop, target_list, expanded_target_list, source_list);
   1400             }
   1401         }
   1402     }
   1403 }
   1404 
   1405 // Add the component layers of a meta-layer to the active list of layers
   1406 bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
   1407                            struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
   1408                            const struct loader_layer_list *source_list) {
   1409     bool found = true;
   1410 
   1411     // We need to add all the individual component layers
   1412     for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
   1413         bool found_comp = false;
   1414         const struct loader_layer_properties *search_prop =
   1415             loader_get_layer_property(prop->component_layer_names[comp_layer], source_list);
   1416         if (search_prop != NULL) {
   1417             found_comp = true;
   1418 
   1419             // If the component layer is itself an implicit layer, we need to do the implicit layer enable
   1420             // checks
   1421             if (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
   1422                 loader_add_implicit_layer(inst, search_prop, target_list, expanded_target_list, source_list);
   1423             } else {
   1424                 if (NULL != expanded_target_list && !has_vk_layer_property(&search_prop->info, expanded_target_list)) {
   1425                     loader_add_to_layer_list(inst, expanded_target_list, 1, search_prop);
   1426                 }
   1427             }
   1428         }
   1429         if (!found_comp) {
   1430             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   1431                        "loader_add_meta_layer: Failed to find layer name %s component layer "
   1432                        "%s to activate",
   1433                        search_prop->info.layerName, prop->component_layer_names[comp_layer]);
   1434             found = false;
   1435         }
   1436     }
   1437 
   1438     // Add this layer to the overall target list (not the expanded one)
   1439     if (found && !has_vk_layer_property(&prop->info, target_list)) {
   1440         loader_add_to_layer_list(inst, target_list, 1, prop);
   1441     }
   1442 
   1443     return found;
   1444 }
   1445 
   1446 // Search the source_list for any layer with a name that matches the given name and a type
   1447 // that matches the given type.  Add all matching layers to the target_list.
   1448 // Do not add if found loader_layer_properties is already on the target_list.
   1449 void loader_find_layer_name_add_list(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
   1450                                      const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
   1451                                      struct loader_layer_list *expanded_target_list) {
   1452     bool found = false;
   1453     for (uint32_t i = 0; i < source_list->count; i++) {
   1454         struct loader_layer_properties *source_prop = &source_list->list[i];
   1455         if (0 == strcmp(source_prop->info.layerName, name) && (source_prop->type_flags & type_flags) == type_flags) {
   1456             // If not a meta-layer, simply add it.
   1457             if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
   1458                 if (NULL != target_list && !has_vk_layer_property(&source_prop->info, target_list) &&
   1459                     VK_SUCCESS == loader_add_to_layer_list(inst, target_list, 1, source_prop)) {
   1460                     found = true;
   1461                 }
   1462                 if (NULL != expanded_target_list && !has_vk_layer_property(&source_prop->info, expanded_target_list) &&
   1463                     VK_SUCCESS == loader_add_to_layer_list(inst, expanded_target_list, 1, source_prop)) {
   1464                     found = true;
   1465                 }
   1466             } else {
   1467                 found = loader_add_meta_layer(inst, source_prop, target_list, expanded_target_list, source_list);
   1468             }
   1469         }
   1470     }
   1471     if (!found) {
   1472         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   1473                    "loader_find_layer_name_add_list: Failed to find layer name %s to activate", name);
   1474     }
   1475 }
   1476 
   1477 static VkExtensionProperties *get_extension_property(const char *name, const struct loader_extension_list *list) {
   1478     for (uint32_t i = 0; i < list->count; i++) {
   1479         if (strcmp(name, list->list[i].extensionName) == 0) return &list->list[i];
   1480     }
   1481     return NULL;
   1482 }
   1483 
   1484 static VkExtensionProperties *get_dev_extension_property(const char *name, const struct loader_device_extension_list *list) {
   1485     for (uint32_t i = 0; i < list->count; i++) {
   1486         if (strcmp(name, list->list[i].props.extensionName) == 0) return &list->list[i].props;
   1487     }
   1488     return NULL;
   1489 }
   1490 
   1491 // For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
   1492 // the extension must provide two entry points for the loader to use:
   1493 // - "trampoline" entry point - this is the address returned by GetProcAddr
   1494 //                              and will always do what's necessary to support a
   1495 //                              global call.
   1496 // - "terminator" function    - this function will be put at the end of the
   1497 //                              instance chain and will contain the necessary logic
   1498 //                              to call / process the extension for the appropriate
   1499 //                              ICDs that are available.
   1500 // There is no generic mechanism for including these functions, the references
   1501 // must be placed into the appropriate loader entry points.
   1502 // GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr
   1503 // requests
   1504 // loader_coalesce_extensions(void) - add extension records to the list of global
   1505 //                                    extension available to the app.
   1506 // instance_disp                    - add function pointer for terminator function
   1507 //                                    to this array.
   1508 // The extension itself should be in a separate file that will be linked directly
   1509 // with the loader.
   1510 VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
   1511                                                    struct loader_extension_list *inst_exts) {
   1512     struct loader_extension_list icd_exts;
   1513     VkResult res = VK_SUCCESS;
   1514     char *env_value;
   1515     bool filter_extensions = true;
   1516 
   1517     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
   1518 
   1519     // Check if a user wants to disable the instance extension filtering behavior
   1520     env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst);
   1521     if (NULL != env_value && atoi(env_value) != 0) {
   1522         filter_extensions = false;
   1523     }
   1524     loader_free_getenv(env_value, inst);
   1525 
   1526     // traverse scanned icd list adding non-duplicate extensions to the list
   1527     for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
   1528         res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties));
   1529         if (VK_SUCCESS != res) {
   1530             goto out;
   1531         }
   1532         res = loader_add_instance_extensions(inst, icd_tramp_list->scanned_list[i].EnumerateInstanceExtensionProperties,
   1533                                              icd_tramp_list->scanned_list[i].lib_name, &icd_exts);
   1534         if (VK_SUCCESS == res) {
   1535             if (filter_extensions) {
   1536                 // Remove any extensions not recognized by the loader
   1537                 for (int32_t j = 0; j < (int32_t)icd_exts.count; j++) {
   1538                     // See if the extension is in the list of supported extensions
   1539                     bool found = false;
   1540                     for (uint32_t k = 0; LOADER_INSTANCE_EXTENSIONS[k] != NULL; k++) {
   1541                         if (strcmp(icd_exts.list[j].extensionName, LOADER_INSTANCE_EXTENSIONS[k]) == 0) {
   1542                             found = true;
   1543                             break;
   1544                         }
   1545                     }
   1546 
   1547                     // If it isn't in the list, remove it
   1548                     if (!found) {
   1549                         for (uint32_t k = j + 1; k < icd_exts.count; k++) {
   1550                             icd_exts.list[k - 1] = icd_exts.list[k];
   1551                         }
   1552                         --icd_exts.count;
   1553                         --j;
   1554                     }
   1555                 }
   1556             }
   1557 
   1558             res = loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list);
   1559         }
   1560         loader_destroy_generic_list(inst, (struct loader_generic_list *)&icd_exts);
   1561         if (VK_SUCCESS != res) {
   1562             goto out;
   1563         }
   1564     };
   1565 
   1566     // Traverse loader's extensions, adding non-duplicate extensions to the list
   1567     debug_report_add_instance_extensions(inst, inst_exts);
   1568 
   1569 out:
   1570     return res;
   1571 }
   1572 
   1573 struct loader_icd_term *loader_get_icd_and_device(const VkDevice device, struct loader_device **found_dev, uint32_t *icd_index) {
   1574     *found_dev = NULL;
   1575     for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
   1576         uint32_t index = 0;
   1577         for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
   1578             for (struct loader_device *dev = icd_term->logical_device_list; dev; dev = dev->next)
   1579                 // Value comparison of device prevents object wrapping by layers
   1580                 if (loader_get_dispatch(dev->icd_device) == loader_get_dispatch(device) ||
   1581                     loader_get_dispatch(dev->chain_device) == loader_get_dispatch(device)) {
   1582                     *found_dev = dev;
   1583                     if (NULL != icd_index) {
   1584                         *icd_index = index;
   1585                     }
   1586                     return icd_term;
   1587                 }
   1588             index++;
   1589         }
   1590     }
   1591     return NULL;
   1592 }
   1593 
   1594 void loader_destroy_logical_device(const struct loader_instance *inst, struct loader_device *dev,
   1595                                    const VkAllocationCallbacks *pAllocator) {
   1596     if (pAllocator) {
   1597         dev->alloc_callbacks = *pAllocator;
   1598     }
   1599     if (NULL != dev->expanded_activated_layer_list.list) {
   1600         loader_deactivate_layers(inst, dev, &dev->expanded_activated_layer_list);
   1601     }
   1602     if (NULL != dev->app_activated_layer_list.list) {
   1603         loader_destroy_layer_list(inst, dev, &dev->app_activated_layer_list);
   1604     }
   1605     loader_device_heap_free(dev, dev);
   1606 }
   1607 
   1608 struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) {
   1609     struct loader_device *new_dev;
   1610 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   1611     {
   1612 #else
   1613     if (pAllocator) {
   1614         new_dev = (struct loader_device *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(struct loader_device),
   1615                                                                     sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
   1616     } else {
   1617 #endif
   1618         new_dev = (struct loader_device *)malloc(sizeof(struct loader_device));
   1619     }
   1620 
   1621     if (!new_dev) {
   1622         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1623                    "loader_create_logical_device: Failed to alloc struct "
   1624                    "loader_device");
   1625         return NULL;
   1626     }
   1627 
   1628     memset(new_dev, 0, sizeof(struct loader_device));
   1629     if (pAllocator) {
   1630         new_dev->alloc_callbacks = *pAllocator;
   1631     }
   1632 
   1633     return new_dev;
   1634 }
   1635 
   1636 void loader_add_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term, struct loader_device *dev) {
   1637     dev->next = icd_term->logical_device_list;
   1638     icd_term->logical_device_list = dev;
   1639 }
   1640 
   1641 void loader_remove_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
   1642                                   struct loader_device *found_dev, const VkAllocationCallbacks *pAllocator) {
   1643     struct loader_device *dev, *prev_dev;
   1644 
   1645     if (!icd_term || !found_dev) return;
   1646 
   1647     prev_dev = NULL;
   1648     dev = icd_term->logical_device_list;
   1649     while (dev && dev != found_dev) {
   1650         prev_dev = dev;
   1651         dev = dev->next;
   1652     }
   1653 
   1654     if (prev_dev)
   1655         prev_dev->next = found_dev->next;
   1656     else
   1657         icd_term->logical_device_list = found_dev->next;
   1658     loader_destroy_logical_device(inst, found_dev, pAllocator);
   1659 }
   1660 
   1661 static void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term,
   1662                                const VkAllocationCallbacks *pAllocator) {
   1663     ptr_inst->total_icd_count--;
   1664     for (struct loader_device *dev = icd_term->logical_device_list; dev;) {
   1665         struct loader_device *next_dev = dev->next;
   1666         loader_destroy_logical_device(ptr_inst, dev, pAllocator);
   1667         dev = next_dev;
   1668     }
   1669 
   1670     loader_instance_heap_free(ptr_inst, icd_term);
   1671 }
   1672 
   1673 static struct loader_icd_term *loader_icd_create(const struct loader_instance *inst) {
   1674     struct loader_icd_term *icd_term;
   1675 
   1676     icd_term = loader_instance_heap_alloc(inst, sizeof(struct loader_icd_term), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1677     if (!icd_term) {
   1678         return NULL;
   1679     }
   1680 
   1681     memset(icd_term, 0, sizeof(struct loader_icd_term));
   1682 
   1683     return icd_term;
   1684 }
   1685 
   1686 static struct loader_icd_term *loader_icd_add(struct loader_instance *ptr_inst, const struct loader_scanned_icd *scanned_icd) {
   1687     struct loader_icd_term *icd_term;
   1688 
   1689     icd_term = loader_icd_create(ptr_inst);
   1690     if (!icd_term) {
   1691         return NULL;
   1692     }
   1693 
   1694     icd_term->scanned_icd = scanned_icd;
   1695     icd_term->this_instance = ptr_inst;
   1696 
   1697     // Prepend to the list
   1698     icd_term->next = ptr_inst->icd_terms;
   1699     ptr_inst->icd_terms = icd_term;
   1700     ptr_inst->total_icd_count++;
   1701 
   1702     return icd_term;
   1703 }
   1704 
   1705 // Determine the ICD interface version to use.
   1706 //     @param icd
   1707 //     @param pVersion Output parameter indicating which version to use or 0 if
   1708 //            the negotiation API is not supported by the ICD
   1709 //     @return  bool indicating true if the selected interface version is supported
   1710 //            by the loader, false indicates the version is not supported
   1711 bool loader_get_icd_interface_version(PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version, uint32_t *pVersion) {
   1712     if (fp_negotiate_icd_version == NULL) {
   1713         // ICD does not support the negotiation API, it supports version 0 or 1
   1714         // calling code must determine if it is version 0 or 1
   1715         *pVersion = 0;
   1716     } else {
   1717         // ICD supports the negotiation API, so call it with the loader's
   1718         // latest version supported
   1719         *pVersion = CURRENT_LOADER_ICD_INTERFACE_VERSION;
   1720         VkResult result = fp_negotiate_icd_version(pVersion);
   1721 
   1722         if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
   1723             // ICD no longer supports the loader's latest interface version so
   1724             // fail loading the ICD
   1725             return false;
   1726         }
   1727     }
   1728 
   1729 #if MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION > 0
   1730     if (*pVersion < MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION) {
   1731         // Loader no longer supports the ICD's latest interface version so fail
   1732         // loading the ICD
   1733         return false;
   1734     }
   1735 #endif
   1736     return true;
   1737 }
   1738 
   1739 void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
   1740     if (0 != icd_tramp_list->capacity) {
   1741         for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
   1742             loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
   1743             loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name);
   1744         }
   1745         loader_instance_heap_free(inst, icd_tramp_list->scanned_list);
   1746         icd_tramp_list->capacity = 0;
   1747         icd_tramp_list->count = 0;
   1748         icd_tramp_list->scanned_list = NULL;
   1749     }
   1750 }
   1751 
   1752 static VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
   1753     VkResult err = VK_SUCCESS;
   1754     loader_scanned_icd_clear(inst, icd_tramp_list);
   1755     icd_tramp_list->capacity = 8 * sizeof(struct loader_scanned_icd);
   1756     icd_tramp_list->scanned_list = loader_instance_heap_alloc(inst, icd_tramp_list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1757     if (NULL == icd_tramp_list->scanned_list) {
   1758         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1759                    "loader_scanned_icd_init: Realloc failed for layer list when "
   1760                    "attempting to add new layer");
   1761         err = VK_ERROR_OUT_OF_HOST_MEMORY;
   1762     }
   1763     return err;
   1764 }
   1765 
   1766 static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
   1767                                        const char *filename, uint32_t api_version) {
   1768     loader_platform_dl_handle handle;
   1769     PFN_vkCreateInstance fp_create_inst;
   1770     PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
   1771     PFN_vkGetInstanceProcAddr fp_get_proc_addr;
   1772     PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL;
   1773     PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version;
   1774     struct loader_scanned_icd *new_scanned_icd;
   1775     uint32_t interface_vers;
   1776     VkResult res = VK_SUCCESS;
   1777 
   1778     // TODO implement smarter opening/closing of libraries. For now this
   1779     // function leaves libraries open and the scanned_icd_clear closes them
   1780     handle = loader_platform_open_library(filename);
   1781     if (NULL == handle) {
   1782         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_open_library_error(filename));
   1783         goto out;
   1784     }
   1785 
   1786     // Get and settle on an ICD interface version
   1787     fp_negotiate_icd_version = loader_platform_get_proc_address(handle, "vk_icdNegotiateLoaderICDInterfaceVersion");
   1788 
   1789     if (!loader_get_icd_interface_version(fp_negotiate_icd_version, &interface_vers)) {
   1790         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1791                    "loader_scanned_icd_add: ICD %s doesn't support interface"
   1792                    " version compatible with loader, skip this ICD.",
   1793                    filename);
   1794         goto out;
   1795     }
   1796 
   1797     fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
   1798     if (NULL == fp_get_proc_addr) {
   1799         assert(interface_vers == 0);
   1800         // Use deprecated interface from version 0
   1801         fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
   1802         if (NULL == fp_get_proc_addr) {
   1803             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1804                        "loader_scanned_icd_add: Attempt to retrieve either "
   1805                        "\'vkGetInstanceProcAddr\' or "
   1806                        "\'vk_icdGetInstanceProcAddr\' from ICD %s failed.",
   1807                        filename);
   1808             goto out;
   1809         } else {
   1810             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   1811                        "loader_scanned_icd_add: Using deprecated ICD "
   1812                        "interface of \'vkGetInstanceProcAddr\' instead of "
   1813                        "\'vk_icdGetInstanceProcAddr\' for ICD %s",
   1814                        filename);
   1815         }
   1816         fp_create_inst = loader_platform_get_proc_address(handle, "vkCreateInstance");
   1817         if (NULL == fp_create_inst) {
   1818             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1819                        "loader_scanned_icd_add:  Failed querying "
   1820                        "\'vkCreateInstance\' via dlsym/loadlibrary for "
   1821                        "ICD %s",
   1822                        filename);
   1823             goto out;
   1824         }
   1825         fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties");
   1826         if (NULL == fp_get_inst_ext_props) {
   1827             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1828                        "loader_scanned_icd_add: Could not get \'vkEnumerate"
   1829                        "InstanceExtensionProperties\' via dlsym/loadlibrary "
   1830                        "for ICD %s",
   1831                        filename);
   1832             goto out;
   1833         }
   1834     } else {
   1835         // Use newer interface version 1 or later
   1836         if (interface_vers == 0) {
   1837             interface_vers = 1;
   1838         }
   1839 
   1840         fp_create_inst = (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance");
   1841         if (NULL == fp_create_inst) {
   1842             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1843                        "loader_scanned_icd_add: Could not get "
   1844                        "\'vkCreateInstance\' via \'vk_icdGetInstanceProcAddr\'"
   1845                        " for ICD %s",
   1846                        filename);
   1847             goto out;
   1848         }
   1849         fp_get_inst_ext_props =
   1850             (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties");
   1851         if (NULL == fp_get_inst_ext_props) {
   1852             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1853                        "loader_scanned_icd_add: Could not get \'vkEnumerate"
   1854                        "InstanceExtensionProperties\' via "
   1855                        "\'vk_icdGetInstanceProcAddr\' for ICD %s",
   1856                        filename);
   1857             goto out;
   1858         }
   1859         fp_get_phys_dev_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetPhysicalDeviceProcAddr");
   1860     }
   1861 
   1862     // check for enough capacity
   1863     if ((icd_tramp_list->count * sizeof(struct loader_scanned_icd)) >= icd_tramp_list->capacity) {
   1864         void *new_ptr = loader_instance_heap_realloc(inst, icd_tramp_list->scanned_list, icd_tramp_list->capacity,
   1865                                                      icd_tramp_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1866         if (NULL == new_ptr) {
   1867             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   1868             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1869                        "loader_scanned_icd_add: Realloc failed on icd library list for ICD %s", filename);
   1870             goto out;
   1871         }
   1872         icd_tramp_list->scanned_list = new_ptr;
   1873 
   1874         // double capacity
   1875         icd_tramp_list->capacity *= 2;
   1876     }
   1877 
   1878     new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
   1879     new_scanned_icd->handle = handle;
   1880     new_scanned_icd->api_version = api_version;
   1881     new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr;
   1882     new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr;
   1883     new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
   1884     new_scanned_icd->CreateInstance = fp_create_inst;
   1885     new_scanned_icd->interface_version = interface_vers;
   1886 
   1887     new_scanned_icd->lib_name = (char *)loader_instance_heap_alloc(inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1888     if (NULL == new_scanned_icd->lib_name) {
   1889         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_scanned_icd_add: Out of memory can't add ICD %s", filename);
   1890         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   1891         goto out;
   1892     }
   1893     strcpy(new_scanned_icd->lib_name, filename);
   1894     icd_tramp_list->count++;
   1895 
   1896 out:
   1897 
   1898     return res;
   1899 }
   1900 
   1901 static void loader_debug_init(void) {
   1902     char *env, *orig;
   1903 
   1904     if (g_loader_debug > 0) return;
   1905 
   1906     g_loader_debug = 0;
   1907 
   1908     // Parse comma-separated debug options
   1909     orig = env = loader_getenv("VK_LOADER_DEBUG", NULL);
   1910     while (env) {
   1911         char *p = strchr(env, ',');
   1912         size_t len;
   1913 
   1914         if (p)
   1915             len = p - env;
   1916         else
   1917             len = strlen(env);
   1918 
   1919         if (len > 0) {
   1920             if (strncmp(env, "all", len) == 0) {
   1921                 g_loader_debug = ~0u;
   1922                 g_loader_log_msgs = ~0u;
   1923             } else if (strncmp(env, "warn", len) == 0) {
   1924                 g_loader_debug |= LOADER_WARN_BIT;
   1925                 g_loader_log_msgs |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
   1926             } else if (strncmp(env, "info", len) == 0) {
   1927                 g_loader_debug |= LOADER_INFO_BIT;
   1928                 g_loader_log_msgs |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
   1929             } else if (strncmp(env, "perf", len) == 0) {
   1930                 g_loader_debug |= LOADER_PERF_BIT;
   1931                 g_loader_log_msgs |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
   1932             } else if (strncmp(env, "error", len) == 0) {
   1933                 g_loader_debug |= LOADER_ERROR_BIT;
   1934                 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
   1935             } else if (strncmp(env, "debug", len) == 0) {
   1936                 g_loader_debug |= LOADER_DEBUG_BIT;
   1937                 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
   1938             }
   1939         }
   1940 
   1941         if (!p) break;
   1942 
   1943         env = p + 1;
   1944     }
   1945 
   1946     loader_free_getenv(orig, NULL);
   1947 }
   1948 
   1949 void loader_initialize(void) {
   1950     // initialize mutexs
   1951     loader_platform_thread_create_mutex(&loader_lock);
   1952     loader_platform_thread_create_mutex(&loader_json_lock);
   1953 
   1954     // initialize logging
   1955     loader_debug_init();
   1956 
   1957     // initial cJSON to use alloc callbacks
   1958     cJSON_Hooks alloc_fns = {
   1959         .malloc_fn = loader_instance_tls_heap_alloc, .free_fn = loader_instance_tls_heap_free,
   1960     };
   1961     cJSON_InitHooks(&alloc_fns);
   1962 }
   1963 
   1964 struct loader_manifest_files {
   1965     uint32_t count;
   1966     char **filename_list;
   1967 };
   1968 
   1969 void loader_release() {
   1970     // release mutexs
   1971     loader_platform_thread_delete_mutex(&loader_lock);
   1972     loader_platform_thread_delete_mutex(&loader_json_lock);
   1973 }
   1974 
   1975 // Get next file or dirname given a string list or registry key path
   1976 //
   1977 // \returns
   1978 // A pointer to first char in the next path.
   1979 // The next path (or NULL) in the list is returned in next_path.
   1980 // Note: input string is modified in some cases. PASS IN A COPY!
   1981 static char *loader_get_next_path(char *path) {
   1982     uint32_t len;
   1983     char *next;
   1984 
   1985     if (path == NULL) return NULL;
   1986     next = strchr(path, PATH_SEPARATOR);
   1987     if (next == NULL) {
   1988         len = (uint32_t)strlen(path);
   1989         next = path + len;
   1990     } else {
   1991         *next = '\0';
   1992         next++;
   1993     }
   1994 
   1995     return next;
   1996 }
   1997 
   1998 // Given a path which is absolute or relative, expand the path if relative or
   1999 // leave the path unmodified if absolute. The base path to prepend to relative
   2000 // paths is given in rel_base.
   2001 //
   2002 // @return - A string in out_fullpath of the full absolute path
   2003 static void loader_expand_path(const char *path, const char *rel_base, size_t out_size, char *out_fullpath) {
   2004     if (loader_platform_is_path_absolute(path)) {
   2005         // do not prepend a base to an absolute path
   2006         rel_base = "";
   2007     }
   2008 
   2009     loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
   2010 }
   2011 
   2012 // Given a filename (file)  and a list of paths (dir), try to find an existing
   2013 // file in the paths.  If filename already is a path then no searching in the given paths.
   2014 //
   2015 // @return - A string in out_fullpath of either the full path or file.
   2016 static void loader_get_fullpath(const char *file, const char *dirs, size_t out_size, char *out_fullpath) {
   2017     if (!loader_platform_is_path(file) && *dirs) {
   2018         char *dirs_copy, *dir, *next_dir;
   2019 
   2020         dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
   2021         strcpy(dirs_copy, dirs);
   2022 
   2023         // find if file exists after prepending paths in given list
   2024         for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); dir = next_dir) {
   2025             loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
   2026             if (loader_platform_file_exists(out_fullpath)) {
   2027                 return;
   2028             }
   2029         }
   2030     }
   2031 
   2032     (void)snprintf(out_fullpath, out_size, "%s", file);
   2033 }
   2034 
   2035 // Read a JSON file into a buffer.
   2036 //
   2037 // @return -  A pointer to a cJSON object representing the JSON parse tree.
   2038 //            This returned buffer should be freed by caller.
   2039 static VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
   2040     FILE *file = NULL;
   2041     char *json_buf;
   2042     size_t len;
   2043     VkResult res = VK_SUCCESS;
   2044 
   2045     if (NULL == json) {
   2046         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Received invalid JSON file");
   2047         res = VK_ERROR_INITIALIZATION_FAILED;
   2048         goto out;
   2049     }
   2050 
   2051     *json = NULL;
   2052 
   2053     file = fopen(filename, "rb");
   2054     if (!file) {
   2055         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Failed to open JSON file %s", filename);
   2056         res = VK_ERROR_INITIALIZATION_FAILED;
   2057         goto out;
   2058     }
   2059     fseek(file, 0, SEEK_END);
   2060     len = ftell(file);
   2061     fseek(file, 0, SEEK_SET);
   2062     json_buf = (char *)loader_stack_alloc(len + 1);
   2063     if (json_buf == NULL) {
   2064         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2065                    "loader_get_json: Failed to allocate space for "
   2066                    "JSON file %s buffer of length %d",
   2067                    filename, len);
   2068         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2069         goto out;
   2070     }
   2071     if (fread(json_buf, sizeof(char), len, file) != len) {
   2072         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Failed to read JSON file %s.", filename);
   2073         res = VK_ERROR_INITIALIZATION_FAILED;
   2074         goto out;
   2075     }
   2076     json_buf[len] = '\0';
   2077 
   2078     // Parse text from file
   2079     *json = cJSON_Parse(json_buf);
   2080     if (*json == NULL) {
   2081         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2082                    "loader_get_json: Failed to parse JSON file %s, "
   2083                    "this is usually because something ran out of "
   2084                    "memory.",
   2085                    filename);
   2086         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2087         goto out;
   2088     }
   2089 
   2090 out:
   2091     if (NULL != file) {
   2092         fclose(file);
   2093     }
   2094 
   2095     return res;
   2096 }
   2097 
   2098 // Do a deep copy of the loader_layer_properties structure.
   2099 VkResult loader_copy_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *dst,
   2100                                       struct loader_layer_properties *src) {
   2101     uint32_t cnt, i;
   2102     memcpy(dst, src, sizeof(*src));
   2103     dst->instance_extension_list.list = loader_instance_heap_alloc(
   2104         inst, sizeof(VkExtensionProperties) * src->instance_extension_list.count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   2105     if (NULL == dst->instance_extension_list.list) {
   2106         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2107                    "loader_copy_layer_properties: Failed to allocate space "
   2108                    "for instance extension list of size %d.",
   2109                    src->instance_extension_list.count);
   2110         return VK_ERROR_OUT_OF_HOST_MEMORY;
   2111     }
   2112     dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) * src->instance_extension_list.count;
   2113     memcpy(dst->instance_extension_list.list, src->instance_extension_list.list, dst->instance_extension_list.capacity);
   2114     dst->device_extension_list.list = loader_instance_heap_alloc(
   2115         inst, sizeof(struct loader_dev_ext_props) * src->device_extension_list.count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   2116     if (NULL == dst->device_extension_list.list) {
   2117         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2118                    "loader_copy_layer_properties: Failed to allocate space "
   2119                    "for device extension list of size %d.",
   2120                    src->device_extension_list.count);
   2121         return VK_ERROR_OUT_OF_HOST_MEMORY;
   2122     }
   2123     memset(dst->device_extension_list.list, 0, sizeof(struct loader_dev_ext_props) * src->device_extension_list.count);
   2124 
   2125     dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) * src->device_extension_list.count;
   2126     memcpy(dst->device_extension_list.list, src->device_extension_list.list, dst->device_extension_list.capacity);
   2127     if (src->device_extension_list.count > 0 && src->device_extension_list.list->entrypoint_count > 0) {
   2128         cnt = src->device_extension_list.list->entrypoint_count;
   2129         dst->device_extension_list.list->entrypoints =
   2130             loader_instance_heap_alloc(inst, sizeof(char *) * cnt, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   2131         if (NULL == dst->device_extension_list.list->entrypoints) {
   2132             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2133                        "loader_copy_layer_properties: Failed to allocate space "
   2134                        "for device extension entrypoint list of size %d.",
   2135                        cnt);
   2136             return VK_ERROR_OUT_OF_HOST_MEMORY;
   2137         }
   2138         memset(dst->device_extension_list.list->entrypoints, 0, sizeof(char *) * cnt);
   2139 
   2140         for (i = 0; i < cnt; i++) {
   2141             dst->device_extension_list.list->entrypoints[i] = loader_instance_heap_alloc(
   2142                 inst, strlen(src->device_extension_list.list->entrypoints[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   2143             if (NULL == dst->device_extension_list.list->entrypoints[i]) {
   2144                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2145                            "loader_copy_layer_properties: Failed to "
   2146                            "allocate space for device extension entrypoint "
   2147                            "%d name of length",
   2148                            i);
   2149                 return VK_ERROR_OUT_OF_HOST_MEMORY;
   2150             }
   2151             strcpy(dst->device_extension_list.list->entrypoints[i], src->device_extension_list.list->entrypoints[i]);
   2152         }
   2153     }
   2154 
   2155     return VK_SUCCESS;
   2156 }
   2157 
   2158 static bool loader_find_layer_name_list(const char *name, const struct loader_layer_list *layer_list) {
   2159     if (NULL == layer_list) {
   2160         return false;
   2161     }
   2162     for (uint32_t j = 0; j < layer_list->count; j++) {
   2163         if (!strcmp(name, layer_list->list[j].info.layerName)) {
   2164             return true;
   2165         }
   2166     }
   2167     return false;
   2168 }
   2169 
   2170 bool loader_find_layer_name_array(const char *name, uint32_t layer_count, const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]) {
   2171     if (!layer_list) return false;
   2172     for (uint32_t j = 0; j < layer_count; j++)
   2173         if (!strcmp(name, layer_list[j])) return true;
   2174     return false;
   2175 }
   2176 
   2177 const char *std_validation_str = "VK_LAYER_LUNARG_standard_validation";
   2178 
   2179 // Adds the legacy VK_LAYER_LUNARG_standard_validation as a meta-layer if it
   2180 // fails to find it in the list already.  This is usually an indication that a
   2181 // newer loader is being used with an older layer set.
   2182 static bool loader_add_legacy_std_val_layer(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list) {
   2183     uint32_t i;
   2184     bool success = true;
   2185     struct loader_layer_properties *props = loader_get_next_layer_property(inst, layer_instance_list);
   2186     const char std_validation_names[6][VK_MAX_EXTENSION_NAME_SIZE] = {
   2187         "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker",
   2188         "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects"};
   2189     uint32_t layer_count = sizeof(std_validation_names) / sizeof(std_validation_names[0]);
   2190 
   2191     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   2192                "Adding VK_LAYER_LUNARG_standard_validation using the loader legacy path.  This is"
   2193                " not an error.");
   2194 
   2195     if (NULL == props) {
   2196         goto out;
   2197     }
   2198 
   2199     memset(props, 0, sizeof(struct loader_layer_properties));
   2200     props->type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER | VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER | VK_LAYER_TYPE_FLAG_META_LAYER;
   2201     strncpy(props->info.description, "LunarG Standard Validation Layer", sizeof(props->info.description));
   2202     props->info.implementationVersion = 1;
   2203     strncpy(props->info.layerName, std_validation_str, sizeof(props->info.layerName));
   2204     props->info.specVersion = VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION);
   2205 
   2206     props->component_layer_names =
   2207         loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * layer_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   2208     if (NULL == props->component_layer_names) {
   2209         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2210                    "Failed to allocate space for legacy VK_LAYER_LUNARG_standard_validation"
   2211                    " meta-layer component_layers information.");
   2212         success = false;
   2213         goto out;
   2214     }
   2215     for (i = 0; i < layer_count; i++) {
   2216         strncpy(props->component_layer_names[i], std_validation_names[i], MAX_STRING_SIZE - 1);
   2217         props->component_layer_names[i][MAX_STRING_SIZE - 1] = '\0';
   2218     }
   2219 
   2220 out:
   2221 
   2222     if (!success && NULL != props && NULL != props->component_layer_names) {
   2223         loader_instance_heap_free(inst, props->component_layer_names);
   2224         props->component_layer_names = NULL;
   2225     }
   2226 
   2227     return success;
   2228 }
   2229 
   2230 // Verify that all component layers in a meta-layer are valid.
   2231 static bool verify_meta_layer_comp_layers(const struct loader_instance *inst, struct loader_layer_properties *prop,
   2232                                           struct loader_layer_list *instance_layers) {
   2233     bool success = true;
   2234     const uint32_t expected_major = VK_VERSION_MAJOR(prop->info.specVersion);
   2235     const uint32_t expected_minor = VK_VERSION_MINOR(prop->info.specVersion);
   2236 
   2237     for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
   2238         if (!loader_find_layer_name_list(prop->component_layer_names[comp_layer], instance_layers)) {
   2239             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2240                        "Meta-layer %s can't find component layer %s at index %d."
   2241                        "  Skipping this layer.",
   2242                        prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer);
   2243             success = false;
   2244             break;
   2245         } else {
   2246             struct loader_layer_properties *comp_prop =
   2247                 loader_get_layer_property(prop->component_layer_names[comp_layer], instance_layers);
   2248             if (comp_prop == NULL) {
   2249                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2250                            "Meta-layer %s can't find property for component layer %s at index %d."
   2251                            "  Skipping this layer.",
   2252                            prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer);
   2253                 success = false;
   2254                 break;
   2255             }
   2256 
   2257             // Check the version of each layer, they need to at least match MAJOR and MINOR
   2258             uint32_t cur_major = VK_VERSION_MAJOR(comp_prop->info.specVersion);
   2259             uint32_t cur_minor = VK_VERSION_MINOR(comp_prop->info.specVersion);
   2260             if (cur_major != expected_major || cur_minor != expected_minor) {
   2261                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2262                            "Meta-layer uses API version %d.%d, but component layer %d uses API "
   2263                            "version %d.%d.  Skipping this layer.",
   2264                            expected_major, expected_minor, comp_layer, cur_major, cur_minor);
   2265                 success = false;
   2266                 break;
   2267             }
   2268 
   2269             // Make sure the layer isn't using it's own name
   2270             if (!strcmp(prop->info.layerName, prop->component_layer_names[comp_layer])) {
   2271                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2272                            "Meta-layer %s lists itself in its component layer list at index %d."
   2273                            "  Skipping this layer.",
   2274                            prop->info.layerName, comp_layer);
   2275                 success = false;
   2276                 break;
   2277             }
   2278             if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
   2279                 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   2280                            "verify_meta_layer_comp_layers: Adding meta-layer %s which also contains meta-layer %s",
   2281                            prop->info.layerName, comp_prop->info.layerName);
   2282 
   2283                 // Make sure if the layer is using a meta-layer in its component list that we also verify that.
   2284                 if (!verify_meta_layer_comp_layers(inst, comp_prop, instance_layers)) {
   2285                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2286                                "Meta-layer %s component layer %s can not find all component layers."
   2287                                "  Skipping this layer.",
   2288                                prop->info.layerName, prop->component_layer_names[comp_layer]);
   2289                     success = false;
   2290                     break;
   2291                 }
   2292             }
   2293 
   2294             // Add any instance and device extensions from component layers to this layer
   2295             // list, so that anyone querying extensions will only need to look at the meta-layer
   2296             for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) {
   2297                 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Meta-layer %s component layer %s adding instance extension %s",
   2298                            prop->info.layerName, prop->component_layer_names[comp_layer],
   2299                            comp_prop->instance_extension_list.list[ext].extensionName);
   2300                 if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) {
   2301                     loader_add_to_ext_list(inst, &prop->instance_extension_list, 1, &comp_prop->instance_extension_list.list[ext]);
   2302                 }
   2303             }
   2304 
   2305             for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) {
   2306                 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Meta-layer %s component layer %s adding device extension %s",
   2307                            prop->info.layerName, prop->component_layer_names[comp_layer],
   2308                            comp_prop->device_extension_list.list[ext].props.extensionName);
   2309                 if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) {
   2310                     loader_add_to_dev_ext_list(inst, &prop->device_extension_list,
   2311                                                &comp_prop->device_extension_list.list[ext].props, 0, NULL);
   2312                 }
   2313             }
   2314         }
   2315     }
   2316     if (success) {
   2317         loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Meta-layer %s all %d component layers appear to be valid.",
   2318                    prop->info.layerName, prop->num_component_layers);
   2319     }
   2320     return success;
   2321 }
   2322 
   2323 // Verify that all meta-layers in a layer list are valid.
   2324 static void verify_all_meta_layers(const struct loader_instance *inst, struct loader_layer_list *instance_layers) {
   2325     for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
   2326         struct loader_layer_properties *prop = &instance_layers->list[i];
   2327 
   2328         // If this is a meta-layer, make sure it is valid
   2329         if ((prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) && !verify_meta_layer_comp_layers(inst, prop, instance_layers)) {
   2330             loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   2331                        "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName);
   2332 
   2333             // Delete the component layers
   2334             loader_instance_heap_free(inst, prop->component_layer_names);
   2335 
   2336             // Remove the current invalid meta-layer from the layer list.  Use memmove since we are
   2337             // overlapping the source and destination addresses.
   2338             memmove(&instance_layers->list[i], &instance_layers->list[i + 1],
   2339                     sizeof(struct loader_layer_properties) * (instance_layers->count - 1 - i));
   2340 
   2341             // Decrement the count (because we now have one less) and decrement the loop index since we need to
   2342             // re-check this index.
   2343             instance_layers->count--;
   2344             i--;
   2345         }
   2346     }
   2347 }
   2348 
   2349 // This structure is used to store the json file version
   2350 // in a more manageable way.
   2351 typedef struct {
   2352     uint16_t major;
   2353     uint16_t minor;
   2354     uint16_t patch;
   2355 } layer_json_version;
   2356 
   2357 static inline bool is_valid_layer_json_version(const layer_json_version *layer_json) {
   2358     // Supported versions are: 1.0.0, 1.0.1, 1.1.0, 1.1.1, and 1.1.2.
   2359     if ((layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) ||
   2360         (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
   2361         return true;
   2362     }
   2363     return false;
   2364 }
   2365 
   2366 static inline bool layer_json_supports_layers_tag(const layer_json_version *layer_json) {
   2367     // Supported versions started in 1.0.1, so anything newer
   2368     if ((layer_json->major > 1 || layer_json->minor > 0 || layer_json->patch > 1)) {
   2369         return true;
   2370     }
   2371     return false;
   2372 }
   2373 
   2374 static inline bool layer_json_supports_pre_instance_tag(const layer_json_version *layer_json) {
   2375     // Supported versions started in 1.1.2, so anything newer
   2376     return layer_json->major > 1 || layer_json->minor > 1 || (layer_json->minor == 1 && layer_json->patch > 1);
   2377 }
   2378 
   2379 static VkResult loader_read_json_layer(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
   2380                                        cJSON *layer_node, layer_json_version version, cJSON *item, cJSON *disable_environment,
   2381                                        bool is_implicit, char *filename) {
   2382     char *temp;
   2383     char *name, *type, *library_path_str, *api_version;
   2384     char *implementation_version, *description;
   2385     cJSON *ext_item, *library_path, *component_layers;
   2386     VkExtensionProperties ext_prop;
   2387     VkResult result = VK_ERROR_INITIALIZATION_FAILED;
   2388     struct loader_layer_properties *props = NULL;
   2389     int i, j;
   2390 
   2391 // The following are required in the "layer" object:
   2392 // (required) "name"
   2393 // (required) "type"
   2394 // (required) "library_path"
   2395 // (required) "api_version"
   2396 // (required) "implementation_version"
   2397 // (required) "description"
   2398 // (required for implicit layers) "disable_environment"
   2399 #define GET_JSON_OBJECT(node, var)                                         \
   2400     {                                                                      \
   2401         var = cJSON_GetObjectItem(node, #var);                             \
   2402         if (var == NULL) {                                                 \
   2403             layer_node = layer_node->next;                                 \
   2404             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,           \
   2405                        "Didn't find required layer object %s in manifest " \
   2406                        "JSON file, skipping this layer",                   \
   2407                        #var);                                              \
   2408             goto out;                                                      \
   2409         }                                                                  \
   2410     }
   2411 #define GET_JSON_ITEM(node, var)                                               \
   2412     {                                                                          \
   2413         item = cJSON_GetObjectItem(node, #var);                                \
   2414         if (item == NULL) {                                                    \
   2415             layer_node = layer_node->next;                                     \
   2416             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,               \
   2417                        "Didn't find required layer value %s in manifest JSON " \
   2418                        "file, skipping this layer",                            \
   2419                        #var);                                                  \
   2420             goto out;                                                          \
   2421         }                                                                      \
   2422         temp = cJSON_Print(item);                                              \
   2423         if (temp == NULL) {                                                    \
   2424             layer_node = layer_node->next;                                     \
   2425             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,               \
   2426                        "Problem accessing layer value %s in manifest JSON "    \
   2427                        "file, skipping this layer",                            \
   2428                        #var);                                                  \
   2429             result = VK_ERROR_OUT_OF_HOST_MEMORY;                              \
   2430             goto out;                                                          \
   2431         }                                                                      \
   2432         temp[strlen(temp) - 1] = '\0';                                         \
   2433         var = loader_stack_alloc(strlen(temp) + 1);                            \
   2434         strcpy(var, &temp[1]);                                                 \
   2435         cJSON_Free(temp);                                                      \
   2436     }
   2437     GET_JSON_ITEM(layer_node, name)
   2438     GET_JSON_ITEM(layer_node, type)
   2439     GET_JSON_ITEM(layer_node, api_version)
   2440     GET_JSON_ITEM(layer_node, implementation_version)
   2441     GET_JSON_ITEM(layer_node, description)
   2442 
   2443     // Add list entry
   2444     if (!strcmp(type, "DEVICE")) {
   2445         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Device layers are deprecated skipping this layer");
   2446         layer_node = layer_node->next;
   2447         goto out;
   2448     }
   2449 
   2450     // Allow either GLOBAL or INSTANCE type interchangeably to handle
   2451     // layers that must work with older loaders
   2452     if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
   2453         if (layer_instance_list == NULL) {
   2454             layer_node = layer_node->next;
   2455             goto out;
   2456         }
   2457         props = loader_get_next_layer_property(inst, layer_instance_list);
   2458         if (NULL == props) {
   2459             // Error already triggered in loader_get_next_layer_property.
   2460             result = VK_ERROR_OUT_OF_HOST_MEMORY;
   2461             goto out;
   2462         }
   2463         props->type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER;
   2464         if (!is_implicit) {
   2465             props->type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER;
   2466         }
   2467     } else {
   2468         layer_node = layer_node->next;
   2469         goto out;
   2470     }
   2471 
   2472     // Library path no longer required unless component_layers is also not defined
   2473     library_path = cJSON_GetObjectItem(layer_node, "library_path");
   2474     component_layers = cJSON_GetObjectItem(layer_node, "component_layers");
   2475     if (NULL != library_path) {
   2476         if (NULL != component_layers) {
   2477             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2478                        "Indicating meta-layer-specific component_layers, but also "
   2479                        "defining layer library path.  Both are not compatible, so "
   2480                        "skipping this layer");
   2481             goto out;
   2482         }
   2483         props->num_component_layers = 0;
   2484         props->component_layer_names = NULL;
   2485 
   2486         temp = cJSON_Print(library_path);
   2487         if (NULL == temp) {
   2488             layer_node = layer_node->next;
   2489             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2490                        "Problem accessing layer value library_path in manifest JSON "
   2491                        "file, skipping this layer");
   2492             result = VK_ERROR_OUT_OF_HOST_MEMORY;
   2493             goto out;
   2494         }
   2495         temp[strlen(temp) - 1] = '\0';
   2496         library_path_str = loader_stack_alloc(strlen(temp) + 1);
   2497         strcpy(library_path_str, &temp[1]);
   2498         cJSON_Free(temp);
   2499 
   2500         char *fullpath = props->lib_name;
   2501         char *rel_base;
   2502         if (NULL != library_path_str) {
   2503             if (loader_platform_is_path(library_path_str)) {
   2504                 // A relative or absolute path
   2505                 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
   2506                 strcpy(name_copy, filename);
   2507                 rel_base = loader_platform_dirname(name_copy);
   2508                 loader_expand_path(library_path_str, rel_base, MAX_STRING_SIZE, fullpath);
   2509             } else {
   2510                 // A filename which is assumed in a system directory
   2511                 loader_get_fullpath(library_path_str, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
   2512             }
   2513         }
   2514     } else if (NULL != component_layers) {
   2515         if (version.major == 1 && (version.minor < 1 || version.patch < 1)) {
   2516             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2517                        "Indicating meta-layer-specific component_layers, but using older "
   2518                        "JSON file version.");
   2519         }
   2520         int count = cJSON_GetArraySize(component_layers);
   2521         props->num_component_layers = count;
   2522 
   2523         // Allocate buffer for layer names
   2524         props->component_layer_names =
   2525             loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   2526         if (NULL == props->component_layer_names) {
   2527             result = VK_ERROR_OUT_OF_HOST_MEMORY;
   2528             goto out;
   2529         }
   2530 
   2531         // Copy the component layers into the array
   2532         for (i = 0; i < count; i++) {
   2533             cJSON *comp_layer = cJSON_GetArrayItem(component_layers, i);
   2534             if (NULL != comp_layer) {
   2535                 temp = cJSON_Print(comp_layer);
   2536                 if (NULL == temp) {
   2537                     result = VK_ERROR_OUT_OF_HOST_MEMORY;
   2538                     goto out;
   2539                 }
   2540                 temp[strlen(temp) - 1] = '\0';
   2541                 strncpy(props->component_layer_names[i], temp + 1, MAX_STRING_SIZE - 1);
   2542                 props->component_layer_names[i][MAX_STRING_SIZE - 1] = '\0';
   2543                 cJSON_Free(temp);
   2544             }
   2545         }
   2546 
   2547         // This is now, officially, a meta-layer
   2548         props->type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
   2549         loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Encountered meta-layer %s", name);
   2550 
   2551         // Make sure we set up other things so we head down the correct branches below
   2552         library_path_str = NULL;
   2553     } else {
   2554         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2555                    "Layer missing both library_path and component_layers fields.  One or the "
   2556                    "other MUST be defined.  Skipping this layer");
   2557         goto out;
   2558     }
   2559 
   2560     if (is_implicit) {
   2561         GET_JSON_OBJECT(layer_node, disable_environment)
   2562     }
   2563 #undef GET_JSON_ITEM
   2564 #undef GET_JSON_OBJECT
   2565 
   2566     strncpy(props->info.layerName, name, sizeof(props->info.layerName));
   2567     props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
   2568     props->info.specVersion = loader_make_version(api_version);
   2569     props->info.implementationVersion = atoi(implementation_version);
   2570     strncpy((char *)props->info.description, description, sizeof(props->info.description));
   2571     props->info.description[sizeof(props->info.description) - 1] = '\0';
   2572     if (is_implicit) {
   2573         if (!disable_environment || !disable_environment->child) {
   2574             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2575                        "Didn't find required layer child value disable_environment"
   2576                        "in manifest JSON file, skipping this layer");
   2577             layer_node = layer_node->next;
   2578             goto out;
   2579         }
   2580         strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof(props->disable_env_var.name));
   2581         props->disable_env_var.name[sizeof(props->disable_env_var.name) - 1] = '\0';
   2582         strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof(props->disable_env_var.value));
   2583         props->disable_env_var.value[sizeof(props->disable_env_var.value) - 1] = '\0';
   2584     }
   2585 
   2586 // Now get all optional items and objects and put in list:
   2587 // functions
   2588 // instance_extensions
   2589 // device_extensions
   2590 // enable_environment (implicit layers only)
   2591 #define GET_JSON_OBJECT(node, var) \
   2592     { var = cJSON_GetObjectItem(node, #var); }
   2593 #define GET_JSON_ITEM(node, var)                            \
   2594     {                                                       \
   2595         item = cJSON_GetObjectItem(node, #var);             \
   2596         if (item != NULL) {                                 \
   2597             temp = cJSON_Print(item);                       \
   2598             if (temp != NULL) {                             \
   2599                 temp[strlen(temp) - 1] = '\0';              \
   2600                 var = loader_stack_alloc(strlen(temp) + 1); \
   2601                 strcpy(var, &temp[1]);                      \
   2602                 cJSON_Free(temp);                           \
   2603             } else {                                        \
   2604                 result = VK_ERROR_OUT_OF_HOST_MEMORY;       \
   2605                 goto out;                                   \
   2606             }                                               \
   2607         }                                                   \
   2608     }
   2609 
   2610     cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
   2611     cJSON *entrypoints = NULL;
   2612     char *vkGetInstanceProcAddr = NULL;
   2613     char *vkGetDeviceProcAddr = NULL;
   2614     char *vkNegotiateLoaderLayerInterfaceVersion = NULL;
   2615     char *spec_version = NULL;
   2616     char **entry_array = NULL;
   2617 
   2618     // Layer interface functions
   2619     //    vkGetInstanceProcAddr
   2620     //    vkGetDeviceProcAddr
   2621     //    vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
   2622     GET_JSON_OBJECT(layer_node, functions)
   2623     if (functions != NULL) {
   2624         if (version.major > 1 || version.minor >= 1) {
   2625             GET_JSON_ITEM(functions, vkNegotiateLoaderLayerInterfaceVersion)
   2626             if (vkNegotiateLoaderLayerInterfaceVersion != NULL)
   2627                 strncpy(props->functions.str_negotiate_interface, vkNegotiateLoaderLayerInterfaceVersion,
   2628                         sizeof(props->functions.str_negotiate_interface));
   2629             props->functions.str_negotiate_interface[sizeof(props->functions.str_negotiate_interface) - 1] = '\0';
   2630         } else {
   2631             props->functions.str_negotiate_interface[0] = '\0';
   2632         }
   2633         GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
   2634         GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
   2635         if (vkGetInstanceProcAddr != NULL) {
   2636             strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof(props->functions.str_gipa));
   2637             if (version.major > 1 || version.minor >= 1) {
   2638                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2639                            "Indicating layer-specific vkGetInstanceProcAddr "
   2640                            "function is deprecated starting with JSON file "
   2641                            "version 1.1.0.  Instead, use the new "
   2642                            "vkNegotiateLayerInterfaceVersion function to "
   2643                            "return the GetInstanceProcAddr function for this"
   2644                            "layer");
   2645             }
   2646         }
   2647         props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = '\0';
   2648         if (vkGetDeviceProcAddr != NULL) {
   2649             strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof(props->functions.str_gdpa));
   2650             if (version.major > 1 || version.minor >= 1) {
   2651                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2652                            "Indicating layer-specific vkGetDeviceProcAddr "
   2653                            "function is deprecated starting with JSON file "
   2654                            "version 1.1.0.  Instead, use the new "
   2655                            "vkNegotiateLayerInterfaceVersion function to "
   2656                            "return the GetDeviceProcAddr function for this"
   2657                            "layer");
   2658             }
   2659         }
   2660         props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = '\0';
   2661     }
   2662 
   2663     // instance_extensions
   2664     //   array of {
   2665     //     name
   2666     //     spec_version
   2667     //   }
   2668     GET_JSON_OBJECT(layer_node, instance_extensions)
   2669     if (instance_extensions != NULL) {
   2670         int count = cJSON_GetArraySize(instance_extensions);
   2671         for (i = 0; i < count; i++) {
   2672             ext_item = cJSON_GetArrayItem(instance_extensions, i);
   2673             GET_JSON_ITEM(ext_item, name)
   2674             if (name != NULL) {
   2675                 strncpy(ext_prop.extensionName, name, sizeof(ext_prop.extensionName));
   2676                 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = '\0';
   2677             }
   2678             GET_JSON_ITEM(ext_item, spec_version)
   2679             if (NULL != spec_version) {
   2680                 ext_prop.specVersion = atoi(spec_version);
   2681             } else {
   2682                 ext_prop.specVersion = 0;
   2683             }
   2684             bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop);
   2685             if (!ext_unsupported) {
   2686                 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
   2687             }
   2688         }
   2689     }
   2690 
   2691     // device_extensions
   2692     //   array of {
   2693     //     name
   2694     //     spec_version
   2695     //     entrypoints
   2696     //   }
   2697     GET_JSON_OBJECT(layer_node, device_extensions)
   2698     if (device_extensions != NULL) {
   2699         int count = cJSON_GetArraySize(device_extensions);
   2700         for (i = 0; i < count; i++) {
   2701             ext_item = cJSON_GetArrayItem(device_extensions, i);
   2702             GET_JSON_ITEM(ext_item, name)
   2703             GET_JSON_ITEM(ext_item, spec_version)
   2704             if (name != NULL) {
   2705                 strncpy(ext_prop.extensionName, name, sizeof(ext_prop.extensionName));
   2706                 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = '\0';
   2707             }
   2708             if (NULL != spec_version) {
   2709                 ext_prop.specVersion = atoi(spec_version);
   2710             } else {
   2711                 ext_prop.specVersion = 0;
   2712             }
   2713             // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
   2714             GET_JSON_OBJECT(ext_item, entrypoints)
   2715             int entry_count;
   2716             if (entrypoints == NULL) {
   2717                 loader_add_to_dev_ext_list(inst, &props->device_extension_list, &ext_prop, 0, NULL);
   2718                 continue;
   2719             }
   2720             entry_count = cJSON_GetArraySize(entrypoints);
   2721             if (entry_count) {
   2722                 entry_array = (char **)loader_stack_alloc(sizeof(char *) * entry_count);
   2723             }
   2724             for (j = 0; j < entry_count; j++) {
   2725                 ext_item = cJSON_GetArrayItem(entrypoints, j);
   2726                 if (ext_item != NULL) {
   2727                     temp = cJSON_Print(ext_item);
   2728                     if (NULL == temp) {
   2729                         entry_array[j] = NULL;
   2730                         result = VK_ERROR_OUT_OF_HOST_MEMORY;
   2731                         goto out;
   2732                     }
   2733                     temp[strlen(temp) - 1] = '\0';
   2734                     entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
   2735                     strcpy(entry_array[j], &temp[1]);
   2736                     cJSON_Free(temp);
   2737                 }
   2738             }
   2739             loader_add_to_dev_ext_list(inst, &props->device_extension_list, &ext_prop, entry_count, entry_array);
   2740         }
   2741     }
   2742     if (is_implicit) {
   2743         GET_JSON_OBJECT(layer_node, enable_environment)
   2744 
   2745         // enable_environment is optional
   2746         if (enable_environment) {
   2747             strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof(props->enable_env_var.name));
   2748             props->enable_env_var.name[sizeof(props->enable_env_var.name) - 1] = '\0';
   2749             strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof(props->enable_env_var.value));
   2750             props->enable_env_var.value[sizeof(props->enable_env_var.value) - 1] = '\0';
   2751         }
   2752     }
   2753 
   2754     // Read in the pre-instance stuff
   2755     cJSON *pre_instance = cJSON_GetObjectItem(layer_node, "pre_instance_functions");
   2756     if (pre_instance) {
   2757         if (!layer_json_supports_pre_instance_tag(&version)) {
   2758             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2759                        "Found pre_instance_functions section in layer from \"%s\". "
   2760                        "This section is only valid in manifest version 1.1.2 or later. The section will be ignored",
   2761                        filename);
   2762         } else if (!is_implicit) {
   2763             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2764                        "Found pre_instance_functions section in explicit layer from "
   2765                        "\"%s\". This section is only valid in implicit layers. The section will be ignored",
   2766                        filename);
   2767         } else {
   2768             cJSON *inst_ext_json = cJSON_GetObjectItem(pre_instance, "vkEnumerateInstanceExtensionProperties");
   2769             if (inst_ext_json) {
   2770                 char *inst_ext_name = cJSON_Print(inst_ext_json);
   2771                 size_t len = strlen(inst_ext_name) >= MAX_STRING_SIZE ? MAX_STRING_SIZE - 3 : strlen(inst_ext_name) - 2;
   2772                 strncpy(props->pre_instance_functions.enumerate_instance_extension_properties, inst_ext_name + 1, len);
   2773                 props->pre_instance_functions.enumerate_instance_extension_properties[len] = '\0';
   2774                 cJSON_Free(inst_ext_name);
   2775             }
   2776 
   2777             cJSON *inst_layer_json = cJSON_GetObjectItem(pre_instance, "vkEnumerateInstanceLayerProperties");
   2778             if (inst_layer_json) {
   2779                 char *inst_layer_name = cJSON_Print(inst_layer_json);
   2780                 size_t len = strlen(inst_layer_name) >= MAX_STRING_SIZE ? MAX_STRING_SIZE - 3 : strlen(inst_layer_name) - 2;
   2781                 strncpy(props->pre_instance_functions.enumerate_instance_layer_properties, inst_layer_name + 1, len);
   2782                 props->pre_instance_functions.enumerate_instance_layer_properties[len] = '\0';
   2783                 cJSON_Free(inst_layer_name);
   2784             }
   2785         }
   2786     }
   2787 
   2788     result = VK_SUCCESS;
   2789 
   2790 out:
   2791 
   2792 #undef GET_JSON_ITEM
   2793 #undef GET_JSON_OBJECT
   2794 
   2795     if (VK_SUCCESS != result && NULL != props) {
   2796         props->num_component_layers = 0;
   2797         if (NULL != props->component_layer_names) {
   2798             loader_instance_heap_free(inst, props->component_layer_names);
   2799         }
   2800         props->component_layer_names = NULL;
   2801     }
   2802 
   2803     return result;
   2804 }
   2805 
   2806 // Given a cJSON struct (json) of the top level JSON object from layer manifest
   2807 // file, add entry to the layer_list. Fill out the layer_properties in this list
   2808 // entry from the input cJSON object.
   2809 //
   2810 // \returns
   2811 // void
   2812 // layer_list has a new entry and initialized accordingly.
   2813 // If the json input object does not have all the required fields no entry
   2814 // is added to the list.
   2815 static VkResult loader_add_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
   2816                                             cJSON *json, bool is_implicit, char *filename) {
   2817     // The following Fields in layer manifest file that are required:
   2818     //   - "file_format_version"
   2819     //   - If more than one "layer" object are used, then the "layers" array is
   2820     //     required
   2821     VkResult result = VK_ERROR_INITIALIZATION_FAILED;
   2822     cJSON *item, *layers_node, *layer_node;
   2823     layer_json_version json_version = {0, 0, 0};
   2824     char *vers_tok;
   2825     cJSON *disable_environment = NULL;
   2826     item = cJSON_GetObjectItem(json, "file_format_version");
   2827     if (item == NULL) {
   2828         goto out;
   2829     }
   2830     char *file_vers = cJSON_PrintUnformatted(item);
   2831     if (NULL == file_vers) {
   2832         goto out;
   2833     }
   2834     loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found manifest file %s, version %s", filename, file_vers);
   2835     // Get the major/minor/and patch as integers for easier comparison
   2836     vers_tok = strtok(file_vers, ".\"\n\r");
   2837     if (NULL != vers_tok) {
   2838         json_version.major = (uint16_t)atoi(vers_tok);
   2839         vers_tok = strtok(NULL, ".\"\n\r");
   2840         if (NULL != vers_tok) {
   2841             json_version.minor = (uint16_t)atoi(vers_tok);
   2842             vers_tok = strtok(NULL, ".\"\n\r");
   2843             if (NULL != vers_tok) {
   2844                 json_version.patch = (uint16_t)atoi(vers_tok);
   2845             }
   2846         }
   2847     }
   2848 
   2849     if (!is_valid_layer_json_version(&json_version)) {
   2850         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2851                    "loader_add_layer_properties: %s invalid layer "
   2852                    "manifest file version %d.%d.%d.  May cause errors.",
   2853                    filename, json_version.major, json_version.minor, json_version.patch);
   2854     }
   2855     cJSON_Free(file_vers);
   2856 
   2857     // If "layers" is present, read in the array of layer objects
   2858     layers_node = cJSON_GetObjectItem(json, "layers");
   2859     if (layers_node != NULL) {
   2860         int numItems = cJSON_GetArraySize(layers_node);
   2861         if (!layer_json_supports_layers_tag(&json_version)) {
   2862             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2863                        "loader_add_layer_properties: \'layers\' tag not "
   2864                        "supported until file version 1.0.1, but %s is "
   2865                        "reporting version %s",
   2866                        filename, file_vers);
   2867         }
   2868         for (int curLayer = 0; curLayer < numItems; curLayer++) {
   2869             layer_node = cJSON_GetArrayItem(layers_node, curLayer);
   2870             if (layer_node == NULL) {
   2871                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2872                            "loader_add_layer_properties: Can not find "
   2873                            "\'layers\' array element %d object in manifest "
   2874                            "JSON file %s.  Skipping this file",
   2875                            curLayer, filename);
   2876                 goto out;
   2877             }
   2878             result = loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment,
   2879                                             is_implicit, filename);
   2880         }
   2881     } else {
   2882         // Otherwise, try to read in individual layers
   2883         layer_node = cJSON_GetObjectItem(json, "layer");
   2884         if (layer_node == NULL) {
   2885             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2886                        "loader_add_layer_properties: Can not find \'layer\' "
   2887                        "object in manifest JSON file %s.  Skipping this file.",
   2888                        filename);
   2889             goto out;
   2890         }
   2891         // Loop through all "layer" objects in the file to get a count of them
   2892         // first.
   2893         uint16_t layer_count = 0;
   2894         cJSON *tempNode = layer_node;
   2895         do {
   2896             tempNode = tempNode->next;
   2897             layer_count++;
   2898         } while (tempNode != NULL);
   2899 
   2900         // Throw a warning if we encounter multiple "layer" objects in file
   2901         // versions newer than 1.0.0.  Having multiple objects with the same
   2902         // name at the same level is actually a JSON standard violation.
   2903         if (layer_count > 1 && layer_json_supports_layers_tag(&json_version)) {
   2904             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2905                        "loader_add_layer_properties: Multiple \'layer\' nodes"
   2906                        " are deprecated starting in file version \"1.0.1\".  "
   2907                        "Please use \'layers\' : [] array instead in %s.",
   2908                        filename);
   2909         } else {
   2910             do {
   2911                 result = loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment,
   2912                                                 is_implicit, filename);
   2913                 layer_node = layer_node->next;
   2914             } while (layer_node != NULL);
   2915         }
   2916     }
   2917 
   2918 out:
   2919 
   2920     return result;
   2921 }
   2922 
   2923 // Find the Vulkan library manifest files.
   2924 //
   2925 // This function scans the "location" or "env_override" directories/files
   2926 // for a list of JSON manifest files.  If env_override is non-NULL
   2927 // and has a valid value. Then the location is ignored.  Otherwise
   2928 // location is used to look for manifest files. The location
   2929 // is interpreted as  Registry path on Windows and a directory path(s)
   2930 // on Linux. "home_location" is an additional directory in the users home
   2931 // directory to look at. It is expanded into the dir path
   2932 // $XDG_DATA_HOME/home_location or $HOME/.local/share/home_location depending
   2933 // on environment variables. This "home_location" is only used on Linux.
   2934 //
   2935 // \returns
   2936 // VKResult
   2937 // A string list of manifest files to be opened in out_files param.
   2938 // List has a pointer to string for each manifest filename.
   2939 // When done using the list in out_files, pointers should be freed.
   2940 // Location or override  string lists can be either files or directories as
   2941 // follows:
   2942 //            | location | override
   2943 // --------------------------------
   2944 // Win ICD    | files    | files
   2945 // Win Layer  | files    | dirs
   2946 // Linux ICD  | dirs     | files
   2947 // Linux Layer| dirs     | dirs
   2948 static VkResult loader_get_manifest_files(const struct loader_instance *inst, const char *env_override, const char *source_override,
   2949                                           bool is_layer, bool warn_if_not_present, const char *location,
   2950                                           const char *relative_location, struct loader_manifest_files *out_files) {
   2951     const char *override = NULL;
   2952     char *override_getenv = NULL;
   2953     char *loc, *orig_loc = NULL;
   2954     char *reg = NULL;
   2955     char *file, *next_file, *name;
   2956     size_t alloced_count = 64;
   2957     char full_path[2048];
   2958     DIR *sysdir = NULL;
   2959     bool list_is_dirs = false;
   2960     struct dirent *dent;
   2961     VkResult res = VK_SUCCESS;
   2962 
   2963     out_files->count = 0;
   2964     out_files->filename_list = NULL;
   2965 
   2966     if (source_override != NULL) {
   2967         override = source_override;
   2968     } else if (env_override != NULL) {
   2969 #if !defined(_WIN32)
   2970         if (geteuid() != getuid() || getegid() != getgid()) {
   2971             // Don't allow setuid apps to use the env var:
   2972             env_override = NULL;
   2973         }
   2974 #endif
   2975         if (env_override != NULL) {
   2976             override = override_getenv = loader_secure_getenv(env_override, inst);
   2977         }
   2978     }
   2979 
   2980 #if !defined(_WIN32)
   2981     if (relative_location == NULL) {
   2982 #else
   2983     relative_location = NULL;
   2984     if (location == NULL) {
   2985 #endif
   2986         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2987                    "loader_get_manifest_files: Can not get manifest files with "
   2988                    "NULL location, env_override=%s",
   2989                    (env_override != NULL) ? env_override : "");
   2990         res = VK_ERROR_INITIALIZATION_FAILED;
   2991         goto out;
   2992     }
   2993 
   2994 #if defined(_WIN32)
   2995     list_is_dirs = (is_layer && override != NULL) ? true : false;
   2996 #else
   2997     list_is_dirs = (override == NULL || is_layer) ? true : false;
   2998 #endif
   2999     // Make a copy of the input we are using so it is not modified
   3000     // Also handle getting the location(s) from registry on Windows
   3001     if (override == NULL) {
   3002         size_t loc_size = 0;
   3003 #if !defined(_WIN32)
   3004         const char *xdgconfdirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
   3005         const char *xdgdatadirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
   3006         if (xdgconfdirs == NULL || xdgconfdirs[0] == '\0') xdgconfdirs = FALLBACK_CONFIG_DIRS;
   3007         if (xdgdatadirs == NULL || xdgdatadirs[0] == '\0') xdgdatadirs = FALLBACK_DATA_DIRS;
   3008         const size_t rel_size = strlen(relative_location);
   3009         // Leave space for trailing separators
   3010         loc_size += strlen(xdgconfdirs) + strlen(xdgdatadirs) + 2 * rel_size + 2;
   3011         for (const char *x = xdgconfdirs; *x; ++x)
   3012             if (*x == PATH_SEPARATOR) loc_size += rel_size;
   3013         for (const char *x = xdgdatadirs; *x; ++x)
   3014             if (*x == PATH_SEPARATOR) loc_size += rel_size;
   3015         loc_size += strlen(SYSCONFDIR) + rel_size + 1;
   3016 #if defined(EXTRASYSCONFDIR)
   3017         loc_size += strlen(EXTRASYSCONFDIR) + rel_size + 1;
   3018 #endif
   3019 #else
   3020         loc_size += strlen(location) + 1;
   3021 #endif
   3022         loc = loader_stack_alloc(loc_size);
   3023         if (loc == NULL) {
   3024             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3025                        "loader_get_manifest_files: Failed to allocate "
   3026                        "%d bytes for manifest file location.",
   3027                        loc_size);
   3028             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3029             goto out;
   3030         }
   3031         char *loc_write = loc;
   3032 #if !defined(_WIN32)
   3033         const char *loc_read;
   3034         size_t start, stop;
   3035 
   3036         loc_read = &xdgconfdirs[0];
   3037         start = 0;
   3038         while (loc_read[start] != '\0') {
   3039             while (loc_read[start] == PATH_SEPARATOR) {
   3040                 start++;
   3041             }
   3042             stop = start;
   3043             while (loc_read[stop] != PATH_SEPARATOR && loc_read[stop] != '\0') {
   3044                 stop++;
   3045             }
   3046             const size_t s = stop - start;
   3047             if (s) {
   3048                 memcpy(loc_write, &loc_read[start], s);
   3049                 loc_write += s;
   3050                 memcpy(loc_write, relative_location, rel_size);
   3051                 loc_write += rel_size;
   3052                 *loc_write++ = PATH_SEPARATOR;
   3053                 start = stop;
   3054             }
   3055         }
   3056 
   3057         memcpy(loc_write, SYSCONFDIR, strlen(SYSCONFDIR));
   3058         loc_write += strlen(SYSCONFDIR);
   3059         memcpy(loc_write, relative_location, rel_size);
   3060         loc_write += rel_size;
   3061         *loc_write++ = PATH_SEPARATOR;
   3062 
   3063 #if defined(EXTRASYSCONFDIR)
   3064         memcpy(loc_write, EXTRASYSCONFDIR, strlen(EXTRASYSCONFDIR));
   3065         loc_write += strlen(EXTRASYSCONFDIR);
   3066         memcpy(loc_write, relative_location, rel_size);
   3067         loc_write += rel_size;
   3068         *loc_write++ = PATH_SEPARATOR;
   3069 #endif
   3070 
   3071         loc_read = &xdgdatadirs[0];
   3072         start = 0;
   3073         while (loc_read[start] != '\0') {
   3074             while (loc_read[start] == PATH_SEPARATOR) {
   3075                 start++;
   3076             }
   3077             stop = start;
   3078             while (loc_read[stop] != PATH_SEPARATOR && loc_read[stop] != '\0') {
   3079                 stop++;
   3080             }
   3081             const size_t s = stop - start;
   3082             if (s) {
   3083                 memcpy(loc_write, &loc_read[start], s);
   3084                 loc_write += s;
   3085                 memcpy(loc_write, relative_location, rel_size);
   3086                 loc_write += rel_size;
   3087                 *loc_write++ = PATH_SEPARATOR;
   3088                 start = stop;
   3089             }
   3090         }
   3091 
   3092         --loc_write;
   3093 #else
   3094         memcpy(loc_write, location, strlen(location));
   3095         loc_write += strlen(location);
   3096 #endif
   3097         assert(loc_write - loc < (ptrdiff_t)loc_size);
   3098         *loc_write = '\0';
   3099 
   3100 #if defined(_WIN32)
   3101         VkResult regHKR_result = VK_SUCCESS;
   3102 
   3103         DWORD reg_size = 4096;
   3104 
   3105         // These calls look at the PNP/Device section of the registry.
   3106         if (!strncmp(loc, DEFAULT_VK_DRIVERS_INFO, sizeof(DEFAULT_VK_DRIVERS_INFO))) {
   3107             regHKR_result = loaderGetDeviceRegistryFiles(inst, &reg, &reg_size, LoaderPnpDriverRegistry());
   3108         } else if (!strncmp(loc, DEFAULT_VK_ELAYERS_INFO, sizeof(DEFAULT_VK_ELAYERS_INFO))) {
   3109             regHKR_result = loaderGetDeviceRegistryFiles(inst, &reg, &reg_size, LoaderPnpELayerRegistry());
   3110         } else if (!strncmp(loc, DEFAULT_VK_ILAYERS_INFO, sizeof(DEFAULT_VK_ILAYERS_INFO))) {
   3111             regHKR_result = loaderGetDeviceRegistryFiles(inst, &reg, &reg_size, LoaderPnpILayerRegistry());
   3112         }
   3113 
   3114         // This call looks into the Khronos non-device specific section of the registry.
   3115         VkResult reg_result = loaderGetRegistryFiles(inst, loc, is_layer, &reg, &reg_size);
   3116 
   3117         if ((VK_SUCCESS != reg_result && VK_SUCCESS != regHKR_result) || NULL == reg) {
   3118             if (!is_layer) {
   3119                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3120                            "loader_get_manifest_files: Registry lookup failed "
   3121                            "to get ICD manifest files.  Possibly missing Vulkan"
   3122                            " driver?");
   3123                 if (VK_SUCCESS == regHKR_result || VK_ERROR_OUT_OF_HOST_MEMORY == regHKR_result) {
   3124                     res = regHKR_result;
   3125                 } else if (VK_SUCCESS == reg_result || VK_ERROR_OUT_OF_HOST_MEMORY == reg_result) {
   3126                     res = reg_result;
   3127                 } else {
   3128                     res = VK_ERROR_INCOMPATIBLE_DRIVER;
   3129                 }
   3130             } else {
   3131                 if (warn_if_not_present) {
   3132                     // This is only a warning for layers
   3133                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3134                                "loader_get_manifest_files: Registry lookup failed "
   3135                                "to get layer manifest files.");
   3136                 }
   3137                 if (reg_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
   3138                     res = reg_result;
   3139                 } else {
   3140                     // Return success for now since it's not critical for layers
   3141                     res = VK_SUCCESS;
   3142                 }
   3143             }
   3144             goto out;
   3145         }
   3146         orig_loc = loc;
   3147         loc = reg;
   3148 #endif
   3149     } else {
   3150         loc = loader_stack_alloc(strlen(override) + 1);
   3151         if (loc == NULL) {
   3152             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3153                        "loader_get_manifest_files: Failed to allocate space for "
   3154                        "override environment variable of length %d",
   3155                        strlen(override) + 1);
   3156             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3157             goto out;
   3158         }
   3159         strcpy(loc, override);
   3160     }
   3161 
   3162     // Print out the paths being searched if debugging is enabled
   3163     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following paths for manifest files: %s\n", loc);
   3164 
   3165     file = loc;
   3166     while (*file) {
   3167         next_file = loader_get_next_path(file);
   3168         if (list_is_dirs) {
   3169             sysdir = opendir(file);
   3170             name = NULL;
   3171             if (sysdir) {
   3172                 dent = readdir(sysdir);
   3173                 if (dent == NULL) break;
   3174                 name = &(dent->d_name[0]);
   3175                 loader_get_fullpath(name, file, sizeof(full_path), full_path);
   3176                 name = full_path;
   3177             }
   3178         } else {
   3179 #if defined(_WIN32)
   3180             name = file;
   3181 #else
   3182             // only Linux has relative paths
   3183             char *dir;
   3184             // make a copy of location so it isn't modified
   3185             dir = loader_stack_alloc(strlen(loc) + 1);
   3186             if (dir == NULL) {
   3187                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3188                            "loader_get_manifest_files: Failed to allocate "
   3189                            "space for relative location path length %d",
   3190                            strlen(loc) + 1);
   3191                 goto out;
   3192             }
   3193             strcpy(dir, loc);
   3194 
   3195             loader_get_fullpath(file, dir, sizeof(full_path), full_path);
   3196 
   3197             name = full_path;
   3198 #endif
   3199         }
   3200         while (name) {
   3201             // Look for files ending with ".json" suffix
   3202             uint32_t nlen = (uint32_t)strlen(name);
   3203             const char *suf = name + nlen - 5;
   3204 
   3205             // Check if the file is already present
   3206             bool file_already_loaded = false;
   3207             for (uint32_t i = 0; i < out_files->count; ++i) {
   3208                 if (!strcmp(out_files->filename_list[i], name)) {
   3209                     file_already_loaded = true;
   3210                 }
   3211             }
   3212 
   3213             if (!file_already_loaded && (nlen > 5) && !strncmp(suf, ".json", 5)) {
   3214                 if (out_files->count == 0) {
   3215                     out_files->filename_list =
   3216                         loader_instance_heap_alloc(inst, alloced_count * sizeof(char *), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
   3217                     if (NULL == out_files->filename_list) {
   3218                         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3219                                    "loader_get_manifest_files: Failed to allocate space for manifest file name list");
   3220                         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3221                         goto out;
   3222                     }
   3223                 } else if (out_files->count == alloced_count) {
   3224                     void *new_ptr =
   3225                         loader_instance_heap_realloc(inst, out_files->filename_list, alloced_count * sizeof(char *),
   3226                                                      alloced_count * sizeof(char *) * 2, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
   3227                     if (NULL == new_ptr) {
   3228                         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3229                                    "loader_get_manifest_files: Failed to reallocate space for manifest file name list");
   3230                         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3231                         goto out;
   3232                     }
   3233                     out_files->filename_list = new_ptr;
   3234                     alloced_count *= 2;
   3235                 }
   3236                 out_files->filename_list[out_files->count] =
   3237                     loader_instance_heap_alloc(inst, strlen(name) + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
   3238                 if (out_files->filename_list[out_files->count] == NULL) {
   3239                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3240                                "loader_get_manifest_files: Failed to allocate "
   3241                                "space for manifest file %d list",
   3242                                out_files->count);
   3243                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3244                     goto out;
   3245                 }
   3246                 strcpy(out_files->filename_list[out_files->count], name);
   3247                 out_files->count++;
   3248             } else if(file_already_loaded) {
   3249                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3250                     "Skipping manifest file %s - The file has already been read once", name);
   3251             } else if (!list_is_dirs) {
   3252                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Skipping manifest file %s, file name must end in .json",
   3253                            name);
   3254             }
   3255             if (list_is_dirs) {
   3256                 dent = readdir(sysdir);
   3257                 if (dent == NULL) {
   3258                     break;
   3259                 }
   3260                 name = &(dent->d_name[0]);
   3261                 loader_get_fullpath(name, file, sizeof(full_path), full_path);
   3262                 name = full_path;
   3263             } else {
   3264                 break;
   3265             }
   3266         }
   3267         if (sysdir) {
   3268             closedir(sysdir);
   3269             sysdir = NULL;
   3270         }
   3271         file = next_file;
   3272 #if !defined(_WIN32)
   3273         if (relative_location != NULL && (next_file == NULL || *next_file == '\0') && override == NULL) {
   3274             char *xdgdatahome = loader_secure_getenv("XDG_DATA_HOME", inst);
   3275             size_t len;
   3276             if (xdgdatahome != NULL) {
   3277                 size_t alloc_len = strlen(xdgdatahome) + 2 + strlen(relative_location);
   3278                 char *home_loc = loader_stack_alloc(alloc_len);
   3279                 if (home_loc == NULL) {
   3280                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3281                                "loader_get_manifest_files: Failed to allocate "
   3282                                "space for manifest file XDG Home location");
   3283                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3284                     goto out;
   3285                 }
   3286                 strcpy(home_loc, xdgdatahome);
   3287                 // Add directory separator if needed
   3288                 if (relative_location[0] != DIRECTORY_SYMBOL) {
   3289                     len = strlen(home_loc);
   3290                     home_loc[len] = DIRECTORY_SYMBOL;
   3291                     home_loc[len + 1] = '\0';
   3292                 }
   3293                 strncat(home_loc, relative_location, alloc_len);
   3294                 file = home_loc;
   3295                 next_file = loader_get_next_path(file);
   3296                 relative_location = NULL;
   3297 
   3298                 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following path for manifest files: %s\n",
   3299                            home_loc);
   3300                 list_is_dirs = true;
   3301 
   3302             } else {
   3303                 char *home = loader_secure_getenv("HOME", inst);
   3304                 if (home != NULL) {
   3305                     size_t alloc_len = strlen(home) + 16 + strlen(relative_location);
   3306                     char *home_loc = loader_stack_alloc(alloc_len);
   3307                     if (home_loc == NULL) {
   3308                         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3309                                    "loader_get_manifest_files: Failed to allocate "
   3310                                    "space for manifest file Home location");
   3311                         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3312                         goto out;
   3313                     }
   3314                     strncpy(home_loc, home, alloc_len);
   3315 
   3316                     len = strlen(home);
   3317                     if (home[len] != DIRECTORY_SYMBOL) {
   3318                         home_loc[len] = DIRECTORY_SYMBOL;
   3319                         home_loc[len + 1] = '\0';
   3320                     }
   3321                     strncat(home_loc, ".local/share", alloc_len);
   3322 
   3323                     if (relative_location[0] != DIRECTORY_SYMBOL) {
   3324                         len = strlen(home_loc);
   3325                         home_loc[len] = DIRECTORY_SYMBOL;
   3326                         home_loc[len + 1] = '\0';
   3327                     }
   3328                     strncat(home_loc, relative_location, alloc_len);
   3329                     file = home_loc;
   3330                     next_file = loader_get_next_path(file);
   3331                     relative_location = NULL;
   3332 
   3333                     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following path for manifest files: %s\n",
   3334                                home_loc);
   3335                     list_is_dirs = true;
   3336                 } else {
   3337                     // without knowing HOME, we just.. give up
   3338                 }
   3339             }
   3340         }
   3341 #endif
   3342     }
   3343 
   3344 out:
   3345     if (VK_SUCCESS != res && NULL != out_files->filename_list) {
   3346         for (uint32_t remove = 0; remove < out_files->count; remove++) {
   3347             loader_instance_heap_free(inst, out_files->filename_list[remove]);
   3348         }
   3349         loader_instance_heap_free(inst, out_files->filename_list);
   3350         out_files->count = 0;
   3351         out_files->filename_list = NULL;
   3352     }
   3353 
   3354     if (NULL != sysdir) {
   3355         closedir(sysdir);
   3356     }
   3357 
   3358     if (override_getenv != NULL) {
   3359         loader_free_getenv(override_getenv, inst);
   3360     }
   3361 
   3362     if (NULL != reg && reg != orig_loc) {
   3363         loader_instance_heap_free(inst, reg);
   3364     }
   3365     return res;
   3366 }
   3367 
   3368 void loader_init_icd_lib_list() {}
   3369 
   3370 void loader_destroy_icd_lib_list() {}
   3371 
   3372 // Try to find the Vulkan ICD driver(s).
   3373 //
   3374 // This function scans the default system loader path(s) or path
   3375 // specified by the \c VK_ICD_FILENAMES environment variable in
   3376 // order to find loadable VK ICDs manifest files. From these
   3377 // manifest files it finds the ICD libraries.
   3378 //
   3379 // \returns
   3380 // Vulkan result
   3381 // (on result == VK_SUCCESS) a list of icds that were discovered
   3382 VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
   3383     char *file_str;
   3384     uint16_t file_major_vers = 0;
   3385     uint16_t file_minor_vers = 0;
   3386     uint16_t file_patch_vers = 0;
   3387     char *vers_tok;
   3388     struct loader_manifest_files manifest_files;
   3389     VkResult res = VK_SUCCESS;
   3390     bool lockedMutex = false;
   3391     cJSON *json = NULL;
   3392     uint32_t num_good_icds = 0;
   3393 
   3394     memset(&manifest_files, 0, sizeof(struct loader_manifest_files));
   3395 
   3396     res = loader_scanned_icd_init(inst, icd_tramp_list);
   3397     if (VK_SUCCESS != res) {
   3398         goto out;
   3399     }
   3400 
   3401     // Get a list of manifest files for ICDs
   3402     res = loader_get_manifest_files(inst, "VK_ICD_FILENAMES", NULL, false, true, DEFAULT_VK_DRIVERS_INFO, RELATIVE_VK_DRIVERS_INFO,
   3403                                     &manifest_files);
   3404     if (VK_SUCCESS != res || manifest_files.count == 0) {
   3405         goto out;
   3406     }
   3407 
   3408     loader_platform_thread_lock_mutex(&loader_json_lock);
   3409     lockedMutex = true;
   3410     for (uint32_t i = 0; i < manifest_files.count; i++) {
   3411         file_str = manifest_files.filename_list[i];
   3412         if (file_str == NULL) {
   3413             continue;
   3414         }
   3415 
   3416         VkResult temp_res = loader_get_json(inst, file_str, &json);
   3417         if (NULL == json || temp_res != VK_SUCCESS) {
   3418             if (NULL != json) {
   3419                 cJSON_Delete(json);
   3420                 json = NULL;
   3421             }
   3422             // If we haven't already found an ICD, copy this result to
   3423             // the returned result.
   3424             if (num_good_icds == 0) {
   3425                 res = temp_res;
   3426             }
   3427             if (temp_res == VK_ERROR_OUT_OF_HOST_MEMORY) {
   3428                 break;
   3429             } else {
   3430                 continue;
   3431             }
   3432         }
   3433         res = temp_res;
   3434 
   3435         cJSON *item, *itemICD;
   3436         item = cJSON_GetObjectItem(json, "file_format_version");
   3437         if (item == NULL) {
   3438             if (num_good_icds == 0) {
   3439                 res = VK_ERROR_INITIALIZATION_FAILED;
   3440             }
   3441             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3442                        "loader_icd_scan: ICD JSON %s does not have a"
   3443                        " \'file_format_version\' field. Skipping ICD JSON.",
   3444                        file_str);
   3445             cJSON_Delete(json);
   3446             json = NULL;
   3447             continue;
   3448         }
   3449 
   3450         char *file_vers = cJSON_Print(item);
   3451         if (NULL == file_vers) {
   3452             // Only reason the print can fail is if there was an allocation issue
   3453             if (num_good_icds == 0) {
   3454                 res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3455             }
   3456             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3457                        "loader_icd_scan: Failed retrieving ICD JSON %s"
   3458                        " \'file_format_version\' field.  Skipping ICD JSON",
   3459                        file_str);
   3460             cJSON_Delete(json);
   3461             json = NULL;
   3462             continue;
   3463         }
   3464         loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers);
   3465 
   3466         // Get the major/minor/and patch as integers for easier comparison
   3467         vers_tok = strtok(file_vers, ".\"\n\r");
   3468         if (NULL != vers_tok) {
   3469             file_major_vers = (uint16_t)atoi(vers_tok);
   3470             vers_tok = strtok(NULL, ".\"\n\r");
   3471             if (NULL != vers_tok) {
   3472                 file_minor_vers = (uint16_t)atoi(vers_tok);
   3473                 vers_tok = strtok(NULL, ".\"\n\r");
   3474                 if (NULL != vers_tok) {
   3475                     file_patch_vers = (uint16_t)atoi(vers_tok);
   3476                 }
   3477             }
   3478         }
   3479 
   3480         if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1) {
   3481             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3482                        "loader_icd_scan: Unexpected manifest file version "
   3483                        "(expected 1.0.0 or 1.0.1), may cause errors");
   3484         }
   3485         cJSON_Free(file_vers);
   3486 
   3487         itemICD = cJSON_GetObjectItem(json, "ICD");
   3488         if (itemICD != NULL) {
   3489             item = cJSON_GetObjectItem(itemICD, "library_path");
   3490             if (item != NULL) {
   3491                 char *temp = cJSON_Print(item);
   3492                 if (!temp || strlen(temp) == 0) {
   3493                     if (num_good_icds == 0) {
   3494                         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3495                     }
   3496                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3497                                "loader_icd_scan: Failed retrieving ICD JSON %s"
   3498                                " \'library_path\' field.  Skipping ICD JSON.",
   3499                                file_str);
   3500                     cJSON_Free(temp);
   3501                     cJSON_Delete(json);
   3502                     json = NULL;
   3503                     continue;
   3504                 }
   3505                 // strip out extra quotes
   3506                 temp[strlen(temp) - 1] = '\0';
   3507                 char *library_path = loader_stack_alloc(strlen(temp) + 1);
   3508                 if (NULL == library_path) {
   3509                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3510                                "loader_icd_scan: Failed to allocate space for "
   3511                                "ICD JSON %s \'library_path\' value.  Skipping "
   3512                                "ICD JSON.",
   3513                                file_str);
   3514                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3515                     cJSON_Free(temp);
   3516                     cJSON_Delete(json);
   3517                     json = NULL;
   3518                     goto out;
   3519                 }
   3520                 strcpy(library_path, &temp[1]);
   3521                 cJSON_Free(temp);
   3522                 if (strlen(library_path) == 0) {
   3523                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3524                                "loader_icd_scan: ICD JSON %s \'library_path\'"
   3525                                " field is empty.  Skipping ICD JSON.",
   3526                                file_str);
   3527                     cJSON_Delete(json);
   3528                     json = NULL;
   3529                     continue;
   3530                 }
   3531                 char fullpath[MAX_STRING_SIZE];
   3532                 // Print out the paths being searched if debugging is enabled
   3533                 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching for ICD drivers named %s, using default dir %s",
   3534                            library_path, DEFAULT_VK_DRIVERS_PATH);
   3535                 if (loader_platform_is_path(library_path)) {
   3536                     // a relative or absolute path
   3537                     char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
   3538                     char *rel_base;
   3539                     strcpy(name_copy, file_str);
   3540                     rel_base = loader_platform_dirname(name_copy);
   3541                     loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
   3542                 } else {
   3543                     // a filename which is assumed in a system directory
   3544                     loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
   3545                 }
   3546 
   3547                 uint32_t vers = 0;
   3548                 item = cJSON_GetObjectItem(itemICD, "api_version");
   3549                 if (item != NULL) {
   3550                     temp = cJSON_Print(item);
   3551                     if (NULL == temp) {
   3552                         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3553                                    "loader_icd_scan: Failed retrieving ICD JSON %s"
   3554                                    " \'api_version\' field.  Skipping ICD JSON.",
   3555                                    file_str);
   3556 
   3557                         // Only reason the print can fail is if there was an
   3558                         // allocation issue
   3559                         if (num_good_icds == 0) {
   3560                             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3561                         }
   3562 
   3563                         cJSON_Free(temp);
   3564                         cJSON_Delete(json);
   3565                         json = NULL;
   3566                         continue;
   3567                     }
   3568                     vers = loader_make_version(temp);
   3569                     cJSON_Free(temp);
   3570                 } else {
   3571                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3572                                "loader_icd_scan: ICD JSON %s does not have an"
   3573                                " \'api_version\' field.",
   3574                                file_str);
   3575                 }
   3576 
   3577                 res = loader_scanned_icd_add(inst, icd_tramp_list, fullpath, vers);
   3578                 if (VK_SUCCESS != res) {
   3579                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3580                                "loader_icd_scan: Failed to add ICD JSON %s. "
   3581                                " Skipping ICD JSON.",
   3582                                fullpath);
   3583                     cJSON_Delete(json);
   3584                     json = NULL;
   3585                     continue;
   3586                 }
   3587                 num_good_icds++;
   3588             } else {
   3589                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3590                            "loader_icd_scan: Failed to find \'library_path\' "
   3591                            "object in ICD JSON file %s.  Skipping ICD JSON.",
   3592                            file_str);
   3593             }
   3594         } else {
   3595             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3596                        "loader_icd_scan: Can not find \'ICD\' object in ICD JSON "
   3597                        "file %s.  Skipping ICD JSON",
   3598                        file_str);
   3599         }
   3600 
   3601         cJSON_Delete(json);
   3602         json = NULL;
   3603     }
   3604 
   3605 out:
   3606 
   3607     if (NULL != json) {
   3608         cJSON_Delete(json);
   3609     }
   3610 
   3611     if (NULL != manifest_files.filename_list) {
   3612         for (uint32_t i = 0; i < manifest_files.count; i++) {
   3613             if (NULL != manifest_files.filename_list[i]) {
   3614                 loader_instance_heap_free(inst, manifest_files.filename_list[i]);
   3615             }
   3616         }
   3617         loader_instance_heap_free(inst, manifest_files.filename_list);
   3618     }
   3619     if (lockedMutex) {
   3620         loader_platform_thread_unlock_mutex(&loader_json_lock);
   3621     }
   3622 
   3623     return res;
   3624 }
   3625 
   3626 void loader_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers) {
   3627     char *file_str;
   3628     struct loader_manifest_files manifest_files[2];  // [0] = explicit, [1] = implicit
   3629     cJSON *json;
   3630     uint32_t implicit;
   3631     bool lockedMutex = false;
   3632 
   3633     memset(manifest_files, 0, sizeof(struct loader_manifest_files) * 2);
   3634 
   3635     // Get a list of manifest files for explicit layers
   3636     if (VK_SUCCESS != loader_get_manifest_files(inst, LAYERS_PATH_ENV, LAYERS_SOURCE_PATH, true, true, DEFAULT_VK_ELAYERS_INFO,
   3637                                                 RELATIVE_VK_ELAYERS_INFO, &manifest_files[0])) {
   3638         goto out;
   3639     }
   3640 
   3641     // Get a list of manifest files for any implicit layers
   3642     // Pass NULL for environment variable override - implicit layers are not
   3643     // overridden by LAYERS_PATH_ENV
   3644     if (VK_SUCCESS != loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO,
   3645                                                 &manifest_files[1])) {
   3646         goto out;
   3647     }
   3648 
   3649     // Make sure we have at least one layer, if not, go ahead and return
   3650     if (manifest_files[0].count == 0 && manifest_files[1].count == 0) {
   3651         goto out;
   3652     }
   3653 
   3654     // cleanup any previously scanned libraries
   3655     loader_delete_layer_properties(inst, instance_layers);
   3656 
   3657     loader_platform_thread_lock_mutex(&loader_json_lock);
   3658     lockedMutex = true;
   3659     for (implicit = 0; implicit < 2; implicit++) {
   3660         for (uint32_t i = 0; i < manifest_files[implicit].count; i++) {
   3661             file_str = manifest_files[implicit].filename_list[i];
   3662             if (file_str == NULL) continue;
   3663 
   3664             // parse file into JSON struct
   3665             VkResult res = loader_get_json(inst, file_str, &json);
   3666             if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   3667                 break;
   3668             } else if (VK_SUCCESS != res || NULL == json) {
   3669                 continue;
   3670             }
   3671 
   3672             VkResult local_res = loader_add_layer_properties(inst, instance_layers, json, (implicit == 1), file_str);
   3673             cJSON_Delete(json);
   3674 
   3675             // If the error is anything other than out of memory we still want to try to load the other layers
   3676             if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
   3677                 goto out;
   3678             }
   3679         }
   3680     }
   3681 
   3682     // See if "VK_LAYER_LUNARG_standard_validation" already in list.
   3683     bool found_std_val = false;
   3684     for (uint32_t i = 0; i < instance_layers->count; i++) {
   3685         struct loader_layer_properties *props = &instance_layers->list[i];
   3686         if (strcmp(props->info.layerName, std_validation_str) == 0) {
   3687             found_std_val = true;
   3688             break;
   3689         }
   3690     }
   3691 
   3692     // If we didn't find the VK_LAYER_LUNARG_standard_validation meta-layer in
   3693     // the list, then we need to add it manually.  This is likely because we're
   3694     // dealing with a new loader, but an old layer folder.
   3695     if (!found_std_val && !loader_add_legacy_std_val_layer(inst, instance_layers)) {
   3696         goto out;
   3697     }
   3698 
   3699     // Verify any meta-layers in the list are valid and all the component layers are
   3700     // actually present in the available layer list
   3701     verify_all_meta_layers(inst, instance_layers);
   3702 
   3703 out:
   3704 
   3705     for (uint32_t manFile = 0; manFile < 2; manFile++) {
   3706         if (NULL != manifest_files[manFile].filename_list) {
   3707             for (uint32_t i = 0; i < manifest_files[manFile].count; i++) {
   3708                 if (NULL != manifest_files[manFile].filename_list[i]) {
   3709                     loader_instance_heap_free(inst, manifest_files[manFile].filename_list[i]);
   3710                 }
   3711             }
   3712             loader_instance_heap_free(inst, manifest_files[manFile].filename_list);
   3713         }
   3714     }
   3715     if (lockedMutex) {
   3716         loader_platform_thread_unlock_mutex(&loader_json_lock);
   3717     }
   3718 }
   3719 
   3720 void loader_implicit_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers) {
   3721     char *file_str;
   3722     struct loader_manifest_files manifest_files;
   3723     cJSON *json;
   3724     uint32_t i;
   3725 
   3726     // Pass NULL for environment variable override - implicit layers are not
   3727     // overridden by LAYERS_PATH_ENV
   3728     VkResult res = loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO,
   3729                                              &manifest_files);
   3730     if (VK_SUCCESS != res || manifest_files.count == 0) {
   3731         return;
   3732     }
   3733 
   3734     // Cleanup any previously scanned libraries
   3735     loader_delete_layer_properties(inst, instance_layers);
   3736 
   3737     loader_platform_thread_lock_mutex(&loader_json_lock);
   3738 
   3739     for (i = 0; i < manifest_files.count; i++) {
   3740         file_str = manifest_files.filename_list[i];
   3741         if (file_str == NULL) {
   3742             continue;
   3743         }
   3744 
   3745         // parse file into JSON struct
   3746         res = loader_get_json(inst, file_str, &json);
   3747         if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   3748             break;
   3749         } else if (VK_SUCCESS != res || NULL == json) {
   3750             continue;
   3751         }
   3752 
   3753         res = loader_add_layer_properties(inst, instance_layers, json, true, file_str);
   3754 
   3755         loader_instance_heap_free(inst, file_str);
   3756         cJSON_Delete(json);
   3757 
   3758         if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   3759             break;
   3760         }
   3761     }
   3762     loader_instance_heap_free(inst, manifest_files.filename_list);
   3763     loader_platform_thread_unlock_mutex(&loader_json_lock);
   3764 }
   3765 
   3766 // Check if an implicit layer should be enabled.
   3767 bool loader_is_implicit_layer_enabled(const struct loader_instance *inst, const struct loader_layer_properties *prop) {
   3768     bool enable = false;
   3769     char *env_value = NULL;
   3770 
   3771     // if no enable_environment variable is specified, this implicit layer
   3772     // should always be enabled. Otherwise check if the variable is set
   3773     if (prop->enable_env_var.name[0] == 0) {
   3774         enable = true;
   3775     } else {
   3776         env_value = loader_secure_getenv(prop->enable_env_var.name, inst);
   3777         if (env_value && !strcmp(prop->enable_env_var.value, env_value)) enable = true;
   3778         loader_free_getenv(env_value, inst);
   3779     }
   3780 
   3781     // disable_environment has priority, i.e. if both enable and disable
   3782     // environment variables are set, the layer is disabled. Implicit
   3783     // layers are required to have a disable_environment variables
   3784     env_value = loader_secure_getenv(prop->disable_env_var.name, inst);
   3785     if (env_value && !strcmp(prop->disable_env_var.value, env_value)) enable = false;
   3786     loader_free_getenv(env_value, inst);
   3787 
   3788     return enable;
   3789 }
   3790 
   3791 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_internal(VkInstance inst, const char *pName) {
   3792     // inst is not wrapped
   3793     if (inst == VK_NULL_HANDLE) {
   3794         return NULL;
   3795     }
   3796     VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst;
   3797     void *addr;
   3798 
   3799     if (disp_table == NULL) return NULL;
   3800 
   3801     bool found_name;
   3802     addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
   3803     if (found_name) {
   3804         return addr;
   3805     }
   3806 
   3807     if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, true, NULL, &addr)) return addr;
   3808 
   3809     // Don't call down the chain, this would be an infinite loop
   3810     loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpdpa_instance_internal() unrecognized name %s", pName);
   3811     return NULL;
   3812 }
   3813 
   3814 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_terminator(VkInstance inst, const char *pName) {
   3815     // inst is not wrapped
   3816     if (inst == VK_NULL_HANDLE) {
   3817         return NULL;
   3818     }
   3819     VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst;
   3820     void *addr;
   3821 
   3822     if (disp_table == NULL) return NULL;
   3823 
   3824     bool found_name;
   3825     addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
   3826     if (found_name) {
   3827         return addr;
   3828     }
   3829 
   3830     // Get the terminator, but don't perform checking since it should already
   3831     // have been setup if we get here.
   3832     if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, false, NULL, &addr)) {
   3833         return addr;
   3834     }
   3835 
   3836     // Don't call down the chain, this would be an infinite loop
   3837     loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpdpa_instance_terminator() unrecognized name %s", pName);
   3838     return NULL;
   3839 }
   3840 
   3841 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char *pName) {
   3842     if (!strcmp(pName, "vkGetInstanceProcAddr")) {
   3843         return (PFN_vkVoidFunction)loader_gpa_instance_internal;
   3844     }
   3845     if (!strcmp(pName, "vk_layerGetPhysicalDeviceProcAddr")) {
   3846         return (PFN_vkVoidFunction)loader_gpdpa_instance_terminator;
   3847     }
   3848     if (!strcmp(pName, "vkCreateInstance")) {
   3849         return (PFN_vkVoidFunction)terminator_CreateInstance;
   3850     }
   3851     if (!strcmp(pName, "vkCreateDevice")) {
   3852         return (PFN_vkVoidFunction)terminator_CreateDevice;
   3853     }
   3854 
   3855     // inst is not wrapped
   3856     if (inst == VK_NULL_HANDLE) {
   3857         return NULL;
   3858     }
   3859     VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst;
   3860     void *addr;
   3861 
   3862     if (disp_table == NULL) return NULL;
   3863 
   3864     bool found_name;
   3865     addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
   3866     if (found_name) {
   3867         return addr;
   3868     }
   3869 
   3870     // Don't call down the chain, this would be an infinite loop
   3871     loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpa_instance_internal() unrecognized name %s", pName);
   3872     return NULL;
   3873 }
   3874 
   3875 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_device_internal(VkDevice device, const char *pName) {
   3876     struct loader_device *dev;
   3877     struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL);
   3878 
   3879     // Return this function if a layer above here is asking for the vkGetDeviceProcAddr.
   3880     // This is so we can properly intercept any device commands needing a terminator.
   3881     if (!strcmp(pName, "vkGetDeviceProcAddr")) {
   3882         return (PFN_vkVoidFunction)loader_gpa_device_internal;
   3883     }
   3884 
   3885     // NOTE: Device Funcs needing Trampoline/Terminator.
   3886     // Overrides for device functions needing a trampoline and
   3887     // a terminator because certain device entry-points still need to go
   3888     // through a terminator before hitting the ICD.  This could be for
   3889     // several reasons, but the main one is currently unwrapping an
   3890     // object before passing the appropriate info along to the ICD.
   3891     // This is why we also have to override the direct ICD call to
   3892     // vkGetDeviceProcAddr to intercept those calls.
   3893     PFN_vkVoidFunction addr = get_extension_device_proc_terminator(pName);
   3894     if (NULL != addr) {
   3895         return addr;
   3896     }
   3897 
   3898     return icd_term->dispatch.GetDeviceProcAddr(device, pName);
   3899 }
   3900 
   3901 // Initialize device_ext dispatch table entry as follows:
   3902 // If dev == NULL find all logical devices created within this instance and
   3903 //  init the entry (given by idx) in the ext dispatch table.
   3904 // If dev != NULL only initialize the entry in the given dev's dispatch table.
   3905 // The initialization value is gotten by calling down the device chain with
   3906 // GDPA.
   3907 // If GDPA returns NULL then don't initialize the dispatch table entry.
   3908 static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst, struct loader_device *dev, uint32_t idx,
   3909                                                const char *funcName)
   3910 
   3911 {
   3912     void *gdpa_value;
   3913     if (dev != NULL) {
   3914         gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(dev->chain_device, funcName);
   3915         if (gdpa_value != NULL) dev->loader_dispatch.ext_dispatch.dev_ext[idx] = (PFN_vkDevExt)gdpa_value;
   3916     } else {
   3917         for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) {
   3918             struct loader_device *ldev = icd_term->logical_device_list;
   3919             while (ldev) {
   3920                 gdpa_value = ldev->loader_dispatch.core_dispatch.GetDeviceProcAddr(ldev->chain_device, funcName);
   3921                 if (gdpa_value != NULL) ldev->loader_dispatch.ext_dispatch.dev_ext[idx] = (PFN_vkDevExt)gdpa_value;
   3922                 ldev = ldev->next;
   3923             }
   3924         }
   3925     }
   3926 }
   3927 
   3928 // Find all dev extension in the hash table  and initialize the dispatch table
   3929 // for dev  for each of those extension entrypoints found in hash table.
   3930 void loader_init_dispatch_dev_ext(struct loader_instance *inst, struct loader_device *dev) {
   3931     for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
   3932         if (inst->dev_ext_disp_hash[i].func_name != NULL)
   3933             loader_init_dispatch_dev_ext_entry(inst, dev, i, inst->dev_ext_disp_hash[i].func_name);
   3934     }
   3935 }
   3936 
   3937 static bool loader_check_icds_for_dev_ext_address(struct loader_instance *inst, const char *funcName) {
   3938     struct loader_icd_term *icd_term;
   3939     icd_term = inst->icd_terms;
   3940     while (NULL != icd_term) {
   3941         if (icd_term->scanned_icd->GetInstanceProcAddr(icd_term->instance, funcName))
   3942             // this icd supports funcName
   3943             return true;
   3944         icd_term = icd_term->next;
   3945     }
   3946 
   3947     return false;
   3948 }
   3949 
   3950 static bool loader_check_layer_list_for_dev_ext_address(const struct loader_layer_list *const layers, const char *funcName) {
   3951     // Iterate over the layers.
   3952     for (uint32_t layer = 0; layer < layers->count; ++layer) {
   3953         // Iterate over the extensions.
   3954         const struct loader_device_extension_list *const extensions = &(layers->list[layer].device_extension_list);
   3955         for (uint32_t extension = 0; extension < extensions->count; ++extension) {
   3956             // Iterate over the entry points.
   3957             const struct loader_dev_ext_props *const property = &(extensions->list[extension]);
   3958             for (uint32_t entry = 0; entry < property->entrypoint_count; ++entry) {
   3959                 if (strcmp(property->entrypoints[entry], funcName) == 0) {
   3960                     return true;
   3961                 }
   3962             }
   3963         }
   3964     }
   3965 
   3966     return false;
   3967 }
   3968 
   3969 static void loader_free_dev_ext_table(struct loader_instance *inst) {
   3970     for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
   3971         loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].func_name);
   3972         loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].list.index);
   3973     }
   3974     memset(inst->dev_ext_disp_hash, 0, sizeof(inst->dev_ext_disp_hash));
   3975 }
   3976 
   3977 static bool loader_add_dev_ext_table(struct loader_instance *inst, uint32_t *ptr_idx, const char *funcName) {
   3978     uint32_t i;
   3979     uint32_t idx = *ptr_idx;
   3980     struct loader_dispatch_hash_list *list = &inst->dev_ext_disp_hash[idx].list;
   3981 
   3982     if (!inst->dev_ext_disp_hash[idx].func_name) {
   3983         // no entry here at this idx, so use it
   3984         assert(list->capacity == 0);
   3985         inst->dev_ext_disp_hash[idx].func_name =
   3986             (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   3987         if (inst->dev_ext_disp_hash[idx].func_name == NULL) {
   3988             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3989                        "loader_add_dev_ext_table: Failed to allocate memory "
   3990                        "for func_name %s",
   3991                        funcName);
   3992             return false;
   3993         }
   3994         strncpy(inst->dev_ext_disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
   3995         return true;
   3996     }
   3997 
   3998     // check for enough capacity
   3999     if (list->capacity == 0) {
   4000         list->index = loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4001         if (list->index == NULL) {
   4002             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_dev_ext_table: Failed to allocate memory for list index",
   4003                        funcName);
   4004             return false;
   4005         }
   4006         list->capacity = 8 * sizeof(*(list->index));
   4007     } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
   4008         void *new_ptr = loader_instance_heap_realloc(inst, list->index, list->capacity, list->capacity * 2,
   4009                                                      VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4010         if (NULL == new_ptr) {
   4011             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4012                        "loader_add_dev_ext_table: Failed to reallocate memory for list index", funcName);
   4013             return false;
   4014         }
   4015         list->index = new_ptr;
   4016         list->capacity *= 2;
   4017     }
   4018 
   4019     // find an unused index in the hash table and use it
   4020     i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS;
   4021     do {
   4022         if (!inst->dev_ext_disp_hash[i].func_name) {
   4023             assert(inst->dev_ext_disp_hash[i].list.capacity == 0);
   4024             inst->dev_ext_disp_hash[i].func_name =
   4025                 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4026             if (inst->dev_ext_disp_hash[i].func_name == NULL) {
   4027                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4028                            "loader_add_dev_ext_table: Failed to allocate memory "
   4029                            "for func_name %s",
   4030                            funcName);
   4031                 return false;
   4032             }
   4033             strncpy(inst->dev_ext_disp_hash[i].func_name, funcName, strlen(funcName) + 1);
   4034             list->index[list->count] = i;
   4035             list->count++;
   4036             *ptr_idx = i;
   4037             return true;
   4038         }
   4039         i = (i + 1) % MAX_NUM_UNKNOWN_EXTS;
   4040     } while (i != idx);
   4041 
   4042     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4043                "loader_add_dev_ext_table:  Could not insert into hash table; is "
   4044                "it full?");
   4045 
   4046     return false;
   4047 }
   4048 
   4049 static bool loader_name_in_dev_ext_table(struct loader_instance *inst, uint32_t *idx, const char *funcName) {
   4050     uint32_t alt_idx;
   4051     if (inst->dev_ext_disp_hash[*idx].func_name && !strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName)) return true;
   4052 
   4053     // funcName wasn't at the primary spot in the hash table
   4054     // search the list of secondary locations (shallow search, not deep search)
   4055     for (uint32_t i = 0; i < inst->dev_ext_disp_hash[*idx].list.count; i++) {
   4056         alt_idx = inst->dev_ext_disp_hash[*idx].list.index[i];
   4057         if (!strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName)) {
   4058             *idx = alt_idx;
   4059             return true;
   4060         }
   4061     }
   4062 
   4063     return false;
   4064 }
   4065 
   4066 // This function returns generic trampoline code address for unknown entry
   4067 // points.
   4068 // Presumably, these unknown entry points (as given by funcName) are device
   4069 // extension entrypoints.  A hash table is used to keep a list of unknown entry
   4070 // points and their mapping to the device extension dispatch table
   4071 // (struct loader_dev_ext_dispatch_table).
   4072 // \returns
   4073 // For a given entry point string (funcName), if an existing mapping is found
   4074 // the
   4075 // trampoline address for that mapping is returned. Otherwise, this unknown
   4076 // entry point
   4077 // has not been seen yet. Next check if a layer or ICD supports it.  If so then
   4078 // a
   4079 // new entry in the hash table is initialized and that trampoline address for
   4080 // the new entry is returned. Null is returned if the hash table is full or
   4081 // if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
   4082 void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) {
   4083     uint32_t idx;
   4084     uint32_t seed = 0;
   4085 
   4086     idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS;
   4087 
   4088     if (loader_name_in_dev_ext_table(inst, &idx, funcName))
   4089         // found funcName already in hash
   4090         return loader_get_dev_ext_trampoline(idx);
   4091 
   4092     // Check if funcName is supported in either ICDs or a layer library
   4093     if (!loader_check_icds_for_dev_ext_address(inst, funcName) &&
   4094         !loader_check_layer_list_for_dev_ext_address(&inst->app_activated_layer_list, funcName)) {
   4095         // if support found in layers continue on
   4096         return NULL;
   4097     }
   4098 
   4099     if (loader_add_dev_ext_table(inst, &idx, funcName)) {
   4100         // successfully added new table entry
   4101         // init any dev dispatch table entries as needed
   4102         loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
   4103         return loader_get_dev_ext_trampoline(idx);
   4104     }
   4105 
   4106     return NULL;
   4107 }
   4108 
   4109 static bool loader_check_icds_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) {
   4110     struct loader_icd_term *icd_term;
   4111     icd_term = inst->icd_terms;
   4112     while (NULL != icd_term) {
   4113         if (icd_term->scanned_icd->interface_version >= MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION &&
   4114             icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName))
   4115             // this icd supports funcName
   4116             return true;
   4117         icd_term = icd_term->next;
   4118     }
   4119 
   4120     return false;
   4121 }
   4122 
   4123 static bool loader_check_layer_list_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) {
   4124     struct loader_layer_properties *layer_prop_list = inst->expanded_activated_layer_list.list;
   4125     for (uint32_t layer = 0; layer < inst->expanded_activated_layer_list.count; ++layer) {
   4126         // If this layer supports the vk_layerGetPhysicalDeviceProcAddr, then call
   4127         // it and see if it returns a valid pointer for this function name.
   4128         if (layer_prop_list[layer].interface_version > 1) {
   4129             const struct loader_layer_functions *const functions = &(layer_prop_list[layer].functions);
   4130             if (NULL != functions->get_physical_device_proc_addr &&
   4131                 NULL != functions->get_physical_device_proc_addr((VkInstance)inst->instance, funcName)) {
   4132                 return true;
   4133             }
   4134         }
   4135     }
   4136 
   4137     return false;
   4138 }
   4139 
   4140 static void loader_free_phys_dev_ext_table(struct loader_instance *inst) {
   4141     for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
   4142         loader_instance_heap_free(inst, inst->phys_dev_ext_disp_hash[i].func_name);
   4143         loader_instance_heap_free(inst, inst->phys_dev_ext_disp_hash[i].list.index);
   4144     }
   4145     memset(inst->phys_dev_ext_disp_hash, 0, sizeof(inst->phys_dev_ext_disp_hash));
   4146 }
   4147 
   4148 static bool loader_add_phys_dev_ext_table(struct loader_instance *inst, uint32_t *ptr_idx, const char *funcName) {
   4149     uint32_t i;
   4150     uint32_t idx = *ptr_idx;
   4151     struct loader_dispatch_hash_list *list = &inst->phys_dev_ext_disp_hash[idx].list;
   4152 
   4153     if (!inst->phys_dev_ext_disp_hash[idx].func_name) {
   4154         // no entry here at this idx, so use it
   4155         assert(list->capacity == 0);
   4156         inst->phys_dev_ext_disp_hash[idx].func_name =
   4157             (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4158         if (inst->phys_dev_ext_disp_hash[idx].func_name == NULL) {
   4159             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4160                        "loader_add_phys_dev_ext_table() can't allocate memory for "
   4161                        "func_name");
   4162             return false;
   4163         }
   4164         strncpy(inst->phys_dev_ext_disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
   4165         return true;
   4166     }
   4167 
   4168     // check for enough capacity
   4169     if (list->capacity == 0) {
   4170         list->index = loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4171         if (list->index == NULL) {
   4172             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_phys_dev_ext_table() can't allocate list memory");
   4173             return false;
   4174         }
   4175         list->capacity = 8 * sizeof(*(list->index));
   4176     } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
   4177         void *new_ptr = loader_instance_heap_realloc(inst, list->index, list->capacity, list->capacity * 2,
   4178                                                      VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4179         if (NULL == new_ptr) {
   4180             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_phys_dev_ext_table() can't reallocate list memory");
   4181             return false;
   4182         }
   4183         list->index = new_ptr;
   4184         list->capacity *= 2;
   4185     }
   4186 
   4187     // find an unused index in the hash table and use it
   4188     i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS;
   4189     do {
   4190         if (!inst->phys_dev_ext_disp_hash[i].func_name) {
   4191             assert(inst->phys_dev_ext_disp_hash[i].list.capacity == 0);
   4192             inst->phys_dev_ext_disp_hash[i].func_name =
   4193                 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4194             if (inst->phys_dev_ext_disp_hash[i].func_name == NULL) {
   4195                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4196                            "loader_add_dev_ext_table() can't reallocate "
   4197                            "func_name memory");
   4198                 return false;
   4199             }
   4200             strncpy(inst->phys_dev_ext_disp_hash[i].func_name, funcName, strlen(funcName) + 1);
   4201             list->index[list->count] = i;
   4202             list->count++;
   4203             *ptr_idx = i;
   4204             return true;
   4205         }
   4206         i = (i + 1) % MAX_NUM_UNKNOWN_EXTS;
   4207     } while (i != idx);
   4208 
   4209     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4210                "loader_add_phys_dev_ext_table() couldn't insert into hash table; is "
   4211                "it full?");
   4212     return false;
   4213 }
   4214 
   4215 static bool loader_name_in_phys_dev_ext_table(struct loader_instance *inst, uint32_t *idx, const char *funcName) {
   4216     uint32_t alt_idx;
   4217     if (inst->phys_dev_ext_disp_hash[*idx].func_name && !strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName))
   4218         return true;
   4219 
   4220     // funcName wasn't at the primary spot in the hash table
   4221     // search the list of secondary locations (shallow search, not deep search)
   4222     for (uint32_t i = 0; i < inst->phys_dev_ext_disp_hash[*idx].list.count; i++) {
   4223         alt_idx = inst->phys_dev_ext_disp_hash[*idx].list.index[i];
   4224         if (!strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName)) {
   4225             *idx = alt_idx;
   4226             return true;
   4227         }
   4228     }
   4229 
   4230     return false;
   4231 }
   4232 
   4233 // This function returns a generic trampoline and/or terminator function
   4234 // address for any unknown physical device extension commands.  A hash
   4235 // table is used to keep a list of unknown entry points and their
   4236 // mapping to the physical device extension dispatch table (struct
   4237 // loader_phys_dev_ext_dispatch_table).
   4238 // For a given entry point string (funcName), if an existing mapping is
   4239 // found, then the trampoline address for that mapping is returned in
   4240 // tramp_addr (if it is not NULL) and the terminator address for that
   4241 // mapping is returned in term_addr (if it is not NULL). Otherwise,
   4242 // this unknown entry point has not been seen yet.
   4243 // If it has not been seen before, and perform_checking is 'true',
   4244 // check if a layer or and ICD supports it.  If so then a new entry in
   4245 // the hash table is initialized and the trampoline and/or terminator
   4246 // addresses are returned.
   4247 // Null is returned if the hash table is full or if no discovered layer or
   4248 // ICD returns a non-NULL GetProcAddr for it.
   4249 bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName, bool perform_checking, void **tramp_addr,
   4250                              void **term_addr) {
   4251     uint32_t idx;
   4252     uint32_t seed = 0;
   4253     bool success = false;
   4254 
   4255     if (inst == NULL) {
   4256         goto out;
   4257     }
   4258 
   4259     if (NULL != tramp_addr) {
   4260         *tramp_addr = NULL;
   4261     }
   4262     if (NULL != term_addr) {
   4263         *term_addr = NULL;
   4264     }
   4265 
   4266     // We should always check to see if any ICD supports it.
   4267     if (!loader_check_icds_for_phys_dev_ext_address(inst, funcName)) {
   4268         // If we're not checking layers, or we are and it's not in a layer, just
   4269         // return
   4270         if (!perform_checking || !loader_check_layer_list_for_phys_dev_ext_address(inst, funcName)) {
   4271             goto out;
   4272         }
   4273     }
   4274 
   4275     idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS;
   4276     if (perform_checking && !loader_name_in_phys_dev_ext_table(inst, &idx, funcName)) {
   4277         uint32_t i;
   4278         bool added = false;
   4279 
   4280         // Only need to add first one to get index in Instance.  Others will use
   4281         // the same index.
   4282         if (!added && loader_add_phys_dev_ext_table(inst, &idx, funcName)) {
   4283             added = true;
   4284         }
   4285 
   4286         // Setup the ICD function pointers
   4287         struct loader_icd_term *icd_term = inst->icd_terms;
   4288         while (NULL != icd_term) {
   4289             if (MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION <= icd_term->scanned_icd->interface_version &&
   4290                 NULL != icd_term->scanned_icd->GetPhysicalDeviceProcAddr) {
   4291                 icd_term->phys_dev_ext[idx] =
   4292                     (PFN_PhysDevExt)icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName);
   4293 
   4294                 // Make sure we set the instance dispatch to point to the
   4295                 // loader's terminator now since we can at least handle it
   4296                 // in one ICD.
   4297                 inst->disp->phys_dev_ext[idx] = loader_get_phys_dev_ext_termin(idx);
   4298             } else {
   4299                 icd_term->phys_dev_ext[idx] = NULL;
   4300             }
   4301 
   4302             icd_term = icd_term->next;
   4303         }
   4304 
   4305         // Now, search for the first layer attached and query using it to get
   4306         // the first entry point.
   4307         for (i = 0; i < inst->expanded_activated_layer_list.count; i++) {
   4308             struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i];
   4309             if (layer_prop->interface_version > 1 && NULL != layer_prop->functions.get_physical_device_proc_addr) {
   4310                 inst->disp->phys_dev_ext[idx] =
   4311                     (PFN_PhysDevExt)layer_prop->functions.get_physical_device_proc_addr((VkInstance)inst->instance, funcName);
   4312                 if (NULL != inst->disp->phys_dev_ext[idx]) {
   4313                     break;
   4314                 }
   4315             }
   4316         }
   4317     }
   4318 
   4319     if (NULL != tramp_addr) {
   4320         *tramp_addr = loader_get_phys_dev_ext_tramp(idx);
   4321     }
   4322 
   4323     if (NULL != term_addr) {
   4324         *term_addr = loader_get_phys_dev_ext_termin(idx);
   4325     }
   4326 
   4327     success = true;
   4328 
   4329 out:
   4330     return success;
   4331 }
   4332 
   4333 struct loader_instance *loader_get_instance(const VkInstance instance) {
   4334     // look up the loader_instance in our list by comparing dispatch tables, as
   4335     // there is no guarantee the instance is still a loader_instance* after any
   4336     // layers which wrap the instance object.
   4337     const VkLayerInstanceDispatchTable *disp;
   4338     struct loader_instance *ptr_instance = NULL;
   4339     disp = loader_get_instance_layer_dispatch(instance);
   4340     for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
   4341         if (&inst->disp->layer_inst_disp == disp) {
   4342             ptr_instance = inst;
   4343             break;
   4344         }
   4345     }
   4346     return ptr_instance;
   4347 }
   4348 
   4349 static loader_platform_dl_handle loader_open_layer_lib(const struct loader_instance *inst, const char *chain_type,
   4350                                                        struct loader_layer_properties *prop) {
   4351     if ((prop->lib_handle = loader_platform_open_library(prop->lib_name)) == NULL) {
   4352         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_open_library_error(prop->lib_name));
   4353     } else {
   4354         loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Loading layer library %s", prop->lib_name);
   4355     }
   4356 
   4357     return prop->lib_handle;
   4358 }
   4359 
   4360 static void loader_close_layer_lib(const struct loader_instance *inst, struct loader_layer_properties *prop) {
   4361     if (prop->lib_handle) {
   4362         loader_platform_close_library(prop->lib_handle);
   4363         loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Unloading layer library %s", prop->lib_name);
   4364         prop->lib_handle = NULL;
   4365     }
   4366 }
   4367 
   4368 void loader_deactivate_layers(const struct loader_instance *instance, struct loader_device *device,
   4369                               struct loader_layer_list *list) {
   4370     // Delete instance list of enabled layers and close any layer libraries
   4371     for (uint32_t i = 0; i < list->count; i++) {
   4372         struct loader_layer_properties *layer_prop = &list->list[i];
   4373 
   4374         loader_close_layer_lib(instance, layer_prop);
   4375     }
   4376     loader_destroy_layer_list(instance, device, list);
   4377 }
   4378 
   4379 // Go through the search_list and find any layers which match type. If layer
   4380 // type match is found in then add it to ext_list.
   4381 static void loader_add_implicit_layers(const struct loader_instance *inst, struct loader_layer_list *target_list,
   4382                                        struct loader_layer_list *expanded_target_list,
   4383                                        const struct loader_layer_list *source_list) {
   4384     for (uint32_t src_layer = 0; src_layer < source_list->count; src_layer++) {
   4385         const struct loader_layer_properties *prop = &source_list->list[src_layer];
   4386         if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
   4387             loader_add_implicit_layer(inst, prop, target_list, expanded_target_list, source_list);
   4388         }
   4389     }
   4390 }
   4391 
   4392 // Get the layer name(s) from the env_name environment variable. If layer is found in
   4393 // search_list then add it to layer_list.  But only add it to layer_list if type_flags matches.
   4394 static void loader_add_env_layers(const struct loader_instance *inst, const enum layer_type_flags type_flags, const char *env_name,
   4395                                   struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
   4396                                   const struct loader_layer_list *source_list) {
   4397     char *next, *name;
   4398     char *layer_env = loader_secure_getenv(env_name, inst);
   4399     if (layer_env == NULL) {
   4400         goto out;
   4401     }
   4402     name = loader_stack_alloc(strlen(layer_env) + 1);
   4403     if (name == NULL) {
   4404         goto out;
   4405     }
   4406     strcpy(name, layer_env);
   4407 
   4408     while (name && *name) {
   4409         next = loader_get_next_path(name);
   4410         loader_find_layer_name_add_list(inst, name, type_flags, source_list, target_list, expanded_target_list);
   4411         name = next;
   4412     }
   4413 
   4414 out:
   4415 
   4416     if (layer_env != NULL) {
   4417         loader_free_getenv(layer_env, inst);
   4418     }
   4419 
   4420     return;
   4421 }
   4422 
   4423 VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
   4424                                        const struct loader_layer_list *instance_layers) {
   4425     VkResult err;
   4426 
   4427     assert(inst && "Cannot have null instance");
   4428 
   4429     if (!loader_init_layer_list(inst, &inst->app_activated_layer_list)) {
   4430         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4431                    "loader_enable_instance_layers: Failed to initialize"
   4432                    " application version of the layer list");
   4433         return VK_ERROR_OUT_OF_HOST_MEMORY;
   4434     }
   4435 
   4436     if (!loader_init_layer_list(inst, &inst->expanded_activated_layer_list)) {
   4437         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4438                    "loader_enable_instance_layers: Failed to initialize"
   4439                    " expanded version of the layer list");
   4440         return VK_ERROR_OUT_OF_HOST_MEMORY;
   4441     }
   4442 
   4443     // Add any implicit layers first
   4444     loader_add_implicit_layers(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers);
   4445 
   4446     // Add any layers specified via environment variable next
   4447     loader_add_env_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &inst->app_activated_layer_list,
   4448                           &inst->expanded_activated_layer_list, instance_layers);
   4449 
   4450     // Add layers specified by the application
   4451     err = loader_add_layer_names_to_list(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list,
   4452                                          pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers);
   4453 
   4454     return err;
   4455 }
   4456 
   4457 // Determine the layer interface version to use.
   4458 bool loader_get_layer_interface_version(PFN_vkNegotiateLoaderLayerInterfaceVersion fp_negotiate_layer_version,
   4459                                         VkNegotiateLayerInterface *interface_struct) {
   4460     memset(interface_struct, 0, sizeof(VkNegotiateLayerInterface));
   4461     interface_struct->sType = LAYER_NEGOTIATE_INTERFACE_STRUCT;
   4462     interface_struct->loaderLayerInterfaceVersion = 1;
   4463 
   4464     if (fp_negotiate_layer_version != NULL) {
   4465         // Layer supports the negotiation API, so call it with the loader's
   4466         // latest version supported
   4467         interface_struct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
   4468         VkResult result = fp_negotiate_layer_version(interface_struct);
   4469 
   4470         if (result != VK_SUCCESS) {
   4471             // Layer no longer supports the loader's latest interface version so
   4472             // fail loading the Layer
   4473             return false;
   4474         }
   4475     }
   4476 
   4477     if (interface_struct->loaderLayerInterfaceVersion < MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION) {
   4478         // Loader no longer supports the layer's latest interface version so
   4479         // fail loading the layer
   4480         return false;
   4481     }
   4482 
   4483     return true;
   4484 }
   4485 
   4486 // Given the list of layers to activate in the loader_instance
   4487 // structure. This function will add a VkLayerInstanceCreateInfo
   4488 // structure to the VkInstanceCreateInfo.pNext pointer.
   4489 // Each activated layer will have it's own VkLayerInstanceLink
   4490 // structure that tells the layer what Get*ProcAddr to call to
   4491 // get function pointers to the next layer down.
   4492 // Once the chain info has been created this function will
   4493 // execute the CreateInstance call chain. Each layer will
   4494 // then have an opportunity in it's CreateInstance function
   4495 // to setup it's dispatch table when the lower layer returns
   4496 // successfully.
   4497 // Each layer can wrap or not-wrap the returned VkInstance object
   4498 // as it sees fit.
   4499 // The instance chain is terminated by a loader function
   4500 // that will call CreateInstance on all available ICD's and
   4501 // cache those VkInstance objects for future use.
   4502 VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
   4503                                       struct loader_instance *inst, VkInstance *created_instance) {
   4504     uint32_t activated_layers = 0;
   4505     VkLayerInstanceCreateInfo chain_info;
   4506     VkLayerInstanceLink *layer_instance_link_info = NULL;
   4507     VkInstanceCreateInfo loader_create_info;
   4508     VkResult res;
   4509 
   4510     PFN_vkGetInstanceProcAddr next_gipa = loader_gpa_instance_internal;
   4511     PFN_vkGetInstanceProcAddr cur_gipa = loader_gpa_instance_internal;
   4512     PFN_GetPhysicalDeviceProcAddr next_gpdpa = loader_gpdpa_instance_internal;
   4513     PFN_GetPhysicalDeviceProcAddr cur_gpdpa = loader_gpdpa_instance_internal;
   4514 
   4515     memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
   4516 
   4517     if (inst->expanded_activated_layer_list.count > 0) {
   4518         chain_info.u.pLayerInfo = NULL;
   4519         chain_info.pNext = pCreateInfo->pNext;
   4520         chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
   4521         chain_info.function = VK_LAYER_LINK_INFO;
   4522         loader_create_info.pNext = &chain_info;
   4523 
   4524         layer_instance_link_info = loader_stack_alloc(sizeof(VkLayerInstanceLink) * inst->expanded_activated_layer_list.count);
   4525         if (!layer_instance_link_info) {
   4526             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4527                        "loader_create_instance_chain: Failed to alloc Instance"
   4528                        " objects for layer");
   4529             return VK_ERROR_OUT_OF_HOST_MEMORY;
   4530         }
   4531 
   4532         // Create instance chain of enabled layers
   4533         for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) {
   4534             struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i];
   4535             loader_platform_dl_handle lib_handle;
   4536 
   4537             lib_handle = loader_open_layer_lib(inst, "instance", layer_prop);
   4538             if (!lib_handle) {
   4539                 continue;
   4540             }
   4541 
   4542             if (NULL == layer_prop->functions.negotiate_layer_interface) {
   4543                 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface = NULL;
   4544                 bool functions_in_interface = false;
   4545                 if (strlen(layer_prop->functions.str_negotiate_interface) == 0) {
   4546                     negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address(
   4547                         lib_handle, "vkNegotiateLoaderLayerInterfaceVersion");
   4548                 } else {
   4549                     negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address(
   4550                         lib_handle, layer_prop->functions.str_negotiate_interface);
   4551                 }
   4552 
   4553                 // If we can negotiate an interface version, then we can also
   4554                 // get everything we need from the one function call, so try
   4555                 // that first, and see if we can get all the function pointers
   4556                 // necessary from that one call.
   4557                 if (NULL != negotiate_interface) {
   4558                     layer_prop->functions.negotiate_layer_interface = negotiate_interface;
   4559 
   4560                     VkNegotiateLayerInterface interface_struct;
   4561 
   4562                     if (loader_get_layer_interface_version(negotiate_interface, &interface_struct)) {
   4563                         // Go ahead and set the properties version to the
   4564                         // correct value.
   4565                         layer_prop->interface_version = interface_struct.loaderLayerInterfaceVersion;
   4566 
   4567                         // If the interface is 2 or newer, we have access to the
   4568                         // new GetPhysicalDeviceProcAddr function, so grab it,
   4569                         // and the other necessary functions, from the
   4570                         // structure.
   4571                         if (interface_struct.loaderLayerInterfaceVersion > 1) {
   4572                             cur_gipa = interface_struct.pfnGetInstanceProcAddr;
   4573                             cur_gpdpa = interface_struct.pfnGetPhysicalDeviceProcAddr;
   4574                             if (cur_gipa != NULL) {
   4575                                 // We've set the functions, so make sure we
   4576                                 // don't do the unnecessary calls later.
   4577                                 functions_in_interface = true;
   4578                             }
   4579                         }
   4580                     }
   4581                 }
   4582 
   4583                 if (!functions_in_interface) {
   4584                     if ((cur_gipa = layer_prop->functions.get_instance_proc_addr) == NULL) {
   4585                         if (strlen(layer_prop->functions.str_gipa) == 0) {
   4586                             cur_gipa =
   4587                                 (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
   4588                             layer_prop->functions.get_instance_proc_addr = cur_gipa;
   4589                         } else {
   4590                             cur_gipa = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle,
   4591                                                                                                    layer_prop->functions.str_gipa);
   4592                         }
   4593 
   4594                         if (NULL == cur_gipa) {
   4595                             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4596                                        "loader_create_instance_chain: Failed to"
   4597                                        " find \'vkGetInstanceProcAddr\' in "
   4598                                        "layer %s",
   4599                                        layer_prop->lib_name);
   4600                             continue;
   4601                         }
   4602                     }
   4603                 }
   4604             }
   4605 
   4606             layer_instance_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
   4607             layer_instance_link_info[activated_layers].pfnNextGetInstanceProcAddr = next_gipa;
   4608             layer_instance_link_info[activated_layers].pfnNextGetPhysicalDeviceProcAddr = next_gpdpa;
   4609             next_gipa = cur_gipa;
   4610             if (layer_prop->interface_version > 1 && cur_gpdpa != NULL) {
   4611                 layer_prop->functions.get_physical_device_proc_addr = cur_gpdpa;
   4612                 next_gpdpa = cur_gpdpa;
   4613             }
   4614 
   4615             chain_info.u.pLayerInfo = &layer_instance_link_info[activated_layers];
   4616 
   4617             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Insert instance layer %s (%s)", layer_prop->info.layerName,
   4618                        layer_prop->lib_name);
   4619 
   4620             activated_layers++;
   4621         }
   4622     }
   4623 
   4624     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)next_gipa(*created_instance, "vkCreateInstance");
   4625     if (fpCreateInstance) {
   4626         VkLayerInstanceCreateInfo create_info_disp;
   4627 
   4628         create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
   4629         create_info_disp.function = VK_LOADER_DATA_CALLBACK;
   4630 
   4631         create_info_disp.u.pfnSetInstanceLoaderData = vkSetInstanceDispatch;
   4632 
   4633         create_info_disp.pNext = loader_create_info.pNext;
   4634         loader_create_info.pNext = &create_info_disp;
   4635         res = fpCreateInstance(&loader_create_info, pAllocator, created_instance);
   4636     } else {
   4637         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4638                    "loader_create_instance_chain: Failed to find "
   4639                    "\'vkCreateInstance\'");
   4640         // Couldn't find CreateInstance function!
   4641         res = VK_ERROR_INITIALIZATION_FAILED;
   4642     }
   4643 
   4644     if (res == VK_SUCCESS) {
   4645         loader_init_instance_core_dispatch_table(&inst->disp->layer_inst_disp, next_gipa, *created_instance);
   4646         inst->instance = *created_instance;
   4647     }
   4648 
   4649     return res;
   4650 }
   4651 
   4652 void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst) {
   4653     loader_init_instance_extension_dispatch_table(&inst->disp->layer_inst_disp, inst->disp->layer_inst_disp.GetInstanceProcAddr,
   4654                                                   created_inst);
   4655 }
   4656 
   4657 VkResult loader_create_device_chain(const struct loader_physical_device_tramp *pd, const VkDeviceCreateInfo *pCreateInfo,
   4658                                     const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst,
   4659                                     struct loader_device *dev) {
   4660     uint32_t activated_layers = 0;
   4661     VkLayerDeviceLink *layer_device_link_info;
   4662     VkLayerDeviceCreateInfo chain_info;
   4663     VkDeviceCreateInfo loader_create_info;
   4664     VkResult res;
   4665 
   4666     PFN_vkGetDeviceProcAddr fpGDPA = NULL, nextGDPA = loader_gpa_device_internal;
   4667     PFN_vkGetInstanceProcAddr fpGIPA = NULL, nextGIPA = loader_gpa_instance_internal;
   4668 
   4669     memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
   4670 
   4671     // Before we continue, we need to find out if the KHX_device_group extension is in the enabled list.  If it is, we then
   4672     // need to look for the corresponding VkDeviceGroupDeviceCreateInfoKHX struct in the device list.  This is because we
   4673     // need to replace all the incoming physical device values (which are really loader trampoline physical device values)
   4674     // with the layer/ICD version.
   4675     if (inst->enabled_known_extensions.khx_device_group_creation == 1) {
   4676         struct VkStructureHeader *pNext = (struct VkStructureHeader *)loader_create_info.pNext;
   4677         struct VkStructureHeader *pPrev = (struct VkStructureHeader *)&loader_create_info;
   4678         while (NULL != pNext) {
   4679             if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX == pNext->sType) {
   4680                 VkDeviceGroupDeviceCreateInfoKHX *cur_struct = (VkDeviceGroupDeviceCreateInfoKHX *)pNext;
   4681                 if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) {
   4682                     VkDeviceGroupDeviceCreateInfoKHX *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfoKHX));
   4683                     VkPhysicalDevice *phys_dev_array = NULL;
   4684                     if (NULL == temp_struct) {
   4685                         return VK_ERROR_OUT_OF_HOST_MEMORY;
   4686                     }
   4687                     memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfoKHX));
   4688                     phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount);
   4689                     if (NULL == phys_dev_array) {
   4690                         return VK_ERROR_OUT_OF_HOST_MEMORY;
   4691                     }
   4692 
   4693                     // Before calling down, replace the incoming physical device values (which are really loader trampoline
   4694                     // physical devices) with the next layer (or possibly even the terminator) physical device values.
   4695                     struct loader_physical_device_tramp *cur_tramp;
   4696                     for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) {
   4697                         cur_tramp = (struct loader_physical_device_tramp *)cur_struct->pPhysicalDevices[phys_dev];
   4698                         phys_dev_array[phys_dev] = cur_tramp->phys_dev;
   4699                     }
   4700                     temp_struct->pPhysicalDevices = phys_dev_array;
   4701 
   4702                     // Replace the old struct in the pNext chain with this one.
   4703                     pPrev->pNext = (const void *)temp_struct;
   4704                     pNext = (struct VkStructureHeader *)(temp_struct);
   4705                 }
   4706                 break;
   4707             }
   4708 
   4709             pPrev = pNext;
   4710             pNext = (struct VkStructureHeader *)(pPrev->pNext);
   4711         }
   4712     }
   4713 
   4714     layer_device_link_info = loader_stack_alloc(sizeof(VkLayerDeviceLink) * dev->expanded_activated_layer_list.count);
   4715     if (!layer_device_link_info) {
   4716         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4717                    "loader_create_device_chain: Failed to alloc Device objects"
   4718                    " for layer.  Skipping Layer.");
   4719         return VK_ERROR_OUT_OF_HOST_MEMORY;
   4720     }
   4721 
   4722     if (dev->expanded_activated_layer_list.count > 0) {
   4723         chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
   4724         chain_info.function = VK_LAYER_LINK_INFO;
   4725         chain_info.u.pLayerInfo = NULL;
   4726         chain_info.pNext = loader_create_info.pNext;
   4727         loader_create_info.pNext = &chain_info;
   4728 
   4729         // Create instance chain of enabled layers
   4730         for (int32_t i = dev->expanded_activated_layer_list.count - 1; i >= 0; i--) {
   4731             struct loader_layer_properties *layer_prop = &dev->expanded_activated_layer_list.list[i];
   4732             loader_platform_dl_handle lib_handle;
   4733             bool functions_in_interface = false;
   4734 
   4735             lib_handle = loader_open_layer_lib(inst, "device", layer_prop);
   4736             if (!lib_handle) {
   4737                 continue;
   4738             }
   4739 
   4740             // If we can negotiate an interface version, then we can also get everything we need from the one function
   4741             // call, so try that first, and see if we can get all the function pointers necessary from that one call.
   4742             if (NULL == layer_prop->functions.negotiate_layer_interface) {
   4743                 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface = NULL;
   4744                 if (strlen(layer_prop->functions.str_negotiate_interface) == 0) {
   4745                     negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address(
   4746                         lib_handle, "vkNegotiateLoaderLayerInterfaceVersion");
   4747                 } else {
   4748                     negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address(
   4749                         lib_handle, layer_prop->functions.str_negotiate_interface);
   4750                 }
   4751 
   4752                 if (NULL != negotiate_interface) {
   4753                     layer_prop->functions.negotiate_layer_interface = negotiate_interface;
   4754 
   4755                     VkNegotiateLayerInterface interface_struct;
   4756 
   4757                     if (loader_get_layer_interface_version(negotiate_interface, &interface_struct)) {
   4758                         // Go ahead and set the properties version to the correct value.
   4759                         layer_prop->interface_version = interface_struct.loaderLayerInterfaceVersion;
   4760 
   4761                         // If the interface is 2 or newer, we have access to the new GetPhysicalDeviceProcAddr
   4762                         // function, so grab it, and the other necessary functions, from the structure.
   4763                         if (interface_struct.loaderLayerInterfaceVersion > 1) {
   4764                             fpGIPA = interface_struct.pfnGetInstanceProcAddr;
   4765                             fpGDPA = interface_struct.pfnGetDeviceProcAddr;
   4766                             if (fpGIPA != NULL && fpGDPA) {
   4767                                 // We've set the functions, so make sure we
   4768                                 // don't do the unnecessary calls later.
   4769                                 functions_in_interface = true;
   4770                             }
   4771                         }
   4772                     }
   4773                 }
   4774             }
   4775 
   4776             if (!functions_in_interface) {
   4777                 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
   4778                     if (strlen(layer_prop->functions.str_gipa) == 0) {
   4779                         fpGIPA = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
   4780                         layer_prop->functions.get_instance_proc_addr = fpGIPA;
   4781                     } else
   4782                         fpGIPA =
   4783                             (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
   4784                     if (!fpGIPA) {
   4785                         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4786                                    "loader_create_device_chain: Failed to find "
   4787                                    "\'vkGetInstanceProcAddr\' in layer %s.  Skipping"
   4788                                    " layer.",
   4789                                    layer_prop->lib_name);
   4790                         continue;
   4791                     }
   4792                 }
   4793                 if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
   4794                     if (strlen(layer_prop->functions.str_gdpa) == 0) {
   4795                         fpGDPA = (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
   4796                         layer_prop->functions.get_device_proc_addr = fpGDPA;
   4797                     } else
   4798                         fpGDPA =
   4799                             (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
   4800                     if (!fpGDPA) {
   4801                         loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s",
   4802                                    layer_prop->lib_name);
   4803                         continue;
   4804                     }
   4805                 }
   4806             }
   4807             layer_device_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
   4808             layer_device_link_info[activated_layers].pfnNextGetInstanceProcAddr = nextGIPA;
   4809             layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr = nextGDPA;
   4810             chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers];
   4811             nextGIPA = fpGIPA;
   4812             nextGDPA = fpGDPA;
   4813 
   4814             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Inserted device layer %s (%s)", layer_prop->info.layerName,
   4815                        layer_prop->lib_name);
   4816 
   4817             activated_layers++;
   4818         }
   4819     }
   4820 
   4821     VkDevice created_device = (VkDevice)dev;
   4822     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)nextGIPA(inst->instance, "vkCreateDevice");
   4823     if (fpCreateDevice) {
   4824         VkLayerDeviceCreateInfo create_info_disp;
   4825 
   4826         create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
   4827         create_info_disp.function = VK_LOADER_DATA_CALLBACK;
   4828 
   4829         create_info_disp.u.pfnSetDeviceLoaderData = vkSetDeviceDispatch;
   4830 
   4831         create_info_disp.pNext = loader_create_info.pNext;
   4832         loader_create_info.pNext = &create_info_disp;
   4833         res = fpCreateDevice(pd->phys_dev, &loader_create_info, pAllocator, &created_device);
   4834         if (res != VK_SUCCESS) {
   4835             return res;
   4836         }
   4837         dev->chain_device = created_device;
   4838     } else {
   4839         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4840                    "loader_create_device_chain: Failed to find \'vkCreateDevice\' "
   4841                    "in layer %s");
   4842         // Couldn't find CreateDevice function!
   4843         return VK_ERROR_INITIALIZATION_FAILED;
   4844     }
   4845 
   4846     // Initialize device dispatch table
   4847     loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA, dev->chain_device);
   4848 
   4849     return res;
   4850 }
   4851 
   4852 VkResult loader_validate_layers(const struct loader_instance *inst, const uint32_t layer_count,
   4853                                 const char *const *ppEnabledLayerNames, const struct loader_layer_list *list) {
   4854     struct loader_layer_properties *prop;
   4855 
   4856     for (uint32_t i = 0; i < layer_count; i++) {
   4857         VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]);
   4858         if (result != VK_STRING_ERROR_NONE) {
   4859             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4860                        "loader_validate_layers: Device ppEnabledLayerNames "
   4861                        "contains string that is too long or is badly formed");
   4862             return VK_ERROR_LAYER_NOT_PRESENT;
   4863         }
   4864 
   4865         prop = loader_get_layer_property(ppEnabledLayerNames[i], list);
   4866         if (NULL == prop) {
   4867             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4868                        "loader_validate_layers: Layer %d does not exist in the list of available layers", i);
   4869             return VK_ERROR_LAYER_NOT_PRESENT;
   4870         }
   4871     }
   4872     return VK_SUCCESS;
   4873 }
   4874 
   4875 VkResult loader_validate_instance_extensions(const struct loader_instance *inst, const struct loader_extension_list *icd_exts,
   4876                                              const struct loader_layer_list *instance_layers,
   4877                                              const VkInstanceCreateInfo *pCreateInfo) {
   4878     VkExtensionProperties *extension_prop;
   4879     char *env_value;
   4880     bool check_if_known = true;
   4881     VkResult res = VK_SUCCESS;
   4882 
   4883     struct loader_layer_list active_layers;
   4884     struct loader_layer_list expanded_layers;
   4885     memset(&active_layers, 0, sizeof(active_layers));
   4886     memset(&expanded_layers, 0, sizeof(expanded_layers));
   4887     if (!loader_init_layer_list(inst, &active_layers)) {
   4888         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   4889         goto out;
   4890     }
   4891     if (!loader_init_layer_list(inst, &expanded_layers)) {
   4892         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   4893         goto out;
   4894     }
   4895 
   4896     // Build the lists of active layers (including metalayers) and expanded layers (with metalayers resolved to their components)
   4897     loader_add_implicit_layers(inst, &active_layers, &expanded_layers, instance_layers);
   4898     loader_add_env_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &active_layers, &expanded_layers,
   4899                           instance_layers);
   4900     res = loader_add_layer_names_to_list(inst, &active_layers, &expanded_layers, pCreateInfo->enabledLayerCount,
   4901                                          pCreateInfo->ppEnabledLayerNames, instance_layers);
   4902     if (VK_SUCCESS != res) {
   4903         goto out;
   4904     }
   4905 
   4906     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
   4907         VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
   4908         if (result != VK_STRING_ERROR_NONE) {
   4909             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4910                        "loader_validate_instance_extensions: Instance ppEnabledExtensionNames contains "
   4911                        "string that is too long or is badly formed");
   4912             res = VK_ERROR_EXTENSION_NOT_PRESENT;
   4913             goto out;
   4914         }
   4915 
   4916         // Check if a user wants to disable the instance extension filtering behavior
   4917         env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst);
   4918         if (NULL != env_value && atoi(env_value) != 0) {
   4919             check_if_known = false;
   4920         }
   4921         loader_free_getenv(env_value, inst);
   4922 
   4923         if (check_if_known) {
   4924             // See if the extension is in the list of supported extensions
   4925             bool found = false;
   4926             for (uint32_t j = 0; LOADER_INSTANCE_EXTENSIONS[j] != NULL; j++) {
   4927                 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], LOADER_INSTANCE_EXTENSIONS[j]) == 0) {
   4928                     found = true;
   4929                     break;
   4930                 }
   4931             }
   4932 
   4933             // If it isn't in the list, return an error
   4934             if (!found) {
   4935                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4936                            "loader_validate_instance_extensions: Extension %s not found in list of known instance extensions.",
   4937                            pCreateInfo->ppEnabledExtensionNames[i]);
   4938                 res = VK_ERROR_EXTENSION_NOT_PRESENT;
   4939                 goto out;
   4940             }
   4941         }
   4942 
   4943         extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], icd_exts);
   4944 
   4945         if (extension_prop) {
   4946             continue;
   4947         }
   4948 
   4949         extension_prop = NULL;
   4950 
   4951         // Not in global list, search expanded layer extension list
   4952         for (uint32_t j = 0; NULL == extension_prop && j < expanded_layers.count; ++j) {
   4953             extension_prop =
   4954                 get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], &expanded_layers.list[j].instance_extension_list);
   4955         }
   4956 
   4957         if (!extension_prop) {
   4958             // Didn't find extension name in any of the global layers, error out
   4959             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4960                        "loader_validate_instance_extensions: Instance extension %s not supported by available ICDs or enabled "
   4961                        "layers.",
   4962                        pCreateInfo->ppEnabledExtensionNames[i]);
   4963             res = VK_ERROR_EXTENSION_NOT_PRESENT;
   4964             goto out;
   4965         }
   4966     }
   4967 
   4968 out:
   4969     loader_destroy_layer_list(inst, NULL, &active_layers);
   4970     loader_destroy_layer_list(inst, NULL, &expanded_layers);
   4971     return res;
   4972 }
   4973 
   4974 VkResult loader_validate_device_extensions(struct loader_physical_device_tramp *phys_dev,
   4975                                            const struct loader_layer_list *activated_device_layers,
   4976                                            const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo) {
   4977     VkExtensionProperties *extension_prop;
   4978     struct loader_layer_properties *layer_prop;
   4979 
   4980     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
   4981         VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
   4982         if (result != VK_STRING_ERROR_NONE) {
   4983             loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4984                        "loader_validate_device_extensions: Device ppEnabledExtensionNames contains "
   4985                        "string that is too long or is badly formed");
   4986             return VK_ERROR_EXTENSION_NOT_PRESENT;
   4987         }
   4988 
   4989         const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
   4990         extension_prop = get_extension_property(extension_name, icd_exts);
   4991 
   4992         if (extension_prop) {
   4993             continue;
   4994         }
   4995 
   4996         // Not in global list, search activated layer extension lists
   4997         for (uint32_t j = 0; j < activated_device_layers->count; j++) {
   4998             layer_prop = &activated_device_layers->list[j];
   4999 
   5000             extension_prop = get_dev_extension_property(extension_name, &layer_prop->device_extension_list);
   5001             if (extension_prop) {
   5002                 // Found the extension in one of the layers enabled by the app.
   5003                 break;
   5004             }
   5005         }
   5006 
   5007         if (!extension_prop) {
   5008             // Didn't find extension name in any of the device layers, error out
   5009             loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5010                        "loader_validate_device_extensions: Device extension %s not supported by selected physical device "
   5011                        "or enabled layers.",
   5012                        pCreateInfo->ppEnabledExtensionNames[i]);
   5013             return VK_ERROR_EXTENSION_NOT_PRESENT;
   5014         }
   5015     }
   5016     return VK_SUCCESS;
   5017 }
   5018 
   5019 // Terminator functions for the Instance chain
   5020 // All named terminator_<Vulakn API name>
   5021 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
   5022                                                          const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
   5023     struct loader_icd_term *icd_term;
   5024     VkExtensionProperties *prop;
   5025     char **filtered_extension_names = NULL;
   5026     VkInstanceCreateInfo icd_create_info;
   5027     VkResult res = VK_SUCCESS;
   5028     bool one_icd_successful = false;
   5029 
   5030     struct loader_instance *ptr_instance = (struct loader_instance *)*pInstance;
   5031     memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
   5032 
   5033     icd_create_info.enabledLayerCount = 0;
   5034     icd_create_info.ppEnabledLayerNames = NULL;
   5035 
   5036     // NOTE: Need to filter the extensions to only those supported by the ICD.
   5037     //       No ICD will advertise support for layers. An ICD library could
   5038     //       support a layer, but it would be independent of the actual ICD,
   5039     //       just in the same library.
   5040     filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
   5041     if (!filtered_extension_names) {
   5042         loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5043                    "terminator_CreateInstance: Failed create extension name array for %d extensions",
   5044                    pCreateInfo->enabledExtensionCount);
   5045         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5046         goto out;
   5047     }
   5048     icd_create_info.ppEnabledExtensionNames = (const char *const *)filtered_extension_names;
   5049 
   5050     for (uint32_t i = 0; i < ptr_instance->icd_tramp_list.count; i++) {
   5051         icd_term = loader_icd_add(ptr_instance, &ptr_instance->icd_tramp_list.scanned_list[i]);
   5052         if (NULL == icd_term) {
   5053             loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5054                        "terminator_CreateInstance: Failed to add ICD %d to ICD trampoline list.", i);
   5055             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5056             goto out;
   5057         }
   5058 
   5059         // If any error happens after here, we need to remove the ICD from the list,
   5060         // because we've already added it, but haven't validated it
   5061 
   5062         icd_create_info.enabledExtensionCount = 0;
   5063         struct loader_extension_list icd_exts;
   5064 
   5065         loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
   5066         // traverse scanned icd list adding non-duplicate extensions to the list
   5067         res = loader_init_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties));
   5068         if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   5069             // If out of memory, bail immediately.
   5070             goto out;
   5071         } else if (VK_SUCCESS != res) {
   5072             // Something bad happened with this ICD, so free it and try the
   5073             // next.
   5074             ptr_instance->icd_terms = icd_term->next;
   5075             icd_term->next = NULL;
   5076             loader_icd_destroy(ptr_instance, icd_term, pAllocator);
   5077             continue;
   5078         }
   5079 
   5080         res = loader_add_instance_extensions(ptr_instance, icd_term->scanned_icd->EnumerateInstanceExtensionProperties,
   5081                                              icd_term->scanned_icd->lib_name, &icd_exts);
   5082         if (VK_SUCCESS != res) {
   5083             loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts);
   5084             if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   5085                 // If out of memory, bail immediately.
   5086                 goto out;
   5087             } else {
   5088                 // Something bad happened with this ICD, so free it and try the next.
   5089                 ptr_instance->icd_terms = icd_term->next;
   5090                 icd_term->next = NULL;
   5091                 loader_icd_destroy(ptr_instance, icd_term, pAllocator);
   5092                 continue;
   5093             }
   5094         }
   5095 
   5096         for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) {
   5097             prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[j], &icd_exts);
   5098             if (prop) {
   5099                 filtered_extension_names[icd_create_info.enabledExtensionCount] = (char *)pCreateInfo->ppEnabledExtensionNames[j];
   5100                 icd_create_info.enabledExtensionCount++;
   5101             }
   5102         }
   5103 
   5104         loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts);
   5105 
   5106         VkResult icd_result =
   5107             ptr_instance->icd_tramp_list.scanned_list[i].CreateInstance(&icd_create_info, pAllocator, &(icd_term->instance));
   5108         if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_result) {
   5109             // If out of memory, bail immediately.
   5110             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5111             goto out;
   5112         } else if (VK_SUCCESS != icd_result) {
   5113             loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   5114                        "terminator_CreateInstance: Failed to CreateInstance in "
   5115                        "ICD %d.  Skipping ICD.",
   5116                        i);
   5117             ptr_instance->icd_terms = icd_term->next;
   5118             icd_term->next = NULL;
   5119             loader_icd_destroy(ptr_instance, icd_term, pAllocator);
   5120             continue;
   5121         }
   5122 
   5123         if (!loader_icd_init_entries(icd_term, icd_term->instance,
   5124                                      ptr_instance->icd_tramp_list.scanned_list[i].GetInstanceProcAddr)) {
   5125             loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   5126                        "terminator_CreateInstance: Failed to CreateInstance and find "
   5127                        "entrypoints with ICD.  Skipping ICD.");
   5128             ptr_instance->icd_terms = icd_term->next;
   5129             icd_term->next = NULL;
   5130             loader_icd_destroy(ptr_instance, icd_term, pAllocator);
   5131             continue;
   5132         }
   5133 
   5134         // If we made it this far, at least one ICD was successful
   5135         one_icd_successful = true;
   5136     }
   5137 
   5138     // If no ICDs were added to instance list and res is unchanged from it's initial value, the loader was unable to
   5139     // find a suitable ICD.
   5140     if (VK_SUCCESS == res && (ptr_instance->icd_terms == NULL || !one_icd_successful)) {
   5141         res = VK_ERROR_INCOMPATIBLE_DRIVER;
   5142     }
   5143 
   5144 out:
   5145 
   5146     if (VK_SUCCESS != res) {
   5147         while (NULL != ptr_instance->icd_terms) {
   5148             icd_term = ptr_instance->icd_terms;
   5149             ptr_instance->icd_terms = icd_term->next;
   5150             if (NULL != icd_term->instance) {
   5151                 icd_term->dispatch.DestroyInstance(icd_term->instance, pAllocator);
   5152             }
   5153             loader_icd_destroy(ptr_instance, icd_term, pAllocator);
   5154         }
   5155     }
   5156 
   5157     return res;
   5158 }
   5159 
   5160 VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
   5161     struct loader_instance *ptr_instance = loader_instance(instance);
   5162     if (NULL == ptr_instance) {
   5163         return;
   5164     }
   5165     struct loader_icd_term *icd_terms = ptr_instance->icd_terms;
   5166     struct loader_icd_term *next_icd_term;
   5167 
   5168     // Remove this instance from the list of instances:
   5169     struct loader_instance *prev = NULL;
   5170     struct loader_instance *next = loader.instances;
   5171     while (next != NULL) {
   5172         if (next == ptr_instance) {
   5173             // Remove this instance from the list:
   5174             if (prev)
   5175                 prev->next = next->next;
   5176             else
   5177                 loader.instances = next->next;
   5178             break;
   5179         }
   5180         prev = next;
   5181         next = next->next;
   5182     }
   5183 
   5184     while (NULL != icd_terms) {
   5185         if (icd_terms->instance) {
   5186             icd_terms->dispatch.DestroyInstance(icd_terms->instance, pAllocator);
   5187         }
   5188         next_icd_term = icd_terms->next;
   5189         icd_terms->instance = VK_NULL_HANDLE;
   5190         loader_icd_destroy(ptr_instance, icd_terms, pAllocator);
   5191 
   5192         icd_terms = next_icd_term;
   5193     }
   5194 
   5195     loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
   5196     loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_tramp_list);
   5197     loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list);
   5198     if (NULL != ptr_instance->phys_devs_term) {
   5199         for (uint32_t i = 0; i < ptr_instance->phys_dev_count_term; i++) {
   5200             loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term[i]);
   5201         }
   5202         loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term);
   5203     }
   5204     if (NULL != ptr_instance->phys_dev_groups_term) {
   5205         for (uint32_t i = 0; i < ptr_instance->phys_dev_group_count_term; i++) {
   5206             loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term[i]);
   5207         }
   5208         loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term);
   5209     }
   5210     loader_free_dev_ext_table(ptr_instance);
   5211     loader_free_phys_dev_ext_table(ptr_instance);
   5212 }
   5213 
   5214 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
   5215                                                        const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
   5216     VkResult res = VK_SUCCESS;
   5217     struct loader_physical_device_term *phys_dev_term;
   5218     phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5219     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5220 
   5221     struct loader_device *dev = (struct loader_device *)*pDevice;
   5222     PFN_vkCreateDevice fpCreateDevice = icd_term->dispatch.CreateDevice;
   5223     struct loader_extension_list icd_exts;
   5224 
   5225     struct VkStructureHeader *caller_dgci_container = NULL;
   5226     VkDeviceGroupDeviceCreateInfoKHX *caller_dgci = NULL;
   5227 
   5228     dev->phys_dev_term = phys_dev_term;
   5229 
   5230     icd_exts.list = NULL;
   5231 
   5232     if (fpCreateDevice == NULL) {
   5233         loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5234                    "terminator_CreateDevice: No vkCreateDevice command exposed "
   5235                    "by ICD %s",
   5236                    icd_term->scanned_icd->lib_name);
   5237         res = VK_ERROR_INITIALIZATION_FAILED;
   5238         goto out;
   5239     }
   5240 
   5241     VkDeviceCreateInfo localCreateInfo;
   5242     memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
   5243 
   5244     // NOTE: Need to filter the extensions to only those supported by the ICD.
   5245     //       No ICD will advertise support for layers. An ICD library could support a layer,
   5246     //       but it would be independent of the actual ICD, just in the same library.
   5247     char **filtered_extension_names = NULL;
   5248     if (0 < pCreateInfo->enabledExtensionCount) {
   5249         filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
   5250         if (NULL == filtered_extension_names) {
   5251             loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5252                        "terminator_CreateDevice: Failed to create extension name "
   5253                        "storage for %d extensions %d",
   5254                        pCreateInfo->enabledExtensionCount);
   5255             return VK_ERROR_OUT_OF_HOST_MEMORY;
   5256         }
   5257     }
   5258 
   5259     localCreateInfo.enabledLayerCount = 0;
   5260     localCreateInfo.ppEnabledLayerNames = NULL;
   5261 
   5262     localCreateInfo.enabledExtensionCount = 0;
   5263     localCreateInfo.ppEnabledExtensionNames = (const char *const *)filtered_extension_names;
   5264 
   5265     // Get the physical device (ICD) extensions
   5266     res = loader_init_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties));
   5267     if (VK_SUCCESS != res) {
   5268         goto out;
   5269     }
   5270 
   5271     res = loader_add_device_extensions(icd_term->this_instance, icd_term->dispatch.EnumerateDeviceExtensionProperties,
   5272                                        phys_dev_term->phys_dev, icd_term->scanned_icd->lib_name, &icd_exts);
   5273     if (res != VK_SUCCESS) {
   5274         goto out;
   5275     }
   5276 
   5277     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
   5278         const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
   5279         VkExtensionProperties *prop = get_extension_property(extension_name, &icd_exts);
   5280         if (prop) {
   5281             filtered_extension_names[localCreateInfo.enabledExtensionCount] = (char *)extension_name;
   5282             localCreateInfo.enabledExtensionCount++;
   5283         } else {
   5284             loader_log(icd_term->this_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   5285                        "vkCreateDevice extension %s not available for "
   5286                        "devices associated with ICD %s",
   5287                        extension_name, icd_term->scanned_icd->lib_name);
   5288         }
   5289     }
   5290 
   5291     // Before we continue, If KHX_device_group is the list of enabled and viable extensions, then we then need to look for the
   5292     // corresponding VkDeviceGroupDeviceCreateInfoKHX struct in the device list and replace all the physical device values (which
   5293     // are really loader physical device terminator values) with the ICD versions.
   5294     if (icd_term->this_instance->enabled_known_extensions.khx_device_group_creation == 1) {
   5295         struct VkStructureHeader *pNext = (struct VkStructureHeader *)localCreateInfo.pNext;
   5296         struct VkStructureHeader *pPrev = (struct VkStructureHeader *)&localCreateInfo;
   5297         while (NULL != pNext) {
   5298             if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX == pNext->sType) {
   5299                 VkDeviceGroupDeviceCreateInfoKHX *cur_struct = (VkDeviceGroupDeviceCreateInfoKHX *)pNext;
   5300                 if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) {
   5301                     VkDeviceGroupDeviceCreateInfoKHX *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfoKHX));
   5302                     VkPhysicalDevice *phys_dev_array = NULL;
   5303                     if (NULL == temp_struct) {
   5304                         return VK_ERROR_OUT_OF_HOST_MEMORY;
   5305                     }
   5306                     memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfoKHX));
   5307                     phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount);
   5308                     if (NULL == phys_dev_array) {
   5309                         return VK_ERROR_OUT_OF_HOST_MEMORY;
   5310                     }
   5311 
   5312                     // Before calling down, replace the incoming physical device values (which are really loader terminator
   5313                     // physical devices) with the ICDs physical device values.
   5314                     struct loader_physical_device_term *cur_term;
   5315                     for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) {
   5316                         cur_term = (struct loader_physical_device_term *)cur_struct->pPhysicalDevices[phys_dev];
   5317                         phys_dev_array[phys_dev] = cur_term->phys_dev;
   5318                     }
   5319                     temp_struct->pPhysicalDevices = phys_dev_array;
   5320 
   5321                     // Keep track of pointers to restore pNext chain before returning
   5322                     caller_dgci_container = pPrev;
   5323                     caller_dgci = cur_struct;
   5324 
   5325                     // Replace the old struct in the pNext chain with this one.
   5326                     pPrev->pNext = (const void *)temp_struct;
   5327                     pNext = (struct VkStructureHeader *)(temp_struct);
   5328                 }
   5329                 break;
   5330             }
   5331 
   5332             pPrev = pNext;
   5333             pNext = (struct VkStructureHeader *)(pPrev->pNext);
   5334         }
   5335     }
   5336 
   5337     // Handle loader emulation for structs that are not supported by the ICD:
   5338     // Presently, the emulation leaves the pNext chain alone. This means that the ICD will receive items in the chain which
   5339     // are not recognized by the ICD. If this causes the ICD to fail, then the items would have to be removed here. The current
   5340     // implementation does not remove them because copying the pNext chain would be impossible if the loader does not recognize
   5341     // the any of the struct types, as the loader would not know the size to allocate and copy.
   5342     if (icd_term->dispatch.GetPhysicalDeviceFeatures2KHR == NULL) {
   5343         const void *pNext = localCreateInfo.pNext;
   5344         while (pNext != NULL) {
   5345             switch (*(VkStructureType *)pNext) {
   5346                 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
   5347                     loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   5348                                "vkCreateDevice: Emulating handling of VkPhysicalDeviceFeatures2KHR in pNext chain for ICD \"%s\"",
   5349                                icd_term->scanned_icd->lib_name);
   5350                     const VkPhysicalDeviceFeatures2KHR *features = pNext;
   5351 
   5352                     // Verify that VK_KHR_get_physical_device_properties2 is enabled
   5353                     if (icd_term->this_instance->enabled_known_extensions.khr_get_physical_device_properties2) {
   5354                         localCreateInfo.pEnabledFeatures = &features->features;
   5355                     }
   5356 
   5357                     // Leave this item in the pNext chain for now
   5358 
   5359                     pNext = features->pNext;
   5360                     break;
   5361                 }
   5362 
   5363                 case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX: {
   5364                     loader_log(
   5365                         icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   5366                         "vkCreateDevice: Emulating handling of VkDeviceGroupDeviceCreateInfoKHX in pNext chain for ICD \"%s\"",
   5367                         icd_term->scanned_icd->lib_name);
   5368                     const VkDeviceGroupDeviceCreateInfoKHX *group_info = pNext;
   5369 
   5370                     // The group must contain only this one device, since physical device groups aren't actually supported
   5371                     if (group_info->physicalDeviceCount != 1 || group_info->pPhysicalDevices[0] != physicalDevice) {
   5372                         loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5373                                    "vkCreateDevice: Emulation failed to create device from device group info");
   5374                         res = VK_ERROR_INITIALIZATION_FAILED;
   5375                         goto out;
   5376                     }
   5377 
   5378                     // Nothing needs to be done here because we're leaving the item in the pNext chain and because the spec states
   5379                     // that the physicalDevice argument must be included in the device group, and we've already checked that it is
   5380 
   5381                     pNext = group_info->pNext;
   5382                     break;
   5383                 }
   5384 
   5385                 // Multiview properties are also allowed, but since VK_KHX_multiview is a device extension, we'll just let the ICD
   5386                 // handle that error when the user enables the extension here
   5387                 default: {
   5388                     const struct VkStructureHeader *header = pNext;
   5389                     pNext = header->pNext;
   5390                     break;
   5391                 }
   5392             }
   5393         }
   5394     }
   5395 
   5396     res = fpCreateDevice(phys_dev_term->phys_dev, &localCreateInfo, pAllocator, &dev->icd_device);
   5397     if (res != VK_SUCCESS) {
   5398         loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5399                    "terminator_CreateDevice: Failed in ICD %s vkCreateDevice"
   5400                    "call",
   5401                    icd_term->scanned_icd->lib_name);
   5402         goto out;
   5403     }
   5404 
   5405     *pDevice = dev->icd_device;
   5406     loader_add_logical_device(icd_term->this_instance, icd_term, dev);
   5407 
   5408     // Init dispatch pointer in new device object
   5409     loader_init_dispatch(*pDevice, &dev->loader_dispatch);
   5410 
   5411 out:
   5412     if (NULL != icd_exts.list) {
   5413         loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts);
   5414     }
   5415 
   5416     // Restore pNext pointer to old VkDeviceGroupDeviceCreateInfoKHX
   5417     // in the chain to maintain consistency for the caller.
   5418     if (caller_dgci_container != NULL) {
   5419         caller_dgci_container->pNext = caller_dgci;
   5420     }
   5421 
   5422     return res;
   5423 }
   5424 
   5425 VkResult setupLoaderTrampPhysDevs(VkInstance instance) {
   5426     VkResult res = VK_SUCCESS;
   5427     VkPhysicalDevice *local_phys_devs = NULL;
   5428     struct loader_instance *inst;
   5429     uint32_t total_count = 0;
   5430     struct loader_physical_device_tramp **new_phys_devs = NULL;
   5431 
   5432     inst = loader_get_instance(instance);
   5433     if (NULL == inst) {
   5434         res = VK_ERROR_INITIALIZATION_FAILED;
   5435         goto out;
   5436     }
   5437 
   5438     // Query how many GPUs there
   5439     res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(instance, &total_count, NULL);
   5440     if (res != VK_SUCCESS) {
   5441         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5442                    "setupLoaderTrampPhysDevs:  Failed during dispatch call "
   5443                    "of \'vkEnumeratePhysicalDevices\' to lower layers or "
   5444                    "loader to get count.");
   5445         goto out;
   5446     }
   5447 
   5448     // Really use what the total GPU count is since Optimus and other layers may mess
   5449     // the count up.
   5450     total_count = inst->total_gpu_count;
   5451 
   5452     // Create an array for the new physical devices, which will be stored
   5453     // in the instance for the trampoline code.
   5454     new_phys_devs = (struct loader_physical_device_tramp **)loader_instance_heap_alloc(
   5455         inst, total_count * sizeof(struct loader_physical_device_tramp *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   5456     if (NULL == new_phys_devs) {
   5457         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5458                    "setupLoaderTrampPhysDevs:  Failed to allocate new physical device"
   5459                    " array of size %d",
   5460                    total_count);
   5461         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5462         goto out;
   5463     }
   5464     memset(new_phys_devs, 0, total_count * sizeof(struct loader_physical_device_tramp *));
   5465 
   5466     // Create a temporary array (on the stack) to keep track of the
   5467     // returned VkPhysicalDevice values.
   5468     local_phys_devs = loader_stack_alloc(sizeof(VkPhysicalDevice) * total_count);
   5469     if (NULL == local_phys_devs) {
   5470         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5471                    "setupLoaderTrampPhysDevs:  Failed to allocate local "
   5472                    "physical device array of size %d",
   5473                    total_count);
   5474         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5475         goto out;
   5476     }
   5477     memset(local_phys_devs, 0, sizeof(VkPhysicalDevice) * total_count);
   5478 
   5479     res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(instance, &total_count, local_phys_devs);
   5480     if (VK_SUCCESS != res) {
   5481         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5482                    "setupLoaderTrampPhysDevs:  Failed during dispatch call "
   5483                    "of \'vkEnumeratePhysicalDevices\' to lower layers or "
   5484                    "loader to get content.");
   5485         goto out;
   5486     }
   5487 
   5488     // Copy or create everything to fill the new array of physical devices
   5489     for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) {
   5490         // Check if this physical device is already in the old buffer
   5491         for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_tramp; old_idx++) {
   5492             if (local_phys_devs[new_idx] == inst->phys_devs_tramp[old_idx]->phys_dev) {
   5493                 new_phys_devs[new_idx] = inst->phys_devs_tramp[old_idx];
   5494                 break;
   5495             }
   5496         }
   5497 
   5498         // If this physical device isn't in the old buffer, create it
   5499         if (NULL == new_phys_devs[new_idx]) {
   5500             new_phys_devs[new_idx] = (struct loader_physical_device_tramp *)loader_instance_heap_alloc(
   5501                 inst, sizeof(struct loader_physical_device_tramp), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   5502             if (NULL == new_phys_devs[new_idx]) {
   5503                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5504                            "setupLoaderTrampPhysDevs:  Failed to allocate "
   5505                            "physical device trampoline object %d",
   5506                            new_idx);
   5507                 total_count = new_idx;
   5508                 res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5509                 goto out;
   5510             }
   5511 
   5512             // Initialize the new physicalDevice object
   5513             loader_set_dispatch((void *)new_phys_devs[new_idx], inst->disp);
   5514             new_phys_devs[new_idx]->this_instance = inst;
   5515             new_phys_devs[new_idx]->phys_dev = local_phys_devs[new_idx];
   5516         }
   5517     }
   5518 
   5519 out:
   5520 
   5521     if (VK_SUCCESS != res) {
   5522         if (NULL != new_phys_devs) {
   5523             for (uint32_t i = 0; i < total_count; i++) {
   5524                 loader_instance_heap_free(inst, new_phys_devs[i]);
   5525             }
   5526             loader_instance_heap_free(inst, new_phys_devs);
   5527         }
   5528         total_count = 0;
   5529     } else {
   5530         // Free everything that didn't carry over to the new array of
   5531         // physical devices
   5532         if (NULL != inst->phys_devs_tramp) {
   5533             for (uint32_t i = 0; i < inst->phys_dev_count_tramp; i++) {
   5534                 bool found = false;
   5535                 for (uint32_t j = 0; j < total_count; j++) {
   5536                     if (inst->phys_devs_tramp[i] == new_phys_devs[j]) {
   5537                         found = true;
   5538                         break;
   5539                     }
   5540                 }
   5541                 if (!found) {
   5542                     loader_instance_heap_free(inst, inst->phys_devs_tramp[i]);
   5543                 }
   5544             }
   5545             loader_instance_heap_free(inst, inst->phys_devs_tramp);
   5546         }
   5547 
   5548         // Swap in the new physical device list
   5549         inst->phys_dev_count_tramp = total_count;
   5550         inst->phys_devs_tramp = new_phys_devs;
   5551     }
   5552 
   5553     return res;
   5554 }
   5555 
   5556 VkResult setupLoaderTermPhysDevs(struct loader_instance *inst) {
   5557     VkResult res = VK_SUCCESS;
   5558     struct loader_icd_term *icd_term;
   5559     struct loader_phys_dev_per_icd *icd_phys_dev_array = NULL;
   5560     struct loader_physical_device_term **new_phys_devs = NULL;
   5561 
   5562     inst->total_gpu_count = 0;
   5563 
   5564     // Allocate something to store the physical device characteristics
   5565     // that we read from each ICD.
   5566     icd_phys_dev_array =
   5567         (struct loader_phys_dev_per_icd *)loader_stack_alloc(sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count);
   5568     if (NULL == icd_phys_dev_array) {
   5569         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5570                    "setupLoaderTermPhysDevs:  Failed to allocate temporary "
   5571                    "ICD Physical device info array of size %d",
   5572                    inst->total_gpu_count);
   5573         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5574         goto out;
   5575     }
   5576     memset(icd_phys_dev_array, 0, sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count);
   5577     icd_term = inst->icd_terms;
   5578 
   5579     // For each ICD, query the number of physical devices, and then get an
   5580     // internal value for those physical devices.
   5581     for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) {
   5582         res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &icd_phys_dev_array[icd_idx].count, NULL);
   5583         if (VK_SUCCESS != res) {
   5584             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5585                        "setupLoaderTermPhysDevs:  Call to "
   5586                        "ICD %d's \'vkEnumeratePhysicalDevices\' failed with"
   5587                        " error 0x%08x",
   5588                        icd_idx, res);
   5589             goto out;
   5590         }
   5591 
   5592         icd_phys_dev_array[icd_idx].phys_devs =
   5593             (VkPhysicalDevice *)loader_stack_alloc(icd_phys_dev_array[icd_idx].count * sizeof(VkPhysicalDevice));
   5594         if (NULL == icd_phys_dev_array[icd_idx].phys_devs) {
   5595             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5596                        "setupLoaderTermPhysDevs:  Failed to allocate temporary "
   5597                        "ICD Physical device array for ICD %d of size %d",
   5598                        icd_idx, inst->total_gpu_count);
   5599             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5600             goto out;
   5601         }
   5602 
   5603         res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &(icd_phys_dev_array[icd_idx].count),
   5604                                                           icd_phys_dev_array[icd_idx].phys_devs);
   5605         if (VK_SUCCESS != res) {
   5606             goto out;
   5607         }
   5608         inst->total_gpu_count += icd_phys_dev_array[icd_idx].count;
   5609         icd_phys_dev_array[icd_idx].this_icd_term = icd_term;
   5610     }
   5611 
   5612     if (0 == inst->total_gpu_count) {
   5613         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5614                    "setupLoaderTermPhysDevs:  Failed to detect any valid"
   5615                    " GPUs in the current config");
   5616         res = VK_ERROR_INITIALIZATION_FAILED;
   5617         goto out;
   5618     }
   5619 
   5620     new_phys_devs = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term *) * inst->total_gpu_count,
   5621                                                VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   5622     if (NULL == new_phys_devs) {
   5623         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5624                    "setupLoaderTermPhysDevs:  Failed to allocate new physical"
   5625                    " device array of size %d",
   5626                    inst->total_gpu_count);
   5627         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5628         goto out;
   5629     }
   5630     memset(new_phys_devs, 0, sizeof(struct loader_physical_device_term *) * inst->total_gpu_count);
   5631 
   5632     // Copy or create everything to fill the new array of physical devices
   5633     uint32_t idx = 0;
   5634     for (uint32_t icd_idx = 0; icd_idx < inst->total_icd_count; icd_idx++) {
   5635         for (uint32_t pd_idx = 0; pd_idx < icd_phys_dev_array[icd_idx].count; pd_idx++) {
   5636             // Check if this physical device is already in the old buffer
   5637             if (NULL != inst->phys_devs_term) {
   5638                 for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_term; old_idx++) {
   5639                     if (icd_phys_dev_array[icd_idx].phys_devs[pd_idx] == inst->phys_devs_term[old_idx]->phys_dev) {
   5640                         new_phys_devs[idx] = inst->phys_devs_term[old_idx];
   5641                         break;
   5642                     }
   5643                 }
   5644             }
   5645             // If this physical device isn't in the old buffer, then we
   5646             // need to create it.
   5647             if (NULL == new_phys_devs[idx]) {
   5648                 new_phys_devs[idx] = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term),
   5649                                                                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   5650                 if (NULL == new_phys_devs[idx]) {
   5651                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5652                                "setupLoaderTermPhysDevs:  Failed to allocate "
   5653                                "physical device terminator object %d",
   5654                                idx);
   5655                     inst->total_gpu_count = idx;
   5656                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5657                     goto out;
   5658                 }
   5659 
   5660                 loader_set_dispatch((void *)new_phys_devs[idx], inst->disp);
   5661                 new_phys_devs[idx]->this_icd_term = icd_phys_dev_array[icd_idx].this_icd_term;
   5662                 new_phys_devs[idx]->icd_index = (uint8_t)(icd_idx);
   5663                 new_phys_devs[idx]->phys_dev = icd_phys_dev_array[icd_idx].phys_devs[pd_idx];
   5664             }
   5665             idx++;
   5666         }
   5667     }
   5668 
   5669 out:
   5670 
   5671     if (VK_SUCCESS != res) {
   5672         if (NULL != new_phys_devs) {
   5673             // We've encountered an error, so we should free the new buffers.
   5674             for (uint32_t i = 0; i < inst->total_gpu_count; i++) {
   5675                 loader_instance_heap_free(inst, new_phys_devs[i]);
   5676             }
   5677             loader_instance_heap_free(inst, new_phys_devs);
   5678         }
   5679         inst->total_gpu_count = 0;
   5680     } else {
   5681         // Free everything that didn't carry over to the new array of
   5682         // physical devices.  Everything else will have been copied over
   5683         // to the new array.
   5684         if (NULL != inst->phys_devs_term) {
   5685             for (uint32_t cur_pd = 0; cur_pd < inst->phys_dev_count_term; cur_pd++) {
   5686                 bool found = false;
   5687                 for (uint32_t new_pd_idx = 0; new_pd_idx < inst->total_gpu_count; new_pd_idx++) {
   5688                     if (inst->phys_devs_term[cur_pd] == new_phys_devs[new_pd_idx]) {
   5689                         found = true;
   5690                         break;
   5691                     }
   5692                 }
   5693                 if (!found) {
   5694                     loader_instance_heap_free(inst, inst->phys_devs_term[cur_pd]);
   5695                 }
   5696             }
   5697             loader_instance_heap_free(inst, inst->phys_devs_term);
   5698         }
   5699 
   5700         // Swap out old and new devices list
   5701         inst->phys_dev_count_term = inst->total_gpu_count;
   5702         inst->phys_devs_term = new_phys_devs;
   5703     }
   5704 
   5705     return res;
   5706 }
   5707 
   5708 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
   5709                                                                    VkPhysicalDevice *pPhysicalDevices) {
   5710     struct loader_instance *inst = (struct loader_instance *)instance;
   5711     VkResult res = VK_SUCCESS;
   5712 
   5713     // Always call the setup loader terminator physical devices because they may
   5714     // have changed at any point.
   5715     res = setupLoaderTermPhysDevs(inst);
   5716     if (VK_SUCCESS != res) {
   5717         goto out;
   5718     }
   5719 
   5720     uint32_t copy_count = inst->total_gpu_count;
   5721     if (NULL != pPhysicalDevices) {
   5722         if (copy_count > *pPhysicalDeviceCount) {
   5723             copy_count = *pPhysicalDeviceCount;
   5724             res = VK_INCOMPLETE;
   5725         }
   5726 
   5727         for (uint32_t i = 0; i < copy_count; i++) {
   5728             pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i];
   5729         }
   5730     }
   5731 
   5732     *pPhysicalDeviceCount = copy_count;
   5733 
   5734 out:
   5735 
   5736     return res;
   5737 }
   5738 
   5739 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
   5740                                                                   VkPhysicalDeviceProperties *pProperties) {
   5741     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5742     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5743     if (NULL != icd_term->dispatch.GetPhysicalDeviceProperties) {
   5744         icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, pProperties);
   5745     }
   5746 }
   5747 
   5748 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
   5749                                                                              uint32_t *pQueueFamilyPropertyCount,
   5750                                                                              VkQueueFamilyProperties *pProperties) {
   5751     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5752     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5753     if (NULL != icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties) {
   5754         icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, pProperties);
   5755     }
   5756 }
   5757 
   5758 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
   5759                                                                         VkPhysicalDeviceMemoryProperties *pProperties) {
   5760     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5761     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5762     if (NULL != icd_term->dispatch.GetPhysicalDeviceMemoryProperties) {
   5763         icd_term->dispatch.GetPhysicalDeviceMemoryProperties(phys_dev_term->phys_dev, pProperties);
   5764     }
   5765 }
   5766 
   5767 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
   5768                                                                 VkPhysicalDeviceFeatures *pFeatures) {
   5769     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5770     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5771     if (NULL != icd_term->dispatch.GetPhysicalDeviceFeatures) {
   5772         icd_term->dispatch.GetPhysicalDeviceFeatures(phys_dev_term->phys_dev, pFeatures);
   5773     }
   5774 }
   5775 
   5776 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
   5777                                                                         VkFormatProperties *pFormatInfo) {
   5778     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5779     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5780     if (NULL != icd_term->dispatch.GetPhysicalDeviceFormatProperties) {
   5781         icd_term->dispatch.GetPhysicalDeviceFormatProperties(phys_dev_term->phys_dev, format, pFormatInfo);
   5782     }
   5783 }
   5784 
   5785 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
   5786                                                                                  VkImageType type, VkImageTiling tiling,
   5787                                                                                  VkImageUsageFlags usage, VkImageCreateFlags flags,
   5788                                                                                  VkImageFormatProperties *pImageFormatProperties) {
   5789     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5790     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5791     if (NULL == icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) {
   5792         loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5793                    "Encountered the vkEnumerateDeviceLayerProperties "
   5794                    "terminator.  This means a layer improperly continued.");
   5795         return VK_ERROR_INITIALIZATION_FAILED;
   5796     }
   5797     return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(phys_dev_term->phys_dev, format, type, tiling, usage, flags,
   5798                                                                      pImageFormatProperties);
   5799 }
   5800 
   5801 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
   5802                                                                                    VkImageType type, VkSampleCountFlagBits samples,
   5803                                                                                    VkImageUsageFlags usage, VkImageTiling tiling,
   5804                                                                                    uint32_t *pNumProperties,
   5805                                                                                    VkSparseImageFormatProperties *pProperties) {
   5806     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5807     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5808     if (NULL != icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties) {
   5809         icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(phys_dev_term->phys_dev, format, type, samples, usage,
   5810                                                                         tiling, pNumProperties, pProperties);
   5811     }
   5812 }
   5813 
   5814 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
   5815                                                                              const char *pLayerName, uint32_t *pPropertyCount,
   5816                                                                              VkExtensionProperties *pProperties) {
   5817     struct loader_physical_device_term *phys_dev_term;
   5818 
   5819     struct loader_layer_list implicit_layer_list = {0};
   5820     struct loader_extension_list all_exts = {0};
   5821     struct loader_extension_list icd_exts = {0};
   5822 
   5823     assert(pLayerName == NULL || strlen(pLayerName) == 0);
   5824 
   5825     // Any layer or trampoline wrapping should be removed at this point in time can just cast to the expected
   5826     // type for VkPhysicalDevice.
   5827     phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5828 
   5829     // This case is during the call down the instance chain with pLayerName == NULL
   5830     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5831     uint32_t icd_ext_count = *pPropertyCount;
   5832     VkResult res;
   5833 
   5834     // Get the available device extensions
   5835     res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &icd_ext_count, pProperties);
   5836     if (res != VK_SUCCESS) {
   5837         goto out;
   5838     }
   5839 
   5840     if (!loader_init_layer_list(icd_term->this_instance, &implicit_layer_list)) {
   5841         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   5842         goto out;
   5843     }
   5844 
   5845     loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, NULL, &icd_term->this_instance->instance_layer_list);
   5846     // We need to determine which implicit layers are active, and then add their extensions. This can't be cached as
   5847     // it depends on results of environment variables (which can change).
   5848     if (pProperties != NULL) {
   5849         // Initialize dev_extension list within the physicalDevice object
   5850         res = loader_init_device_extensions(icd_term->this_instance, phys_dev_term, icd_ext_count, pProperties, &icd_exts);
   5851         if (res != VK_SUCCESS) {
   5852             goto out;
   5853         }
   5854 
   5855         // We need to determine which implicit layers are active, and then add their extensions. This can't be cached as
   5856         // it depends on results of environment variables (which can change).
   5857         res = loader_add_to_ext_list(icd_term->this_instance, &all_exts, icd_exts.count, icd_exts.list);
   5858         if (res != VK_SUCCESS) {
   5859             goto out;
   5860         }
   5861 
   5862         loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, NULL,
   5863                                    &icd_term->this_instance->instance_layer_list);
   5864 
   5865         for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
   5866             for (uint32_t j = 0; j < implicit_layer_list.list[i].device_extension_list.count; j++) {
   5867                 res = loader_add_to_ext_list(icd_term->this_instance, &all_exts, 1,
   5868                                              &implicit_layer_list.list[i].device_extension_list.list[j].props);
   5869                 if (res != VK_SUCCESS) {
   5870                     goto out;
   5871                 }
   5872             }
   5873         }
   5874         uint32_t capacity = *pPropertyCount;
   5875         VkExtensionProperties *props = pProperties;
   5876 
   5877         for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) {
   5878             props[i] = all_exts.list[i];
   5879         }
   5880 
   5881         // Wasn't enough space for the extensions, we did partial copy now return VK_INCOMPLETE
   5882         if (capacity < all_exts.count) {
   5883             res = VK_INCOMPLETE;
   5884         } else {
   5885             *pPropertyCount = all_exts.count;
   5886         }
   5887     } else {
   5888         // Just return the count; need to add in the count of implicit layer extensions
   5889         // don't worry about duplicates being added in the count
   5890         *pPropertyCount = icd_ext_count;
   5891 
   5892         for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
   5893             *pPropertyCount += implicit_layer_list.list[i].device_extension_list.count;
   5894         }
   5895         res = VK_SUCCESS;
   5896     }
   5897 
   5898 out:
   5899 
   5900     if (NULL != implicit_layer_list.list) {
   5901         loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&implicit_layer_list);
   5902     }
   5903     if (NULL != all_exts.list) {
   5904         loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&all_exts);
   5905     }
   5906     if (NULL != icd_exts.list) {
   5907         loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts);
   5908     }
   5909 
   5910     return res;
   5911 }
   5912 
   5913 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
   5914                                                                          VkLayerProperties *pProperties) {
   5915     struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
   5916     struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
   5917     loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   5918                "Encountered the vkEnumerateDeviceLayerProperties "
   5919                "terminator.  This means a layer improperly continued.");
   5920     // Should never get here this call isn't dispatched down the chain
   5921     return VK_ERROR_INITIALIZATION_FAILED;
   5922 }
   5923 
   5924 VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
   5925     VkStringErrorFlags result = VK_STRING_ERROR_NONE;
   5926     int num_char_bytes = 0;
   5927     int i, j;
   5928 
   5929     for (i = 0; i <= max_length; i++) {
   5930         if (utf8[i] == 0) {
   5931             break;
   5932         } else if (i == max_length) {
   5933             result |= VK_STRING_ERROR_LENGTH;
   5934             break;
   5935         } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) {
   5936             num_char_bytes = 0;
   5937         } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) {
   5938             num_char_bytes = 1;
   5939         } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) {
   5940             num_char_bytes = 2;
   5941         } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
   5942             num_char_bytes = 3;
   5943         } else {
   5944             result = VK_STRING_ERROR_BAD_DATA;
   5945         }
   5946 
   5947         // Validate the following num_char_bytes of data
   5948         for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
   5949             if (++i == max_length) {
   5950                 result |= VK_STRING_ERROR_LENGTH;
   5951                 break;
   5952             }
   5953             if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
   5954                 result |= VK_STRING_ERROR_BAD_DATA;
   5955             }
   5956         }
   5957     }
   5958     return result;
   5959 }
   5960 
   5961 VKAPI_ATTR VkResult VKAPI_CALL
   5962 terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName,
   5963                                                 uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
   5964     struct loader_extension_list *global_ext_list = NULL;
   5965     struct loader_layer_list instance_layers;
   5966     struct loader_extension_list local_ext_list;
   5967     struct loader_icd_tramp_list icd_tramp_list;
   5968     uint32_t copy_size;
   5969     VkResult res = VK_SUCCESS;
   5970 
   5971     // tls_instance = NULL;
   5972     memset(&local_ext_list, 0, sizeof(local_ext_list));
   5973     memset(&instance_layers, 0, sizeof(instance_layers));
   5974 
   5975     // Get layer libraries if needed
   5976     if (pLayerName && strlen(pLayerName) != 0) {
   5977         if (vk_string_validate(MaxLoaderStringLength, pLayerName) != VK_STRING_ERROR_NONE) {
   5978             assert(VK_FALSE &&
   5979                    "vkEnumerateInstanceExtensionProperties:  "
   5980                    "pLayerName is too long or is badly formed");
   5981             res = VK_ERROR_EXTENSION_NOT_PRESENT;
   5982             goto out;
   5983         }
   5984 
   5985         loader_layer_scan(NULL, &instance_layers);
   5986         for (uint32_t i = 0; i < instance_layers.count; i++) {
   5987             struct loader_layer_properties *props = &instance_layers.list[i];
   5988             if (strcmp(props->info.layerName, pLayerName) == 0) {
   5989                 global_ext_list = &props->instance_extension_list;
   5990                 break;
   5991             }
   5992         }
   5993     } else {
   5994         // Scan/discover all ICD libraries
   5995         memset(&icd_tramp_list, 0, sizeof(icd_tramp_list));
   5996         res = loader_icd_scan(NULL, &icd_tramp_list);
   5997         if (VK_SUCCESS != res) {
   5998             goto out;
   5999         }
   6000         // Get extensions from all ICD's, merge so no duplicates
   6001         res = loader_get_icd_loader_instance_extensions(NULL, &icd_tramp_list, &local_ext_list);
   6002         if (VK_SUCCESS != res) {
   6003             goto out;
   6004         }
   6005         loader_scanned_icd_clear(NULL, &icd_tramp_list);
   6006 
   6007         // Append enabled implicit layers.
   6008         loader_implicit_layer_scan(NULL, &instance_layers);
   6009         for (uint32_t i = 0; i < instance_layers.count; i++) {
   6010             if (!loader_is_implicit_layer_enabled(NULL, &instance_layers.list[i])) {
   6011                 continue;
   6012             }
   6013             struct loader_extension_list *ext_list = &instance_layers.list[i].instance_extension_list;
   6014             loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count, ext_list->list);
   6015         }
   6016 
   6017         global_ext_list = &local_ext_list;
   6018     }
   6019 
   6020     if (global_ext_list == NULL) {
   6021         res = VK_ERROR_LAYER_NOT_PRESENT;
   6022         goto out;
   6023     }
   6024 
   6025     if (pProperties == NULL) {
   6026         *pPropertyCount = global_ext_list->count;
   6027         goto out;
   6028     }
   6029 
   6030     copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
   6031     for (uint32_t i = 0; i < copy_size; i++) {
   6032         memcpy(&pProperties[i], &global_ext_list->list[i], sizeof(VkExtensionProperties));
   6033     }
   6034     *pPropertyCount = copy_size;
   6035 
   6036     if (copy_size < global_ext_list->count) {
   6037         res = VK_INCOMPLETE;
   6038         goto out;
   6039     }
   6040 
   6041 out:
   6042 
   6043     loader_destroy_generic_list(NULL, (struct loader_generic_list *)&local_ext_list);
   6044     loader_delete_layer_properties(NULL, &instance_layers);
   6045     return res;
   6046 }
   6047 
   6048 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(const VkEnumerateInstanceLayerPropertiesChain *chain,
   6049                                                                            uint32_t *pPropertyCount,
   6050                                                                            VkLayerProperties *pProperties) {
   6051     VkResult result = VK_SUCCESS;
   6052     struct loader_layer_list instance_layer_list;
   6053     tls_instance = NULL;
   6054 
   6055     LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
   6056 
   6057     uint32_t copy_size;
   6058 
   6059     // Get layer libraries
   6060     memset(&instance_layer_list, 0, sizeof(instance_layer_list));
   6061     loader_layer_scan(NULL, &instance_layer_list);
   6062 
   6063     if (pProperties == NULL) {
   6064         *pPropertyCount = instance_layer_list.count;
   6065         goto out;
   6066     }
   6067 
   6068     copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
   6069     for (uint32_t i = 0; i < copy_size; i++) {
   6070         memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
   6071     }
   6072 
   6073     *pPropertyCount = copy_size;
   6074 
   6075     if (copy_size < instance_layer_list.count) {
   6076         result = VK_INCOMPLETE;
   6077         goto out;
   6078     }
   6079 
   6080 out:
   6081 
   6082     loader_delete_layer_properties(NULL, &instance_layer_list);
   6083     return result;
   6084 }
   6085 
   6086 #if defined(_WIN32) && defined(LOADER_DYNAMIC_LIB)
   6087 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
   6088     switch (reason) {
   6089         case DLL_PROCESS_ATTACH:
   6090             loader_initialize();
   6091             break;
   6092         case DLL_PROCESS_DETACH:
   6093             if (NULL == reserved) {
   6094                 loader_release();
   6095             }
   6096             break;
   6097         default:
   6098             // Do nothing
   6099             break;
   6100     }
   6101     return TRUE;
   6102 }
   6103 #elif !defined(_WIN32)
   6104 __attribute__((constructor)) void loader_init_library() { loader_initialize(); }
   6105 
   6106 __attribute__((destructor)) void loader_free_library() { loader_release(); }
   6107 #endif
   6108