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