Home | History | Annotate | Download | only in loader
      1 /*
      2  *
      3  * Copyright (c) 2014-2016 The Khronos Group Inc.
      4  * Copyright (c) 2014-2016 Valve Corporation
      5  * Copyright (c) 2014-2016 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  *
     24  */
     25 
     26 #define _GNU_SOURCE
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <stdarg.h>
     30 #include <stdbool.h>
     31 #include <string.h>
     32 
     33 #include <sys/types.h>
     34 #if defined(_WIN32)
     35 #include "dirent_on_windows.h"
     36 #else // _WIN32
     37 #include <dirent.h>
     38 #endif // _WIN32
     39 #include "vk_loader_platform.h"
     40 #include "loader.h"
     41 #include "gpa_helper.h"
     42 #include "table_ops.h"
     43 #include "debug_report.h"
     44 #include "wsi.h"
     45 #include "extensions.h"
     46 #include "vulkan/vk_icd.h"
     47 #include "cJSON.h"
     48 #include "murmurhash.h"
     49 
     50 #if defined(__GNUC__)
     51 #if (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 17))
     52 #define secure_getenv __secure_getenv
     53 #endif
     54 #endif
     55 
     56 struct loader_struct loader = {0};
     57 // TLS for instance for alloc/free callbacks
     58 THREAD_LOCAL_DECL struct loader_instance *tls_instance;
     59 
     60 static size_t loader_platform_combine_path(char *dest, size_t len, ...);
     61 
     62 struct loader_phys_dev_per_icd {
     63     uint32_t count;
     64     VkPhysicalDevice *phys_devs;
     65     struct loader_icd *this_icd;
     66 };
     67 
     68 enum loader_debug {
     69     LOADER_INFO_BIT = 0x01,
     70     LOADER_WARN_BIT = 0x02,
     71     LOADER_PERF_BIT = 0x04,
     72     LOADER_ERROR_BIT = 0x08,
     73     LOADER_DEBUG_BIT = 0x10,
     74 };
     75 
     76 uint32_t g_loader_debug = 0;
     77 uint32_t g_loader_log_msgs = 0;
     78 
     79 // thread safety lock for accessing global data structures such as "loader"
     80 // all entrypoints on the instance chain need to be locked except GPA
     81 // additionally CreateDevice and DestroyDevice needs to be locked
     82 loader_platform_thread_mutex loader_lock;
     83 loader_platform_thread_mutex loader_json_lock;
     84 
     85 const char *std_validation_str = "VK_LAYER_LUNARG_standard_validation";
     86 
     87 // This table contains the loader's instance dispatch table, which contains
     88 // default functions if no instance layers are activated.  This contains
     89 // pointers to "terminator functions".
     90 const VkLayerInstanceDispatchTable instance_disp = {
     91     .GetInstanceProcAddr = vkGetInstanceProcAddr,
     92     .DestroyInstance = terminator_DestroyInstance,
     93     .EnumeratePhysicalDevices = terminator_EnumeratePhysicalDevices,
     94     .GetPhysicalDeviceFeatures = terminator_GetPhysicalDeviceFeatures,
     95     .GetPhysicalDeviceFormatProperties =
     96         terminator_GetPhysicalDeviceFormatProperties,
     97     .GetPhysicalDeviceImageFormatProperties =
     98         terminator_GetPhysicalDeviceImageFormatProperties,
     99     .GetPhysicalDeviceProperties = terminator_GetPhysicalDeviceProperties,
    100     .GetPhysicalDeviceQueueFamilyProperties =
    101         terminator_GetPhysicalDeviceQueueFamilyProperties,
    102     .GetPhysicalDeviceMemoryProperties =
    103         terminator_GetPhysicalDeviceMemoryProperties,
    104     .EnumerateDeviceExtensionProperties =
    105         terminator_EnumerateDeviceExtensionProperties,
    106     .EnumerateDeviceLayerProperties = terminator_EnumerateDeviceLayerProperties,
    107     .GetPhysicalDeviceSparseImageFormatProperties =
    108         terminator_GetPhysicalDeviceSparseImageFormatProperties,
    109     .DestroySurfaceKHR = terminator_DestroySurfaceKHR,
    110     .GetPhysicalDeviceSurfaceSupportKHR =
    111         terminator_GetPhysicalDeviceSurfaceSupportKHR,
    112     .GetPhysicalDeviceSurfaceCapabilitiesKHR =
    113         terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR,
    114     .GetPhysicalDeviceSurfaceFormatsKHR =
    115         terminator_GetPhysicalDeviceSurfaceFormatsKHR,
    116     .GetPhysicalDeviceSurfacePresentModesKHR =
    117         terminator_GetPhysicalDeviceSurfacePresentModesKHR,
    118     .CreateDebugReportCallbackEXT = terminator_CreateDebugReportCallback,
    119     .DestroyDebugReportCallbackEXT = terminator_DestroyDebugReportCallback,
    120     .DebugReportMessageEXT = terminator_DebugReportMessage,
    121     .GetPhysicalDeviceExternalImageFormatPropertiesNV =
    122         terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV,
    123 #ifdef VK_USE_PLATFORM_MIR_KHR
    124     .CreateMirSurfaceKHR = terminator_CreateMirSurfaceKHR,
    125     .GetPhysicalDeviceMirPresentationSupportKHR =
    126         terminator_GetPhysicalDeviceMirPresentationSupportKHR,
    127 #endif
    128 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
    129     .CreateWaylandSurfaceKHR = terminator_CreateWaylandSurfaceKHR,
    130     .GetPhysicalDeviceWaylandPresentationSupportKHR =
    131         terminator_GetPhysicalDeviceWaylandPresentationSupportKHR,
    132 #endif
    133 #ifdef VK_USE_PLATFORM_WIN32_KHR
    134     .CreateWin32SurfaceKHR = terminator_CreateWin32SurfaceKHR,
    135     .GetPhysicalDeviceWin32PresentationSupportKHR =
    136         terminator_GetPhysicalDeviceWin32PresentationSupportKHR,
    137 #endif
    138 #ifdef VK_USE_PLATFORM_XCB_KHR
    139     .CreateXcbSurfaceKHR = terminator_CreateXcbSurfaceKHR,
    140     .GetPhysicalDeviceXcbPresentationSupportKHR =
    141         terminator_GetPhysicalDeviceXcbPresentationSupportKHR,
    142 #endif
    143 #ifdef VK_USE_PLATFORM_XLIB_KHR
    144     .CreateXlibSurfaceKHR = terminator_CreateXlibSurfaceKHR,
    145     .GetPhysicalDeviceXlibPresentationSupportKHR =
    146         terminator_GetPhysicalDeviceXlibPresentationSupportKHR,
    147 #endif
    148 #ifdef VK_USE_PLATFORM_ANDROID_KHR
    149     .CreateAndroidSurfaceKHR = terminator_CreateAndroidSurfaceKHR,
    150 #endif
    151     .GetPhysicalDeviceDisplayPropertiesKHR =
    152         terminator_GetPhysicalDeviceDisplayPropertiesKHR,
    153     .GetPhysicalDeviceDisplayPlanePropertiesKHR =
    154         terminator_GetPhysicalDeviceDisplayPlanePropertiesKHR,
    155     .GetDisplayPlaneSupportedDisplaysKHR =
    156         terminator_GetDisplayPlaneSupportedDisplaysKHR,
    157     .GetDisplayModePropertiesKHR = terminator_GetDisplayModePropertiesKHR,
    158     .CreateDisplayModeKHR = terminator_CreateDisplayModeKHR,
    159     .GetDisplayPlaneCapabilitiesKHR = terminator_GetDisplayPlaneCapabilitiesKHR,
    160     .CreateDisplayPlaneSurfaceKHR = terminator_CreateDisplayPlaneSurfaceKHR,
    161 };
    162 
    163 LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
    164 
    165 void *loader_instance_heap_alloc(const struct loader_instance *instance,
    166                                  size_t size,
    167                                  VkSystemAllocationScope alloc_scope) {
    168     void *pMemory = NULL;
    169 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    170     {
    171 #else
    172     if (instance && instance->alloc_callbacks.pfnAllocation) {
    173         /* These are internal structures, so it's best to align everything to
    174          * the largest unit size which is the size of a uint64_t.
    175         */
    176         pMemory = instance->alloc_callbacks.pfnAllocation(
    177             instance->alloc_callbacks.pUserData, size, sizeof(uint64_t),
    178             alloc_scope);
    179     } else {
    180 #endif
    181         pMemory = malloc(size);
    182     }
    183     return pMemory;
    184 }
    185 
    186 void loader_instance_heap_free(const struct loader_instance *instance,
    187                                void *pMemory) {
    188     if (pMemory != NULL) {
    189 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    190         {
    191 #else
    192         if (instance && instance->alloc_callbacks.pfnFree) {
    193             instance->alloc_callbacks.pfnFree(
    194                 instance->alloc_callbacks.pUserData, pMemory);
    195         } else {
    196 #endif
    197             free(pMemory);
    198         }
    199     }
    200 }
    201 
    202 void *loader_instance_heap_realloc(const struct loader_instance *instance,
    203                                    void *pMemory, size_t orig_size, size_t size,
    204                                    VkSystemAllocationScope alloc_scope) {
    205     void *pNewMem = NULL;
    206     if (pMemory == NULL || orig_size == 0) {
    207         pNewMem = loader_instance_heap_alloc(instance, size, alloc_scope);
    208     } else if (size == 0) {
    209         loader_instance_heap_free(instance, pMemory);
    210 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    211 #else
    212     } else if (instance && instance->alloc_callbacks.pfnReallocation) {
    213         /* These are internal structures, so it's best to align everything to
    214          * the largest unit size which is the size of a uint64_t.
    215          */
    216         pNewMem = instance->alloc_callbacks.pfnReallocation(
    217             instance->alloc_callbacks.pUserData, pMemory, size,
    218             sizeof(uint64_t), alloc_scope);
    219 #endif
    220     } else {
    221         pNewMem = realloc(pMemory, size);
    222     }
    223     return pNewMem;
    224 }
    225 
    226 void *loader_instance_tls_heap_alloc(size_t size) {
    227     return loader_instance_heap_alloc(tls_instance, size,
    228                                       VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    229 }
    230 
    231 void loader_instance_tls_heap_free(void *pMemory) {
    232     loader_instance_heap_free(tls_instance, pMemory);
    233 }
    234 
    235 void *loader_device_heap_alloc(const struct loader_device *device, size_t size,
    236                                VkSystemAllocationScope alloc_scope) {
    237     void *pMemory = NULL;
    238 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    239     {
    240 #else
    241     if (device && device->alloc_callbacks.pfnAllocation) {
    242         /* These are internal structures, so it's best to align everything to
    243          * the largest unit size which is the size of a uint64_t.
    244         */
    245         pMemory = device->alloc_callbacks.pfnAllocation(
    246             device->alloc_callbacks.pUserData, size, sizeof(uint64_t),
    247             alloc_scope);
    248     } else {
    249 #endif
    250         pMemory = malloc(size);
    251     }
    252     return pMemory;
    253 }
    254 
    255 void loader_device_heap_free(const struct loader_device *device,
    256                              void *pMemory) {
    257     if (pMemory != NULL) {
    258 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    259         {
    260 #else
    261         if (device && device->alloc_callbacks.pfnFree) {
    262             device->alloc_callbacks.pfnFree(device->alloc_callbacks.pUserData,
    263                                             pMemory);
    264         } else {
    265 #endif
    266             free(pMemory);
    267         }
    268     }
    269 }
    270 
    271 void *loader_device_heap_realloc(const struct loader_device *device,
    272                                  void *pMemory, size_t orig_size, size_t size,
    273                                  VkSystemAllocationScope alloc_scope) {
    274     void *pNewMem = NULL;
    275     if (pMemory == NULL || orig_size == 0) {
    276         pNewMem = loader_device_heap_alloc(device, size, alloc_scope);
    277     } else if (size == 0) {
    278         loader_device_heap_free(device, pMemory);
    279 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
    280 #else
    281     } else if (device && device->alloc_callbacks.pfnReallocation) {
    282         /* These are internal structures, so it's best to align everything to
    283          * the largest unit size which is the size of a uint64_t.
    284         */
    285         pNewMem = device->alloc_callbacks.pfnReallocation(
    286             device->alloc_callbacks.pUserData, pMemory, size, sizeof(uint64_t),
    287             alloc_scope);
    288 #endif
    289     } else {
    290         pNewMem = realloc(pMemory, size);
    291     }
    292     return pNewMem;
    293 }
    294 
    295 // Environment variables
    296 #if defined(__linux__)
    297 
    298 static inline char *loader_getenv(const char *name,
    299                                   const struct loader_instance *inst) {
    300     // No allocation of memory necessary for Linux, but we should at least touch
    301     // the inst pointer to get rid of compiler warnings.
    302     (void)inst;
    303     return getenv(name);
    304 }
    305 static inline void loader_free_getenv(const char *val,
    306                                       const struct loader_instance *inst) {
    307     // No freeing of memory necessary for Linux, but we should at least touch
    308     // the val and inst pointers to get rid of compiler warnings.
    309     (void)val;
    310     (void)inst;
    311 }
    312 
    313 #elif defined(WIN32)
    314 
    315 static inline char *loader_getenv(const char *name,
    316                                   const struct loader_instance *inst) {
    317     char *retVal;
    318     DWORD valSize;
    319 
    320     valSize = GetEnvironmentVariableA(name, NULL, 0);
    321 
    322     // valSize DOES include the null terminator, so for any set variable
    323     // will always be at least 1. If it's 0, the variable wasn't set.
    324     if (valSize == 0)
    325         return NULL;
    326 
    327     // Allocate the space necessary for the registry entry
    328     if (NULL != inst && NULL != inst->alloc_callbacks.pfnAllocation) {
    329         retVal = (char *)inst->alloc_callbacks.pfnAllocation(
    330             inst->alloc_callbacks.pUserData, valSize, sizeof(char *),
    331             VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    332     } else {
    333         retVal = (char *)malloc(valSize);
    334     }
    335 
    336     if (NULL != retVal) {
    337         GetEnvironmentVariableA(name, retVal, valSize);
    338     }
    339 
    340     return retVal;
    341 }
    342 
    343 static inline void loader_free_getenv(char *val,
    344                                       const struct loader_instance *inst) {
    345     if (NULL != inst && NULL != inst->alloc_callbacks.pfnFree) {
    346         inst->alloc_callbacks.pfnFree(inst->alloc_callbacks.pUserData, val);
    347     } else {
    348         free((void *)val);
    349     }
    350 }
    351 
    352 #else
    353 
    354 static inline char *loader_getenv(const char *name,
    355     const struct loader_instance *inst) {
    356     // stub func
    357     (void)inst;
    358     (void)name;
    359     return NULL;
    360 }
    361 static inline void loader_free_getenv(const char *val,
    362     const struct loader_instance *inst) {
    363     // stub func
    364     (void)val;
    365     (void)inst;
    366 }
    367 
    368 #endif
    369 
    370 void loader_log(const struct loader_instance *inst, VkFlags msg_type,
    371                 int32_t msg_code, const char *format, ...) {
    372     char msg[512];
    373     va_list ap;
    374     int ret;
    375 
    376     va_start(ap, format);
    377     ret = vsnprintf(msg, sizeof(msg), format, ap);
    378     if ((ret >= (int)sizeof(msg)) || ret < 0) {
    379         msg[sizeof(msg) - 1] = '\0';
    380     }
    381     va_end(ap);
    382 
    383     if (inst) {
    384         util_DebugReportMessage(inst, msg_type,
    385                                 VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
    386                                 (uint64_t)inst, 0, msg_code, "loader", msg);
    387     }
    388 
    389     if (!(msg_type & g_loader_log_msgs)) {
    390         return;
    391     }
    392 
    393 #if defined(WIN32)
    394     OutputDebugString(msg);
    395     OutputDebugString("\n");
    396 #endif
    397     fputs(msg, stderr);
    398     fputc('\n', stderr);
    399 }
    400 
    401 VKAPI_ATTR VkResult VKAPI_CALL
    402 vkSetInstanceDispatch(VkInstance instance, void *object) {
    403 
    404     struct loader_instance *inst = loader_get_instance(instance);
    405     if (!inst) {
    406         return VK_ERROR_INITIALIZATION_FAILED;
    407     }
    408     loader_set_dispatch(object, inst->disp);
    409     return VK_SUCCESS;
    410 }
    411 
    412 VKAPI_ATTR VkResult VKAPI_CALL
    413 vkSetDeviceDispatch(VkDevice device, void *object) {
    414     struct loader_device *dev;
    415     struct loader_icd *icd = loader_get_icd_and_device(device, &dev, NULL);
    416 
    417     if (!icd) {
    418         return VK_ERROR_INITIALIZATION_FAILED;
    419     }
    420     loader_set_dispatch(object, &dev->loader_dispatch);
    421     return VK_SUCCESS;
    422 }
    423 
    424 #if defined(WIN32)
    425 static char *loader_get_next_path(char *path);
    426 /**
    427 * Find the list of registry files (names within a key) in key "location".
    428 *
    429 * This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as
    430 *given in "location"
    431 * for a list or name/values which are added to a returned list (function return
    432 *value).
    433 * The DWORD values within the key must be 0 or they are skipped.
    434 * Function return is a string with a ';'  separated list of filenames.
    435 * Function return is NULL if no valid name/value pairs  are found in the key,
    436 * or the key is not found.
    437 *
    438 * \returns
    439 * A string list of filenames as pointer.
    440 * When done using the returned string list, pointer should be freed.
    441 */
    442 static char *loader_get_registry_files(const struct loader_instance *inst,
    443                                        char *location) {
    444     LONG rtn_value;
    445     HKEY hive, key;
    446     DWORD access_flags;
    447     char name[2048];
    448     char *out = NULL;
    449     char *loc = location;
    450     char *next;
    451     DWORD idx = 0;
    452     DWORD name_size = sizeof(name);
    453     DWORD value;
    454     DWORD total_size = 4096;
    455     DWORD value_size = sizeof(value);
    456 
    457     while (*loc) {
    458         next = loader_get_next_path(loc);
    459         hive = DEFAULT_VK_REGISTRY_HIVE;
    460         access_flags = KEY_QUERY_VALUE;
    461         rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
    462         if (rtn_value != ERROR_SUCCESS) {
    463             // We still couldn't find the key, so give up:
    464             loc = next;
    465             continue;
    466         }
    467 
    468         while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL,
    469                                          NULL, (LPBYTE)&value, &value_size)) ==
    470                ERROR_SUCCESS) {
    471             if (value_size == sizeof(value) && value == 0) {
    472                 if (out == NULL) {
    473                     out = loader_instance_heap_alloc(
    474                         inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    475                     if (NULL == out) {
    476                         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    477                                    "Out of memory can't alloc space for registry data");
    478                         return NULL;
    479                     }
    480                     out[0] = '\0';
    481                 } else if (strlen(out) + name_size + 1 > total_size) {
    482                     out = loader_instance_heap_realloc(
    483                         inst, out, total_size, total_size * 2,
    484                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    485                     if (NULL == out) {
    486                         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    487                                    "Out of memory can't realloc space for registry data");
    488                         return NULL;
    489                     }
    490                     total_size *= 2;
    491                 }
    492                 if (strlen(out) == 0)
    493                     snprintf(out, name_size + 1, "%s", name);
    494                 else
    495                     snprintf(out + strlen(out), name_size + 2, "%c%s",
    496                              PATH_SEPERATOR, name);
    497             }
    498             name_size = 2048;
    499         }
    500         loc = next;
    501     }
    502 
    503     return out;
    504 }
    505 
    506 #endif // WIN32
    507 
    508 /**
    509  * Combine path elements, separating each element with the platform-specific
    510  * directory separator, and save the combined string to a destination buffer,
    511  * not exceeding the given length. Path elements are given as variadic args,
    512  * with a NULL element terminating the list.
    513  *
    514  * \returns the total length of the combined string, not including an ASCII
    515  * NUL termination character. This length may exceed the available storage:
    516  * in this case, the written string will be truncated to avoid a buffer
    517  * overrun, and the return value will greater than or equal to the storage
    518  * size. A NULL argument may be provided as the destination buffer in order
    519  * to determine the required string length without actually writing a string.
    520  */
    521 
    522 static size_t loader_platform_combine_path(char *dest, size_t len, ...) {
    523     size_t required_len = 0;
    524     va_list ap;
    525     const char *component;
    526 
    527     va_start(ap, len);
    528 
    529     while ((component = va_arg(ap, const char *))) {
    530         if (required_len > 0) {
    531             // This path element is not the first non-empty element; prepend
    532             // a directory separator if space allows
    533             if (dest && required_len + 1 < len) {
    534                 snprintf(dest + required_len, len - required_len, "%c",
    535                          DIRECTORY_SYMBOL);
    536             }
    537             required_len++;
    538         }
    539 
    540         if (dest && required_len < len) {
    541             strncpy(dest + required_len, component, len - required_len);
    542         }
    543         required_len += strlen(component);
    544     }
    545 
    546     va_end(ap);
    547 
    548     // strncpy(3) won't add a NUL terminating byte in the event of truncation.
    549     if (dest && required_len >= len) {
    550         dest[len - 1] = '\0';
    551     }
    552 
    553     return required_len;
    554 }
    555 
    556 /**
    557  * Given string of three part form "maj.min.pat" convert to a vulkan version
    558  * number.
    559  */
    560 static uint32_t loader_make_version(char *vers_str) {
    561     uint32_t vers = 0, major = 0, minor = 0, patch = 0;
    562     char *vers_tok;
    563 
    564     if (!vers_str) {
    565         return vers;
    566     }
    567 
    568     vers_tok = strtok(vers_str, ".\"\n\r");
    569     if (NULL != vers_tok) {
    570         major = (uint16_t)atoi(vers_tok);
    571         vers_tok = strtok(NULL, ".\"\n\r");
    572         if (NULL != vers_tok) {
    573             minor = (uint16_t)atoi(vers_tok);
    574             vers_tok = strtok(NULL, ".\"\n\r");
    575             if (NULL != vers_tok) {
    576                 patch = (uint16_t)atoi(vers_tok);
    577             }
    578         }
    579     }
    580 
    581     return VK_MAKE_VERSION(major, minor, patch);
    582 }
    583 
    584 bool compare_vk_extension_properties(const VkExtensionProperties *op1,
    585                                      const VkExtensionProperties *op2) {
    586     return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
    587 }
    588 
    589 /**
    590  * Search the given ext_array for an extension
    591  * matching the given vk_ext_prop
    592  */
    593 bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop,
    594                                      const uint32_t count,
    595                                      const VkExtensionProperties *ext_array) {
    596     for (uint32_t i = 0; i < count; i++) {
    597         if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
    598             return true;
    599     }
    600     return false;
    601 }
    602 
    603 /**
    604  * Search the given ext_list for an extension
    605  * matching the given vk_ext_prop
    606  */
    607 bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop,
    608                                const struct loader_extension_list *ext_list) {
    609     for (uint32_t i = 0; i < ext_list->count; i++) {
    610         if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
    611             return true;
    612     }
    613     return false;
    614 }
    615 
    616 /**
    617  * Search the given ext_list for a device extension matching the given ext_prop
    618  */
    619 bool has_vk_dev_ext_property(
    620     const VkExtensionProperties *ext_prop,
    621     const struct loader_device_extension_list *ext_list) {
    622     for (uint32_t i = 0; i < ext_list->count; i++) {
    623         if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop))
    624             return true;
    625     }
    626     return false;
    627 }
    628 
    629 /*
    630  * Search the given layer list for a layer matching the given layer name
    631  */
    632 static struct loader_layer_properties *
    633 loader_get_layer_property(const char *name,
    634                           const struct loader_layer_list *layer_list) {
    635     for (uint32_t i = 0; i < layer_list->count; i++) {
    636         const VkLayerProperties *item = &layer_list->list[i].info;
    637         if (strcmp(name, item->layerName) == 0)
    638             return &layer_list->list[i];
    639     }
    640     return NULL;
    641 }
    642 
    643 /**
    644  * Get the next unused layer property in the list. Init the property to zero.
    645  */
    646 static struct loader_layer_properties *
    647 loader_get_next_layer_property(const struct loader_instance *inst,
    648                                struct loader_layer_list *layer_list) {
    649     if (layer_list->capacity == 0) {
    650         layer_list->list =
    651             loader_instance_heap_alloc(
    652                 inst, sizeof(struct loader_layer_properties) * 64,
    653                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    654         if (layer_list->list == NULL) {
    655             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    656                        "Out of memory can't add any layer properties to list");
    657             return NULL;
    658         }
    659         memset(layer_list->list, 0,
    660                sizeof(struct loader_layer_properties) * 64);
    661         layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
    662     }
    663 
    664     // ensure enough room to add an entry
    665     if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) >
    666         layer_list->capacity) {
    667         layer_list->list = loader_instance_heap_realloc(
    668             inst, layer_list->list, layer_list->capacity,
    669             layer_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    670         if (layer_list->list == NULL) {
    671             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    672                        "realloc failed for layer list");
    673             return NULL;
    674         }
    675         layer_list->capacity *= 2;
    676     }
    677 
    678     layer_list->count++;
    679     return &(layer_list->list[layer_list->count - 1]);
    680 }
    681 
    682 /**
    683  * Remove all layer properties entrys from the list
    684  */
    685 void loader_delete_layer_properties(const struct loader_instance *inst,
    686                                     struct loader_layer_list *layer_list) {
    687     uint32_t i, j;
    688     struct loader_device_extension_list *dev_ext_list;
    689     if (!layer_list)
    690         return;
    691 
    692     for (i = 0; i < layer_list->count; i++) {
    693         loader_destroy_generic_list(
    694             inst, (struct loader_generic_list *)&layer_list->list[i]
    695                       .instance_extension_list);
    696         dev_ext_list = &layer_list->list[i].device_extension_list;
    697         if (dev_ext_list->capacity > 0 &&
    698             NULL != dev_ext_list->list &&
    699             dev_ext_list->list->entrypoint_count > 0) {
    700             for (j = 0; j < dev_ext_list->list->entrypoint_count; j++) {
    701                 loader_instance_heap_free(inst, dev_ext_list->list->entrypoints[j]);
    702             }
    703             loader_instance_heap_free(inst, dev_ext_list->list->entrypoints);
    704         }
    705         loader_destroy_generic_list(inst,
    706                                     (struct loader_generic_list *)dev_ext_list);
    707     }
    708     layer_list->count = 0;
    709 
    710     if (layer_list->capacity > 0) {
    711         layer_list->capacity = 0;
    712         loader_instance_heap_free(inst, layer_list->list);
    713     }
    714 }
    715 
    716 static VkResult loader_add_instance_extensions(
    717     const struct loader_instance *inst,
    718     const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
    719     const char *lib_name, struct loader_extension_list *ext_list) {
    720     uint32_t i, count = 0;
    721     VkExtensionProperties *ext_props;
    722     VkResult res = VK_SUCCESS;
    723 
    724     if (!fp_get_props) {
    725         /* No EnumerateInstanceExtensionProperties defined */
    726         goto out;
    727     }
    728 
    729     res = fp_get_props(NULL, &count, NULL);
    730     if (res != VK_SUCCESS) {
    731         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
    732                    "Error getting Instance extension count from %s", lib_name);
    733         goto out;
    734     }
    735 
    736     if (count == 0) {
    737         /* No ExtensionProperties to report */
    738         goto out;
    739     }
    740 
    741     ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
    742 
    743     res = fp_get_props(NULL, &count, ext_props);
    744     if (res != VK_SUCCESS) {
    745         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
    746                    "Error getting Instance extensions from %s", lib_name);
    747         goto out;
    748     }
    749 
    750     for (i = 0; i < count; i++) {
    751         char spec_version[64];
    752 
    753         bool ext_unsupported =
    754             wsi_unsupported_instance_extension(&ext_props[i]);
    755         if (!ext_unsupported) {
    756             snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
    757                      VK_MAJOR(ext_props[i].specVersion),
    758                      VK_MINOR(ext_props[i].specVersion),
    759                      VK_PATCH(ext_props[i].specVersion));
    760             loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
    761                        "Instance Extension: %s (%s) version %s",
    762                        ext_props[i].extensionName, lib_name, spec_version);
    763             res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
    764             if (res != VK_SUCCESS) {
    765                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
    766                            "Failed to add %s to Instance extension list",
    767                            lib_name);
    768                 goto out;
    769             }
    770         }
    771     }
    772 out:
    773     return res;
    774 }
    775 
    776 /*
    777  * Initialize ext_list with the physical device extensions.
    778  * The extension properties are passed as inputs in count and ext_props.
    779  */
    780 static VkResult
    781 loader_init_device_extensions(const struct loader_instance *inst,
    782                               struct loader_physical_device *phys_dev,
    783                               uint32_t count, VkExtensionProperties *ext_props,
    784                               struct loader_extension_list *ext_list) {
    785     VkResult res;
    786     uint32_t i;
    787 
    788     res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
    789                                    sizeof(VkExtensionProperties));
    790     if (VK_SUCCESS != res) {
    791         return res;
    792     }
    793 
    794     for (i = 0; i < count; i++) {
    795         char spec_version[64];
    796 
    797         snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
    798                  VK_MAJOR(ext_props[i].specVersion),
    799                  VK_MINOR(ext_props[i].specVersion),
    800                  VK_PATCH(ext_props[i].specVersion));
    801         loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
    802                    "Device Extension: %s (%s) version %s",
    803                    ext_props[i].extensionName,
    804                    phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
    805         res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
    806         if (res != VK_SUCCESS)
    807             return res;
    808     }
    809 
    810     return VK_SUCCESS;
    811 }
    812 
    813 VkResult loader_add_device_extensions(const struct loader_instance *inst,
    814                                       PFN_vkEnumerateDeviceExtensionProperties
    815                                           fpEnumerateDeviceExtensionProperties,
    816                                       VkPhysicalDevice physical_device,
    817                                       const char *lib_name,
    818                                       struct loader_extension_list *ext_list) {
    819     uint32_t i, count;
    820     VkResult res;
    821     VkExtensionProperties *ext_props;
    822 
    823     res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count,
    824                                                NULL);
    825     if (res == VK_SUCCESS && count > 0) {
    826         ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
    827         if (!ext_props) {
    828             return VK_ERROR_OUT_OF_HOST_MEMORY;
    829         }
    830         res = fpEnumerateDeviceExtensionProperties(physical_device, NULL,
    831                                                    &count, ext_props);
    832         if (res != VK_SUCCESS) {
    833             return res;
    834         }
    835         for (i = 0; i < count; i++) {
    836             char spec_version[64];
    837 
    838             snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
    839                      VK_MAJOR(ext_props[i].specVersion),
    840                      VK_MINOR(ext_props[i].specVersion),
    841                      VK_PATCH(ext_props[i].specVersion));
    842             loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
    843                        "Device Extension: %s (%s) version %s",
    844                        ext_props[i].extensionName, lib_name, spec_version);
    845             res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
    846             if (res != VK_SUCCESS)
    847                 return res;
    848         }
    849     } else {
    850         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
    851                    "Error getting physical device extension info count from "
    852                    "library %s",
    853                    lib_name);
    854         return res;
    855     }
    856 
    857     return VK_SUCCESS;
    858 }
    859 
    860 VkResult loader_init_generic_list(const struct loader_instance *inst,
    861                               struct loader_generic_list *list_info,
    862                               size_t element_size) {
    863     size_t capacity = 32 * element_size;
    864     list_info->count = 0;
    865     list_info->capacity = 0;
    866     list_info->list = loader_instance_heap_alloc(
    867         inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    868     if (list_info->list == NULL) {
    869         return VK_ERROR_OUT_OF_HOST_MEMORY;
    870     }
    871     memset(list_info->list, 0, capacity);
    872     list_info->capacity = capacity;
    873     return VK_SUCCESS;
    874 }
    875 
    876 void loader_destroy_generic_list(const struct loader_instance *inst,
    877                                  struct loader_generic_list *list) {
    878     loader_instance_heap_free(inst, list->list);
    879     list->count = 0;
    880     list->capacity = 0;
    881 }
    882 
    883 /*
    884  * Append non-duplicate extension properties defined in props
    885  * to the given ext_list.
    886  * Return
    887  *  Vk_SUCCESS on success
    888  */
    889 VkResult loader_add_to_ext_list(const struct loader_instance *inst,
    890                                 struct loader_extension_list *ext_list,
    891                                 uint32_t prop_list_count,
    892                                 const VkExtensionProperties *props) {
    893     uint32_t i;
    894     const VkExtensionProperties *cur_ext;
    895 
    896     if (ext_list->list == NULL || ext_list->capacity == 0) {
    897         VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
    898                                  sizeof(VkExtensionProperties));
    899         if (VK_SUCCESS != res) {
    900             return res;
    901         }
    902     }
    903 
    904     for (i = 0; i < prop_list_count; i++) {
    905         cur_ext = &props[i];
    906 
    907         // look for duplicates
    908         if (has_vk_extension_property(cur_ext, ext_list)) {
    909             continue;
    910         }
    911 
    912         // add to list at end
    913         // check for enough capacity
    914         if (ext_list->count * sizeof(VkExtensionProperties) >=
    915             ext_list->capacity) {
    916 
    917             ext_list->list = loader_instance_heap_realloc(
    918                 inst, ext_list->list, ext_list->capacity,
    919                 ext_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    920 
    921             if (ext_list->list == NULL)
    922                 return VK_ERROR_OUT_OF_HOST_MEMORY;
    923 
    924             // double capacity
    925             ext_list->capacity *= 2;
    926         }
    927 
    928         memcpy(&ext_list->list[ext_list->count], cur_ext,
    929                sizeof(VkExtensionProperties));
    930         ext_list->count++;
    931     }
    932     return VK_SUCCESS;
    933 }
    934 
    935 /*
    936  * Append one extension property defined in props with entrypoints
    937  * defined in entrys to the given ext_list. Do not append if a duplicate
    938  * Return
    939  *  Vk_SUCCESS on success
    940  */
    941 VkResult
    942 loader_add_to_dev_ext_list(const struct loader_instance *inst,
    943                            struct loader_device_extension_list *ext_list,
    944                            const VkExtensionProperties *props,
    945                            uint32_t entry_count, char **entrys) {
    946     uint32_t idx;
    947     if (ext_list->list == NULL || ext_list->capacity == 0) {
    948         VkResult res = loader_init_generic_list(
    949             inst, (struct loader_generic_list *)ext_list,
    950             sizeof(struct loader_dev_ext_props));
    951         if (VK_SUCCESS != res) {
    952             return res;
    953         }
    954     }
    955 
    956     // look for duplicates
    957     if (has_vk_dev_ext_property(props, ext_list)) {
    958         return VK_SUCCESS;
    959     }
    960 
    961     idx = ext_list->count;
    962     // add to list at end
    963     // check for enough capacity
    964     if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
    965 
    966         ext_list->list = loader_instance_heap_realloc(
    967             inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
    968             VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    969 
    970         if (ext_list->list == NULL)
    971             return VK_ERROR_OUT_OF_HOST_MEMORY;
    972 
    973         // double capacity
    974         ext_list->capacity *= 2;
    975     }
    976 
    977     memcpy(&ext_list->list[idx].props, props,
    978            sizeof(struct loader_dev_ext_props));
    979     ext_list->list[idx].entrypoint_count = entry_count;
    980     ext_list->list[idx].entrypoints =
    981         loader_instance_heap_alloc(inst, sizeof(char *) * entry_count,
    982                                    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    983     if (ext_list->list[idx].entrypoints == NULL) {
    984         ext_list->list[idx].entrypoint_count = 0;
    985         return VK_ERROR_OUT_OF_HOST_MEMORY;
    986     }
    987     for (uint32_t i = 0; i < entry_count; i++) {
    988         ext_list->list[idx].entrypoints[i] = loader_instance_heap_alloc(
    989             inst, strlen(entrys[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    990         if (ext_list->list[idx].entrypoints[i] == NULL) {
    991             for (uint32_t j = 0; j < i; j++) {
    992                 loader_instance_heap_free(inst,
    993                                           ext_list->list[idx].entrypoints[j]);
    994             }
    995             loader_instance_heap_free(inst, ext_list->list[idx].entrypoints);
    996             ext_list->list[idx].entrypoint_count = 0;
    997             ext_list->list[idx].entrypoints = NULL;
    998             return VK_ERROR_OUT_OF_HOST_MEMORY;
    999         }
   1000         strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
   1001     }
   1002     ext_list->count++;
   1003 
   1004     return VK_SUCCESS;
   1005 }
   1006 
   1007 /**
   1008  * Search the given search_list for any layers in the props list.
   1009  * Add these to the output layer_list.  Don't add duplicates to the output
   1010  * layer_list.
   1011  */
   1012 static VkResult
   1013 loader_add_layer_names_to_list(const struct loader_instance *inst,
   1014                                struct loader_layer_list *output_list,
   1015                                uint32_t name_count, const char *const *names,
   1016                                const struct loader_layer_list *search_list) {
   1017     struct loader_layer_properties *layer_prop;
   1018     VkResult err = VK_SUCCESS;
   1019 
   1020     for (uint32_t i = 0; i < name_count; i++) {
   1021         const char *search_target = names[i];
   1022         layer_prop = loader_get_layer_property(search_target, search_list);
   1023         if (!layer_prop) {
   1024             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1025                        "Unable to find layer %s", search_target);
   1026             err = VK_ERROR_LAYER_NOT_PRESENT;
   1027             continue;
   1028         }
   1029 
   1030         err = loader_add_to_layer_list(inst, output_list, 1, layer_prop);
   1031     }
   1032 
   1033     return err;
   1034 }
   1035 
   1036 /*
   1037  * Manage lists of VkLayerProperties
   1038  */
   1039 static bool loader_init_layer_list(const struct loader_instance *inst,
   1040                                    struct loader_layer_list *list) {
   1041     list->capacity = 32 * sizeof(struct loader_layer_properties);
   1042     list->list = loader_instance_heap_alloc(
   1043         inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1044     if (list->list == NULL) {
   1045         return false;
   1046     }
   1047     memset(list->list, 0, list->capacity);
   1048     list->count = 0;
   1049     return true;
   1050 }
   1051 
   1052 void loader_destroy_layer_list(const struct loader_instance *inst,
   1053                                struct loader_device *device,
   1054                                struct loader_layer_list *layer_list) {
   1055     if (device) {
   1056         loader_device_heap_free(device, layer_list->list);
   1057     } else {
   1058         loader_instance_heap_free(inst, layer_list->list);
   1059     }
   1060     layer_list->count = 0;
   1061     layer_list->capacity = 0;
   1062 }
   1063 
   1064 /*
   1065  * Search the given layer list for a list
   1066  * matching the given VkLayerProperties
   1067  */
   1068 bool has_vk_layer_property(const VkLayerProperties *vk_layer_prop,
   1069                            const struct loader_layer_list *list) {
   1070     for (uint32_t i = 0; i < list->count; i++) {
   1071         if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
   1072             return true;
   1073     }
   1074     return false;
   1075 }
   1076 
   1077 /*
   1078  * Search the given layer list for a layer
   1079  * matching the given name
   1080  */
   1081 bool has_layer_name(const char *name, const struct loader_layer_list *list) {
   1082     for (uint32_t i = 0; i < list->count; i++) {
   1083         if (strcmp(name, list->list[i].info.layerName) == 0)
   1084             return true;
   1085     }
   1086     return false;
   1087 }
   1088 
   1089 /*
   1090  * Append non-duplicate layer properties defined in prop_list
   1091  * to the given layer_info list
   1092  */
   1093 VkResult loader_add_to_layer_list(const struct loader_instance *inst,
   1094                                   struct loader_layer_list *list,
   1095                                   uint32_t prop_list_count,
   1096                                   const struct loader_layer_properties *props) {
   1097     uint32_t i;
   1098     struct loader_layer_properties *layer;
   1099 
   1100     if (list->list == NULL || list->capacity == 0) {
   1101         loader_init_layer_list(inst, list);
   1102     }
   1103 
   1104     if (list->list == NULL)
   1105         return VK_SUCCESS;
   1106 
   1107     for (i = 0; i < prop_list_count; i++) {
   1108         layer = (struct loader_layer_properties *)&props[i];
   1109 
   1110         // look for duplicates
   1111         if (has_vk_layer_property(&layer->info, list)) {
   1112             continue;
   1113         }
   1114 
   1115         // add to list at end
   1116         // check for enough capacity
   1117         if (list->count * sizeof(struct loader_layer_properties) >=
   1118             list->capacity) {
   1119 
   1120             list->list = loader_instance_heap_realloc(
   1121                 inst, list->list, list->capacity, list->capacity * 2,
   1122                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1123             if (NULL == list->list) {
   1124                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1125                            "realloc failed for layer list when attempting to "
   1126                            "add new layer");
   1127                 return VK_ERROR_OUT_OF_HOST_MEMORY;
   1128             }
   1129             // double capacity
   1130             list->capacity *= 2;
   1131         }
   1132 
   1133         memcpy(&list->list[list->count], layer,
   1134                sizeof(struct loader_layer_properties));
   1135         list->count++;
   1136     }
   1137 
   1138     return VK_SUCCESS;
   1139 }
   1140 
   1141 /**
   1142  * Search the search_list for any layer with a name
   1143  * that matches the given name and a type that matches the given type
   1144  * Add all matching layers to the found_list
   1145  * Do not add if found loader_layer_properties is already
   1146  * on the found_list.
   1147  */
   1148 void loader_find_layer_name_add_list(
   1149     const struct loader_instance *inst, const char *name,
   1150     const enum layer_type type, const struct loader_layer_list *search_list,
   1151     struct loader_layer_list *found_list) {
   1152     bool found = false;
   1153     for (uint32_t i = 0; i < search_list->count; i++) {
   1154         struct loader_layer_properties *layer_prop = &search_list->list[i];
   1155         if (0 == strcmp(layer_prop->info.layerName, name) &&
   1156             (layer_prop->type & type)) {
   1157             /* Found a layer with the same name, add to found_list */
   1158             if (VK_SUCCESS == loader_add_to_layer_list(inst, found_list, 1, layer_prop)) {
   1159                 found = true;
   1160             }
   1161         }
   1162     }
   1163     if (!found) {
   1164         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   1165                    "Warning, couldn't find layer name %s to activate", name);
   1166     }
   1167 }
   1168 
   1169 static VkExtensionProperties *
   1170 get_extension_property(const char *name,
   1171                        const struct loader_extension_list *list) {
   1172     for (uint32_t i = 0; i < list->count; i++) {
   1173         if (strcmp(name, list->list[i].extensionName) == 0)
   1174             return &list->list[i];
   1175     }
   1176     return NULL;
   1177 }
   1178 
   1179 static VkExtensionProperties *
   1180 get_dev_extension_property(const char *name,
   1181                            const struct loader_device_extension_list *list) {
   1182     for (uint32_t i = 0; i < list->count; i++) {
   1183         if (strcmp(name, list->list[i].props.extensionName) == 0)
   1184             return &list->list[i].props;
   1185     }
   1186     return NULL;
   1187 }
   1188 
   1189 /*
   1190  * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
   1191  * the extension must provide two entry points for the loader to use:
   1192  * - "trampoline" entry point - this is the address returned by GetProcAddr
   1193  * and will always do what's necessary to support a global call.
   1194  * - "terminator" function - this function will be put at the end of the
   1195  * instance chain and will contain the necessary logic to call / process
   1196  * the extension for the appropriate ICDs that are available.
   1197  * There is no generic mechanism for including these functions, the references
   1198  * must be placed into the appropriate loader entry points.
   1199  * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for
   1200  * GetProcAddr requests
   1201  * loader_coalesce_extensions(void) - add extension records to the list of
   1202  * global
   1203  * extension available to the app.
   1204  * instance_disp - add function pointer for terminator function to this array.
   1205  * The extension itself should be in a separate file that will be
   1206  * linked directly with the loader.
   1207  */
   1208 
   1209 VkResult loader_get_icd_loader_instance_extensions(
   1210     const struct loader_instance *inst, struct loader_icd_libs *icd_libs,
   1211     struct loader_extension_list *inst_exts) {
   1212     struct loader_extension_list icd_exts;
   1213     VkResult res = VK_SUCCESS;
   1214 
   1215     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   1216                "Build ICD instance extension list");
   1217 
   1218     // traverse scanned icd list adding non-duplicate extensions to the list
   1219     for (uint32_t i = 0; i < icd_libs->count; i++) {
   1220         res = loader_init_generic_list(inst,
   1221                                        (struct loader_generic_list *)&icd_exts,
   1222                                        sizeof(VkExtensionProperties));
   1223         if (VK_SUCCESS != res) {
   1224             goto out;
   1225         }
   1226         res = loader_add_instance_extensions(
   1227             inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
   1228             icd_libs->list[i].lib_name, &icd_exts);
   1229         if (VK_SUCCESS == res) {
   1230             res = loader_add_to_ext_list(inst, inst_exts, icd_exts.count,
   1231                                          icd_exts.list);
   1232         }
   1233         loader_destroy_generic_list(inst,
   1234                                     (struct loader_generic_list *)&icd_exts);
   1235         if (VK_SUCCESS != res) {
   1236             goto out;
   1237         }
   1238     };
   1239 
   1240     // Traverse loader's extensions, adding non-duplicate extensions to the list
   1241     debug_report_add_instance_extensions(inst, inst_exts);
   1242 
   1243 out:
   1244     return res;
   1245 }
   1246 
   1247 struct loader_icd *loader_get_icd_and_device(const VkDevice device,
   1248                                              struct loader_device **found_dev,
   1249                                              uint32_t *icd_index) {
   1250     *found_dev = NULL;
   1251     uint32_t index = 0;
   1252     for (struct loader_instance *inst = loader.instances; inst;
   1253          inst = inst->next) {
   1254         for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
   1255             for (struct loader_device *dev = icd->logical_device_list; dev;
   1256                  dev = dev->next)
   1257                 /* Value comparison of device prevents object wrapping by layers
   1258                  */
   1259                 if (loader_get_dispatch(dev->device) ==
   1260                     loader_get_dispatch(device)) {
   1261                     *found_dev = dev;
   1262                     if (NULL != icd_index) {
   1263                         *icd_index = index;
   1264                     }
   1265                     return icd;
   1266                 }
   1267             index++;
   1268         }
   1269     }
   1270     return NULL;
   1271 }
   1272 
   1273 void loader_destroy_logical_device(const struct loader_instance *inst,
   1274                                    struct loader_device *dev,
   1275                                    const VkAllocationCallbacks *pAllocator) {
   1276     if (pAllocator) {
   1277         dev->alloc_callbacks = *pAllocator;
   1278     }
   1279     if (NULL != dev->activated_layer_list.list) {
   1280         loader_deactivate_layers(inst, dev, &dev->activated_layer_list);
   1281     }
   1282     loader_device_heap_free(dev, dev);
   1283 }
   1284 
   1285 struct loader_device *
   1286 loader_create_logical_device(const struct loader_instance *inst,
   1287                              const VkAllocationCallbacks *pAllocator) {
   1288     struct loader_device *new_dev;
   1289 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   1290     {
   1291 #else
   1292     if (pAllocator) {
   1293         new_dev = (struct loader_device *)pAllocator->pfnAllocation(
   1294             pAllocator->pUserData, sizeof(struct loader_device), sizeof(int *),
   1295             VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
   1296     } else {
   1297 #endif
   1298         new_dev = (struct loader_device *)malloc(sizeof(struct loader_device));
   1299     }
   1300 
   1301     if (!new_dev) {
   1302         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1303                    "Failed to alloc struct loader-device");
   1304         return NULL;
   1305     }
   1306 
   1307     memset(new_dev, 0, sizeof(struct loader_device));
   1308     if (pAllocator) {
   1309         new_dev->alloc_callbacks = *pAllocator;
   1310     }
   1311 
   1312     return new_dev;
   1313 }
   1314 
   1315 void loader_add_logical_device(const struct loader_instance *inst,
   1316                                struct loader_icd *icd,
   1317                                struct loader_device *dev) {
   1318     dev->next = icd->logical_device_list;
   1319     icd->logical_device_list = dev;
   1320 }
   1321 
   1322 void loader_remove_logical_device(const struct loader_instance *inst,
   1323                                   struct loader_icd *icd,
   1324                                   struct loader_device *found_dev,
   1325                                   const VkAllocationCallbacks *pAllocator) {
   1326     struct loader_device *dev, *prev_dev;
   1327 
   1328     if (!icd || !found_dev)
   1329         return;
   1330 
   1331     prev_dev = NULL;
   1332     dev = icd->logical_device_list;
   1333     while (dev && dev != found_dev) {
   1334         prev_dev = dev;
   1335         dev = dev->next;
   1336     }
   1337 
   1338     if (prev_dev)
   1339         prev_dev->next = found_dev->next;
   1340     else
   1341         icd->logical_device_list = found_dev->next;
   1342     loader_destroy_logical_device(inst, found_dev, pAllocator);
   1343 }
   1344 
   1345 static void loader_icd_destroy(struct loader_instance *ptr_inst,
   1346                                struct loader_icd *icd,
   1347                                const VkAllocationCallbacks *pAllocator) {
   1348     ptr_inst->total_icd_count--;
   1349     for (struct loader_device *dev = icd->logical_device_list; dev;) {
   1350         struct loader_device *next_dev = dev->next;
   1351         loader_destroy_logical_device(ptr_inst, dev, pAllocator);
   1352         dev = next_dev;
   1353     }
   1354 
   1355     loader_instance_heap_free(ptr_inst, icd);
   1356 }
   1357 
   1358 static struct loader_icd *
   1359 loader_icd_create(const struct loader_instance *inst) {
   1360     struct loader_icd *icd;
   1361 
   1362     icd = loader_instance_heap_alloc(inst, sizeof(struct loader_icd),
   1363                                      VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1364     if (!icd) {
   1365         return NULL;
   1366     }
   1367 
   1368     memset(icd, 0, sizeof(struct loader_icd));
   1369 
   1370     return icd;
   1371 }
   1372 
   1373 static struct loader_icd *
   1374 loader_icd_add(struct loader_instance *ptr_inst,
   1375                const struct loader_scanned_icds *icd_lib) {
   1376     struct loader_icd *icd;
   1377 
   1378     icd = loader_icd_create(ptr_inst);
   1379     if (!icd) {
   1380         return NULL;
   1381     }
   1382 
   1383     icd->this_icd_lib = icd_lib;
   1384     icd->this_instance = ptr_inst;
   1385 
   1386     /* prepend to the list */
   1387     icd->next = ptr_inst->icds;
   1388     ptr_inst->icds = icd;
   1389     ptr_inst->total_icd_count++;
   1390 
   1391     return icd;
   1392 }
   1393 /**
   1394  * Determine the ICD interface version to use.
   1395  * @param icd
   1396  * @param pVersion Output parameter indicating which version to use or 0 if
   1397  * the negotiation API is not supported by the ICD
   1398  * @return  bool indicating true if the selected interface version is supported
   1399  *          by the loader, false indicates the version is not supported
   1400  * version 0   doesn't support vk_icdGetInstanceProcAddr nor
   1401  *             vk_icdNegotiateLoaderICDInterfaceVersion
   1402  * version 1   supports vk_icdGetInstanceProcAddr
   1403  * version 2   supports vk_icdNegotiateLoaderICDInterfaceVersion
   1404  */
   1405 bool loader_get_icd_interface_version(
   1406         PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version,
   1407         uint32_t *pVersion) {
   1408 
   1409     if (fp_negotiate_icd_version == NULL) {
   1410         // ICD does not support the negotiation API, it supports version 0 or 1
   1411         // calling code must determine if it is version 0 or 1
   1412         *pVersion = 0;
   1413     } else {
   1414         // ICD supports the negotiation API, so call it with the loader's
   1415         // latest version supported
   1416         *pVersion = CURRENT_LOADER_ICD_INTERFACE_VERSION;
   1417         VkResult result = fp_negotiate_icd_version(pVersion);
   1418 
   1419         if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
   1420             // ICD no longer supports the loader's latest interface version so
   1421             // fail loading the ICD
   1422             return false;
   1423         }
   1424     }
   1425 
   1426 #if MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION > 0
   1427     if (*pVersion < MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION) {
   1428         // Loader no longer supports the ICD's latest interface version so fail
   1429         // loading the ICD
   1430         return false;
   1431     }
   1432 #endif
   1433     return true;
   1434 }
   1435 
   1436 void loader_scanned_icd_clear(const struct loader_instance *inst,
   1437                               struct loader_icd_libs *icd_libs) {
   1438     if (icd_libs->capacity == 0)
   1439         return;
   1440     for (uint32_t i = 0; i < icd_libs->count; i++) {
   1441         loader_platform_close_library(icd_libs->list[i].handle);
   1442         loader_instance_heap_free(inst, icd_libs->list[i].lib_name);
   1443     }
   1444     loader_instance_heap_free(inst, icd_libs->list);
   1445     icd_libs->capacity = 0;
   1446     icd_libs->count = 0;
   1447     icd_libs->list = NULL;
   1448 }
   1449 
   1450 static VkResult loader_scanned_icd_init(const struct loader_instance *inst,
   1451                                         struct loader_icd_libs *icd_libs) {
   1452     VkResult err = VK_SUCCESS;
   1453     loader_scanned_icd_clear(inst, icd_libs);
   1454     icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
   1455     icd_libs->list = loader_instance_heap_alloc(
   1456         inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1457     if (NULL == icd_libs->list) {
   1458         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1459             "realloc failed for layer list when attempting to add new layer");
   1460         err = VK_ERROR_OUT_OF_HOST_MEMORY;
   1461     }
   1462     return err;
   1463 }
   1464 
   1465 static VkResult loader_scanned_icd_add(const struct loader_instance *inst,
   1466                                        struct loader_icd_libs *icd_libs,
   1467                                        const char *filename,
   1468                                        uint32_t api_version) {
   1469     loader_platform_dl_handle handle;
   1470     PFN_vkCreateInstance fp_create_inst;
   1471     PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
   1472     PFN_vkGetInstanceProcAddr fp_get_proc_addr;
   1473     PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version;
   1474     struct loader_scanned_icds *new_node;
   1475     uint32_t interface_vers;
   1476     VkResult res = VK_SUCCESS;
   1477 
   1478     /* TODO implement smarter opening/closing of libraries. For now this
   1479      * function leaves libraries open and the scanned_icd_clear closes them */
   1480     handle = loader_platform_open_library(filename);
   1481     if (!handle) {
   1482         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   1483                    loader_platform_open_library_error(filename));
   1484         goto out;
   1485     }
   1486 
   1487     // Get and settle on an ICD interface version
   1488     fp_negotiate_icd_version = loader_platform_get_proc_address(
   1489         handle, "vk_icdNegotiateLoaderICDInterfaceVersion");
   1490 
   1491     if (!loader_get_icd_interface_version(fp_negotiate_icd_version,
   1492                                           &interface_vers)) {
   1493         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1494                    "ICD (%s) doesn't support interface version compatible"
   1495                    "with loader, skip this ICD %s",
   1496                    filename);
   1497         goto out;
   1498     }
   1499 
   1500     fp_get_proc_addr =
   1501         loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
   1502     if (!fp_get_proc_addr) {
   1503         assert(interface_vers == 0);
   1504         // Use deprecated interface from version 0
   1505         fp_get_proc_addr =
   1506             loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
   1507         if (!fp_get_proc_addr) {
   1508             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1509                        loader_platform_get_proc_address_error(
   1510                            "vk_icdGetInstanceProcAddr"));
   1511             goto out;
   1512         } else {
   1513             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   1514                        "Using deprecated ICD interface of "
   1515                        "vkGetInstanceProcAddr instead of "
   1516                        "vk_icdGetInstanceProcAddr for ICD %s",
   1517                        filename);
   1518         }
   1519         fp_create_inst =
   1520             loader_platform_get_proc_address(handle, "vkCreateInstance");
   1521         if (!fp_create_inst) {
   1522             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1523                        "Couldn't get vkCreateInstance via dlsym/loadlibrary "
   1524                        "for ICD %s",
   1525                        filename);
   1526             goto out;
   1527         }
   1528         fp_get_inst_ext_props = loader_platform_get_proc_address(
   1529             handle, "vkEnumerateInstanceExtensionProperties");
   1530         if (!fp_get_inst_ext_props) {
   1531             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1532                        "Couldn't get vkEnumerateInstanceExtensionProperties "
   1533                        "via dlsym/loadlibrary for ICD %s",
   1534                        filename);
   1535             goto out;
   1536         }
   1537     } else {
   1538         // Use newer interface version 1 or later
   1539         if (interface_vers == 0)
   1540             interface_vers = 1;
   1541 
   1542         fp_create_inst =
   1543             (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance");
   1544         if (!fp_create_inst) {
   1545             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1546                        "Couldn't get vkCreateInstance via "
   1547                        "vk_icdGetInstanceProcAddr for ICD %s",
   1548                        filename);
   1549             goto out;
   1550         }
   1551         fp_get_inst_ext_props =
   1552             (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(
   1553                 NULL, "vkEnumerateInstanceExtensionProperties");
   1554         if (!fp_get_inst_ext_props) {
   1555             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1556                        "Couldn't get vkEnumerateInstanceExtensionProperties "
   1557                        "via vk_icdGetInstanceProcAddr for ICD %s",
   1558                        filename);
   1559             goto out;
   1560         }
   1561     }
   1562 
   1563     // check for enough capacity
   1564     if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >=
   1565         icd_libs->capacity) {
   1566 
   1567         icd_libs->list = loader_instance_heap_realloc(
   1568             inst, icd_libs->list, icd_libs->capacity, icd_libs->capacity * 2,
   1569             VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1570         if (NULL == icd_libs->list) {
   1571             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   1572             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1573                        "realloc failed on icd library list");
   1574             goto out;
   1575         }
   1576         // double capacity
   1577         icd_libs->capacity *= 2;
   1578     }
   1579     new_node = &(icd_libs->list[icd_libs->count]);
   1580 
   1581     new_node->handle = handle;
   1582     new_node->api_version = api_version;
   1583     new_node->GetInstanceProcAddr = fp_get_proc_addr;
   1584     new_node->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
   1585     new_node->CreateInstance = fp_create_inst;
   1586     new_node->interface_version = interface_vers;
   1587 
   1588     new_node->lib_name = (char *)loader_instance_heap_alloc(
   1589         inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1590     if (NULL == new_node->lib_name) {
   1591         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   1592         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   1593                    "Out of memory can't add icd");
   1594         goto out;
   1595     }
   1596     strcpy(new_node->lib_name, filename);
   1597     icd_libs->count++;
   1598 
   1599 out:
   1600 
   1601     return res;
   1602 }
   1603 
   1604 static bool loader_icd_init_entrys(struct loader_icd *icd, VkInstance inst,
   1605                                    const PFN_vkGetInstanceProcAddr fp_gipa) {
   1606 /* initialize entrypoint function pointers */
   1607 
   1608 #define LOOKUP_GIPA(func, required)                                            \
   1609     do {                                                                       \
   1610         icd->func = (PFN_vk##func)fp_gipa(inst, "vk" #func);                   \
   1611         if (!icd->func && required) {                                          \
   1612             loader_log((struct loader_instance *)inst,                         \
   1613                        VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,                     \
   1614                        loader_platform_get_proc_address_error("vk" #func));    \
   1615             return false;                                                      \
   1616         }                                                                      \
   1617     } while (0)
   1618 
   1619     LOOKUP_GIPA(GetDeviceProcAddr, true);
   1620     LOOKUP_GIPA(DestroyInstance, true);
   1621     LOOKUP_GIPA(EnumeratePhysicalDevices, true);
   1622     LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
   1623     LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
   1624     LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
   1625     LOOKUP_GIPA(CreateDevice, true);
   1626     LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
   1627     LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
   1628     LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
   1629     LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
   1630     LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
   1631     LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
   1632     LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
   1633     LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
   1634     LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
   1635     LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
   1636     LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
   1637     LOOKUP_GIPA(GetPhysicalDeviceDisplayPropertiesKHR, false);
   1638     LOOKUP_GIPA(GetDisplayModePropertiesKHR, false);
   1639     LOOKUP_GIPA(CreateDisplayPlaneSurfaceKHR, false);
   1640     LOOKUP_GIPA(GetPhysicalDeviceDisplayPlanePropertiesKHR, false);
   1641     LOOKUP_GIPA(GetDisplayPlaneSupportedDisplaysKHR, false);
   1642     LOOKUP_GIPA(CreateDisplayModeKHR, false);
   1643     LOOKUP_GIPA(GetDisplayPlaneCapabilitiesKHR, false);
   1644     LOOKUP_GIPA(DestroySurfaceKHR, false);
   1645     LOOKUP_GIPA(CreateSwapchainKHR, false);
   1646 #ifdef VK_USE_PLATFORM_WIN32_KHR
   1647     LOOKUP_GIPA(CreateWin32SurfaceKHR, false);
   1648     LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
   1649 #endif
   1650 #ifdef VK_USE_PLATFORM_XCB_KHR
   1651     LOOKUP_GIPA(CreateXcbSurfaceKHR, false);
   1652     LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
   1653 #endif
   1654 #ifdef VK_USE_PLATFORM_XLIB_KHR
   1655     LOOKUP_GIPA(CreateXlibSurfaceKHR, false);
   1656     LOOKUP_GIPA(GetPhysicalDeviceXlibPresentationSupportKHR, false);
   1657 #endif
   1658 #ifdef VK_USE_PLATFORM_MIR_KHR
   1659     LOOKUP_GIPA(CreateMirSurfaceKHR, false);
   1660     LOOKUP_GIPA(GetPhysicalDeviceMirPresentationSupportKHR, false);
   1661 #endif
   1662 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
   1663     LOOKUP_GIPA(CreateWaylandSurfaceKHR, false);
   1664     LOOKUP_GIPA(GetPhysicalDeviceWaylandPresentationSupportKHR, false);
   1665 #endif
   1666     LOOKUP_GIPA(GetPhysicalDeviceExternalImageFormatPropertiesNV, false);
   1667 
   1668 #undef LOOKUP_GIPA
   1669 
   1670     return true;
   1671 }
   1672 
   1673 static void loader_debug_init(void) {
   1674     char *env, *orig;
   1675 
   1676     if (g_loader_debug > 0)
   1677         return;
   1678 
   1679     g_loader_debug = 0;
   1680 
   1681     /* parse comma-separated debug options */
   1682     orig = env = loader_getenv("VK_LOADER_DEBUG", NULL);
   1683     while (env) {
   1684         char *p = strchr(env, ',');
   1685         size_t len;
   1686 
   1687         if (p)
   1688             len = p - env;
   1689         else
   1690             len = strlen(env);
   1691 
   1692         if (len > 0) {
   1693             if (strncmp(env, "all", len) == 0) {
   1694                 g_loader_debug = ~0u;
   1695                 g_loader_log_msgs = ~0u;
   1696             } else if (strncmp(env, "warn", len) == 0) {
   1697                 g_loader_debug |= LOADER_WARN_BIT;
   1698                 g_loader_log_msgs |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
   1699             } else if (strncmp(env, "info", len) == 0) {
   1700                 g_loader_debug |= LOADER_INFO_BIT;
   1701                 g_loader_log_msgs |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
   1702             } else if (strncmp(env, "perf", len) == 0) {
   1703                 g_loader_debug |= LOADER_PERF_BIT;
   1704                 g_loader_log_msgs |=
   1705                     VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
   1706             } else if (strncmp(env, "error", len) == 0) {
   1707                 g_loader_debug |= LOADER_ERROR_BIT;
   1708                 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
   1709             } else if (strncmp(env, "debug", len) == 0) {
   1710                 g_loader_debug |= LOADER_DEBUG_BIT;
   1711                 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
   1712             }
   1713         }
   1714 
   1715         if (!p)
   1716             break;
   1717 
   1718         env = p + 1;
   1719     }
   1720 
   1721     loader_free_getenv(orig, NULL);
   1722 }
   1723 
   1724 void loader_initialize(void) {
   1725     // initialize mutexs
   1726     loader_platform_thread_create_mutex(&loader_lock);
   1727     loader_platform_thread_create_mutex(&loader_json_lock);
   1728 
   1729     // initialize logging
   1730     loader_debug_init();
   1731 
   1732     // initial cJSON to use alloc callbacks
   1733     cJSON_Hooks alloc_fns = {
   1734         .malloc_fn = loader_instance_tls_heap_alloc,
   1735         .free_fn = loader_instance_tls_heap_free,
   1736     };
   1737     cJSON_InitHooks(&alloc_fns);
   1738 }
   1739 
   1740 struct loader_manifest_files {
   1741     uint32_t count;
   1742     char **filename_list;
   1743 };
   1744 
   1745 /**
   1746  * Get next file or dirname given a string list or registry key path
   1747  *
   1748  * \returns
   1749  * A pointer to first char in the next path.
   1750  * The next path (or NULL) in the list is returned in next_path.
   1751  * Note: input string is modified in some cases. PASS IN A COPY!
   1752  */
   1753 static char *loader_get_next_path(char *path) {
   1754     uint32_t len;
   1755     char *next;
   1756 
   1757     if (path == NULL)
   1758         return NULL;
   1759     next = strchr(path, PATH_SEPERATOR);
   1760     if (next == NULL) {
   1761         len = (uint32_t)strlen(path);
   1762         next = path + len;
   1763     } else {
   1764         *next = '\0';
   1765         next++;
   1766     }
   1767 
   1768     return next;
   1769 }
   1770 
   1771 /**
   1772  * Given a path which is absolute or relative, expand the path if relative or
   1773  * leave the path unmodified if absolute. The base path to prepend to relative
   1774  * paths is given in rel_base.
   1775  *
   1776  * \returns
   1777  * A string in out_fullpath of the full absolute path
   1778  */
   1779 static void loader_expand_path(const char *path, const char *rel_base,
   1780                                size_t out_size, char *out_fullpath) {
   1781     if (loader_platform_is_path_absolute(path)) {
   1782         // do not prepend a base to an absolute path
   1783         rel_base = "";
   1784     }
   1785 
   1786     loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
   1787 }
   1788 
   1789 /**
   1790  * Given a filename (file)  and a list of paths (dir), try to find an existing
   1791  * file in the paths.  If filename already is a path then no
   1792  * searching in the given paths.
   1793  *
   1794  * \returns
   1795  * A string in out_fullpath of either the full path or file.
   1796  */
   1797 static void loader_get_fullpath(const char *file, const char *dirs,
   1798                                 size_t out_size, char *out_fullpath) {
   1799     if (!loader_platform_is_path(file) && *dirs) {
   1800         char *dirs_copy, *dir, *next_dir;
   1801 
   1802         dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
   1803         strcpy(dirs_copy, dirs);
   1804 
   1805         // find if file exists after prepending paths in given list
   1806         for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir));
   1807              dir = next_dir) {
   1808             loader_platform_combine_path(out_fullpath, out_size, dir, file,
   1809                                          NULL);
   1810             if (loader_platform_file_exists(out_fullpath)) {
   1811                 return;
   1812             }
   1813         }
   1814     }
   1815 
   1816     snprintf(out_fullpath, out_size, "%s", file);
   1817 }
   1818 
   1819 /**
   1820  * Read a JSON file into a buffer.
   1821  *
   1822  * \returns
   1823  * A pointer to a cJSON object representing the JSON parse tree.
   1824  * This returned buffer should be freed by caller.
   1825  */
   1826 static VkResult loader_get_json(const struct loader_instance *inst,
   1827                                 const char *filename, cJSON **json) {
   1828     FILE *file = NULL;
   1829     char *json_buf;
   1830     size_t len;
   1831     VkResult res = VK_SUCCESS;
   1832 
   1833     if (NULL == json) {
   1834         res = VK_ERROR_INITIALIZATION_FAILED;
   1835         goto out;
   1836     }
   1837 
   1838     *json = NULL;
   1839 
   1840     file = fopen(filename, "rb");
   1841     if (!file) {
   1842         res = VK_ERROR_INITIALIZATION_FAILED;
   1843         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1844                    "Couldn't open JSON file %s", filename);
   1845         goto out;
   1846     }
   1847     fseek(file, 0, SEEK_END);
   1848     len = ftell(file);
   1849     fseek(file, 0, SEEK_SET);
   1850     json_buf = (char *)loader_stack_alloc(len + 1);
   1851     if (json_buf == NULL) {
   1852         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   1853         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1854                    "Out of memory can't get JSON file");
   1855         goto out;
   1856     }
   1857     if (fread(json_buf, sizeof(char), len, file) != len) {
   1858         res = VK_ERROR_INITIALIZATION_FAILED;
   1859         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1860                    "fread failed can't get JSON file");
   1861         goto out;
   1862     }
   1863     json_buf[len] = '\0';
   1864 
   1865     // parse text from file
   1866     *json = cJSON_Parse(json_buf);
   1867     if (*json == NULL) {
   1868         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   1869         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1870                    "Can't parse JSON file %s", filename);
   1871         goto out;
   1872     }
   1873 
   1874 out:
   1875     if (NULL != file) {
   1876         fclose(file);
   1877     }
   1878 
   1879     return res;
   1880 }
   1881 
   1882 /**
   1883  * Do a deep copy of the loader_layer_properties structure.
   1884  */
   1885 VkResult loader_copy_layer_properties(const struct loader_instance *inst,
   1886                                       struct loader_layer_properties *dst,
   1887                                       struct loader_layer_properties *src) {
   1888     uint32_t cnt, i;
   1889     memcpy(dst, src, sizeof(*src));
   1890     dst->instance_extension_list.list =
   1891         loader_instance_heap_alloc(inst, sizeof(VkExtensionProperties) *
   1892                                              src->instance_extension_list.count,
   1893                                    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1894     if (NULL == dst->instance_extension_list.list) {
   1895         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1896                    "alloc failed for instance extension list");
   1897         return VK_ERROR_OUT_OF_HOST_MEMORY;
   1898     }
   1899     dst->instance_extension_list.capacity =
   1900         sizeof(VkExtensionProperties) * src->instance_extension_list.count;
   1901     memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
   1902            dst->instance_extension_list.capacity);
   1903     dst->device_extension_list.list =
   1904         loader_instance_heap_alloc(inst, sizeof(struct loader_dev_ext_props) *
   1905                                              src->device_extension_list.count,
   1906                                    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1907     if (NULL == dst->device_extension_list.list) {
   1908         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1909                    "alloc failed for device extension list");
   1910         return VK_ERROR_OUT_OF_HOST_MEMORY;
   1911     }
   1912     memset(dst->device_extension_list.list, 0, sizeof(struct loader_dev_ext_props) *
   1913         src->device_extension_list.count);
   1914 
   1915     dst->device_extension_list.capacity =
   1916         sizeof(struct loader_dev_ext_props) * src->device_extension_list.count;
   1917     memcpy(dst->device_extension_list.list, src->device_extension_list.list,
   1918            dst->device_extension_list.capacity);
   1919     if (src->device_extension_list.count > 0 &&
   1920         src->device_extension_list.list->entrypoint_count > 0) {
   1921         cnt = src->device_extension_list.list->entrypoint_count;
   1922         dst->device_extension_list.list->entrypoints =
   1923             loader_instance_heap_alloc(inst, sizeof(char *) * cnt,
   1924                                        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1925         if (NULL == dst->device_extension_list.list->entrypoints) {
   1926             loader_log(
   1927                 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1928                 "alloc failed for device extension list entrypoint array");
   1929             return VK_ERROR_OUT_OF_HOST_MEMORY;
   1930         }
   1931         memset(dst->device_extension_list.list->entrypoints, 0, sizeof(char *) * cnt);
   1932 
   1933         for (i = 0; i < cnt; i++) {
   1934             dst->device_extension_list.list->entrypoints[i] =
   1935                 loader_instance_heap_alloc(
   1936                     inst,
   1937                     strlen(src->device_extension_list.list->entrypoints[i]) + 1,
   1938                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   1939             if (NULL == dst->device_extension_list.list->entrypoints[i]) {
   1940                 loader_log(
   1941                     inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   1942                     "alloc failed for device extension list entrypoint %d", i);
   1943                 return VK_ERROR_OUT_OF_HOST_MEMORY;
   1944             }
   1945             strcpy(dst->device_extension_list.list->entrypoints[i],
   1946                    src->device_extension_list.list->entrypoints[i]);
   1947         }
   1948     }
   1949 
   1950     return VK_SUCCESS;
   1951 }
   1952 
   1953 static bool
   1954 loader_find_layer_name_list(const char *name,
   1955                             const struct loader_layer_list *layer_list) {
   1956     if (!layer_list)
   1957         return false;
   1958     for (uint32_t j = 0; j < layer_list->count; j++)
   1959         if (!strcmp(name, layer_list->list[j].info.layerName))
   1960             return true;
   1961     return false;
   1962 }
   1963 
   1964 static bool loader_find_layer_name(const char *name, uint32_t layer_count,
   1965                                    const char **layer_list) {
   1966     if (!layer_list)
   1967         return false;
   1968     for (uint32_t j = 0; j < layer_count; j++)
   1969         if (!strcmp(name, layer_list[j]))
   1970             return true;
   1971     return false;
   1972 }
   1973 
   1974 bool loader_find_layer_name_array(
   1975     const char *name, uint32_t layer_count,
   1976     const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]) {
   1977     if (!layer_list)
   1978         return false;
   1979     for (uint32_t j = 0; j < layer_count; j++)
   1980         if (!strcmp(name, layer_list[j]))
   1981             return true;
   1982     return false;
   1983 }
   1984 
   1985 /**
   1986  * Searches through an array of layer names (ppp_layer_names) looking for a
   1987  * layer key_name.
   1988  * If not found then simply returns updating nothing.
   1989  * Otherwise, it uses expand_count, expand_names adding them to layer names.
   1990  * Any duplicate (pre-existing) expand_names in layer names are removed.
   1991  * Order is otherwise preserved, with the layer key_name being replaced by the
   1992  * expand_names.
   1993  * @param inst
   1994  * @param layer_count
   1995  * @param ppp_layer_names
   1996  */
   1997 VkResult loader_expand_layer_names(
   1998     struct loader_instance *inst, const char *key_name, uint32_t expand_count,
   1999     const char expand_names[][VK_MAX_EXTENSION_NAME_SIZE],
   2000     uint32_t *layer_count, char const *const **ppp_layer_names) {
   2001 
   2002     char const *const *pp_src_layers = *ppp_layer_names;
   2003 
   2004     if (!loader_find_layer_name(key_name, *layer_count,
   2005                                 (char const **)pp_src_layers)) {
   2006         inst->activated_layers_are_std_val = false;
   2007         return VK_SUCCESS; // didn't find the key_name in the list.
   2008     }
   2009 
   2010     loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   2011                "Found meta layer %s, replacing with actual layer group",
   2012                key_name);
   2013 
   2014     inst->activated_layers_are_std_val = true;
   2015     char const **pp_dst_layers = loader_instance_heap_alloc(
   2016         inst, (expand_count + *layer_count - 1) * sizeof(char const *),
   2017         VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
   2018     if (NULL == pp_dst_layers) {
   2019         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2020                    "alloc failed for dst layer array");
   2021         return VK_ERROR_OUT_OF_HOST_MEMORY;
   2022     }
   2023 
   2024     // copy layers from src to dst, stripping key_name and anything in
   2025     // expand_names.
   2026     uint32_t src_index, dst_index = 0;
   2027     for (src_index = 0; src_index < *layer_count; src_index++) {
   2028         if (loader_find_layer_name_array(pp_src_layers[src_index], expand_count,
   2029                                          expand_names)) {
   2030             continue;
   2031         }
   2032 
   2033         if (!strcmp(pp_src_layers[src_index], key_name)) {
   2034             // insert all expand_names in place of key_name
   2035             uint32_t expand_index;
   2036             for (expand_index = 0; expand_index < expand_count;
   2037                  expand_index++) {
   2038                 pp_dst_layers[dst_index++] = expand_names[expand_index];
   2039             }
   2040             continue;
   2041         }
   2042 
   2043         pp_dst_layers[dst_index++] = pp_src_layers[src_index];
   2044     }
   2045 
   2046     *ppp_layer_names = pp_dst_layers;
   2047     *layer_count = dst_index;
   2048 
   2049     return VK_SUCCESS;
   2050 }
   2051 
   2052 void loader_delete_shadow_inst_layer_names(const struct loader_instance *inst,
   2053                                            const VkInstanceCreateInfo *orig,
   2054                                            VkInstanceCreateInfo *ours) {
   2055     /* Free the layer names array iff we had to reallocate it */
   2056     if (orig->ppEnabledLayerNames != ours->ppEnabledLayerNames) {
   2057         loader_instance_heap_free(inst, (void *)ours->ppEnabledLayerNames);
   2058     }
   2059 }
   2060 
   2061 void loader_init_std_validation_props(struct loader_layer_properties *props) {
   2062     memset(props, 0, sizeof(struct loader_layer_properties));
   2063     props->type = VK_LAYER_TYPE_META_EXPLICT;
   2064     strncpy(props->info.description, "LunarG Standard Validation Layer",
   2065                 sizeof (props->info.description));
   2066     props->info.implementationVersion = 1;
   2067     strncpy(props->info.layerName, std_validation_str,
   2068                 sizeof (props->info.layerName));
   2069     // TODO what about specVersion? for now insert loader's built version
   2070     props->info.specVersion = VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION);
   2071 }
   2072 
   2073 /**
   2074  * Searches through the existing instance layer lists looking for
   2075  * the set of required layer names. If found then it adds a meta property to the
   2076  * layer list.
   2077  * Assumes the required layers are the same for both instance and device lists.
   2078  * @param inst
   2079  * @param layer_count  number of layers in layer_names
   2080  * @param layer_names  array of required layer names
   2081  * @param layer_instance_list
   2082  */
   2083 static void loader_add_layer_property_meta(
   2084     const struct loader_instance *inst, uint32_t layer_count,
   2085     const char layer_names[][VK_MAX_EXTENSION_NAME_SIZE],
   2086     struct loader_layer_list *layer_instance_list) {
   2087     uint32_t i;
   2088     bool found;
   2089     struct loader_layer_list *layer_list;
   2090 
   2091     if (0 == layer_count || (!layer_instance_list))
   2092         return;
   2093     if (layer_instance_list && (layer_count > layer_instance_list->count))
   2094         return;
   2095 
   2096 
   2097     layer_list = layer_instance_list;
   2098 
   2099     found = true;
   2100     if (layer_list == NULL)
   2101         return;
   2102     for (i = 0; i < layer_count; i++) {
   2103         if (loader_find_layer_name_list(layer_names[i], layer_list))
   2104             continue;
   2105         found = false;
   2106         break;
   2107     }
   2108 
   2109     struct loader_layer_properties *props;
   2110     if (found) {
   2111         props = loader_get_next_layer_property(inst, layer_list);
   2112         if (NULL == props) {
   2113             // Error already triggered in loader_get_next_layer_property.
   2114             return;
   2115         }
   2116         loader_init_std_validation_props(props);
   2117 
   2118     }
   2119 
   2120 }
   2121 
   2122 static void loader_read_json_layer(
   2123     const struct loader_instance *inst,
   2124     struct loader_layer_list *layer_instance_list, cJSON *layer_node,
   2125     cJSON *item, cJSON *disable_environment, bool is_implicit, char *filename) {
   2126     char *temp;
   2127     char *name, *type, *library_path, *api_version;
   2128     char *implementation_version, *description;
   2129     cJSON *ext_item;
   2130     VkExtensionProperties ext_prop;
   2131 
   2132 /*
   2133  * The following are required in the "layer" object:
   2134  * (required) "name"
   2135  * (required) "type"
   2136  * (required) library_path
   2137  * (required) api_version
   2138  * (required) implementation_version
   2139  * (required) description
   2140  * (required for implicit layers) disable_environment
   2141  */
   2142 
   2143 #define GET_JSON_OBJECT(node, var)                                             \
   2144     {                                                                          \
   2145         var = cJSON_GetObjectItem(node, #var);                                 \
   2146         if (var == NULL) {                                                     \
   2147             layer_node = layer_node->next;                                     \
   2148             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,               \
   2149                        "Didn't find required layer object %s in manifest "     \
   2150                        "JSON file, skipping this layer",                       \
   2151                        #var);                                                  \
   2152             return;                                                            \
   2153         }                                                                      \
   2154     }
   2155 #define GET_JSON_ITEM(node, var)                                               \
   2156     {                                                                          \
   2157         item = cJSON_GetObjectItem(node, #var);                                \
   2158         if (item == NULL) {                                                    \
   2159             layer_node = layer_node->next;                                     \
   2160             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,               \
   2161                        "Didn't find required layer value %s in manifest JSON " \
   2162                        "file, skipping this layer",                            \
   2163                        #var);                                                  \
   2164             return;                                                            \
   2165         }                                                                      \
   2166         temp = cJSON_Print(item);                                              \
   2167         if (temp == NULL) {                                                    \
   2168             layer_node = layer_node->next;                                     \
   2169             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,               \
   2170                        "Problem accessing layer value %s in manifest JSON "    \
   2171                        "file, skipping this layer",                            \
   2172                        #var);                                                  \
   2173             return;                                                            \
   2174         }                                                                      \
   2175         temp[strlen(temp) - 1] = '\0';                                         \
   2176         var = loader_stack_alloc(strlen(temp) + 1);                            \
   2177         strcpy(var, &temp[1]);                                                 \
   2178         cJSON_Free(temp);                                                      \
   2179     }
   2180     GET_JSON_ITEM(layer_node, name)
   2181     GET_JSON_ITEM(layer_node, type)
   2182     GET_JSON_ITEM(layer_node, library_path)
   2183     GET_JSON_ITEM(layer_node, api_version)
   2184     GET_JSON_ITEM(layer_node, implementation_version)
   2185     GET_JSON_ITEM(layer_node, description)
   2186     if (is_implicit) {
   2187         GET_JSON_OBJECT(layer_node, disable_environment)
   2188     }
   2189 #undef GET_JSON_ITEM
   2190 #undef GET_JSON_OBJECT
   2191 
   2192     // add list entry
   2193     struct loader_layer_properties *props = NULL;
   2194     if (!strcmp(type, "DEVICE")) {
   2195         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2196                    "Device layers are deprecated skipping this layer");
   2197         layer_node = layer_node->next;
   2198         return;
   2199     }
   2200     // Allow either GLOBAL or INSTANCE type interchangeably to handle
   2201     // layers that must work with older loaders
   2202     if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
   2203         if (layer_instance_list == NULL) {
   2204             layer_node = layer_node->next;
   2205             return;
   2206         }
   2207         props = loader_get_next_layer_property(inst, layer_instance_list);
   2208         if (NULL == props) {
   2209             // Error already triggered in loader_get_next_layer_property.
   2210             return;
   2211         }
   2212         props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT
   2213                                     : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
   2214     }
   2215 
   2216     if (props == NULL) {
   2217         layer_node = layer_node->next;
   2218         return;
   2219     }
   2220 
   2221     strncpy(props->info.layerName, name, sizeof(props->info.layerName));
   2222     props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
   2223 
   2224     char *fullpath = props->lib_name;
   2225     char *rel_base;
   2226     if (loader_platform_is_path(library_path)) {
   2227         // a relative or absolute path
   2228         char *name_copy = loader_stack_alloc(strlen(filename) + 1);
   2229         strcpy(name_copy, filename);
   2230         rel_base = loader_platform_dirname(name_copy);
   2231         loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
   2232     } else {
   2233         // a filename which is assumed in a system directory
   2234         loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH,
   2235                             MAX_STRING_SIZE, fullpath);
   2236     }
   2237     props->info.specVersion = loader_make_version(api_version);
   2238     props->info.implementationVersion = atoi(implementation_version);
   2239     strncpy((char *)props->info.description, description,
   2240             sizeof(props->info.description));
   2241     props->info.description[sizeof(props->info.description) - 1] = '\0';
   2242     if (is_implicit) {
   2243         if (!disable_environment || !disable_environment->child) {
   2244             loader_log(
   2245                 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2246                 "Didn't find required layer child value disable_environment"
   2247                 "in manifest JSON file, skipping this layer");
   2248             layer_node = layer_node->next;
   2249             return;
   2250         }
   2251         strncpy(props->disable_env_var.name, disable_environment->child->string,
   2252                 sizeof(props->disable_env_var.name));
   2253         props->disable_env_var.name[sizeof(props->disable_env_var.name) - 1] =
   2254             '\0';
   2255         strncpy(props->disable_env_var.value,
   2256                 disable_environment->child->valuestring,
   2257                 sizeof(props->disable_env_var.value));
   2258         props->disable_env_var.value[sizeof(props->disable_env_var.value) - 1] =
   2259             '\0';
   2260     }
   2261 
   2262 /**
   2263 * Now get all optional items and objects and put in list:
   2264 * functions
   2265 * instance_extensions
   2266 * device_extensions
   2267 * enable_environment (implicit layers only)
   2268 */
   2269 #define GET_JSON_OBJECT(node, var)                                             \
   2270     { var = cJSON_GetObjectItem(node, #var); }
   2271 #define GET_JSON_ITEM(node, var)                                               \
   2272     {                                                                          \
   2273         item = cJSON_GetObjectItem(node, #var);                                \
   2274         if (item != NULL) {                                                    \
   2275             temp = cJSON_Print(item);                                          \
   2276             if (temp != NULL) {                                                \
   2277                 temp[strlen(temp) - 1] = '\0';                                 \
   2278                 var = loader_stack_alloc(strlen(temp) + 1);                    \
   2279                 strcpy(var, &temp[1]);                                         \
   2280                 cJSON_Free(temp);                                              \
   2281             }                                                                  \
   2282         }                                                                      \
   2283     }
   2284 
   2285     cJSON *instance_extensions, *device_extensions, *functions,
   2286         *enable_environment;
   2287     cJSON *entrypoints;
   2288     char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
   2289     char **entry_array;
   2290     vkGetInstanceProcAddr = NULL;
   2291     vkGetDeviceProcAddr = NULL;
   2292     spec_version = NULL;
   2293     entrypoints = NULL;
   2294     entry_array = NULL;
   2295     int i, j;
   2296 
   2297     /**
   2298     * functions
   2299     *     vkGetInstanceProcAddr
   2300     *     vkGetDeviceProcAddr
   2301     */
   2302     GET_JSON_OBJECT(layer_node, functions)
   2303     if (functions != NULL) {
   2304         GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
   2305         GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
   2306         if (vkGetInstanceProcAddr != NULL)
   2307             strncpy(props->functions.str_gipa, vkGetInstanceProcAddr,
   2308                     sizeof(props->functions.str_gipa));
   2309         props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = '\0';
   2310         if (vkGetDeviceProcAddr != NULL)
   2311             strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr,
   2312                     sizeof(props->functions.str_gdpa));
   2313         props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = '\0';
   2314     }
   2315     /**
   2316     * instance_extensions
   2317     * array of
   2318     *     name
   2319     *     spec_version
   2320     */
   2321     GET_JSON_OBJECT(layer_node, instance_extensions)
   2322     if (instance_extensions != NULL) {
   2323         int count = cJSON_GetArraySize(instance_extensions);
   2324         for (i = 0; i < count; i++) {
   2325             ext_item = cJSON_GetArrayItem(instance_extensions, i);
   2326             GET_JSON_ITEM(ext_item, name)
   2327             if (name != NULL) {
   2328                 strncpy(ext_prop.extensionName, name,
   2329                         sizeof(ext_prop.extensionName));
   2330                 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
   2331                     '\0';
   2332             }
   2333             GET_JSON_ITEM(ext_item, spec_version)
   2334             if (NULL != spec_version) {
   2335                 ext_prop.specVersion = atoi(spec_version);
   2336             } else {
   2337                 ext_prop.specVersion = 0;
   2338             }
   2339             bool ext_unsupported =
   2340                 wsi_unsupported_instance_extension(&ext_prop);
   2341             if (!ext_unsupported) {
   2342                 loader_add_to_ext_list(inst, &props->instance_extension_list, 1,
   2343                                        &ext_prop);
   2344             }
   2345         }
   2346     }
   2347     /**
   2348     * device_extensions
   2349     * array of
   2350     *     name
   2351     *     spec_version
   2352     *     entrypoints
   2353     */
   2354     GET_JSON_OBJECT(layer_node, device_extensions)
   2355     if (device_extensions != NULL) {
   2356         int count = cJSON_GetArraySize(device_extensions);
   2357         for (i = 0; i < count; i++) {
   2358             ext_item = cJSON_GetArrayItem(device_extensions, i);
   2359             GET_JSON_ITEM(ext_item, name)
   2360             GET_JSON_ITEM(ext_item, spec_version)
   2361             if (name != NULL) {
   2362                 strncpy(ext_prop.extensionName, name,
   2363                         sizeof(ext_prop.extensionName));
   2364                 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
   2365                     '\0';
   2366             }
   2367             if (NULL != spec_version) {
   2368                 ext_prop.specVersion = atoi(spec_version);
   2369             } else {
   2370                 ext_prop.specVersion = 0;
   2371             }
   2372             // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
   2373             GET_JSON_OBJECT(ext_item, entrypoints)
   2374             int entry_count;
   2375             if (entrypoints == NULL) {
   2376                 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
   2377                                            &ext_prop, 0, NULL);
   2378                 continue;
   2379             }
   2380             entry_count = cJSON_GetArraySize(entrypoints);
   2381             if (entry_count) {
   2382                 entry_array =
   2383                     (char **)loader_stack_alloc(sizeof(char *) * entry_count);
   2384             }
   2385             for (j = 0; j < entry_count; j++) {
   2386                 ext_item = cJSON_GetArrayItem(entrypoints, j);
   2387                 if (ext_item != NULL) {
   2388                     temp = cJSON_Print(ext_item);
   2389                     if (NULL == temp) {
   2390                         entry_array[j] = NULL;
   2391                         continue;
   2392                     }
   2393                     temp[strlen(temp) - 1] = '\0';
   2394                     entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
   2395                     strcpy(entry_array[j], &temp[1]);
   2396                     cJSON_Free(temp);
   2397                 }
   2398             }
   2399             loader_add_to_dev_ext_list(inst, &props->device_extension_list,
   2400                                        &ext_prop, entry_count, entry_array);
   2401         }
   2402     }
   2403     if (is_implicit) {
   2404         GET_JSON_OBJECT(layer_node, enable_environment)
   2405 
   2406         // enable_environment is optional
   2407         if (enable_environment) {
   2408             strncpy(props->enable_env_var.name,
   2409                     enable_environment->child->string,
   2410                     sizeof(props->enable_env_var.name));
   2411             props->enable_env_var.name[sizeof(props->enable_env_var.name) - 1] =
   2412                 '\0';
   2413             strncpy(props->enable_env_var.value,
   2414                     enable_environment->child->valuestring,
   2415                     sizeof(props->enable_env_var.value));
   2416             props->enable_env_var
   2417                 .value[sizeof(props->enable_env_var.value) - 1] = '\0';
   2418         }
   2419     }
   2420 #undef GET_JSON_ITEM
   2421 #undef GET_JSON_OBJECT
   2422 }
   2423 
   2424 /**
   2425  * Given a cJSON struct (json) of the top level JSON object from layer manifest
   2426  * file, add entry to the layer_list. Fill out the layer_properties in this list
   2427  * entry from the input cJSON object.
   2428  *
   2429  * \returns
   2430  * void
   2431  * layer_list has a new entry and initialized accordingly.
   2432  * If the json input object does not have all the required fields no entry
   2433  * is added to the list.
   2434  */
   2435 static void
   2436 loader_add_layer_properties(const struct loader_instance *inst,
   2437                             struct loader_layer_list *layer_instance_list,
   2438                             cJSON *json, bool is_implicit, char *filename) {
   2439     /* Fields in layer manifest file that are required:
   2440      * (required) file_format_version
   2441      *
   2442      * If more than one "layer" object are to be used, use the "layers" array
   2443      * instead.
   2444      *
   2445      * First get all required items and if any missing abort
   2446      */
   2447 
   2448     cJSON *item, *layers_node, *layer_node;
   2449     uint16_t file_major_vers = 0;
   2450     uint16_t file_minor_vers = 0;
   2451     uint16_t file_patch_vers = 0;
   2452     char *vers_tok;
   2453     cJSON *disable_environment = NULL;
   2454     item = cJSON_GetObjectItem(json, "file_format_version");
   2455     if (item == NULL) {
   2456         return;
   2457     }
   2458     char *file_vers = cJSON_PrintUnformatted(item);
   2459     if (NULL == file_vers) {
   2460         return;
   2461     }
   2462     loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   2463                "Found manifest file %s, version %s", filename, file_vers);
   2464     // Get the major/minor/and patch as integers for easier comparison
   2465     vers_tok = strtok(file_vers, ".\"\n\r");
   2466     if (NULL != vers_tok) {
   2467         file_major_vers = (uint16_t)atoi(vers_tok);
   2468         vers_tok = strtok(NULL, ".\"\n\r");
   2469         if (NULL != vers_tok) {
   2470             file_minor_vers = (uint16_t)atoi(vers_tok);
   2471             vers_tok = strtok(NULL, ".\"\n\r");
   2472             if (NULL != vers_tok) {
   2473                 file_patch_vers = (uint16_t)atoi(vers_tok);
   2474             }
   2475         }
   2476     }
   2477     if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1) {
   2478         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2479                    "%s Unexpected manifest file version (expected 1.0.0 or "
   2480                    "1.0.1), may cause errors",
   2481                    filename);
   2482     }
   2483     cJSON_Free(file_vers);
   2484     // If "layers" is present, read in the array of layer objects
   2485     layers_node = cJSON_GetObjectItem(json, "layers");
   2486     if (layers_node != NULL) {
   2487         int numItems = cJSON_GetArraySize(layers_node);
   2488         if (file_major_vers == 1 && file_minor_vers == 0 &&
   2489             file_patch_vers == 0) {
   2490             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2491                        "\"layers\" tag not officially added until file version "
   2492                        "1.0.1, but %s is reporting version %s",
   2493                        filename, file_vers);
   2494         }
   2495         for (int curLayer = 0; curLayer < numItems; curLayer++) {
   2496             layer_node = cJSON_GetArrayItem(layers_node, curLayer);
   2497             if (layer_node == NULL) {
   2498                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2499                            "Can't find \"layers\" array element %d object in "
   2500                            "manifest JSON file %s, skipping this file",
   2501                            curLayer, filename);
   2502                 return;
   2503             }
   2504             loader_read_json_layer(inst, layer_instance_list, layer_node, item,
   2505                                    disable_environment, is_implicit, filename);
   2506         }
   2507     } else {
   2508         // Otherwise, try to read in individual layers
   2509         layer_node = cJSON_GetObjectItem(json, "layer");
   2510         if (layer_node == NULL) {
   2511             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2512                        "Can't find \"layer\" object in manifest JSON file %s, "
   2513                        "skipping this file",
   2514                        filename);
   2515             return;
   2516         }
   2517         // Loop through all "layer" objects in the file to get a count of them
   2518         // first.
   2519         uint16_t layer_count = 0;
   2520         cJSON *tempNode = layer_node;
   2521         do {
   2522             tempNode = tempNode->next;
   2523             layer_count++;
   2524         } while (tempNode != NULL);
   2525         /*
   2526          * Throw a warning if we encounter multiple "layer" objects in file
   2527          * versions newer than 1.0.0.  Having multiple objects with the same
   2528          * name at the same level is actually a JSON standard violation.
   2529          */
   2530         if (layer_count > 1 &&
   2531             (file_major_vers > 1 ||
   2532              !(file_minor_vers == 0 && file_patch_vers == 0))) {
   2533             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2534                        "Multiple \"layer\" nodes are deprecated starting in "
   2535                        "file version \"1.0.1\".  Please use \"layers\" : [] "
   2536                        "array instead in %s.",
   2537                        filename);
   2538         } else {
   2539             do {
   2540                 loader_read_json_layer(inst, layer_instance_list, layer_node,
   2541                                        item, disable_environment, is_implicit,
   2542                                        filename);
   2543                 layer_node = layer_node->next;
   2544             } while (layer_node != NULL);
   2545         }
   2546     }
   2547     return;
   2548 }
   2549 
   2550 /**
   2551  * Find the Vulkan library manifest files.
   2552  *
   2553  * This function scans the "location" or "env_override" directories/files
   2554  * for a list of JSON manifest files.  If env_override is non-NULL
   2555  * and has a valid value. Then the location is ignored.  Otherwise
   2556  * location is used to look for manifest files. The location
   2557  * is interpreted as  Registry path on Windows and a directory path(s)
   2558  * on Linux. "home_location" is an additional directory in the users home
   2559  * directory to look at. It is expanded into the dir path
   2560  * $XDG_DATA_HOME/home_location or $HOME/.local/share/home_location depending
   2561  * on environment variables. This "home_location" is only used on Linux.
   2562  *
   2563  * \returns
   2564  * VKResult
   2565  * A string list of manifest files to be opened in out_files param.
   2566  * List has a pointer to string for each manifest filename.
   2567  * When done using the list in out_files, pointers should be freed.
   2568  * Location or override  string lists can be either files or directories as
   2569  *follows:
   2570  *            | location | override
   2571  * --------------------------------
   2572  * Win ICD    | files    | files
   2573  * Win Layer  | files    | dirs
   2574  * Linux ICD  | dirs     | files
   2575  * Linux Layer| dirs     | dirs
   2576  */
   2577 static VkResult loader_get_manifest_files(
   2578     const struct loader_instance *inst, const char *env_override,
   2579     char *source_override, bool is_layer, const char *location,
   2580     const char *home_location, struct loader_manifest_files *out_files) {
   2581     char * override = NULL;
   2582     char *loc, *orig_loc = NULL;
   2583     char *reg = NULL;
   2584     char *file, *next_file, *name;
   2585     size_t alloced_count = 64;
   2586     char full_path[2048];
   2587     DIR *sysdir = NULL;
   2588     bool list_is_dirs = false;
   2589     struct dirent *dent;
   2590     VkResult res = VK_SUCCESS;
   2591 
   2592     out_files->count = 0;
   2593     out_files->filename_list = NULL;
   2594 
   2595     if (source_override != NULL) {
   2596         override = source_override;
   2597     } else if (env_override != NULL &&
   2598                (override = loader_getenv(env_override, inst))) {
   2599 #if !defined(_WIN32)
   2600         if (geteuid() != getuid() || getegid() != getgid()) {
   2601             /* Don't allow setuid apps to use the env var: */
   2602             loader_free_getenv(override, inst);
   2603             override = NULL;
   2604         }
   2605 #endif
   2606     }
   2607 
   2608 #if !defined(_WIN32)
   2609     if (location == NULL && home_location == NULL) {
   2610 #else
   2611     home_location = NULL;
   2612     if (location == NULL) {
   2613 #endif
   2614         loader_log(
   2615             inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2616             "Can't get manifest files with NULL location, env_override=%s",
   2617             env_override);
   2618         res = VK_ERROR_INITIALIZATION_FAILED;
   2619         goto out;
   2620     }
   2621 
   2622 #if defined(_WIN32)
   2623     list_is_dirs = (is_layer && override != NULL) ? true : false;
   2624 #else
   2625     list_is_dirs = (override == NULL || is_layer) ? true : false;
   2626 #endif
   2627     // Make a copy of the input we are using so it is not modified
   2628     // Also handle getting the location(s) from registry on Windows
   2629     if (override == NULL) {
   2630         loc = loader_stack_alloc(strlen(location) + 1);
   2631         if (loc == NULL) {
   2632             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2633                        "Out of memory can't get manifest files");
   2634             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2635             goto out;
   2636         }
   2637         strcpy(loc, location);
   2638 #if defined(_WIN32)
   2639         reg = loader_get_registry_files(inst, loc);
   2640         if (reg == NULL) {
   2641             if (!is_layer) {
   2642                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2643                            "Registry lookup failed can't get ICD manifest "
   2644                            "files, do you have a Vulkan driver installed");
   2645                 // This typically only fails when out of memory, which is
   2646                 // critical
   2647                 // if this is for the loader.
   2648                 res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2649             } else {
   2650                 // warning only for layers
   2651                 loader_log(
   2652                     inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2653                     "Registry lookup failed can't get layer manifest files");
   2654                 // Return success for now since it's not critical for layers
   2655                 res = VK_SUCCESS;
   2656             }
   2657             goto out;
   2658         }
   2659         orig_loc = loc;
   2660         loc = reg;
   2661 #endif
   2662     } else {
   2663         loc = loader_stack_alloc(strlen(override) + 1);
   2664         if (loc == NULL) {
   2665             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2666                        "Out of memory can't get manifest files");
   2667             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2668             goto out;
   2669         }
   2670         strcpy(loc, override);
   2671         if (source_override == NULL) {
   2672             loader_free_getenv(override, inst);
   2673         }
   2674     }
   2675 
   2676     // Print out the paths being searched if debugging is enabled
   2677     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   2678                "Searching the following paths for manifest files: %s\n", loc);
   2679 
   2680     file = loc;
   2681     while (*file) {
   2682         next_file = loader_get_next_path(file);
   2683         if (list_is_dirs) {
   2684             sysdir = opendir(file);
   2685             name = NULL;
   2686             if (sysdir) {
   2687                 dent = readdir(sysdir);
   2688                 if (dent == NULL)
   2689                     break;
   2690                 name = &(dent->d_name[0]);
   2691                 loader_get_fullpath(name, file, sizeof(full_path), full_path);
   2692                 name = full_path;
   2693             }
   2694         } else {
   2695 #if defined(_WIN32)
   2696             name = file;
   2697 #else
   2698             // only Linux has relative paths
   2699             char *dir;
   2700             // make a copy of location so it isn't modified
   2701             dir = loader_stack_alloc(strlen(loc) + 1);
   2702             if (dir == NULL) {
   2703                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2704                            "Out of memory can't get manifest files");
   2705                 goto out;
   2706             }
   2707             strcpy(dir, loc);
   2708 
   2709             loader_get_fullpath(file, dir, sizeof(full_path), full_path);
   2710 
   2711             name = full_path;
   2712 #endif
   2713         }
   2714         while (name) {
   2715             /* Look for files ending with ".json" suffix */
   2716             uint32_t nlen = (uint32_t)strlen(name);
   2717             const char *suf = name + nlen - 5;
   2718             if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
   2719                 if (out_files->count == 0) {
   2720                     out_files->filename_list = loader_instance_heap_alloc(
   2721                         inst, alloced_count * sizeof(char *),
   2722                         VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
   2723                 } else if (out_files->count == alloced_count) {
   2724                     out_files->filename_list = loader_instance_heap_realloc(
   2725                         inst, out_files->filename_list,
   2726                         alloced_count * sizeof(char *),
   2727                         alloced_count * sizeof(char *) * 2,
   2728                         VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
   2729                     alloced_count *= 2;
   2730                 }
   2731                 if (out_files->filename_list == NULL) {
   2732                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2733                                "Out of memory can't alloc manifest file list");
   2734                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2735                     goto out;
   2736                 }
   2737                 out_files->filename_list[out_files->count] =
   2738                     loader_instance_heap_alloc(
   2739                         inst, strlen(name) + 1,
   2740                         VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
   2741                 if (out_files->filename_list[out_files->count] == NULL) {
   2742                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2743                                "Out of memory can't get manifest files");
   2744                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2745                     goto out;
   2746                 }
   2747                 strcpy(out_files->filename_list[out_files->count], name);
   2748                 out_files->count++;
   2749             } else if (!list_is_dirs) {
   2750                 loader_log(
   2751                     inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2752                     "Skipping manifest file %s, file name must end in .json",
   2753                     name);
   2754             }
   2755             if (list_is_dirs) {
   2756                 dent = readdir(sysdir);
   2757                 if (dent == NULL) {
   2758                     break;
   2759                 }
   2760                 name = &(dent->d_name[0]);
   2761                 loader_get_fullpath(name, file, sizeof(full_path), full_path);
   2762                 name = full_path;
   2763             } else {
   2764                 break;
   2765             }
   2766         }
   2767         if (sysdir) {
   2768             closedir(sysdir);
   2769             sysdir = NULL;
   2770         }
   2771         file = next_file;
   2772 #if !defined(_WIN32)
   2773         if (home_location != NULL &&
   2774             (next_file == NULL || *next_file == '\0') && override == NULL) {
   2775             char *xdgdatahome = secure_getenv("XDG_DATA_HOME");
   2776             size_t len;
   2777             if (xdgdatahome != NULL) {
   2778 
   2779                 char *home_loc = loader_stack_alloc(strlen(xdgdatahome) + 2 +
   2780                                                     strlen(home_location));
   2781                 if (home_loc == NULL) {
   2782                     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2783                                "Out of memory can't get manifest files");
   2784                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2785                     goto out;
   2786                 }
   2787                 strcpy(home_loc, xdgdatahome);
   2788                 // Add directory separator if needed
   2789                 if (home_location[0] != DIRECTORY_SYMBOL) {
   2790                     len = strlen(home_loc);
   2791                     home_loc[len] = DIRECTORY_SYMBOL;
   2792                     home_loc[len + 1] = '\0';
   2793                 }
   2794                 strcat(home_loc, home_location);
   2795                 file = home_loc;
   2796                 next_file = loader_get_next_path(file);
   2797                 home_location = NULL;
   2798 
   2799                 loader_log(
   2800                     inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   2801                     "Searching the following path for manifest files: %s\n",
   2802                     home_loc);
   2803                 list_is_dirs = true;
   2804 
   2805             } else {
   2806 
   2807                 char *home = secure_getenv("HOME");
   2808                 if (home != NULL) {
   2809                     char *home_loc = loader_stack_alloc(strlen(home) + 16 +
   2810                                                         strlen(home_location));
   2811                     if (home_loc == NULL) {
   2812                         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   2813                                 "Out of memory can't get manifest files");
   2814                         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2815                         goto out;
   2816                     }
   2817                     strcpy(home_loc, home);
   2818 
   2819                     len = strlen(home);
   2820                     if (home[len] != DIRECTORY_SYMBOL) {
   2821                         home_loc[len] = DIRECTORY_SYMBOL;
   2822                         home_loc[len + 1] = '\0';
   2823                     }
   2824                     strcat(home_loc, ".local/share");
   2825 
   2826                     if (home_location[0] != DIRECTORY_SYMBOL) {
   2827                         len = strlen(home_loc);
   2828                         home_loc[len] = DIRECTORY_SYMBOL;
   2829                         home_loc[len + 1] = '\0';
   2830                     }
   2831                     strcat(home_loc, home_location);
   2832                     file = home_loc;
   2833                     next_file = loader_get_next_path(file);
   2834                     home_location = NULL;
   2835 
   2836                     loader_log(
   2837                         inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   2838                         "Searching the following path for manifest files: %s\n",
   2839                         home_loc);
   2840                     list_is_dirs = true;
   2841                 } else {
   2842                     // without knowing HOME, we just.. give up
   2843                 }
   2844             }
   2845         }
   2846 #endif
   2847     }
   2848 
   2849 out:
   2850     if (VK_SUCCESS != res && NULL != out_files->filename_list) {
   2851         for (uint32_t remove = 0; remove < out_files->count; remove++) {
   2852             loader_instance_heap_free(inst, out_files->filename_list[remove]);
   2853         }
   2854         loader_instance_heap_free(inst, out_files->filename_list);
   2855         out_files->count = 0;
   2856         out_files->filename_list = NULL;
   2857     }
   2858 
   2859     if (NULL != sysdir) {
   2860         closedir(sysdir);
   2861     }
   2862 
   2863     if (NULL != reg && reg != orig_loc) {
   2864         loader_instance_heap_free(inst, reg);
   2865     }
   2866     return res;
   2867 }
   2868 
   2869 void loader_init_icd_lib_list() {}
   2870 
   2871 void loader_destroy_icd_lib_list() {}
   2872 /**
   2873  * Try to find the Vulkan ICD driver(s).
   2874  *
   2875  * This function scans the default system loader path(s) or path
   2876  * specified by the \c VK_ICD_FILENAMES environment variable in
   2877  * order to find loadable VK ICDs manifest files. From these
   2878  * manifest files it finds the ICD libraries.
   2879  *
   2880  * \returns
   2881  * Vulkan result
   2882  * (on result == VK_SUCCESS) a list of icds that were discovered
   2883  */
   2884 VkResult loader_icd_scan(const struct loader_instance *inst,
   2885                          struct loader_icd_libs *icds) {
   2886     char *file_str;
   2887     uint16_t file_major_vers = 0;
   2888     uint16_t file_minor_vers = 0;
   2889     uint16_t file_patch_vers = 0;
   2890     char *vers_tok;
   2891     struct loader_manifest_files manifest_files;
   2892     VkResult res = VK_SUCCESS;
   2893     bool lockedMutex = false;
   2894     cJSON *json = NULL;
   2895     uint32_t num_good_icds = 0;
   2896 
   2897     memset(&manifest_files, 0, sizeof(struct loader_manifest_files));
   2898 
   2899     res = loader_scanned_icd_init(inst, icds);
   2900     if (VK_SUCCESS != res) {
   2901         goto out;
   2902     }
   2903 
   2904     // Get a list of manifest files for ICDs
   2905     res = loader_get_manifest_files(inst, "VK_ICD_FILENAMES", NULL, false,
   2906                                     DEFAULT_VK_DRIVERS_INFO,
   2907                                     HOME_VK_DRIVERS_INFO, &manifest_files);
   2908     if (VK_SUCCESS != res || manifest_files.count == 0) {
   2909         goto out;
   2910     }
   2911     loader_platform_thread_lock_mutex(&loader_json_lock);
   2912     lockedMutex = true;
   2913     for (uint32_t i = 0; i < manifest_files.count; i++) {
   2914         file_str = manifest_files.filename_list[i];
   2915         if (file_str == NULL) {
   2916             continue;
   2917         }
   2918 
   2919         res = loader_get_json(inst, file_str, &json);
   2920         if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   2921             break;
   2922         } else if (VK_SUCCESS != res || NULL == json) {
   2923             continue;
   2924         }
   2925 
   2926         cJSON *item, *itemICD;
   2927         item = cJSON_GetObjectItem(json, "file_format_version");
   2928         if (item == NULL) {
   2929             if (num_good_icds == 0) {
   2930                 res = VK_ERROR_INITIALIZATION_FAILED;
   2931             }
   2932             cJSON_Delete(json);
   2933             json = NULL;
   2934             continue;
   2935         }
   2936         char *file_vers = cJSON_Print(item);
   2937         if (NULL == file_vers) {
   2938             // Only reason the print can fail is if there was an allocation
   2939             // issue
   2940             if (num_good_icds == 0) {
   2941                 res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2942             }
   2943             cJSON_Delete(json);
   2944             json = NULL;
   2945             continue;
   2946         }
   2947         loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   2948                    "Found manifest file %s, version %s", file_str, file_vers);
   2949         // Get the major/minor/and patch as integers for easier comparison
   2950         vers_tok = strtok(file_vers, ".\"\n\r");
   2951         if (NULL != vers_tok) {
   2952             file_major_vers = (uint16_t)atoi(vers_tok);
   2953             vers_tok = strtok(NULL, ".\"\n\r");
   2954             if (NULL != vers_tok) {
   2955                 file_minor_vers = (uint16_t)atoi(vers_tok);
   2956                 vers_tok = strtok(NULL, ".\"\n\r");
   2957                 if (NULL != vers_tok) {
   2958                     file_patch_vers = (uint16_t)atoi(vers_tok);
   2959                 }
   2960             }
   2961         }
   2962         if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1)
   2963             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2964                        "Unexpected manifest file version (expected 1.0.0 or "
   2965                        "1.0.1), may "
   2966                        "cause errors");
   2967         cJSON_Free(file_vers);
   2968         itemICD = cJSON_GetObjectItem(json, "ICD");
   2969         if (itemICD != NULL) {
   2970             item = cJSON_GetObjectItem(itemICD, "library_path");
   2971             if (item != NULL) {
   2972                 char *temp = cJSON_Print(item);
   2973                 if (!temp || strlen(temp) == 0) {
   2974                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2975                                "Can't find \"library_path\" in ICD JSON file "
   2976                                "%s, skipping",
   2977                                file_str);
   2978                     if (num_good_icds == 0) {
   2979                         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2980                     }
   2981                     cJSON_Free(temp);
   2982                     cJSON_Delete(json);
   2983                     json = NULL;
   2984                     continue;
   2985                 }
   2986                 // strip out extra quotes
   2987                 temp[strlen(temp) - 1] = '\0';
   2988                 char *library_path = loader_stack_alloc(strlen(temp) + 1);
   2989                 if (NULL == library_path) {
   2990                     loader_log(
   2991                         inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   2992                         "Can't allocate space for \"library_path\" in ICD "
   2993                         "JSON file %s, skipping",
   2994                         file_str);
   2995                     res = VK_ERROR_OUT_OF_HOST_MEMORY;
   2996                     cJSON_Free(temp);
   2997                     cJSON_Delete(json);
   2998                     json = NULL;
   2999                     goto out;
   3000                 }
   3001                 strcpy(library_path, &temp[1]);
   3002                 cJSON_Free(temp);
   3003                 if (strlen(library_path) == 0) {
   3004                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3005                                "Can't find \"library_path\" in ICD JSON file "
   3006                                "%s, skipping",
   3007                                file_str);
   3008                     cJSON_Delete(json);
   3009                     json = NULL;
   3010                     continue;
   3011                 }
   3012                 char fullpath[MAX_STRING_SIZE];
   3013                 // Print out the paths being searched if debugging is enabled
   3014                 loader_log(
   3015                     inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   3016                     "Searching for ICD drivers named %s default dir %s\n",
   3017                     library_path, DEFAULT_VK_DRIVERS_PATH);
   3018                 if (loader_platform_is_path(library_path)) {
   3019                     // a relative or absolute path
   3020                     char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
   3021                     char *rel_base;
   3022                     strcpy(name_copy, file_str);
   3023                     rel_base = loader_platform_dirname(name_copy);
   3024                     loader_expand_path(library_path, rel_base, sizeof(fullpath),
   3025                                        fullpath);
   3026                 } else {
   3027                     // a filename which is assumed in a system directory
   3028                     loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH,
   3029                                         sizeof(fullpath), fullpath);
   3030                 }
   3031 
   3032                 uint32_t vers = 0;
   3033                 item = cJSON_GetObjectItem(itemICD, "api_version");
   3034                 if (item != NULL) {
   3035                     temp = cJSON_Print(item);
   3036                     if (NULL == temp) {
   3037                         // Only reason the print can fail is if there was an
   3038                         // allocation issue
   3039                         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   3040                         goto out;
   3041                     }
   3042                     vers = loader_make_version(temp);
   3043                     cJSON_Free(temp);
   3044                 }
   3045                 res = loader_scanned_icd_add(inst, icds, fullpath, vers);
   3046                 if (VK_SUCCESS != res) {
   3047                     goto out;
   3048                 }
   3049                 num_good_icds++;
   3050             } else {
   3051                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3052                            "Can't find \"library_path\" object in ICD JSON "
   3053                            "file %s, skipping",
   3054                            file_str);
   3055             }
   3056         } else {
   3057             loader_log(
   3058                 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3059                 "Can't find \"ICD\" object in ICD JSON file %s, skipping",
   3060                 file_str);
   3061         }
   3062 
   3063         cJSON_Delete(json);
   3064         json = NULL;
   3065     }
   3066 
   3067 out:
   3068     if (NULL != json) {
   3069         cJSON_Delete(json);
   3070     }
   3071     if (NULL != manifest_files.filename_list) {
   3072         for (uint32_t i = 0; i < manifest_files.count; i++) {
   3073             if (NULL != manifest_files.filename_list[i]) {
   3074                 loader_instance_heap_free(inst,
   3075                                           manifest_files.filename_list[i]);
   3076             }
   3077         }
   3078         loader_instance_heap_free(inst, manifest_files.filename_list);
   3079     }
   3080     if (lockedMutex) {
   3081         loader_platform_thread_unlock_mutex(&loader_json_lock);
   3082     }
   3083     return res;
   3084 }
   3085 
   3086 void loader_layer_scan(const struct loader_instance *inst,
   3087                        struct loader_layer_list *instance_layers) {
   3088     char *file_str;
   3089     struct loader_manifest_files
   3090         manifest_files[2]; // [0] = explicit, [1] = implicit
   3091     cJSON *json;
   3092     uint32_t implicit;
   3093     bool lockedMutex = false;
   3094 
   3095     memset(manifest_files, 0, sizeof(struct loader_manifest_files) * 2);
   3096 
   3097     // Get a list of manifest files for explicit layers
   3098     if (VK_SUCCESS !=
   3099         loader_get_manifest_files(inst, LAYERS_PATH_ENV, LAYERS_SOURCE_PATH,
   3100                                   true, DEFAULT_VK_ELAYERS_INFO,
   3101                                   HOME_VK_ELAYERS_INFO, &manifest_files[0])) {
   3102         goto out;
   3103     }
   3104 
   3105     // Get a list of manifest files for any implicit layers
   3106     // Pass NULL for environment variable override - implicit layers are not
   3107     // overridden by LAYERS_PATH_ENV
   3108     if (VK_SUCCESS != loader_get_manifest_files(
   3109                           inst, NULL, NULL, true, DEFAULT_VK_ILAYERS_INFO,
   3110                           HOME_VK_ILAYERS_INFO, &manifest_files[1])) {
   3111         goto out;
   3112     }
   3113 
   3114     // Make sure we have at least one layer, if not, go ahead and return
   3115     if (manifest_files[0].count == 0 && manifest_files[1].count == 0) {
   3116         goto out;
   3117     }
   3118 
   3119     // cleanup any previously scanned libraries
   3120     loader_delete_layer_properties(inst, instance_layers);
   3121 
   3122     loader_platform_thread_lock_mutex(&loader_json_lock);
   3123     lockedMutex = true;
   3124     for (implicit = 0; implicit < 2; implicit++) {
   3125         for (uint32_t i = 0; i < manifest_files[implicit].count; i++) {
   3126             file_str = manifest_files[implicit].filename_list[i];
   3127             if (file_str == NULL)
   3128                 continue;
   3129 
   3130             // parse file into JSON struct
   3131             VkResult res = loader_get_json(inst, file_str, &json);
   3132             if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   3133                 break;
   3134             } else if (VK_SUCCESS != res || NULL == json) {
   3135                 continue;
   3136             }
   3137 
   3138             loader_add_layer_properties(inst, instance_layers, json,
   3139                                         (implicit == 1), file_str);
   3140             cJSON_Delete(json);
   3141         }
   3142     }
   3143 
   3144     // add a meta layer for validation if the validation layers are all present
   3145     loader_add_layer_property_meta(inst, sizeof(std_validation_names) /
   3146                                              sizeof(std_validation_names[0]),
   3147                                    std_validation_names, instance_layers);
   3148 
   3149 out:
   3150 
   3151     for (uint32_t manFile = 0; manFile < 2; manFile++) {
   3152         if (NULL != manifest_files[manFile].filename_list) {
   3153             for (uint32_t i = 0; i < manifest_files[manFile].count; i++) {
   3154                 if (NULL != manifest_files[manFile].filename_list[i]) {
   3155                     loader_instance_heap_free(
   3156                         inst, manifest_files[manFile].filename_list[i]);
   3157                 }
   3158             }
   3159             loader_instance_heap_free(inst,
   3160                                       manifest_files[manFile].filename_list);
   3161         }
   3162     }
   3163     if (lockedMutex) {
   3164         loader_platform_thread_unlock_mutex(&loader_json_lock);
   3165     }
   3166 }
   3167 
   3168 void loader_implicit_layer_scan(const struct loader_instance *inst,
   3169                                 struct loader_layer_list *instance_layers) {
   3170     char *file_str;
   3171     struct loader_manifest_files manifest_files;
   3172     cJSON *json;
   3173     uint32_t i;
   3174 
   3175     // Pass NULL for environment variable override - implicit layers are not
   3176     // overridden by LAYERS_PATH_ENV
   3177     VkResult res = loader_get_manifest_files(
   3178         inst, NULL, NULL, true, DEFAULT_VK_ILAYERS_INFO, HOME_VK_ILAYERS_INFO,
   3179         &manifest_files);
   3180     if (VK_SUCCESS != res || manifest_files.count == 0) {
   3181         return;
   3182     }
   3183 
   3184     /* cleanup any previously scanned libraries */
   3185     loader_delete_layer_properties(inst, instance_layers);
   3186 
   3187     loader_platform_thread_lock_mutex(&loader_json_lock);
   3188 
   3189     for (i = 0; i < manifest_files.count; i++) {
   3190         file_str = manifest_files.filename_list[i];
   3191         if (file_str == NULL) {
   3192             continue;
   3193         }
   3194 
   3195         // parse file into JSON struct
   3196         res = loader_get_json(inst, file_str, &json);
   3197         if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   3198             break;
   3199         } else if (VK_SUCCESS != res || NULL == json) {
   3200             continue;
   3201         }
   3202 
   3203         loader_add_layer_properties(inst, instance_layers, json, true,
   3204                                     file_str);
   3205 
   3206         loader_instance_heap_free(inst, file_str);
   3207         cJSON_Delete(json);
   3208     }
   3209     loader_instance_heap_free(inst, manifest_files.filename_list);
   3210 
   3211     // add a meta layer for validation if the validation layers are all present
   3212     loader_add_layer_property_meta(inst, sizeof(std_validation_names) /
   3213                                              sizeof(std_validation_names[0]),
   3214                                    std_validation_names, instance_layers);
   3215 
   3216     loader_platform_thread_unlock_mutex(&loader_json_lock);
   3217 }
   3218 
   3219 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
   3220 loader_gpa_instance_internal(VkInstance inst, const char *pName) {
   3221     if (!strcmp(pName, "vkGetInstanceProcAddr"))
   3222         return (void *)loader_gpa_instance_internal;
   3223     if (!strcmp(pName, "vkCreateInstance"))
   3224         return (void *)terminator_CreateInstance;
   3225     if (!strcmp(pName, "vkCreateDevice"))
   3226         return (void *)terminator_CreateDevice;
   3227 
   3228     // inst is not wrapped
   3229     if (inst == VK_NULL_HANDLE) {
   3230         return NULL;
   3231     }
   3232     VkLayerInstanceDispatchTable *disp_table =
   3233         *(VkLayerInstanceDispatchTable **)inst;
   3234     void *addr;
   3235 
   3236     if (disp_table == NULL)
   3237         return NULL;
   3238 
   3239     bool found_name;
   3240     addr =
   3241         loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
   3242     if (found_name) {
   3243         return addr;
   3244     }
   3245 
   3246     // Don't call down the chain, this would be an infinite loop
   3247     loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   3248                "loader_gpa_instance_internal() unrecognized name %s", pName);
   3249     return NULL;
   3250 }
   3251 
   3252 void loader_override_terminating_device_proc(
   3253     VkDevice device, struct loader_dev_dispatch_table *disp_table) {
   3254     struct loader_device *dev;
   3255     struct loader_icd *icd = loader_get_icd_and_device(device, &dev, NULL);
   3256 
   3257     // Certain device entry-points still need to go through a terminator before
   3258     // hitting the ICD.  This could be for several reasons, but the main one
   3259     // is currently unwrapping an object before passing the appropriate info
   3260     // along to the ICD.
   3261     if ((PFN_vkVoidFunction)disp_table->core_dispatch.CreateSwapchainKHR ==
   3262         (PFN_vkVoidFunction)icd->GetDeviceProcAddr(device,
   3263                                                    "vkCreateSwapchainKHR")) {
   3264         disp_table->core_dispatch.CreateSwapchainKHR =
   3265             terminator_vkCreateSwapchainKHR;
   3266     }
   3267 }
   3268 
   3269 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
   3270 loader_gpa_device_internal(VkDevice device, const char *pName) {
   3271     struct loader_device *dev;
   3272     struct loader_icd *icd = loader_get_icd_and_device(device, &dev, NULL);
   3273 
   3274     // Certain device entry-points still need to go through a terminator before
   3275     // hitting the ICD.  This could be for several reasons, but the main one
   3276     // is currently unwrapping an object before passing the appropriate info
   3277     // along to the ICD.
   3278     if (!strcmp(pName, "vkCreateSwapchainKHR")) {
   3279         return (PFN_vkVoidFunction)terminator_vkCreateSwapchainKHR;
   3280     }
   3281 
   3282     return icd->GetDeviceProcAddr(device, pName);
   3283 }
   3284 
   3285 /**
   3286  * Initialize device_ext dispatch table entry as follows:
   3287  * If dev == NULL find all logical devices created within this instance and
   3288  *  init the entry (given by idx) in the ext dispatch table.
   3289  * If dev != NULL only initialize the entry in the given dev's dispatch table.
   3290  * The initialization value is gotten by calling down the device chain with
   3291  * GDPA.
   3292  * If GDPA returns NULL then don't initialize the dispatch table entry.
   3293  */
   3294 static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
   3295                                                struct loader_device *dev,
   3296                                                uint32_t idx,
   3297                                                const char *funcName)
   3298 
   3299 {
   3300     void *gdpa_value;
   3301     if (dev != NULL) {
   3302         gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
   3303             dev->device, funcName);
   3304         if (gdpa_value != NULL)
   3305             dev->loader_dispatch.ext_dispatch.dev_ext[idx] =
   3306                 (PFN_vkDevExt)gdpa_value;
   3307     } else {
   3308         for (uint32_t i = 0; i < inst->total_icd_count; i++) {
   3309             struct loader_icd *icd = &inst->icds[i];
   3310             struct loader_device *ldev = icd->logical_device_list;
   3311             while (ldev) {
   3312                 gdpa_value =
   3313                     ldev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
   3314                         ldev->device, funcName);
   3315                 if (gdpa_value != NULL)
   3316                     ldev->loader_dispatch.ext_dispatch.dev_ext[idx] =
   3317                         (PFN_vkDevExt)gdpa_value;
   3318                 ldev = ldev->next;
   3319             }
   3320         }
   3321     }
   3322 }
   3323 
   3324 /**
   3325  * Find all dev extension in the hash table  and initialize the dispatch table
   3326  * for dev  for each of those extension entrypoints found in hash table.
   3327 
   3328  */
   3329 void loader_init_dispatch_dev_ext(struct loader_instance *inst,
   3330                                   struct loader_device *dev) {
   3331     for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
   3332         if (inst->disp_hash[i].func_name != NULL)
   3333             loader_init_dispatch_dev_ext_entry(inst, dev, i,
   3334                                                inst->disp_hash[i].func_name);
   3335     }
   3336 }
   3337 
   3338 static bool loader_check_icds_for_address(struct loader_instance *inst,
   3339                                           const char *funcName) {
   3340     struct loader_icd *icd;
   3341     icd = inst->icds;
   3342     while (icd) {
   3343         if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
   3344             // this icd supports funcName
   3345             return true;
   3346         icd = icd->next;
   3347     }
   3348 
   3349     return false;
   3350 }
   3351 
   3352 static bool loader_check_layer_list_for_address(
   3353     const struct loader_layer_list *const layers, const char *funcName) {
   3354     // Iterate over the layers.
   3355     for (uint32_t layer = 0; layer < layers->count; ++layer) {
   3356         // Iterate over the extensions.
   3357         const struct loader_device_extension_list *const extensions =
   3358             &(layers->list[layer].device_extension_list);
   3359         for (uint32_t extension = 0; extension < extensions->count;
   3360              ++extension) {
   3361             // Iterate over the entry points.
   3362             const struct loader_dev_ext_props *const property =
   3363                 &(extensions->list[extension]);
   3364             for (uint32_t entry = 0; entry < property->entrypoint_count;
   3365                  ++entry) {
   3366                 if (strcmp(property->entrypoints[entry], funcName) == 0) {
   3367                     return true;
   3368                 }
   3369             }
   3370         }
   3371     }
   3372 
   3373     return false;
   3374 }
   3375 
   3376 static void loader_free_dev_ext_table(struct loader_instance *inst) {
   3377     for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
   3378         loader_instance_heap_free(inst, inst->disp_hash[i].func_name);
   3379         loader_instance_heap_free(inst, inst->disp_hash[i].list.index);
   3380     }
   3381     memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
   3382 }
   3383 
   3384 static bool loader_add_dev_ext_table(struct loader_instance *inst,
   3385                                      uint32_t *ptr_idx, const char *funcName) {
   3386     uint32_t i;
   3387     uint32_t idx = *ptr_idx;
   3388     struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
   3389 
   3390     if (!inst->disp_hash[idx].func_name) {
   3391         // no entry here at this idx, so use it
   3392         assert(list->capacity == 0);
   3393         inst->disp_hash[idx].func_name = (char *)loader_instance_heap_alloc(
   3394             inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   3395         if (inst->disp_hash[idx].func_name == NULL) {
   3396             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3397                        "loader_add_dev_ext_table() can't allocate memory for "
   3398                        "func_name");
   3399             return false;
   3400         }
   3401         strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
   3402         return true;
   3403     }
   3404 
   3405     // check for enough capacity
   3406     if (list->capacity == 0) {
   3407         list->index = loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)),
   3408                                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   3409         if (list->index == NULL) {
   3410             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3411                        "loader_add_dev_ext_table() can't allocate list memory");
   3412             return false;
   3413         }
   3414         list->capacity = 8 * sizeof(*(list->index));
   3415     } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
   3416         list->index = loader_instance_heap_realloc(inst, list->index, list->capacity,
   3417                                           list->capacity * 2,
   3418                                           VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   3419         if (list->index == NULL) {
   3420             loader_log(
   3421                 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3422                 "loader_add_dev_ext_table() can't reallocate list memory");
   3423             return false;
   3424         }
   3425         list->capacity *= 2;
   3426     }
   3427 
   3428     // find an unused index in the hash table and use it
   3429     i = (idx + 1) % MAX_NUM_DEV_EXTS;
   3430     do {
   3431         if (!inst->disp_hash[i].func_name) {
   3432             assert(inst->disp_hash[i].list.capacity == 0);
   3433             inst->disp_hash[i].func_name =
   3434                 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1,
   3435                                           VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   3436             if (inst->disp_hash[i].func_name == NULL) {
   3437                 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3438                            "loader_add_dev_ext_table() can't rallocate "
   3439                            "func_name memory");
   3440                 return false;
   3441             }
   3442             strncpy(inst->disp_hash[i].func_name, funcName,
   3443                     strlen(funcName) + 1);
   3444             list->index[list->count] = i;
   3445             list->count++;
   3446             *ptr_idx = i;
   3447             return true;
   3448         }
   3449         i = (i + 1) % MAX_NUM_DEV_EXTS;
   3450     } while (i != idx);
   3451 
   3452     loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3453                "loader_add_dev_ext_table() couldn't insert into hash table; is "
   3454                "it full?");
   3455     return false;
   3456 }
   3457 
   3458 static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
   3459                                          uint32_t *idx, const char *funcName) {
   3460     uint32_t alt_idx;
   3461     if (inst->disp_hash[*idx].func_name &&
   3462         !strcmp(inst->disp_hash[*idx].func_name, funcName))
   3463         return true;
   3464 
   3465     // funcName wasn't at the primary spot in the hash table
   3466     // search the list of secondary locations (shallow search, not deep search)
   3467     for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
   3468         alt_idx = inst->disp_hash[*idx].list.index[i];
   3469         if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
   3470             *idx = alt_idx;
   3471             return true;
   3472         }
   3473     }
   3474 
   3475     return false;
   3476 }
   3477 
   3478 /**
   3479  * This function returns generic trampoline code address for unknown entry
   3480  * points.
   3481  * Presumably, these unknown entry points (as given by funcName) are device
   3482  * extension entrypoints.  A hash table is used to keep a list of unknown entry
   3483  * points and their mapping to the device extension dispatch table
   3484  * (struct loader_dev_ext_dispatch_table).
   3485  * \returns
   3486  * For a given entry point string (funcName), if an existing mapping is found
   3487  * the
   3488  * trampoline address for that mapping is returned. Otherwise, this unknown
   3489  * entry point
   3490  * has not been seen yet. Next check if a layer or ICD supports it.  If so then
   3491  * a
   3492  * new entry in the hash table is initialized and that trampoline address for
   3493  * the new entry is returned. Null is returned if the hash table is full or
   3494  * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
   3495  */
   3496 void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) {
   3497     uint32_t idx;
   3498     uint32_t seed = 0;
   3499 
   3500     idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
   3501 
   3502     if (loader_name_in_dev_ext_table(inst, &idx, funcName))
   3503         // found funcName already in hash
   3504         return loader_get_dev_ext_trampoline(idx);
   3505 
   3506     // Check if funcName is supported in either ICDs or a layer library
   3507     if (!loader_check_icds_for_address(inst, funcName) &&
   3508         !loader_check_layer_list_for_address(&inst->instance_layer_list, funcName)) {
   3509         // if support found in layers continue on
   3510         return NULL;
   3511     }
   3512 
   3513     if (loader_add_dev_ext_table(inst, &idx, funcName)) {
   3514         // successfully added new table entry
   3515         // init any dev dispatch table entrys as needed
   3516         loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
   3517         return loader_get_dev_ext_trampoline(idx);
   3518     }
   3519 
   3520     return NULL;
   3521 }
   3522 
   3523 struct loader_instance *loader_get_instance(const VkInstance instance) {
   3524     /* look up the loader_instance in our list by comparing dispatch tables, as
   3525      * there is no guarantee the instance is still a loader_instance* after any
   3526      * layers which wrap the instance object.
   3527      */
   3528     const VkLayerInstanceDispatchTable *disp;
   3529     struct loader_instance *ptr_instance = NULL;
   3530     disp = loader_get_instance_dispatch(instance);
   3531     for (struct loader_instance *inst = loader.instances; inst;
   3532          inst = inst->next) {
   3533         if (inst->disp == disp) {
   3534             ptr_instance = inst;
   3535             break;
   3536         }
   3537     }
   3538     return ptr_instance;
   3539 }
   3540 
   3541 static loader_platform_dl_handle
   3542 loader_open_layer_lib(const struct loader_instance *inst, const char *chain_type,
   3543                      struct loader_layer_properties *prop) {
   3544 
   3545     if ((prop->lib_handle = loader_platform_open_library(prop->lib_name)) ==
   3546         NULL) {
   3547         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3548                    loader_platform_open_library_error(prop->lib_name));
   3549     } else {
   3550         loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   3551                    "Chain: %s: Loading layer library %s", chain_type,
   3552                    prop->lib_name);
   3553     }
   3554 
   3555     return prop->lib_handle;
   3556 }
   3557 
   3558 static void
   3559 loader_close_layer_lib(const struct loader_instance *inst,
   3560                         struct loader_layer_properties *prop) {
   3561 
   3562     if (prop->lib_handle) {
   3563         loader_platform_close_library(prop->lib_handle);
   3564         loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   3565                    "Unloading layer library %s", prop->lib_name);
   3566         prop->lib_handle = NULL;
   3567     }
   3568 }
   3569 
   3570 void loader_deactivate_layers(const struct loader_instance *instance,
   3571                               struct loader_device *device,
   3572                               struct loader_layer_list *list) {
   3573     /* delete instance list of enabled layers and close any layer libraries */
   3574     for (uint32_t i = 0; i < list->count; i++) {
   3575         struct loader_layer_properties *layer_prop = &list->list[i];
   3576 
   3577         loader_close_layer_lib(instance, layer_prop);
   3578     }
   3579     loader_destroy_layer_list(instance, device, list);
   3580 }
   3581 
   3582 /**
   3583  * Go through the search_list and find any layers which match type. If layer
   3584  * type match is found in then add it to ext_list.
   3585  */
   3586 static void
   3587 loader_add_layer_implicit(const struct loader_instance *inst,
   3588                           const enum layer_type type,
   3589                           struct loader_layer_list *list,
   3590                           const struct loader_layer_list *search_list) {
   3591     bool enable;
   3592     char *env_value;
   3593     uint32_t i;
   3594     for (i = 0; i < search_list->count; i++) {
   3595         const struct loader_layer_properties *prop = &search_list->list[i];
   3596         if (prop->type & type) {
   3597             /* Found an implicit layer, see if it should be enabled */
   3598             enable = false;
   3599 
   3600             // if no enable_environment variable is specified, this implicit
   3601             // layer
   3602             // should always be enabled. Otherwise check if the variable is set
   3603             if (prop->enable_env_var.name[0] == 0) {
   3604                 enable = true;
   3605             } else {
   3606                 env_value = loader_getenv(prop->enable_env_var.name, inst);
   3607                 if (env_value && !strcmp(prop->enable_env_var.value, env_value))
   3608                     enable = true;
   3609                 loader_free_getenv(env_value, inst);
   3610             }
   3611 
   3612             // disable_environment has priority, i.e. if both enable and disable
   3613             // environment variables are set, the layer is disabled. Implicit
   3614             // layers
   3615             // are required to have a disable_environment variables
   3616             env_value = loader_getenv(prop->disable_env_var.name, inst);
   3617             if (env_value) {
   3618                 enable = false;
   3619             }
   3620             loader_free_getenv(env_value, inst);
   3621 
   3622             if (enable) {
   3623                 loader_add_to_layer_list(inst, list, 1, prop);
   3624             }
   3625         }
   3626     }
   3627 }
   3628 
   3629 /**
   3630  * Get the layer name(s) from the env_name environment variable. If layer
   3631  * is found in search_list then add it to layer_list.  But only add it to
   3632  * layer_list if type matches.
   3633  */
   3634 static void loader_add_layer_env(struct loader_instance *inst,
   3635                                  const enum layer_type type,
   3636                                  const char *env_name,
   3637                                  struct loader_layer_list *layer_list,
   3638                                  const struct loader_layer_list *search_list) {
   3639     char *layerEnv;
   3640     char *next, *name;
   3641 
   3642     layerEnv = loader_getenv(env_name, inst);
   3643     if (layerEnv == NULL) {
   3644         return;
   3645     }
   3646     name = loader_stack_alloc(strlen(layerEnv) + 1);
   3647     if (name == NULL) {
   3648         return;
   3649     }
   3650     strcpy(name, layerEnv);
   3651 
   3652     loader_free_getenv(layerEnv, inst);
   3653 
   3654     while (name && *name) {
   3655         next = loader_get_next_path(name);
   3656         if (!strcmp(std_validation_str, name)) {
   3657             /* add meta list of layers
   3658                don't attempt to remove duplicate layers already added by app or
   3659                env var
   3660              */
   3661             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   3662                        "Expanding meta layer %s found in environment variable",
   3663                        std_validation_str);
   3664             if (type == VK_LAYER_TYPE_INSTANCE_EXPLICIT)
   3665                 inst->activated_layers_are_std_val = true;
   3666             for (uint32_t i = 0; i < sizeof(std_validation_names) /
   3667                                          sizeof(std_validation_names[0]);
   3668                  i++) {
   3669                 loader_find_layer_name_add_list(inst, std_validation_names[i],
   3670                                                 type, search_list, layer_list);
   3671             }
   3672         } else {
   3673             loader_find_layer_name_add_list(inst, name, type, search_list,
   3674                                             layer_list);
   3675         }
   3676         name = next;
   3677     }
   3678 
   3679     return;
   3680 }
   3681 
   3682 VkResult
   3683 loader_enable_instance_layers(struct loader_instance *inst,
   3684                               const VkInstanceCreateInfo *pCreateInfo,
   3685                               const struct loader_layer_list *instance_layers) {
   3686     VkResult err;
   3687 
   3688     assert(inst && "Cannot have null instance");
   3689 
   3690     if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
   3691         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3692                    "Failed to alloc Instance activated layer list");
   3693         return VK_ERROR_OUT_OF_HOST_MEMORY;
   3694     }
   3695 
   3696     /* Add any implicit layers first */
   3697     loader_add_layer_implicit(inst, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
   3698                               &inst->activated_layer_list, instance_layers);
   3699 
   3700     /* Add any layers specified via environment variable next */
   3701     loader_add_layer_env(inst, VK_LAYER_TYPE_INSTANCE_EXPLICIT,
   3702                          "VK_INSTANCE_LAYERS", &inst->activated_layer_list,
   3703                          instance_layers);
   3704 
   3705     /* Add layers specified by the application */
   3706     err = loader_add_layer_names_to_list(
   3707         inst, &inst->activated_layer_list, pCreateInfo->enabledLayerCount,
   3708         pCreateInfo->ppEnabledLayerNames, instance_layers);
   3709 
   3710     return err;
   3711 }
   3712 
   3713 /*
   3714  * Given the list of layers to activate in the loader_instance
   3715  * structure. This function will add a VkLayerInstanceCreateInfo
   3716  * structure to the VkInstanceCreateInfo.pNext pointer.
   3717  * Each activated layer will have it's own VkLayerInstanceLink
   3718  * structure that tells the layer what Get*ProcAddr to call to
   3719  * get function pointers to the next layer down.
   3720  * Once the chain info has been created this function will
   3721  * execute the CreateInstance call chain. Each layer will
   3722  * then have an opportunity in it's CreateInstance function
   3723  * to setup it's dispatch table when the lower layer returns
   3724  * successfully.
   3725  * Each layer can wrap or not-wrap the returned VkInstance object
   3726  * as it sees fit.
   3727  * The instance chain is terminated by a loader function
   3728  * that will call CreateInstance on all available ICD's and
   3729  * cache those VkInstance objects for future use.
   3730  */
   3731 VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
   3732                                       const VkAllocationCallbacks *pAllocator,
   3733                                       struct loader_instance *inst,
   3734                                       VkInstance *created_instance) {
   3735     uint32_t activated_layers = 0;
   3736     VkLayerInstanceCreateInfo chain_info;
   3737     VkLayerInstanceLink *layer_instance_link_info = NULL;
   3738     VkInstanceCreateInfo loader_create_info;
   3739     VkResult res;
   3740 
   3741     PFN_vkGetInstanceProcAddr nextGIPA = loader_gpa_instance_internal;
   3742     PFN_vkGetInstanceProcAddr fpGIPA = loader_gpa_instance_internal;
   3743 
   3744     memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
   3745 
   3746     if (inst->activated_layer_list.count > 0) {
   3747 
   3748         chain_info.u.pLayerInfo = NULL;
   3749         chain_info.pNext = pCreateInfo->pNext;
   3750         chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
   3751         chain_info.function = VK_LAYER_LINK_INFO;
   3752         loader_create_info.pNext = &chain_info;
   3753 
   3754         layer_instance_link_info = loader_stack_alloc(
   3755             sizeof(VkLayerInstanceLink) * inst->activated_layer_list.count);
   3756         if (!layer_instance_link_info) {
   3757             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3758                        "Failed to alloc Instance objects for layer");
   3759             return VK_ERROR_OUT_OF_HOST_MEMORY;
   3760         }
   3761 
   3762         /* Create instance chain of enabled layers */
   3763         for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
   3764             struct loader_layer_properties *layer_prop =
   3765                 &inst->activated_layer_list.list[i];
   3766             loader_platform_dl_handle lib_handle;
   3767 
   3768             lib_handle = loader_open_layer_lib(inst, "instance", layer_prop);
   3769             if (!lib_handle)
   3770                 continue;
   3771             if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) ==
   3772                 NULL) {
   3773                 if (layer_prop->functions.str_gipa == NULL ||
   3774                     strlen(layer_prop->functions.str_gipa) == 0) {
   3775                     fpGIPA = (PFN_vkGetInstanceProcAddr)
   3776                         loader_platform_get_proc_address(
   3777                             lib_handle, "vkGetInstanceProcAddr");
   3778                     layer_prop->functions.get_instance_proc_addr = fpGIPA;
   3779                 } else
   3780                     fpGIPA = (PFN_vkGetInstanceProcAddr)
   3781                         loader_platform_get_proc_address(
   3782                             lib_handle, layer_prop->functions.str_gipa);
   3783                 if (!fpGIPA) {
   3784                     loader_log(
   3785                         inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3786                         "Failed to find vkGetInstanceProcAddr in layer %s",
   3787                         layer_prop->lib_name);
   3788                     continue;
   3789                 }
   3790             }
   3791 
   3792             layer_instance_link_info[activated_layers].pNext =
   3793                 chain_info.u.pLayerInfo;
   3794             layer_instance_link_info[activated_layers]
   3795                 .pfnNextGetInstanceProcAddr = nextGIPA;
   3796             chain_info.u.pLayerInfo =
   3797                 &layer_instance_link_info[activated_layers];
   3798             nextGIPA = fpGIPA;
   3799 
   3800             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   3801                        "Insert instance layer %s (%s)",
   3802                        layer_prop->info.layerName, layer_prop->lib_name);
   3803 
   3804             activated_layers++;
   3805         }
   3806     }
   3807 
   3808     PFN_vkCreateInstance fpCreateInstance =
   3809         (PFN_vkCreateInstance)nextGIPA(*created_instance, "vkCreateInstance");
   3810     if (fpCreateInstance) {
   3811         VkLayerInstanceCreateInfo create_info_disp;
   3812 
   3813         create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
   3814         create_info_disp.function = VK_LOADER_DATA_CALLBACK;
   3815 
   3816         create_info_disp.u.pfnSetInstanceLoaderData = vkSetInstanceDispatch;
   3817 
   3818         create_info_disp.pNext = loader_create_info.pNext;
   3819         loader_create_info.pNext = &create_info_disp;
   3820         res =
   3821             fpCreateInstance(&loader_create_info, pAllocator, created_instance);
   3822     } else {
   3823         // Couldn't find CreateInstance function!
   3824         res = VK_ERROR_INITIALIZATION_FAILED;
   3825     }
   3826 
   3827     if (res != VK_SUCCESS) {
   3828         // TODO: Need to clean up here
   3829     } else {
   3830         loader_init_instance_core_dispatch_table(inst->disp, nextGIPA,
   3831                                                  *created_instance);
   3832         inst->instance = *created_instance;
   3833     }
   3834 
   3835     return res;
   3836 }
   3837 
   3838 void loader_activate_instance_layer_extensions(struct loader_instance *inst,
   3839                                                VkInstance created_inst) {
   3840 
   3841     loader_init_instance_extension_dispatch_table(
   3842         inst->disp, inst->disp->GetInstanceProcAddr, created_inst);
   3843 }
   3844 
   3845 VkResult
   3846 loader_create_device_chain(const struct loader_physical_device_tramp *pd,
   3847                            const VkDeviceCreateInfo *pCreateInfo,
   3848                            const VkAllocationCallbacks *pAllocator,
   3849                            const struct loader_instance *inst,
   3850                            struct loader_device *dev) {
   3851     uint32_t activated_layers = 0;
   3852     VkLayerDeviceLink *layer_device_link_info;
   3853     VkLayerDeviceCreateInfo chain_info;
   3854     VkDeviceCreateInfo loader_create_info;
   3855     VkResult res;
   3856 
   3857     PFN_vkGetDeviceProcAddr fpGDPA, nextGDPA = loader_gpa_device_internal;
   3858     PFN_vkGetInstanceProcAddr fpGIPA, nextGIPA = loader_gpa_instance_internal;
   3859 
   3860     memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
   3861 
   3862     layer_device_link_info = loader_stack_alloc(
   3863         sizeof(VkLayerDeviceLink) * dev->activated_layer_list.count);
   3864     if (!layer_device_link_info) {
   3865         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3866                    "Failed to alloc Device objects for layer");
   3867         return VK_ERROR_OUT_OF_HOST_MEMORY;
   3868     }
   3869 
   3870     if (dev->activated_layer_list.count > 0) {
   3871         chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
   3872         chain_info.function = VK_LAYER_LINK_INFO;
   3873         chain_info.u.pLayerInfo = NULL;
   3874         chain_info.pNext = pCreateInfo->pNext;
   3875         loader_create_info.pNext = &chain_info;
   3876 
   3877         /* Create instance chain of enabled layers */
   3878         for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
   3879             struct loader_layer_properties *layer_prop =
   3880                 &dev->activated_layer_list.list[i];
   3881             loader_platform_dl_handle lib_handle;
   3882 
   3883             lib_handle = loader_open_layer_lib(inst, "device", layer_prop);
   3884             if (!lib_handle)
   3885                 continue;
   3886             if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) ==
   3887                 NULL) {
   3888                 if (layer_prop->functions.str_gipa == NULL ||
   3889                     strlen(layer_prop->functions.str_gipa) == 0) {
   3890                     fpGIPA = (PFN_vkGetInstanceProcAddr)
   3891                         loader_platform_get_proc_address(
   3892                             lib_handle, "vkGetInstanceProcAddr");
   3893                     layer_prop->functions.get_instance_proc_addr = fpGIPA;
   3894                 } else
   3895                     fpGIPA = (PFN_vkGetInstanceProcAddr)
   3896                         loader_platform_get_proc_address(
   3897                             lib_handle, layer_prop->functions.str_gipa);
   3898                 if (!fpGIPA) {
   3899                     loader_log(
   3900                         inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3901                         "Failed to find vkGetInstanceProcAddr in layer %s",
   3902                         layer_prop->lib_name);
   3903                     continue;
   3904                 }
   3905             }
   3906             if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
   3907                 if (layer_prop->functions.str_gdpa == NULL ||
   3908                     strlen(layer_prop->functions.str_gdpa) == 0) {
   3909                     fpGDPA = (PFN_vkGetDeviceProcAddr)
   3910                         loader_platform_get_proc_address(lib_handle,
   3911                                                          "vkGetDeviceProcAddr");
   3912                     layer_prop->functions.get_device_proc_addr = fpGDPA;
   3913                 } else
   3914                     fpGDPA = (PFN_vkGetDeviceProcAddr)
   3915                         loader_platform_get_proc_address(
   3916                             lib_handle, layer_prop->functions.str_gdpa);
   3917                 if (!fpGDPA) {
   3918                     loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   3919                                "Failed to find vkGetDeviceProcAddr in layer %s",
   3920                                layer_prop->lib_name);
   3921                     continue;
   3922                 }
   3923             }
   3924 
   3925             layer_device_link_info[activated_layers].pNext =
   3926                 chain_info.u.pLayerInfo;
   3927             layer_device_link_info[activated_layers]
   3928                 .pfnNextGetInstanceProcAddr = nextGIPA;
   3929             layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr =
   3930                 nextGDPA;
   3931             chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers];
   3932             nextGIPA = fpGIPA;
   3933             nextGDPA = fpGDPA;
   3934 
   3935             loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
   3936                        "Insert device layer %s (%s)",
   3937                        layer_prop->info.layerName, layer_prop->lib_name);
   3938 
   3939             activated_layers++;
   3940         }
   3941     }
   3942 
   3943     VkDevice created_device = (VkDevice)dev;
   3944     PFN_vkCreateDevice fpCreateDevice =
   3945         (PFN_vkCreateDevice)nextGIPA(inst->instance, "vkCreateDevice");
   3946     if (fpCreateDevice) {
   3947         VkLayerDeviceCreateInfo create_info_disp;
   3948 
   3949         create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
   3950         create_info_disp.function = VK_LOADER_DATA_CALLBACK;
   3951 
   3952         create_info_disp.u.pfnSetDeviceLoaderData = vkSetDeviceDispatch;
   3953 
   3954         create_info_disp.pNext = loader_create_info.pNext;
   3955         loader_create_info.pNext = &create_info_disp;
   3956         res = fpCreateDevice(pd->phys_dev, &loader_create_info, pAllocator,
   3957                              &created_device);
   3958         if (res != VK_SUCCESS) {
   3959             return res;
   3960         }
   3961         dev->device = created_device;
   3962     } else {
   3963         // Couldn't find CreateDevice function!
   3964         return VK_ERROR_INITIALIZATION_FAILED;
   3965     }
   3966 
   3967     /* Initialize device dispatch table */
   3968     loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA,
   3969                                       dev->device);
   3970 
   3971     return res;
   3972 }
   3973 
   3974 VkResult loader_validate_layers(const struct loader_instance *inst,
   3975                                 const uint32_t layer_count,
   3976                                 const char *const *ppEnabledLayerNames,
   3977                                 const struct loader_layer_list *list) {
   3978     struct loader_layer_properties *prop;
   3979 
   3980     for (uint32_t i = 0; i < layer_count; i++) {
   3981         VkStringErrorFlags result =
   3982             vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]);
   3983         if (result != VK_STRING_ERROR_NONE) {
   3984             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   3985                        "Loader: Device ppEnabledLayerNames contains string "
   3986                        "that is too long or is badly formed");
   3987             return VK_ERROR_LAYER_NOT_PRESENT;
   3988         }
   3989 
   3990         prop = loader_get_layer_property(ppEnabledLayerNames[i], list);
   3991         if (!prop) {
   3992             return VK_ERROR_LAYER_NOT_PRESENT;
   3993         }
   3994     }
   3995     return VK_SUCCESS;
   3996 }
   3997 
   3998 VkResult loader_validate_instance_extensions(
   3999     const struct loader_instance *inst,
   4000     const struct loader_extension_list *icd_exts,
   4001     const struct loader_layer_list *instance_layer,
   4002     const VkInstanceCreateInfo *pCreateInfo) {
   4003 
   4004     VkExtensionProperties *extension_prop;
   4005     struct loader_layer_properties *layer_prop;
   4006 
   4007     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
   4008         VkStringErrorFlags result = vk_string_validate(
   4009             MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
   4010         if (result != VK_STRING_ERROR_NONE) {
   4011             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4012                        "Loader: Instance ppEnabledExtensionNames contains "
   4013                        "string that is too long or is badly formed");
   4014             return VK_ERROR_EXTENSION_NOT_PRESENT;
   4015         }
   4016 
   4017         extension_prop = get_extension_property(
   4018             pCreateInfo->ppEnabledExtensionNames[i], icd_exts);
   4019 
   4020         if (extension_prop) {
   4021             continue;
   4022         }
   4023 
   4024         extension_prop = NULL;
   4025 
   4026         /* Not in global list, search layer extension lists */
   4027         for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) {
   4028             layer_prop = loader_get_layer_property(
   4029                 pCreateInfo->ppEnabledLayerNames[j], instance_layer);
   4030             if (!layer_prop) {
   4031                 /* Should NOT get here, loader_validate_layers
   4032                  * should have already filtered this case out.
   4033                  */
   4034                 continue;
   4035             }
   4036 
   4037             extension_prop =
   4038                 get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
   4039                                        &layer_prop->instance_extension_list);
   4040             if (extension_prop) {
   4041                 /* Found the extension in one of the layers enabled by the app.
   4042                  */
   4043                 break;
   4044             }
   4045         }
   4046 
   4047         if (!extension_prop) {
   4048             /* Didn't find extension name in any of the global layers, error out
   4049              */
   4050             return VK_ERROR_EXTENSION_NOT_PRESENT;
   4051         }
   4052     }
   4053     return VK_SUCCESS;
   4054 }
   4055 
   4056 VkResult loader_validate_device_extensions(
   4057     struct loader_physical_device_tramp *phys_dev,
   4058     const struct loader_layer_list *activated_device_layers,
   4059     const struct loader_extension_list *icd_exts,
   4060     const VkDeviceCreateInfo *pCreateInfo) {
   4061     VkExtensionProperties *extension_prop;
   4062     struct loader_layer_properties *layer_prop;
   4063 
   4064     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
   4065 
   4066         VkStringErrorFlags result = vk_string_validate(
   4067             MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
   4068         if (result != VK_STRING_ERROR_NONE) {
   4069             loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   4070                        0, "Loader: Device ppEnabledExtensionNames contains "
   4071                           "string that is too long or is badly formed");
   4072             return VK_ERROR_EXTENSION_NOT_PRESENT;
   4073         }
   4074 
   4075         const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
   4076         extension_prop = get_extension_property(extension_name, icd_exts);
   4077 
   4078         if (extension_prop) {
   4079             continue;
   4080         }
   4081 
   4082         /* Not in global list, search activated layer extension lists */
   4083         for (uint32_t j = 0; j < activated_device_layers->count; j++) {
   4084             layer_prop = &activated_device_layers->list[j];
   4085 
   4086             extension_prop = get_dev_extension_property(
   4087                 extension_name, &layer_prop->device_extension_list);
   4088             if (extension_prop) {
   4089                 /* Found the extension in one of the layers enabled by the app.
   4090                  */
   4091                 break;
   4092             }
   4093         }
   4094 
   4095         if (!extension_prop) {
   4096             /* Didn't find extension name in any of the device layers, error out
   4097              */
   4098             return VK_ERROR_EXTENSION_NOT_PRESENT;
   4099         }
   4100     }
   4101     return VK_SUCCESS;
   4102 }
   4103 
   4104 /**
   4105  * Terminator functions for the Instance chain
   4106  * All named terminator_<Vulakn API name>
   4107  */
   4108 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(
   4109     const VkInstanceCreateInfo *pCreateInfo,
   4110     const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
   4111     struct loader_icd *icd;
   4112     VkExtensionProperties *prop;
   4113     char **filtered_extension_names = NULL;
   4114     VkInstanceCreateInfo icd_create_info;
   4115     VkResult res = VK_SUCCESS;
   4116 
   4117     struct loader_instance *ptr_instance = (struct loader_instance *)*pInstance;
   4118     memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
   4119 
   4120     icd_create_info.enabledLayerCount = 0;
   4121     icd_create_info.ppEnabledLayerNames = NULL;
   4122 
   4123     /*
   4124      * NOTE: Need to filter the extensions to only those
   4125      * supported by the ICD.
   4126      * No ICD will advertise support for layers. An ICD
   4127      * library could support a layer, but it would be
   4128      * independent of the actual ICD, just in the same library.
   4129      */
   4130     filtered_extension_names =
   4131         loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
   4132     if (!filtered_extension_names) {
   4133         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   4134         goto out;
   4135     }
   4136     icd_create_info.ppEnabledExtensionNames =
   4137         (const char *const *)filtered_extension_names;
   4138 
   4139     for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
   4140         icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
   4141         if (NULL == icd) {
   4142             res = VK_ERROR_OUT_OF_HOST_MEMORY;
   4143             goto out;
   4144         }
   4145         icd_create_info.enabledExtensionCount = 0;
   4146         struct loader_extension_list icd_exts;
   4147 
   4148         loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
   4149                    "Build ICD instance extension list");
   4150         // traverse scanned icd list adding non-duplicate extensions to the
   4151         // list
   4152         res = loader_init_generic_list(ptr_instance,
   4153                                  (struct loader_generic_list *)&icd_exts,
   4154                                  sizeof(VkExtensionProperties));
   4155         if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   4156             // If out of memory, bail immediately.
   4157             goto out;
   4158         } else if (VK_SUCCESS != res) {
   4159             // Something bad happened with this ICD, so free it and try the
   4160             // next.
   4161             ptr_instance->icds = icd->next;
   4162             icd->next = NULL;
   4163             loader_icd_destroy(ptr_instance, icd, pAllocator);
   4164             continue;
   4165         }
   4166 
   4167         res = loader_add_instance_extensions(
   4168             ptr_instance,
   4169             icd->this_icd_lib->EnumerateInstanceExtensionProperties,
   4170             icd->this_icd_lib->lib_name, &icd_exts);
   4171         if (VK_SUCCESS != res) {
   4172             loader_destroy_generic_list(ptr_instance,
   4173                 (struct loader_generic_list *)&icd_exts);
   4174             if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   4175                 // If out of memory, bail immediately.
   4176                 goto out;
   4177             } else {
   4178                 // Something bad happened with this ICD, so free it and try
   4179                 // the next.
   4180                 ptr_instance->icds = icd->next;
   4181                 icd->next = NULL;
   4182                 loader_icd_destroy(ptr_instance, icd, pAllocator);
   4183                 continue;
   4184             }
   4185         }
   4186 
   4187         for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) {
   4188             prop = get_extension_property(
   4189                 pCreateInfo->ppEnabledExtensionNames[j], &icd_exts);
   4190             if (prop) {
   4191                 filtered_extension_names[icd_create_info
   4192                                              .enabledExtensionCount] =
   4193                     (char *)pCreateInfo->ppEnabledExtensionNames[j];
   4194                 icd_create_info.enabledExtensionCount++;
   4195             }
   4196         }
   4197 
   4198         loader_destroy_generic_list(ptr_instance,
   4199                                     (struct loader_generic_list *)&icd_exts);
   4200 
   4201         res = ptr_instance->icd_libs.list[i].CreateInstance(
   4202             &icd_create_info, pAllocator, &(icd->instance));
   4203         if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
   4204             // If out of memory, bail immediately.
   4205             goto out;
   4206         } else if (VK_SUCCESS != res) {
   4207             loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   4208                        "ICD ignored: failed to CreateInstance in ICD %d", i);
   4209             ptr_instance->icds = icd->next;
   4210             icd->next = NULL;
   4211             loader_icd_destroy(ptr_instance, icd, pAllocator);
   4212             continue;
   4213         }
   4214 
   4215         if (!loader_icd_init_entrys(
   4216                 icd, icd->instance,
   4217                 ptr_instance->icd_libs.list[i].GetInstanceProcAddr)) {
   4218             loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   4219                        "ICD ignored: failed to CreateInstance and find "
   4220                        "entrypoints with ICD");
   4221             continue;
   4222         }
   4223     }
   4224 
   4225     /*
   4226      * If no ICDs were added to instance list and res is unchanged
   4227      * from it's initial value, the loader was unable to find
   4228      * a suitable ICD.
   4229      */
   4230     if (VK_SUCCESS == res && ptr_instance->icds == NULL) {
   4231         res = VK_ERROR_INCOMPATIBLE_DRIVER;
   4232     }
   4233 
   4234 out:
   4235 
   4236     if (VK_SUCCESS != res) {
   4237         while (NULL != ptr_instance->icds) {
   4238             icd = ptr_instance->icds;
   4239             ptr_instance->icds = icd->next;
   4240             if (NULL != icd->instance) {
   4241                 icd->DestroyInstance(icd->instance, pAllocator);
   4242             }
   4243             loader_icd_destroy(ptr_instance, icd, pAllocator);
   4244         }
   4245     }
   4246 
   4247     return res;
   4248 }
   4249 
   4250 VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(
   4251     VkInstance instance, const VkAllocationCallbacks *pAllocator) {
   4252     struct loader_instance *ptr_instance = loader_instance(instance);
   4253     struct loader_icd *icds = ptr_instance->icds;
   4254     struct loader_icd *next_icd;
   4255 
   4256     // Remove this instance from the list of instances:
   4257     struct loader_instance *prev = NULL;
   4258     struct loader_instance *next = loader.instances;
   4259     while (next != NULL) {
   4260         if (next == ptr_instance) {
   4261             // Remove this instance from the list:
   4262             if (prev)
   4263                 prev->next = next->next;
   4264             else
   4265                 loader.instances = next->next;
   4266             break;
   4267         }
   4268         prev = next;
   4269         next = next->next;
   4270     }
   4271 
   4272     while (icds) {
   4273         if (icds->instance) {
   4274             icds->DestroyInstance(icds->instance, pAllocator);
   4275         }
   4276         next_icd = icds->next;
   4277         icds->instance = VK_NULL_HANDLE;
   4278         loader_icd_destroy(ptr_instance, icds, pAllocator);
   4279 
   4280         icds = next_icd;
   4281     }
   4282 
   4283     loader_delete_layer_properties(ptr_instance,
   4284                                    &ptr_instance->instance_layer_list);
   4285     loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
   4286     loader_destroy_generic_list(
   4287         ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list);
   4288     if (ptr_instance->phys_devs_term)
   4289         loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term);
   4290     loader_free_dev_ext_table(ptr_instance);
   4291 }
   4292 
   4293 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(
   4294     VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
   4295     const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
   4296     VkResult res = VK_SUCCESS;
   4297     struct loader_physical_device *phys_dev;
   4298     phys_dev = (struct loader_physical_device *)physicalDevice;
   4299 
   4300     struct loader_device *dev = (struct loader_device *)*pDevice;
   4301     PFN_vkCreateDevice fpCreateDevice = phys_dev->this_icd->CreateDevice;
   4302     struct loader_extension_list icd_exts;
   4303 
   4304     icd_exts.list = NULL;
   4305 
   4306     if (fpCreateDevice == NULL) {
   4307         loader_log(phys_dev->this_icd->this_instance,
   4308                    VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4309                    "No vkCreateDevice command exposed by ICD %s",
   4310                    phys_dev->this_icd->this_icd_lib->lib_name);
   4311         res = VK_ERROR_INITIALIZATION_FAILED;
   4312         goto out;
   4313     }
   4314 
   4315     VkDeviceCreateInfo localCreateInfo;
   4316     memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
   4317 
   4318     /*
   4319      * NOTE: Need to filter the extensions to only those
   4320      * supported by the ICD.
   4321      * No ICD will advertise support for layers. An ICD
   4322      * library could support a layer, but it would be
   4323      * independent of the actual ICD, just in the same library.
   4324      */
   4325     char **filtered_extension_names = NULL;
   4326     filtered_extension_names =
   4327         loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
   4328     if (!filtered_extension_names) {
   4329         return VK_ERROR_OUT_OF_HOST_MEMORY;
   4330     }
   4331 
   4332     localCreateInfo.enabledLayerCount = 0;
   4333     localCreateInfo.ppEnabledLayerNames = NULL;
   4334 
   4335     localCreateInfo.enabledExtensionCount = 0;
   4336     localCreateInfo.ppEnabledExtensionNames =
   4337         (const char *const *)filtered_extension_names;
   4338 
   4339     /* Get the physical device (ICD) extensions  */
   4340     res = loader_init_generic_list(phys_dev->this_icd->this_instance,
   4341                                   (struct loader_generic_list *)&icd_exts,
   4342                                   sizeof(VkExtensionProperties));
   4343     if (VK_SUCCESS != res) {
   4344         goto out;
   4345     }
   4346 
   4347     res = loader_add_device_extensions(
   4348         phys_dev->this_icd->this_instance,
   4349         phys_dev->this_icd->EnumerateDeviceExtensionProperties,
   4350         phys_dev->phys_dev, phys_dev->this_icd->this_icd_lib->lib_name,
   4351         &icd_exts);
   4352     if (res != VK_SUCCESS) {
   4353         goto out;
   4354     }
   4355 
   4356     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
   4357         const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
   4358         VkExtensionProperties *prop =
   4359             get_extension_property(extension_name, &icd_exts);
   4360         if (prop) {
   4361             filtered_extension_names[localCreateInfo.enabledExtensionCount] =
   4362                 (char *)extension_name;
   4363             localCreateInfo.enabledExtensionCount++;
   4364         } else {
   4365             loader_log(phys_dev->this_icd->this_instance,
   4366                        VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
   4367                        "vkCreateDevice extension %s not available for "
   4368                        "devices associated with ICD %s",
   4369                        extension_name,
   4370                        phys_dev->this_icd->this_icd_lib->lib_name);
   4371         }
   4372     }
   4373 
   4374     res = fpCreateDevice(phys_dev->phys_dev, &localCreateInfo, pAllocator,
   4375                          &dev->device);
   4376     if (res != VK_SUCCESS) {
   4377         loader_log(phys_dev->this_icd->this_instance,
   4378                    VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
   4379                    "vkCreateDevice call failed in ICD %s",
   4380                    phys_dev->this_icd->this_icd_lib->lib_name);
   4381         goto out;
   4382     }
   4383 
   4384     *pDevice = dev->device;
   4385     loader_add_logical_device(phys_dev->this_icd->this_instance,
   4386                               phys_dev->this_icd, dev);
   4387 
   4388     /* Init dispatch pointer in new device object */
   4389     loader_init_dispatch(*pDevice, &dev->loader_dispatch);
   4390 
   4391 out:
   4392     if (NULL != icd_exts.list) {
   4393         loader_destroy_generic_list(phys_dev->this_icd->this_instance,
   4394                                     (struct loader_generic_list *)&icd_exts);
   4395     }
   4396 
   4397     return res;
   4398 }
   4399 
   4400 VKAPI_ATTR VkResult VKAPI_CALL
   4401 terminator_EnumeratePhysicalDevices(VkInstance instance,
   4402                                     uint32_t *pPhysicalDeviceCount,
   4403                                     VkPhysicalDevice *pPhysicalDevices) {
   4404     uint32_t i;
   4405     struct loader_instance *inst = (struct loader_instance *)instance;
   4406     VkResult res = VK_SUCCESS;
   4407 
   4408     struct loader_icd *icd;
   4409     struct loader_phys_dev_per_icd *phys_devs;
   4410 
   4411     inst->total_gpu_count = 0;
   4412     phys_devs = (struct loader_phys_dev_per_icd *)loader_stack_alloc(
   4413         sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count);
   4414     if (!phys_devs)
   4415         return VK_ERROR_OUT_OF_HOST_MEMORY;
   4416 
   4417     icd = inst->icds;
   4418     for (i = 0; i < inst->total_icd_count; i++) {
   4419         assert(icd);
   4420         res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count,
   4421                                             NULL);
   4422         if (res != VK_SUCCESS)
   4423             return res;
   4424         icd = icd->next;
   4425     }
   4426 
   4427     icd = inst->icds;
   4428     for (i = 0; i < inst->total_icd_count; i++) {
   4429         assert(icd);
   4430         phys_devs[i].phys_devs = (VkPhysicalDevice *)loader_stack_alloc(
   4431             phys_devs[i].count * sizeof(VkPhysicalDevice));
   4432         if (!phys_devs[i].phys_devs) {
   4433             return VK_ERROR_OUT_OF_HOST_MEMORY;
   4434         }
   4435         res = icd->EnumeratePhysicalDevices(
   4436             icd->instance, &(phys_devs[i].count), phys_devs[i].phys_devs);
   4437         if ((res == VK_SUCCESS)) {
   4438             inst->total_gpu_count += phys_devs[i].count;
   4439         } else {
   4440             return res;
   4441         }
   4442         phys_devs[i].this_icd = icd;
   4443         icd = icd->next;
   4444     }
   4445 
   4446     uint32_t copy_count = inst->total_gpu_count;
   4447 
   4448     if (NULL != pPhysicalDevices) {
   4449         // Initialize the output pPhysicalDevices with wrapped loader
   4450         // terminator physicalDevice objects; save this list of
   4451         // wrapped objects in instance struct for later cleanup and
   4452         // use by trampoline code
   4453         uint32_t j, idx = 0;
   4454 
   4455         if (copy_count > *pPhysicalDeviceCount) {
   4456             copy_count = *pPhysicalDeviceCount;
   4457         }
   4458 
   4459         if (inst->phys_devs_term) {
   4460             loader_instance_heap_free(inst, inst->phys_devs_term);
   4461             inst->phys_devs_term = NULL;
   4462         }
   4463 
   4464         if (inst->total_gpu_count > 0) {
   4465             inst->phys_devs_term = loader_instance_heap_alloc(
   4466                 inst, sizeof(struct loader_physical_device) * inst->total_gpu_count,
   4467                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
   4468             if (!inst->phys_devs_term) {
   4469                 return VK_ERROR_OUT_OF_HOST_MEMORY;
   4470             }
   4471         }
   4472 
   4473         for (i = 0; idx < inst->total_gpu_count && i < inst->total_icd_count; i++) {
   4474             for (j = 0; j < phys_devs[i].count && idx < inst->total_gpu_count; j++) {
   4475                 loader_set_dispatch((void *)&inst->phys_devs_term[idx],
   4476                                     inst->disp);
   4477                 inst->phys_devs_term[idx].this_icd = phys_devs[i].this_icd;
   4478                 inst->phys_devs_term[idx].icd_index = (uint8_t)(i);
   4479                 inst->phys_devs_term[idx].phys_dev = phys_devs[i].phys_devs[j];
   4480                 if (idx < copy_count) {
   4481                     pPhysicalDevices[idx] =
   4482                         (VkPhysicalDevice)&inst->phys_devs_term[idx];
   4483                 }
   4484                 idx++;
   4485             }
   4486         }
   4487 
   4488         if (copy_count < inst->total_gpu_count) {
   4489             res = VK_INCOMPLETE;
   4490         }
   4491     }
   4492 
   4493     *pPhysicalDeviceCount = copy_count;
   4494 
   4495     return res;
   4496 }
   4497 
   4498 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties(
   4499     VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
   4500     struct loader_physical_device *phys_dev =
   4501         (struct loader_physical_device *)physicalDevice;
   4502     struct loader_icd *icd = phys_dev->this_icd;
   4503 
   4504     if (icd->GetPhysicalDeviceProperties)
   4505         icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
   4506 }
   4507 
   4508 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties(
   4509     VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
   4510     VkQueueFamilyProperties *pProperties) {
   4511     struct loader_physical_device *phys_dev =
   4512         (struct loader_physical_device *)physicalDevice;
   4513     struct loader_icd *icd = phys_dev->this_icd;
   4514 
   4515     if (icd->GetPhysicalDeviceQueueFamilyProperties)
   4516         icd->GetPhysicalDeviceQueueFamilyProperties(
   4517             phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
   4518 }
   4519 
   4520 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties(
   4521     VkPhysicalDevice physicalDevice,
   4522     VkPhysicalDeviceMemoryProperties *pProperties) {
   4523     struct loader_physical_device *phys_dev =
   4524         (struct loader_physical_device *)physicalDevice;
   4525     struct loader_icd *icd = phys_dev->this_icd;
   4526 
   4527     if (icd->GetPhysicalDeviceMemoryProperties)
   4528         icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
   4529 }
   4530 
   4531 VKAPI_ATTR void VKAPI_CALL
   4532 terminator_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
   4533                                      VkPhysicalDeviceFeatures *pFeatures) {
   4534     struct loader_physical_device *phys_dev =
   4535         (struct loader_physical_device *)physicalDevice;
   4536     struct loader_icd *icd = phys_dev->this_icd;
   4537 
   4538     if (icd->GetPhysicalDeviceFeatures)
   4539         icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
   4540 }
   4541 
   4542 VKAPI_ATTR void VKAPI_CALL
   4543 terminator_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
   4544                                              VkFormat format,
   4545                                              VkFormatProperties *pFormatInfo) {
   4546     struct loader_physical_device *phys_dev =
   4547         (struct loader_physical_device *)physicalDevice;
   4548     struct loader_icd *icd = phys_dev->this_icd;
   4549 
   4550     if (icd->GetPhysicalDeviceFormatProperties)
   4551         icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format,
   4552                                                pFormatInfo);
   4553 }
   4554 
   4555 VKAPI_ATTR VkResult VKAPI_CALL
   4556 terminator_GetPhysicalDeviceImageFormatProperties(
   4557     VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
   4558     VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
   4559     VkImageFormatProperties *pImageFormatProperties) {
   4560     struct loader_physical_device *phys_dev =
   4561         (struct loader_physical_device *)physicalDevice;
   4562     struct loader_icd *icd = phys_dev->this_icd;
   4563 
   4564     if (!icd->GetPhysicalDeviceImageFormatProperties)
   4565         return VK_ERROR_INITIALIZATION_FAILED;
   4566 
   4567     return icd->GetPhysicalDeviceImageFormatProperties(
   4568         phys_dev->phys_dev, format, type, tiling, usage, flags,
   4569         pImageFormatProperties);
   4570 }
   4571 
   4572 VKAPI_ATTR void VKAPI_CALL
   4573 terminator_GetPhysicalDeviceSparseImageFormatProperties(
   4574     VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
   4575     VkSampleCountFlagBits samples, VkImageUsageFlags usage,
   4576     VkImageTiling tiling, uint32_t *pNumProperties,
   4577     VkSparseImageFormatProperties *pProperties) {
   4578     struct loader_physical_device *phys_dev =
   4579         (struct loader_physical_device *)physicalDevice;
   4580     struct loader_icd *icd = phys_dev->this_icd;
   4581 
   4582     if (icd->GetPhysicalDeviceSparseImageFormatProperties)
   4583         icd->GetPhysicalDeviceSparseImageFormatProperties(
   4584             phys_dev->phys_dev, format, type, samples, usage, tiling,
   4585             pNumProperties, pProperties);
   4586 }
   4587 
   4588 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
   4589     VkPhysicalDevice physicalDevice, const char *pLayerName,
   4590     uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
   4591     struct loader_physical_device *phys_dev;
   4592 
   4593     struct loader_layer_list implicit_layer_list = {0};
   4594     struct loader_extension_list all_exts = {0};
   4595     struct loader_extension_list icd_exts = {0};
   4596 
   4597     assert(pLayerName == NULL || strlen(pLayerName) == 0);
   4598 
   4599     /* Any layer or trampoline wrapping should be removed at this point in time
   4600      * can just cast to the expected type for VkPhysicalDevice. */
   4601     phys_dev = (struct loader_physical_device *)physicalDevice;
   4602 
   4603     /* this case is during the call down the instance chain with pLayerName
   4604      * == NULL*/
   4605     struct loader_icd *icd = phys_dev->this_icd;
   4606     uint32_t icd_ext_count = *pPropertyCount;
   4607     VkResult res;
   4608 
   4609     /* get device extensions */
   4610     res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL,
   4611                                                   &icd_ext_count, pProperties);
   4612     if (res != VK_SUCCESS) {
   4613         goto out;
   4614     }
   4615 
   4616     if (!loader_init_layer_list(icd->this_instance, &implicit_layer_list)) {
   4617         res = VK_ERROR_OUT_OF_HOST_MEMORY;
   4618         goto out;
   4619     }
   4620 
   4621     loader_add_layer_implicit(
   4622         icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
   4623         &implicit_layer_list, &icd->this_instance->instance_layer_list);
   4624     /* we need to determine which implicit layers are active,
   4625      * and then add their extensions. This can't be cached as
   4626      * it depends on results of environment variables (which can change).
   4627      */
   4628     if (pProperties != NULL) {
   4629         /* initialize dev_extension list within the physicalDevice object */
   4630         res = loader_init_device_extensions(icd->this_instance, phys_dev,
   4631                                             icd_ext_count, pProperties,
   4632                                             &icd_exts);
   4633         if (res != VK_SUCCESS) {
   4634             goto out;
   4635         }
   4636 
   4637         /* we need to determine which implicit layers are active,
   4638          * and then add their extensions. This can't be cached as
   4639          * it depends on results of environment variables (which can
   4640          * change).
   4641          */
   4642         res = loader_add_to_ext_list(icd->this_instance, &all_exts,
   4643                                      icd_exts.count, icd_exts.list);
   4644         if (res != VK_SUCCESS) {
   4645             goto out;
   4646         }
   4647 
   4648         loader_add_layer_implicit(
   4649             icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
   4650             &implicit_layer_list, &icd->this_instance->instance_layer_list);
   4651 
   4652         for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
   4653             for (uint32_t j = 0;
   4654                  j < implicit_layer_list.list[i].device_extension_list.count;
   4655                  j++) {
   4656                 res = loader_add_to_ext_list(icd->this_instance, &all_exts, 1,
   4657                                              &implicit_layer_list.list[i]
   4658                                                   .device_extension_list.list[j]
   4659                                                   .props);
   4660                 if (res != VK_SUCCESS) {
   4661                     goto out;
   4662                 }
   4663             }
   4664         }
   4665         uint32_t capacity = *pPropertyCount;
   4666         VkExtensionProperties *props = pProperties;
   4667 
   4668         for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) {
   4669             props[i] = all_exts.list[i];
   4670         }
   4671         /* wasn't enough space for the extensions, we did partial copy now
   4672          * return VK_INCOMPLETE */
   4673         if (capacity < all_exts.count) {
   4674             res = VK_INCOMPLETE;
   4675         } else {
   4676             *pPropertyCount = all_exts.count;
   4677         }
   4678     } else {
   4679         /* just return the count; need to add in the count of implicit layer
   4680          * extensions
   4681          * don't worry about duplicates being added in the count */
   4682         *pPropertyCount = icd_ext_count;
   4683 
   4684         for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
   4685             *pPropertyCount +=
   4686                 implicit_layer_list.list[i].device_extension_list.count;
   4687         }
   4688         res = VK_SUCCESS;
   4689     }
   4690 
   4691 out:
   4692 
   4693     if (NULL != implicit_layer_list.list) {
   4694         loader_destroy_generic_list(
   4695             icd->this_instance,
   4696             (struct loader_generic_list *)&implicit_layer_list);
   4697     }
   4698     if (NULL != all_exts.list) {
   4699         loader_destroy_generic_list(icd->this_instance,
   4700                                     (struct loader_generic_list *)&all_exts);
   4701     }
   4702     if (NULL != icd_exts.list) {
   4703         loader_destroy_generic_list(icd->this_instance,
   4704                                     (struct loader_generic_list *)&icd_exts);
   4705     }
   4706 
   4707     return res;
   4708 }
   4709 
   4710 VKAPI_ATTR VkResult VKAPI_CALL
   4711 terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
   4712                                           uint32_t *pPropertyCount,
   4713                                           VkLayerProperties *pProperties) {
   4714 
   4715     // should never get here this call isn't dispatched down the chain
   4716     return VK_ERROR_INITIALIZATION_FAILED;
   4717 }
   4718 
   4719 VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
   4720     VkStringErrorFlags result = VK_STRING_ERROR_NONE;
   4721     int num_char_bytes = 0;
   4722     int i, j;
   4723 
   4724     for (i = 0; i < max_length; i++) {
   4725         if (utf8[i] == 0) {
   4726             break;
   4727         } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) {
   4728             num_char_bytes = 0;
   4729         } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) {
   4730             num_char_bytes = 1;
   4731         } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) {
   4732             num_char_bytes = 2;
   4733         } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
   4734             num_char_bytes = 3;
   4735         } else {
   4736             result = VK_STRING_ERROR_BAD_DATA;
   4737         }
   4738 
   4739         // Validate the following num_char_bytes of data
   4740         for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
   4741             if (++i == max_length) {
   4742                 result |= VK_STRING_ERROR_LENGTH;
   4743                 break;
   4744             }
   4745             if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
   4746                 result |= VK_STRING_ERROR_BAD_DATA;
   4747             }
   4748         }
   4749     }
   4750     return result;
   4751 }
   4752