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