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