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