loader.c revision fc01b5fc453916f46bb93f52d977deecf9e3611f
1/*
2 * Vulkan
3 *
4 * Copyright (C) 2014 LunarG, 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 * Authors:
25 *   Chia-I Wu <olv@lunarg.com>
26 *   Jon Ashburn <jon@lunarg.com>
27 *   Courtney Goeltzenleuchter <courtney@lunarg.com>
28 *   Ian Elliott <ian@lunarg.com>
29 */
30#define _GNU_SOURCE
31#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <string.h>
36
37#include <sys/types.h>
38#if defined(WIN32)
39#include "dirent_on_windows.h"
40#else // WIN32
41#include <dirent.h>
42#endif // WIN32
43#include "vk_loader_platform.h"
44#include "loader.h"
45#include "gpa_helper.h"
46#include "table_ops.h"
47#include "debug_report.h"
48#include "vk_icd.h"
49#include "cJSON.h"
50
51void loader_add_to_ext_list(
52        struct loader_extension_list *ext_list,
53        uint32_t prop_list_count,
54        const VkExtensionProperties *prop_list);
55
56static loader_platform_dl_handle loader_add_layer_lib(
57        const char *chain_type,
58        struct loader_layer_properties *layer_prop);
59
60static void loader_remove_layer_lib(
61        struct loader_instance *inst,
62        struct loader_layer_properties *layer_prop);
63
64struct loader_struct loader = {0};
65
66static PFN_vkVoidFunction VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName);
67static bool loader_init_ext_list(struct loader_extension_list *ext_info);
68
69enum loader_debug {
70    LOADER_INFO_BIT       = 0x01,
71    LOADER_WARN_BIT       = 0x02,
72    LOADER_PERF_BIT       = 0x04,
73    LOADER_ERROR_BIT      = 0x08,
74    LOADER_DEBUG_BIT      = 0x10,
75};
76
77uint32_t g_loader_debug = 0;
78uint32_t g_loader_log_msgs = 0;
79
80//thread safety lock for accessing global data structures such as "loader"
81// all entrypoints on the instance chain need to be locked except GPA
82// additionally CreateDevice and DestroyDevice needs to be locked
83loader_platform_thread_mutex loader_lock;
84
85// This table contains the loader's instance dispatch table, which contains
86// default functions if no instance layers are activated.  This contains
87// pointers to "terminator functions".
88const VkLayerInstanceDispatchTable instance_disp = {
89    .GetInstanceProcAddr = loader_GetInstanceProcAddr,
90    .CreateInstance = loader_CreateInstance,
91    .DestroyInstance = loader_DestroyInstance,
92    .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
93    .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
94    .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
95    .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
96    .GetPhysicalDeviceLimits = loader_GetPhysicalDeviceLimits,
97    .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
98    .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
99    .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
100    .GetPhysicalDeviceExtensionProperties = loader_GetPhysicalDeviceExtensionProperties,
101    .GetPhysicalDeviceLayerProperties = loader_GetPhysicalDeviceLayerProperties,
102    .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
103    .GetPhysicalDeviceSurfaceSupportWSI = loader_GetPhysicalDeviceSurfaceSupportWSI,
104    .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
105    .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
106};
107
108LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
109
110void* loader_heap_alloc(
111    struct loader_instance     *instance,
112    size_t                      size,
113    VkSystemAllocType           alloc_type)
114{
115    if (instance && instance->alloc_callbacks.pfnAlloc) {
116        /* TODO: What should default alignment be? 1, 4, 8, other? */
117        return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
118    }
119    return malloc(size);
120}
121
122void* loader_aligned_heap_alloc(
123    struct loader_instance     *instance,
124    size_t                      size,
125    size_t                      alignment,
126    VkSystemAllocType           alloc_type)
127{
128    if (instance && instance->alloc_callbacks.pfnAlloc) {
129        return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, alignment, alloc_type);
130    }
131#if defined(_WIN32)
132    return _aligned_malloc(alignment, size);
133#else
134    return aligned_alloc(alignment, size);
135#endif
136}
137
138void loader_heap_free(
139    struct loader_instance     *instance,
140    void                       *pMem)
141{
142    if (instance && instance->alloc_callbacks.pfnFree) {
143        instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
144        return;
145    }
146    free(pMem);
147}
148
149static void loader_log(VkFlags msg_type, int32_t msg_code,
150    const char *format, ...)
151{
152    char msg[512];
153    va_list ap;
154    int ret;
155
156    if (!(msg_type & g_loader_log_msgs)) {
157        return;
158    }
159
160    va_start(ap, format);
161    ret = vsnprintf(msg, sizeof(msg), format, ap);
162    if ((ret >= (int) sizeof(msg)) || ret < 0) {
163        msg[sizeof(msg)-1] = '\0';
164    }
165    va_end(ap);
166
167#if defined(WIN32)
168    OutputDebugString(msg);
169    OutputDebugString("\n");
170#endif
171    fputs(msg, stderr);
172    fputc('\n', stderr);
173}
174
175#if defined(WIN32)
176static char *loader_get_next_path(char *path);
177/**
178* Find the list of registry files (names within a key) in key "location".
179*
180* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
181* for a list or name/values which are added to a returned list (function return value).
182* The DWORD values within the key must be 0 or they are skipped.
183* Function return is a string with a ';'  seperated list of filenames.
184* Function return is NULL if no valid name/value pairs  are found in the key,
185* or the key is not found.
186*
187* \returns
188* A string list of filenames as pointer.
189* When done using the returned string list, pointer should be freed.
190*/
191static char *loader_get_registry_files(char *location)
192{
193    LONG rtn_value;
194    HKEY hive, key;
195    DWORD access_flags = KEY_QUERY_VALUE;
196    char name[2048];
197    char *out = NULL;
198    char *loc = location;
199    char *next;
200    DWORD idx = 0;
201    DWORD name_size = sizeof(name);
202    DWORD value;
203    DWORD total_size = 4096;
204    DWORD value_size = sizeof(value);
205
206    while(*loc)
207    {
208        next = loader_get_next_path(loc);
209        hive = DEFAULT_VK_REGISTRY_HIVE;
210        rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
211        if (rtn_value != ERROR_SUCCESS) {
212            // We didn't find the key.  Try the 32-bit hive (where we've seen the
213            // key end up on some people's systems):
214            access_flags |= KEY_WOW64_32KEY;
215            rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
216            if (rtn_value != ERROR_SUCCESS) {
217                // We still couldn't find the key, so give up:
218                loc = next;
219                continue;
220            }
221        }
222
223        while((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
224            if (value_size == sizeof(value) && value == 0) {
225                if (out == NULL) {
226                    out = malloc(total_size);
227                    out[0] = '\0';
228                }
229                else if (strlen(out) + name_size + 1 > total_size) {
230                    out = realloc(out, total_size * 2);
231                    total_size *= 2;
232                }
233                if (out == NULL) {
234                    loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
235                    return NULL;
236                }
237                if (strlen(out) == 0)
238                     snprintf(out, name_size + 1, "%s", name);
239                else
240                     snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
241            }
242            name_size = 2048;
243        }
244        loc = next;
245    }
246
247    return out;
248}
249
250#endif // WIN32
251
252/**
253 * Given string of three part form "maj.min.pat" convert to a vulkan version
254 * number.
255 */
256static uint32_t loader_make_version(const char *vers_str)
257{
258    uint32_t vers = 0, major, minor, patch;
259    char *minor_str= NULL;
260    char *patch_str = NULL;
261    char *cstr;
262    char *str;
263
264    if (!vers_str)
265        return vers;
266    cstr = loader_stack_alloc(strlen(vers_str) + 1);
267    strcpy(cstr, vers_str);
268    while ((str = strchr(cstr, '.')) != NULL) {
269        if (minor_str == NULL) {
270            minor_str = str + 1;
271            *str = '\0';
272            major = atoi(cstr);
273        }
274        else if (patch_str == NULL) {
275            patch_str = str + 1;
276            *str = '\0';
277            minor = atoi(minor_str);
278        }
279        else {
280            return vers;
281        }
282        cstr = str + 1;
283    }
284    patch = atoi(patch_str);
285
286    return VK_MAKE_VERSION(major, minor, patch);
287
288}
289
290bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
291{
292    return strcmp(op1->extName, op2->extName) == 0 ? true : false;
293}
294
295/**
296 * Search the given ext_array for an extension
297 * matching the given vk_ext_prop
298 */
299bool has_vk_extension_property_array(
300        const VkExtensionProperties *vk_ext_prop,
301        const uint32_t count,
302        const VkExtensionProperties *ext_array)
303{
304    for (uint32_t i = 0; i < count; i++) {
305        if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
306            return true;
307    }
308    return false;
309}
310
311/**
312 * Search the given ext_list for an extension
313 * matching the given vk_ext_prop
314 */
315bool has_vk_extension_property(
316        const VkExtensionProperties *vk_ext_prop,
317        const struct loader_extension_list *ext_list)
318{
319    for (uint32_t i = 0; i < ext_list->count; i++) {
320        if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
321            return true;
322    }
323    return false;
324}
325
326static inline bool loader_is_layer_type_device(const enum layer_type type) {
327    if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
328                (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
329        return true;
330    return false;
331}
332
333/*
334 * Search the given layer list for a layer matching the given layer name
335 */
336static struct loader_layer_properties *loader_get_layer_property(
337        const char *name,
338        const struct loader_layer_list *layer_list)
339{
340    for (uint32_t i = 0; i < layer_list->count; i++) {
341        const VkLayerProperties *item = &layer_list->list[i].info;
342        if (strcmp(name, item->layerName) == 0)
343            return &layer_list->list[i];
344    }
345    return NULL;
346}
347
348/**
349 * Get the next unused layer property in the list. Init the property to zero.
350 */
351static struct loader_layer_properties *loader_get_next_layer_property(
352                                           struct loader_layer_list *layer_list)
353{
354    if (layer_list->capacity == 0) {
355        layer_list->list = malloc(sizeof(struct loader_layer_properties) * 64);
356        if (layer_list->list == NULL) {
357            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
358            return NULL;
359        }
360        memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
361        layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
362    }
363
364    // ensure enough room to add an entry
365    if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
366            > layer_list->capacity) {
367        layer_list->list = realloc(layer_list->list, layer_list->capacity * 2);
368        if (layer_list->list == NULL) {
369            loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
370                            "realloc failed for layer list");
371        }
372        layer_list->capacity *= 2;
373    }
374
375    layer_list->count++;
376    return &(layer_list->list[layer_list->count - 1]);
377}
378
379/**
380 * Remove all layer properties entrys from the list
381 */
382static void loader_delete_layer_properties(struct loader_layer_list *layer_list)
383{
384    uint32_t i;
385
386    if (!layer_list)
387        return;
388
389    for (i = 0; i < layer_list->count; i++) {
390        if (layer_list->list[i].lib_info.lib_name != NULL)
391            free(layer_list->list[i].lib_info.lib_name);
392        loader_destroy_ext_list(&layer_list->list[i].instance_extension_list);
393        loader_destroy_ext_list(&layer_list->list[i].device_extension_list);
394        layer_list->list[i].lib_info.lib_name = NULL;
395    }
396    layer_list->count = 0;
397
398    if (layer_list->capacity > 0) {
399        layer_list->capacity = 0;
400        free(layer_list->list);
401    }
402
403}
404
405static void loader_add_global_extensions(
406        const PFN_vkGetGlobalExtensionProperties fp_get_props,
407        const char *lib_name,
408        struct loader_extension_list *ext_list)
409{
410    uint32_t i, count;
411    VkExtensionProperties *ext_props;
412    VkResult res;
413
414    if (!fp_get_props) {
415        /* No GetGlobalExtensionProperties defined */
416        return;
417    }
418
419    res = fp_get_props(NULL, &count, NULL);
420    if (res != VK_SUCCESS) {
421        loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
422        return;
423    }
424
425    if (count == 0) {
426        /* No ExtensionProperties to report */
427        return;
428    }
429
430    ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
431
432    res = fp_get_props(NULL, &count, ext_props);
433    if (res != VK_SUCCESS) {
434        loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
435        return;
436    }
437
438    for (i = 0; i < count; i++) {
439        char spec_version[64];
440
441        snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
442                 VK_MAJOR(ext_props[i].specVersion),
443                 VK_MINOR(ext_props[i].specVersion),
444                 VK_PATCH(ext_props[i].specVersion));
445        loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
446                   "Global Extension: %s (%s) version %s",
447                   ext_props[i].extName, lib_name, spec_version);
448        loader_add_to_ext_list(ext_list, 1, &ext_props[i]);
449    }
450
451    return;
452}
453
454static void loader_add_physical_device_extensions(
455        PFN_vkGetPhysicalDeviceExtensionProperties get_phys_dev_ext_props,
456        VkPhysicalDevice physical_device,
457        const char *lib_name,
458        struct loader_extension_list *ext_list)
459{
460    uint32_t i, count;
461    VkResult res;
462    VkExtensionProperties *ext_props;
463
464    if (!get_phys_dev_ext_props) {
465        /* No GetPhysicalDeviceExtensionProperties defined */
466        return;
467    }
468
469        res = get_phys_dev_ext_props(physical_device, NULL, &count, NULL);
470        if (res == VK_SUCCESS && count > 0) {
471            ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
472
473            res = get_phys_dev_ext_props(physical_device, NULL, &count, ext_props);
474            for (i = 0; i < count; i++) {
475                char spec_version[64];
476
477                snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
478                         VK_MAJOR(ext_props[i].specVersion),
479                         VK_MINOR(ext_props[i].specVersion),
480                         VK_PATCH(ext_props[i].specVersion));
481                loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
482                           "PhysicalDevice Extension: %s (%s) version %s",
483                           ext_props[i].extName, lib_name, spec_version);
484                loader_add_to_ext_list(ext_list, 1, &ext_props[i]);
485            }
486        } else {
487            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name);
488        }
489
490    return;
491}
492
493static bool loader_init_ext_list(struct loader_extension_list *ext_info)
494{
495    ext_info->capacity = 32 * sizeof(VkExtensionProperties);
496    /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
497    ext_info->list = malloc(ext_info->capacity);
498    if (ext_info->list == NULL) {
499        return false;
500    }
501    memset(ext_info->list, 0, ext_info->capacity);
502    ext_info->count = 0;
503    return true;
504}
505
506void loader_destroy_ext_list(struct loader_extension_list *ext_info)
507{
508    free(ext_info->list);
509    ext_info->count = 0;
510    ext_info->capacity = 0;
511}
512
513/*
514 * Append non-duplicate extension properties defined in props
515 * to the given ext_list.
516 */
517void loader_add_to_ext_list(
518        struct loader_extension_list *ext_list,
519        uint32_t prop_list_count,
520        const VkExtensionProperties *props)
521{
522    uint32_t i;
523    const VkExtensionProperties *cur_ext;
524
525    if (ext_list->list == NULL || ext_list->capacity == 0) {
526        loader_init_ext_list(ext_list);
527    }
528
529    if (ext_list->list == NULL)
530        return;
531
532    for (i = 0; i < prop_list_count; i++) {
533        cur_ext = &props[i];
534
535        // look for duplicates
536        if (has_vk_extension_property(cur_ext, ext_list)) {
537            continue;
538        }
539
540        // add to list at end
541        // check for enough capacity
542        if (ext_list->count * sizeof(VkExtensionProperties)
543                        >= ext_list->capacity) {
544            // double capacity
545            ext_list->capacity *= 2;
546            /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
547            ext_list->list = realloc(ext_list->list, ext_list->capacity);
548        }
549
550        memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
551        ext_list->count++;
552    }
553}
554
555/**
556 * Search the given search_list for any layers in the props list.
557 * Add these to the output layer_list.  Don't add duplicates to the output layer_list.
558 */
559static VkResult loader_add_layer_names_to_list(
560        struct loader_layer_list *output_list,
561        uint32_t name_count,
562        const char * const *names,
563        const struct loader_layer_list *search_list)
564{
565    struct loader_layer_properties *layer_prop;
566    VkResult err = VK_SUCCESS;
567
568    for (uint32_t i = 0; i < name_count; i++) {
569        const char *search_target = names[i];
570        layer_prop = loader_get_layer_property(search_target, search_list);
571        if (!layer_prop) {
572            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
573            err = VK_ERROR_INVALID_LAYER;
574            continue;
575        }
576
577        loader_add_to_layer_list(output_list, 1, layer_prop);
578    }
579
580    return err;
581}
582
583
584/*
585 * Manage lists of VkLayerProperties
586 */
587static bool loader_init_layer_list(struct loader_layer_list *list)
588{
589    list->capacity = 32 * sizeof(struct loader_layer_properties);
590    /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
591    list->list = malloc(list->capacity);
592    if (list->list == NULL) {
593        return false;
594    }
595    memset(list->list, 0, list->capacity);
596    list->count = 0;
597    return true;
598}
599
600void loader_destroy_layer_list(struct loader_layer_list *layer_list)
601{
602    free(layer_list->list);
603    layer_list->count = 0;
604    layer_list->capacity = 0;
605}
606
607/*
608 * Manage list of layer libraries (loader_lib_info)
609 */
610static bool loader_init_layer_library_list(struct loader_layer_library_list *list)
611{
612    list->capacity = 32 * sizeof(struct loader_lib_info);
613    /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
614    list->list = malloc(list->capacity);
615    if (list->list == NULL) {
616        return false;
617    }
618    memset(list->list, 0, list->capacity);
619    list->count = 0;
620    return true;
621}
622
623void loader_destroy_layer_library_list(struct loader_layer_library_list *list)
624{
625    for (uint32_t i = 0; i < list->count; i++) {
626        free(list->list[i].lib_name);
627    }
628    free(list->list);
629    list->count = 0;
630    list->capacity = 0;
631}
632
633void loader_add_to_layer_library_list(
634        struct loader_layer_library_list *list,
635        uint32_t item_count,
636        const struct loader_lib_info *new_items)
637{
638    uint32_t i;
639    struct loader_lib_info *item;
640
641    if (list->list == NULL || list->capacity == 0) {
642        loader_init_layer_library_list(list);
643    }
644
645    if (list->list == NULL)
646        return;
647
648    for (i = 0; i < item_count; i++) {
649        item = (struct loader_lib_info *) &new_items[i];
650
651        // look for duplicates
652        for (uint32_t j = 0; j < list->count; j++) {
653            if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
654                continue;
655            }
656        }
657
658        // add to list at end
659        // check for enough capacity
660        if (list->count * sizeof(struct loader_lib_info)
661                        >= list->capacity) {
662            // double capacity
663            list->capacity *= 2;
664            /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
665            list->list = realloc(list->list, list->capacity);
666        }
667
668        memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
669        list->count++;
670    }
671}
672
673
674/*
675 * Search the given layer list for a list
676 * matching the given VkLayerProperties
677 */
678bool has_vk_layer_property(
679        const VkLayerProperties *vk_layer_prop,
680        const struct loader_layer_list *list)
681{
682    for (uint32_t i = 0; i < list->count; i++) {
683        if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
684            return true;
685    }
686    return false;
687}
688
689/*
690 * Search the given layer list for a layer
691 * matching the given name
692 */
693bool has_layer_name(
694        const char *name,
695        const struct loader_layer_list *list)
696{
697    for (uint32_t i = 0; i < list->count; i++) {
698        if (strcmp(name, list->list[i].info.layerName) == 0)
699            return true;
700    }
701    return false;
702}
703
704/*
705 * Append non-duplicate layer properties defined in prop_list
706 * to the given layer_info list
707 */
708void loader_add_to_layer_list(
709        struct loader_layer_list *list,
710        uint32_t prop_list_count,
711        const struct loader_layer_properties *props)
712{
713    uint32_t i;
714    struct loader_layer_properties *layer;
715
716    if (list->list == NULL || list->capacity == 0) {
717        loader_init_layer_list(list);
718    }
719
720    if (list->list == NULL)
721        return;
722
723    for (i = 0; i < prop_list_count; i++) {
724        layer = (struct loader_layer_properties *) &props[i];
725
726        // look for duplicates
727        if (has_vk_layer_property(&layer->info, list)) {
728            continue;
729        }
730
731        // add to list at end
732        // check for enough capacity
733        if (list->count * sizeof(struct loader_layer_properties)
734                        >= list->capacity) {
735            // double capacity
736            list->capacity *= 2;
737            list->list = realloc(list->list, list->capacity);
738        }
739
740        memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
741        list->count++;
742    }
743}
744
745/**
746 * Search the search_list for any layer with a name
747 * that matches the given name and a type that matches the given type
748 * Add all matching layers to the found_list
749 * Do not add if found loader_layer_properties is already
750 * on the found_list.
751 */
752static void loader_find_layer_name_add_list(
753        const char *name,
754        const enum layer_type type,
755        const struct loader_layer_list *search_list,
756        struct loader_layer_list *found_list)
757{
758    for (uint32_t i = 0; i < search_list->count; i++) {
759        struct loader_layer_properties *layer_prop = &search_list->list[i];
760        if (0 == strcmp(layer_prop->info.layerName, name) &&
761                (layer_prop->type & type)) {
762            /* Found a layer with the same name, add to found_list */
763            loader_add_to_layer_list(found_list, 1, layer_prop);
764        }
765    }
766}
767
768static VkExtensionProperties *get_extension_property(
769        const char *name,
770        const struct loader_extension_list *list)
771{
772    for (uint32_t i = 0; i < list->count; i++) {
773        if (strcmp(name, list->list[i].extName) == 0)
774            return &list->list[i];
775    }
776    return NULL;
777}
778
779/*
780 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
781 * the extension must provide two entry points for the loader to use:
782 * - "trampoline" entry point - this is the address returned by GetProcAddr
783 * and will always do what's necessary to support a global call.
784 * - "terminator" function - this function will be put at the end of the
785 * instance chain and will contain the necessary logica to call / process
786 * the extension for the appropriate ICDs that are available.
787 * There is no generic mechanism for including these functions, the references
788 * must be placed into the appropriate loader entry points.
789 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
790 * loader_coalesce_extensions(void) - add extension records to the list of global
791 * extension available to the app.
792 * instance_disp - add function pointer for terminator function to this array.
793 * The extension itself should be in a separate file that will be
794 * linked directly with the loader.
795 */
796
797void loader_get_icd_loader_instance_extensions(struct loader_extension_list *inst_exts)
798{
799    struct loader_scanned_icds *icd_list = loader.scanned_icd_list;
800    struct loader_extension_list icd_exts;
801    loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
802    // traverse scanned icd list adding non-duplicate extensions to the list
803    while (icd_list != NULL) {
804        loader_init_ext_list(&icd_exts);
805        loader_add_global_extensions(icd_list->GetGlobalExtensionProperties,
806                                     icd_list->lib_name,
807                                     &icd_exts);
808        loader_add_to_ext_list(inst_exts,
809                               icd_exts.count,
810                               icd_exts.list);
811        loader_destroy_ext_list(&icd_exts);
812        icd_list = icd_list->next;
813    };
814
815    // Traverse loader's extensions, adding non-duplicate extensions to the list
816    wsi_swapchain_add_instance_extensions(inst_exts);
817    debug_report_add_instance_extensions(inst_exts);
818}
819
820static struct loader_icd *loader_get_icd_and_device(const VkDevice device,
821                                                    struct loader_device **found_dev)
822{
823    *found_dev = NULL;
824    for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
825        for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
826            for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
827                if (dev->device == device) {
828                    *found_dev = dev;
829                    return icd;
830                }
831        }
832    }
833    return NULL;
834}
835
836static void loader_destroy_logical_device(struct loader_device *dev)
837{
838    free(dev->app_extension_props);
839    if (dev->activated_layer_list.count)
840        loader_destroy_layer_list(&dev->activated_layer_list);
841    free(dev);
842}
843
844static struct loader_device *loader_add_logical_device(const VkDevice dev, struct loader_device **device_list)
845{
846    struct loader_device *new_dev;
847
848    new_dev = malloc(sizeof(struct loader_device));
849    if (!new_dev) {
850        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc struct laoder-device");
851        return NULL;
852    }
853
854    memset(new_dev, 0, sizeof(struct loader_device));
855
856    new_dev->next = *device_list;
857    new_dev->device = dev;
858    *device_list = new_dev;
859    return new_dev;
860}
861
862void loader_remove_logical_device(VkDevice device)
863{
864    struct loader_device *found_dev, *dev, *prev_dev;
865    struct loader_icd *icd;
866    icd = loader_get_icd_and_device(device, &found_dev);
867
868    if (!icd || !found_dev)
869        return;
870
871    prev_dev = NULL;
872    dev = icd->logical_device_list;
873    while (dev && dev != found_dev) {
874        prev_dev = dev;
875        dev = dev->next;
876    }
877
878    if (prev_dev)
879        prev_dev->next = found_dev->next;
880    else
881        icd->logical_device_list = found_dev->next;
882    loader_destroy_logical_device(found_dev);
883}
884
885
886static void loader_icd_destroy(
887        struct loader_instance *ptr_inst,
888        struct loader_icd *icd)
889{
890    ptr_inst->total_icd_count--;
891    free(icd->gpus);
892    for (struct loader_device *dev = icd->logical_device_list; dev; ) {
893        struct loader_device *next_dev = dev->next;
894        loader_destroy_logical_device(dev);
895        dev = next_dev;
896    }
897
898    free(icd);
899}
900
901static struct loader_icd * loader_icd_create(const struct loader_scanned_icds *scanned)
902{
903    struct loader_icd *icd;
904
905    icd = malloc(sizeof(*icd));
906    if (!icd)
907        return NULL;
908
909    memset(icd, 0, sizeof(*icd));
910
911    icd->scanned_icds = scanned;
912
913    return icd;
914}
915
916static struct loader_icd *loader_icd_add(
917        struct loader_instance *ptr_inst,
918        const struct loader_scanned_icds *scanned)
919{
920    struct loader_icd *icd;
921
922    icd = loader_icd_create(scanned);
923    if (!icd)
924        return NULL;
925
926    /* prepend to the list */
927    icd->next = ptr_inst->icds;
928    ptr_inst->icds = icd;
929    ptr_inst->total_icd_count++;
930
931    return icd;
932}
933
934static void loader_scanned_icd_add(const char *filename)
935{
936    loader_platform_dl_handle handle;
937    PFN_vkCreateInstance fp_create_inst;
938    PFN_vkGetGlobalExtensionProperties fp_get_global_ext_props;
939    PFN_vkGetInstanceProcAddr fp_get_proc_addr;
940    struct loader_scanned_icds *new_node;
941
942    // Used to call: dlopen(filename, RTLD_LAZY);
943    handle = loader_platform_open_library(filename);
944    if (!handle) {
945        loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
946        return;
947    }
948
949#define LOOKUP_LD(func_ptr, func) do {                            \
950    func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
951    if (!func_ptr) {                                           \
952        loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
953        return;                                                \
954    }                                                          \
955} while (0)
956
957    LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
958    LOOKUP_LD(fp_create_inst, CreateInstance);
959    LOOKUP_LD(fp_get_global_ext_props, GetGlobalExtensionProperties);
960
961#undef LOOKUP_LD
962
963    new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
964                                                     + strlen(filename) + 1);
965    if (!new_node) {
966        loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
967        return;
968    }
969
970    new_node->handle = handle;
971    new_node->GetInstanceProcAddr = fp_get_proc_addr;
972    new_node->CreateInstance = fp_create_inst;
973    new_node->GetGlobalExtensionProperties = fp_get_global_ext_props;
974    new_node->next = loader.scanned_icd_list;
975
976    new_node->lib_name = (char *) (new_node + 1);
977    if (!new_node->lib_name) {
978        loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
979        return;
980    }
981    strcpy(new_node->lib_name, filename);
982
983    loader.scanned_icd_list = new_node;
984
985}
986
987static bool loader_icd_init_entrys(struct loader_icd *icd,
988                                   VkInstance inst,
989                                   const PFN_vkGetInstanceProcAddr fp_gipa)
990{
991    /* initialize entrypoint function pointers */
992
993    #define LOOKUP_GIPA(func, required) do {                       \
994    icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func);         \
995    if (!icd->func && required) {                                  \
996        loader_log(VK_DBG_REPORT_WARN_BIT, 0,                      \
997              loader_platform_get_proc_address_error("vk" #func)); \
998        return false;                                              \
999    }                                                              \
1000    } while (0)
1001
1002    LOOKUP_GIPA(GetDeviceProcAddr, true);
1003    LOOKUP_GIPA(DestroyInstance, true);
1004    LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1005    LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1006    LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
1007    LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
1008    LOOKUP_GIPA(GetPhysicalDeviceLimits, true);
1009    LOOKUP_GIPA(CreateDevice, true);
1010    LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1011    LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
1012    LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
1013    LOOKUP_GIPA(GetPhysicalDeviceExtensionProperties, true);
1014    LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1015    LOOKUP_GIPA(DbgCreateMsgCallback, false);
1016    LOOKUP_GIPA(DbgDestroyMsgCallback, false);
1017    LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportWSI, false);
1018
1019#undef LOOKUP_GIPA
1020
1021    return true;
1022}
1023
1024static void loader_debug_init(void)
1025{
1026    const char *env;
1027
1028    if (g_loader_debug > 0)
1029        return;
1030
1031    g_loader_debug = 0;
1032
1033    /* parse comma-separated debug options */
1034    env = getenv("VK_LOADER_DEBUG");
1035    while (env) {
1036        const char *p = strchr(env, ',');
1037        size_t len;
1038
1039        if (p)
1040            len = p - env;
1041        else
1042            len = strlen(env);
1043
1044        if (len > 0) {
1045            if (strncmp(env, "warn", len) == 0) {
1046                g_loader_debug |= LOADER_WARN_BIT;
1047                g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1048            } else if (strncmp(env, "info", len) == 0) {
1049                g_loader_debug |= LOADER_INFO_BIT;
1050                g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1051            } else if (strncmp(env, "perf", len) == 0) {
1052                g_loader_debug |= LOADER_PERF_BIT;
1053                g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1054            } else if (strncmp(env, "error", len) == 0) {
1055                g_loader_debug |= LOADER_ERROR_BIT;
1056                g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1057            } else if (strncmp(env, "debug", len) == 0) {
1058                g_loader_debug |= LOADER_DEBUG_BIT;
1059                g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1060            }
1061        }
1062
1063        if (!p)
1064            break;
1065
1066        env = p + 1;
1067    }
1068}
1069
1070struct loader_manifest_files {
1071    uint32_t count;
1072    char **filename_list;
1073};
1074
1075/**
1076 * Get next file or dirname given a string list or registry key path
1077 *
1078 * \returns
1079 * A pointer to first char in the next path.
1080 * The next path (or NULL) in the list is returned in next_path.
1081 * Note: input string is modified in some cases. PASS IN A COPY!
1082 */
1083static char *loader_get_next_path(char *path)
1084{
1085    uint32_t len;
1086    char *next;
1087
1088    if (path == NULL)
1089        return NULL;
1090    next = strchr(path, PATH_SEPERATOR);
1091    if (next == NULL) {
1092        len = (uint32_t) strlen(path);
1093        next = path + len;
1094    }
1095    else {
1096        *next = '\0';
1097        next++;
1098    }
1099
1100    return next;
1101}
1102
1103/**
1104 * Given a path which is absolute or relative. Expand the path if relative otherwise
1105 * leave the path unmodified if absolute. The path which is relative from is
1106 * given in rel_base and should include trailing directory seperator '/'
1107 *
1108 * \returns
1109 * A string in out_fullpath of the full absolute path
1110 * Side effect is that dir string maybe modified.
1111 */
1112static void loader_expand_path(const char *path,
1113                               const char *rel_base,
1114                               size_t out_size,
1115                               char *out_fullpath)
1116{
1117    if (loader_platform_is_path_absolute(path)) {
1118        strncpy(out_fullpath, path, out_size);
1119        out_fullpath[out_size - 1] = '\0';
1120    }
1121    else {
1122        // convert relative to absolute path based on rel_base
1123        size_t len = strlen(path);
1124        strncpy(out_fullpath, rel_base, out_size);
1125        out_fullpath[out_size - 1] = '\0';
1126        assert(out_size >= strlen(out_fullpath) + len + 1);
1127        strncat(out_fullpath, path, len);
1128    }
1129}
1130
1131/**
1132 * Given a filename (file)  and a list of paths (dir), try to find an existing
1133 * file in the paths.  If filename already is a path then no
1134 * searching in the given paths.
1135 *
1136 * \returns
1137 * A string in out_fullpath of either the full path or file.
1138 * Side effect is that dir string maybe modified.
1139 */
1140static void loader_get_fullpath(const char *file,
1141                                char *dir,
1142                                size_t out_size,
1143                                char *out_fullpath)
1144{
1145    char *next_dir;
1146    if (strchr(file,DIRECTORY_SYMBOL) == NULL) {
1147        //find file exists with prepending given path
1148        while (*dir) {
1149            next_dir = loader_get_next_path(dir);
1150            snprintf(out_fullpath, out_size, "%s%c%s",
1151                     dir, DIRECTORY_SYMBOL, file);
1152            if (loader_platform_file_exists(out_fullpath)) {
1153                return;
1154            }
1155            dir = next_dir;
1156        }
1157    }
1158    snprintf(out_fullpath, out_size, "%s", file);
1159}
1160
1161/**
1162 * Read a JSON file into a buffer.
1163 *
1164 * \returns
1165 * A pointer to a cJSON object representing the JSON parse tree.
1166 * This returned buffer should be freed by caller.
1167 */
1168static cJSON *loader_get_json(const char *filename)
1169{
1170    FILE *file;
1171    char *json_buf;
1172    cJSON *json;
1173    uint64_t len;
1174    file = fopen(filename,"rb");
1175    fseek(file, 0, SEEK_END);
1176    len = ftell(file);
1177    fseek(file, 0, SEEK_SET);
1178    json_buf = (char*) loader_stack_alloc(len+1);
1179    if (json_buf == NULL) {
1180        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1181        fclose(file);
1182        return NULL;
1183    }
1184    if (fread(json_buf, sizeof(char), len, file) != len) {
1185        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1186        fclose(file);
1187        return NULL;
1188    }
1189    fclose(file);
1190    json_buf[len] = '\0';
1191
1192    //parse text from file
1193    json = cJSON_Parse(json_buf);
1194    if (json == NULL)
1195        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1196    return json;
1197}
1198
1199/**
1200 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1201 * file, add entry to the layer_list.
1202 * Fill out the layer_properties in this list entry from the input cJSON object.
1203 *
1204 * \returns
1205 * void
1206 * layer_list has a new entry and initialized accordingly.
1207 * If the json input object does not have all the required fields no entry
1208 * is added to the list.
1209 */
1210static void loader_add_layer_properties(struct loader_layer_list *layer_instance_list,
1211                                        struct loader_layer_list *layer_device_list,
1212                                        cJSON *json,
1213                                        bool is_implicit,
1214                                        char *filename)
1215{
1216    /* Fields in layer manifest file that are required:
1217     * (required) “file_format_version”
1218     * following are required in the "layer" object:
1219     * (required) "name"
1220     * (required) "type"
1221     * (required) “library_path”
1222     * (required) “abi_versions”
1223     * (required) “implementation_version”
1224     * (required) “description”
1225     * (required for implicit layers) “disable_environment”
1226     *
1227     * First get all required items and if any missing abort
1228     */
1229
1230    cJSON *item, *layer_node, *ext_item;
1231    char *temp;
1232    char *name, *type, *library_path, *abi_versions;
1233    char *implementation_version, *description;
1234    cJSON *disable_environment;
1235    int i;
1236    VkExtensionProperties ext_prop;
1237    item = cJSON_GetObjectItem(json, "file_format_version");
1238    if (item == NULL) {
1239        return;
1240    }
1241    char *file_vers = cJSON_PrintUnformatted(item);
1242    loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1243               filename, file_vers);
1244    if (strcmp(file_vers, "\"0.9.0\"") != 0)
1245        loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 0.9.0), may cause errors");
1246    free(file_vers);
1247
1248    layer_node = cJSON_GetObjectItem(json, "layer");
1249    if (layer_node == NULL) {
1250        loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1251        return;
1252    }
1253
1254    // loop through all "layer" objects in the file
1255    do {
1256#define GET_JSON_OBJECT(node, var) {                  \
1257        var = cJSON_GetObjectItem(node, #var);        \
1258        if (var == NULL) {                            \
1259            layer_node = layer_node->next;            \
1260            continue;                                 \
1261        }                                             \
1262        }
1263#define GET_JSON_ITEM(node, var) {                    \
1264        item = cJSON_GetObjectItem(node, #var);       \
1265        if (item == NULL) {                           \
1266            layer_node = layer_node->next;            \
1267            continue;                                 \
1268        }                                             \
1269        temp = cJSON_Print(item);                     \
1270        temp[strlen(temp) - 1] = '\0';                \
1271        var = loader_stack_alloc(strlen(temp) + 1);   \
1272        strcpy(var, &temp[1]);                        \
1273        free(temp);                                   \
1274        }
1275        GET_JSON_ITEM(layer_node, name)
1276        GET_JSON_ITEM(layer_node, type)
1277        GET_JSON_ITEM(layer_node, library_path)
1278        GET_JSON_ITEM(layer_node, abi_versions)
1279        GET_JSON_ITEM(layer_node, implementation_version)
1280        GET_JSON_ITEM(layer_node, description)
1281        if (is_implicit) {
1282            GET_JSON_OBJECT(layer_node, disable_environment)
1283        }
1284#undef GET_JSON_ITEM
1285#undef GET_JSON_OBJECT
1286
1287        // add list entry
1288        struct loader_layer_properties *props;
1289        if (!strcmp(type, "DEVICE")) {
1290            if (layer_device_list == NULL) {
1291                layer_node = layer_node->next;
1292                continue;
1293            }
1294            props = loader_get_next_layer_property(layer_device_list);
1295            props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1296        }
1297        if (!strcmp(type, "INSTANCE")) {
1298            if (layer_instance_list == NULL) {
1299                layer_node = layer_node->next;
1300                continue;
1301            }
1302            props = loader_get_next_layer_property(layer_instance_list);
1303            props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1304        }
1305        if (!strcmp(type, "GLOBAL")) {
1306            if (layer_instance_list != NULL)
1307                props = loader_get_next_layer_property(layer_instance_list);
1308            else if (layer_device_list != NULL)
1309                props = loader_get_next_layer_property(layer_device_list);
1310            else {
1311                layer_node = layer_node->next;
1312                continue;
1313            }
1314            props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1315        }
1316
1317        strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1318        props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
1319
1320        char *fullpath = malloc(MAX_STRING_SIZE);
1321        char *rel_base;
1322        if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1323            // a filename which is assumed in the system directory
1324            char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_LAYERS_PATH) + 1);
1325            strcpy(def_path, DEFAULT_VK_LAYERS_PATH);
1326            loader_get_fullpath(library_path, def_path, MAX_STRING_SIZE, fullpath);
1327        } else {
1328            // a relative or absolute path
1329            char *name_copy = loader_stack_alloc(strlen(filename) + 2);
1330            size_t len;
1331            strcpy(name_copy, filename);
1332            rel_base = loader_platform_dirname(name_copy);
1333            len = strlen(rel_base);
1334            rel_base[len] = DIRECTORY_SYMBOL;
1335            rel_base[len + 1] = '\0';
1336            loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
1337        }
1338        props->lib_info.lib_name = fullpath;
1339        props->info.specVersion = loader_make_version(abi_versions);
1340        props->info.implVersion = loader_make_version(implementation_version);
1341        strncpy((char *) props->info.description, description, sizeof (props->info.description));
1342        props->info.description[sizeof (props->info.description) - 1] = '\0';
1343        if (is_implicit) {
1344            strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1345            props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1346            strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1347            props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1348        }
1349
1350        /**
1351         * Now get all optional items and objects and put in list:
1352         * functions
1353         * instance_extensions
1354         * device_extensions
1355         * enable_environment (implicit layers only)
1356         */
1357#define GET_JSON_OBJECT(node, var) {                  \
1358        var = cJSON_GetObjectItem(node, #var);        \
1359        }
1360#define GET_JSON_ITEM(node, var) {                    \
1361        item = cJSON_GetObjectItem(node, #var);       \
1362        if (item != NULL)                             \
1363            temp = cJSON_Print(item);                 \
1364        temp[strlen(temp) - 1] = '\0';                \
1365        var = loader_stack_alloc(strlen(temp) + 1);   \
1366        strcpy(var, &temp[1]);                        \
1367        free(temp);                                   \
1368        }
1369
1370        cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
1371        char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *version;
1372        GET_JSON_OBJECT(layer_node, functions)
1373        if (functions != NULL) {
1374            GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1375            GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
1376            strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
1377            props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
1378            strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
1379            props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
1380        }
1381        GET_JSON_OBJECT(layer_node, instance_extensions)
1382        if (instance_extensions != NULL) {
1383            int count = cJSON_GetArraySize(instance_extensions);
1384            for (i = 0; i < count; i++) {
1385                ext_item = cJSON_GetArrayItem(instance_extensions, i);
1386                GET_JSON_ITEM(ext_item, name)
1387                GET_JSON_ITEM(ext_item, version)
1388                strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1389                ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1390                ext_prop.specVersion = loader_make_version(version);
1391                loader_add_to_ext_list(&props->instance_extension_list, 1, &ext_prop);
1392            }
1393        }
1394        GET_JSON_OBJECT(layer_node, device_extensions)
1395        if (device_extensions != NULL) {
1396            int count = cJSON_GetArraySize(device_extensions);
1397            for (i = 0; i < count; i++) {
1398                ext_item = cJSON_GetArrayItem(device_extensions, i);
1399                GET_JSON_ITEM(ext_item, name);
1400                GET_JSON_ITEM(ext_item, version);
1401                strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1402                ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1403                ext_prop.specVersion = loader_make_version(version);
1404                loader_add_to_ext_list(&props->device_extension_list, 1, &ext_prop);
1405            }
1406        }
1407        if (is_implicit) {
1408            GET_JSON_OBJECT(layer_node, enable_environment)
1409            strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1410            props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1411            strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1412            props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1413        }
1414#undef GET_JSON_ITEM
1415#undef GET_JSON_OBJECT
1416        // for global layers need to add them to both device and instance list
1417        if (!strcmp(type, "GLOBAL")) {
1418            struct loader_layer_properties *dev_props;
1419            if (layer_instance_list == NULL || layer_device_list == NULL) {
1420                layer_node = layer_node->next;
1421                continue;
1422            }
1423            dev_props = loader_get_next_layer_property(layer_device_list);
1424            //copy into device layer list
1425            memcpy(dev_props, props, sizeof (*props));
1426        }
1427        layer_node = layer_node->next;
1428    } while (layer_node != NULL);
1429    return;
1430}
1431
1432/**
1433 * Find the Vulkan library manifest files.
1434 *
1435 * This function scans the location or env_override directories/files
1436 * for a list of JSON manifest files.  If env_override is non-NULL
1437 * and has a valid value. Then the location is ignored.  Otherwise
1438 * location is used to look for manifest files. The location
1439 * is interpreted as  Registry path on Windows and a directory path(s)
1440 * on Linux.
1441 *
1442 * \returns
1443 * A string list of manifest files to be opened in out_files param.
1444 * List has a pointer to string for each manifest filename.
1445 * When done using the list in out_files, pointers should be freed.
1446 * Location or override  string lists can be either files or directories as follows:
1447 *            | location | override
1448 * --------------------------------
1449 * Win ICD    | files    | files
1450 * Win Layer  | files    | dirs
1451 * Linux ICD  | dirs     | files
1452 * Linux Layer| dirs     | dirs
1453 */
1454static void loader_get_manifest_files(const char *env_override,
1455                                      bool is_layer,
1456                                      const char *location,
1457                                      struct loader_manifest_files *out_files)
1458{
1459    char *override = NULL;
1460    char *loc;
1461    char *file, *next_file, *name;
1462    size_t alloced_count = 64;
1463    char full_path[2048];
1464    DIR *sysdir = NULL;
1465    bool list_is_dirs = false;
1466    struct dirent *dent;
1467
1468    out_files->count = 0;
1469    out_files->filename_list = NULL;
1470
1471    if (env_override != NULL && (override = getenv(env_override))) {
1472#if defined(__linux__)
1473        if (geteuid() != getuid()) {
1474            /* Don't allow setuid apps to use the env var: */
1475            override = NULL;
1476        }
1477#endif
1478    }
1479
1480    if (location == NULL) {
1481        loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1482            "Can't get manifest files with NULL location, env_override=%s",
1483            env_override);
1484        return;
1485    }
1486
1487#if defined(__linux__)
1488    list_is_dirs = (override == NULL || is_layer) ? true : false;
1489#else //WIN32
1490    list_is_dirs = (is_layer && override != NULL) ? true : false;
1491#endif
1492    // Make a copy of the input we are using so it is not modified
1493    // Also handle getting the location(s) from registry on Windows
1494    if (override == NULL) {
1495        loc = loader_stack_alloc(strlen(location) + 1);
1496        if (loc == NULL) {
1497            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1498            return;
1499        }
1500        strcpy(loc, location);
1501#if defined (_WIN32)
1502        loc = loader_get_registry_files(loc);
1503        if (loc == NULL) {
1504            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1505            return;
1506        }
1507#endif
1508    }
1509    else {
1510        loc = loader_stack_alloc(strlen(override) + 1);
1511        if (loc == NULL) {
1512            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1513            return;
1514        }
1515        strcpy(loc, override);
1516    }
1517
1518    // Print out the paths being searched if debugging is enabled
1519    loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc);
1520
1521    file = loc;
1522    while (*file) {
1523        next_file = loader_get_next_path(file);
1524        if (list_is_dirs) {
1525            sysdir = opendir(file);
1526            name = NULL;
1527            if (sysdir) {
1528                dent = readdir(sysdir);
1529                if (dent == NULL)
1530                    break;
1531                name = &(dent->d_name[0]);
1532                loader_get_fullpath(name, file, sizeof(full_path), full_path);
1533                name = full_path;
1534            }
1535        }
1536        else {
1537#if defined(__linux__)
1538            // only Linux has relative paths
1539            char *dir;
1540            // make a copy of location so it isn't modified
1541            dir = alloca(strlen(location) + 1);
1542            if (dir == NULL) {
1543                loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1544                return;
1545            }
1546            strcpy(dir, location);
1547
1548            loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1549
1550            name = full_path;
1551#else  // WIN32
1552            name = file;
1553#endif
1554        }
1555        while (name) {
1556                /* Look for files ending with ".json" suffix */
1557                uint32_t nlen = (uint32_t) strlen(name);
1558                const char *suf = name + nlen - 5;
1559                if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1560                    if (out_files->count == 0) {
1561                        out_files->filename_list = malloc(alloced_count * sizeof(char *));
1562                    }
1563                    else if (out_files->count == alloced_count) {
1564                        out_files->filename_list = realloc(out_files->filename_list,
1565                                        alloced_count * sizeof(char *) * 2);
1566                        alloced_count *= 2;
1567                    }
1568                    if (out_files->filename_list == NULL) {
1569                        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1570                        return;
1571                    }
1572                    out_files->filename_list[out_files->count] = malloc(strlen(name) + 1);
1573                    if (out_files->filename_list[out_files->count] == NULL) {
1574                        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1575                        return;
1576                    }
1577                    strcpy(out_files->filename_list[out_files->count], name);
1578                    out_files->count++;
1579                } else if (!list_is_dirs) {
1580                    loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name);
1581                }
1582                if (list_is_dirs) {
1583                    dent = readdir(sysdir);
1584                    if (dent == NULL)
1585                        break;
1586                    name = &(dent->d_name[0]);
1587                    loader_get_fullpath(name, file, sizeof(full_path), full_path);
1588                    name = full_path;
1589                }
1590                else {
1591                    break;
1592                }
1593        }
1594        if (sysdir)
1595            closedir(sysdir);
1596        file = next_file;
1597    }
1598    return;
1599}
1600
1601/**
1602 * Try to find the Vulkan ICD driver(s).
1603 *
1604 * This function scans the default system loader path(s) or path
1605 * specified by the \c VK_ICD_FILENAMES environment variable in
1606 * order to find loadable VK ICDs manifest files. From these
1607 * manifest files it finds the ICD libraries.
1608 *
1609 * \returns
1610 * void
1611 */
1612void loader_icd_scan(void)
1613{
1614    char *file_str;
1615    struct loader_manifest_files manifest_files;
1616
1617
1618    // convenient place to initialize a mutex
1619    loader_platform_thread_create_mutex(&loader_lock);
1620
1621    // convenient place to initialize logging
1622    loader_debug_init();
1623
1624    // Get a list of manifest files for ICDs
1625    loader_get_manifest_files("VK_ICD_FILENAMES", false, DEFAULT_VK_DRIVERS_INFO,
1626                              &manifest_files);
1627    if (manifest_files.count == 0)
1628        return;
1629    for (uint32_t i = 0; i < manifest_files.count; i++) {
1630        file_str = manifest_files.filename_list[i];
1631        if (file_str == NULL)
1632            continue;
1633
1634        cJSON *json;
1635        json = loader_get_json(file_str);
1636        cJSON *item;
1637        item = cJSON_GetObjectItem(json, "file_format_version");
1638        if (item == NULL)
1639            return;
1640        char *file_vers = cJSON_Print(item);
1641        loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1642                   file_str, file_vers);
1643        if (strcmp(file_vers, "\"1.0.0\"") != 0)
1644            loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
1645        free(file_vers);
1646        item = cJSON_GetObjectItem(json, "ICD");
1647        if (item != NULL) {
1648            item = cJSON_GetObjectItem(item, "library_path");
1649            if (item != NULL) {
1650                char *icd_filename = cJSON_PrintUnformatted(item);
1651                char *icd_file = icd_filename;
1652                if (icd_filename != NULL) {
1653                    char def_dir[] = DEFAULT_VK_DRIVERS_PATH;
1654                    char *dir = def_dir;
1655
1656                    // Print out the paths being searched if debugging is enabled
1657                    loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s at %s\n", icd_file, dir);
1658
1659                    // strip off extra quotes
1660                    if (icd_filename[strlen(icd_filename)  - 1] == '"')
1661                        icd_filename[strlen(icd_filename) - 1] = '\0';
1662                    if (icd_filename[0] == '"')
1663                        icd_filename++;
1664#if defined(__linux__)
1665                    char full_path[2048];
1666                    loader_get_fullpath(icd_filename, dir, sizeof(full_path), full_path);
1667                    loader_scanned_icd_add(full_path);
1668#else // WIN32
1669                    loader_scanned_icd_add(icd_filename);
1670#endif
1671                    free(icd_file);
1672                }
1673            }
1674            else
1675                loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
1676        }
1677        else
1678            loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1679
1680        free(file_str);
1681        cJSON_Delete(json);
1682    }
1683    free(manifest_files.filename_list);
1684
1685}
1686
1687
1688void loader_layer_scan(struct loader_layer_list *instance_layers, struct loader_layer_list *device_layers)
1689{
1690    char *file_str;
1691    struct loader_manifest_files manifest_files;
1692    cJSON *json;
1693    uint32_t i;
1694
1695    // Get a list of manifest files for layers
1696    loader_get_manifest_files(LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
1697                              &manifest_files);
1698    if (manifest_files.count == 0)
1699        return;
1700
1701#if 0 //TODO
1702    /**
1703     * We need a list of the layer libraries, not just a list of
1704     * the layer properties (a layer library could expose more than
1705     * one layer property). This list of scanned layers would be
1706     * used to check for global and physicaldevice layer properties.
1707     */
1708    if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1709        loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1710                   "Malloc for layer list failed: %s line: %d", __FILE__, __LINE__);
1711        return;
1712    }
1713#endif
1714
1715    /* cleanup any previously scanned libraries */
1716    loader_delete_layer_properties(instance_layers);
1717    loader_delete_layer_properties(device_layers);
1718
1719
1720    for (i = 0; i < manifest_files.count; i++) {
1721        file_str = manifest_files.filename_list[i];
1722        if (file_str == NULL)
1723            continue;
1724
1725        // parse file into JSON struct
1726        json = loader_get_json(file_str);
1727        if (!json) {
1728            continue;
1729        }
1730
1731
1732        //TODO pass in implicit versus explicit bool
1733        //TODO error if device layers expose instance_extensions
1734        //TODO error if instance layers expose device extensions
1735        loader_add_layer_properties(instance_layers,
1736                                    device_layers,
1737                                    json,
1738                                    false,
1739                                    file_str);
1740
1741
1742        free(file_str);
1743        cJSON_Delete(json);
1744    }
1745    free(manifest_files.filename_list);
1746
1747}
1748
1749static PFN_vkVoidFunction VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
1750{
1751    // inst is not wrapped
1752    if (inst == VK_NULL_HANDLE) {
1753        return NULL;
1754    }
1755    VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1756    void *addr;
1757
1758    if (!strcmp(pName, "vkGetInstanceProcAddr"))
1759        return (void *) loader_gpa_instance_internal;
1760
1761    if (disp_table == NULL)
1762        return NULL;
1763
1764    addr = loader_lookup_instance_dispatch_table(disp_table, pName);
1765    if (addr) {
1766        return addr;
1767    }
1768
1769    if (disp_table->GetInstanceProcAddr == NULL) {
1770        return NULL;
1771    }
1772    return disp_table->GetInstanceProcAddr(inst, pName);
1773}
1774
1775struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
1776{
1777
1778    *gpu_index = 0;
1779    for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1780        for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1781            for (uint32_t i = 0; i < icd->gpu_count; i++)
1782                if (icd->gpus[i] == gpu) {
1783                    *gpu_index = i;
1784                    return icd;
1785                }
1786        }
1787    }
1788    return NULL;
1789}
1790
1791static loader_platform_dl_handle loader_add_layer_lib(
1792        const char *chain_type,
1793        struct loader_layer_properties *layer_prop)
1794{
1795    struct loader_lib_info *new_layer_lib_list, *my_lib;
1796
1797    /*
1798     * TODO: We can now track this information in the
1799     * scanned_layer_libraries list.
1800     */
1801    for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
1802        if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_info.lib_name) == 0) {
1803            /* Have already loaded this library, just increment ref count */
1804            loader.loaded_layer_lib_list[i].ref_count++;
1805            loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
1806                       "%s Chain: Increment layer reference count for layer library %s",
1807                       chain_type, layer_prop->lib_info.lib_name);
1808            return loader.loaded_layer_lib_list[i].lib_handle;
1809        }
1810    }
1811
1812    /* Haven't seen this library so load it */
1813    new_layer_lib_list = realloc(loader.loaded_layer_lib_list,
1814                      (loader.loaded_layer_lib_count + 1) * sizeof(struct loader_lib_info));
1815    if (!new_layer_lib_list) {
1816        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1817        return NULL;
1818    }
1819
1820    my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
1821
1822    /* NOTE: We require that the layer property be immutable */
1823    my_lib->lib_name = (char *) layer_prop->lib_info.lib_name;
1824    my_lib->ref_count = 0;
1825    my_lib->lib_handle = NULL;
1826
1827    if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
1828        loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1829                   loader_platform_open_library_error(my_lib->lib_name));
1830        return NULL;
1831    } else {
1832        loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
1833                   "Chain: %s: Loading layer library %s",
1834                   chain_type, layer_prop->lib_info.lib_name);
1835    }
1836    loader.loaded_layer_lib_count++;
1837    loader.loaded_layer_lib_list = new_layer_lib_list;
1838    my_lib->ref_count++;
1839
1840    return my_lib->lib_handle;
1841}
1842
1843static void loader_remove_layer_lib(
1844        struct loader_instance *inst,
1845        struct loader_layer_properties *layer_prop)
1846{
1847    uint32_t idx;
1848    struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
1849
1850    for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
1851        if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_info.lib_name) == 0) {
1852            /* found matching library */
1853            idx = i;
1854            my_lib = &loader.loaded_layer_lib_list[i];
1855            break;
1856        }
1857    }
1858
1859    if (my_lib) {
1860        my_lib->ref_count--;
1861        if (my_lib->ref_count > 0) {
1862            loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
1863                       "Decrement reference count for layer library %s", layer_prop->lib_info.lib_name);
1864            return;
1865        }
1866    }
1867    loader_platform_close_library(my_lib->lib_handle);
1868    loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
1869               "Unloading layer library %s", layer_prop->lib_info.lib_name);
1870
1871    /* Need to remove unused library from list */
1872    new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
1873    if (!new_layer_lib_list) {
1874        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1875        return;
1876    }
1877
1878    if (idx > 0) {
1879        /* Copy records before idx */
1880        memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
1881               sizeof(struct loader_lib_info) * idx);
1882    }
1883    if (idx < (loader.loaded_layer_lib_count - 1)) {
1884        /* Copy records after idx */
1885        memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
1886                sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
1887    }
1888
1889    free(loader.loaded_layer_lib_list);
1890    loader.loaded_layer_lib_count--;
1891    loader.loaded_layer_lib_list = new_layer_lib_list;
1892}
1893
1894
1895/**
1896 * Go through the search_list and find any layers which match type. If layer
1897 * type match is found in then add it to ext_list.
1898 */
1899//TODO need to handle implict layer enable env var and disable env var
1900static void loader_add_layer_implicit(
1901                const enum layer_type type,
1902                struct loader_layer_list *list,
1903                const struct loader_layer_list *search_list)
1904{
1905    uint32_t i;
1906    for (i = 0; i < search_list->count; i++) {
1907        const struct loader_layer_properties *prop = &search_list->list[i];
1908        if (prop->type & type) {
1909            /* Found an layer with the same type, add to layer_list */
1910            loader_add_to_layer_list(list, 1, prop);
1911        }
1912    }
1913
1914}
1915
1916/**
1917 * Get the layer name(s) from the env_name environment variable. If layer
1918 * is found in search_list then add it to layer_list.  But only add it to
1919 * layer_list if type matches.
1920 */
1921static void loader_add_layer_env(
1922                const enum layer_type type,
1923                const char *env_name,
1924                struct loader_layer_list *layer_list,
1925                const struct loader_layer_list *search_list)
1926{
1927    char *layerEnv;
1928    char *next, *name;
1929
1930    layerEnv = getenv(env_name);
1931    if (layerEnv == NULL) {
1932        return;
1933    }
1934    name = loader_stack_alloc(strlen(layerEnv) + 1);
1935    if (name == NULL) {
1936        return;
1937    }
1938    strcpy(name, layerEnv);
1939
1940    while (name && *name ) {
1941        next = loader_get_next_path(name);
1942        loader_find_layer_name_add_list(name, type, search_list, layer_list);
1943        name = next;
1944    }
1945
1946    return;
1947}
1948
1949void loader_deactivate_instance_layers(struct loader_instance *instance)
1950{
1951    if (!instance->activated_layer_list.count) {
1952        return;
1953    }
1954
1955    /* Create instance chain of enabled layers */
1956    for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
1957        struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
1958
1959        loader_remove_layer_lib(instance, layer_prop);
1960    }
1961    loader_destroy_layer_list(&instance->activated_layer_list);
1962}
1963
1964VkResult loader_enable_instance_layers(
1965                    struct loader_instance *inst,
1966                    const VkInstanceCreateInfo *pCreateInfo,
1967                    const struct loader_layer_list *instance_layers)
1968{
1969    VkResult err;
1970
1971    if (inst == NULL)
1972        return VK_ERROR_UNKNOWN;
1973
1974    if (!loader_init_layer_list(&inst->activated_layer_list)) {
1975        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance activated layer list");
1976        return VK_ERROR_OUT_OF_HOST_MEMORY;
1977    }
1978
1979    /* Add any implicit layers first */
1980    loader_add_layer_implicit(
1981                                VK_LAYER_TYPE_INSTANCE_IMPLICIT,
1982                                &inst->activated_layer_list,
1983                                instance_layers);
1984
1985    /* Add any layers specified via environment variable next */
1986    loader_add_layer_env(
1987                            VK_LAYER_TYPE_INSTANCE_EXPLICIT,
1988                            "VK_INSTANCE_LAYERS",
1989                            &inst->activated_layer_list,
1990                            instance_layers);
1991
1992    /* Add layers specified by the application */
1993    err = loader_add_layer_names_to_list(
1994                &inst->activated_layer_list,
1995                pCreateInfo->layerCount,
1996                pCreateInfo->ppEnabledLayerNames,
1997                instance_layers);
1998
1999    return err;
2000}
2001
2002uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2003{
2004    uint32_t layer_idx;
2005    VkBaseLayerObject *wrappedInstance;
2006
2007    if (inst == NULL) {
2008        return 0;
2009    }
2010
2011    // NOTE inst is unwrapped at this point in time
2012    void* baseObj = (void*) inst;
2013    void* nextObj = (void*) inst;
2014    VkBaseLayerObject *nextInstObj;
2015    PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2016
2017    if (!inst->activated_layer_list.count) {
2018        return 0;
2019    }
2020
2021    wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
2022                                   * inst->activated_layer_list.count);
2023    if (!wrappedInstance) {
2024        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance objects for layer");
2025        return 0;
2026    }
2027
2028    /* Create instance chain of enabled layers */
2029    layer_idx = inst->activated_layer_list.count - 1;
2030    for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
2031        struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
2032        loader_platform_dl_handle lib_handle;
2033
2034         /*
2035         * Note: An extension's Get*ProcAddr should not return a function pointer for
2036         * any extension entry points until the extension has been enabled.
2037         * To do this requires a different behavior from Get*ProcAddr functions implemented
2038         * in layers.
2039         * The very first call to a layer will be it's Get*ProcAddr function requesting
2040         * the layer's vkGet*ProcAddr. The layer should intialize it's internal dispatch table
2041         * with the wrapped object given (either Instance or Device) and return the layer's
2042         * Get*ProcAddr function. The layer should also use this opportunity to record the
2043         * baseObject so that it can find the correct local dispatch table on future calls.
2044         * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2045         * will not use a wrapped object and must look up their local dispatch table from
2046         * the given baseObject.
2047         */
2048        nextInstObj = (wrappedInstance + layer_idx);
2049        nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
2050        nextInstObj->baseObject = baseObj;
2051        nextInstObj->nextObject = nextObj;
2052        nextObj = (void*) nextInstObj;
2053
2054        char funcStr[256];
2055        snprintf(funcStr, 256, "%sGetInstanceProcAddr", layer_prop->info.layerName);
2056        lib_handle = loader_add_layer_lib("instance", layer_prop);
2057        if ((nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
2058            nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2059        if (!nextGPA) {
2060            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_info.lib_name);
2061
2062            /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2063            continue;
2064        }
2065
2066        loader_log(VK_DBG_REPORT_INFO_BIT, 0,
2067                   "Insert instance layer %s (%s)",
2068                   layer_prop->info.layerName,
2069                   layer_prop->lib_info.lib_name);
2070
2071        layer_idx--;
2072    }
2073
2074    loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
2075
2076    return inst->activated_layer_list.count;
2077}
2078
2079void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2080{
2081
2082    loader_init_instance_extension_dispatch_table(inst->disp,
2083                                                  inst->disp->GetInstanceProcAddr,
2084                                                  (VkInstance) inst);
2085}
2086
2087static VkResult loader_enable_device_layers(
2088                        struct loader_icd *icd,
2089                        struct loader_device *dev,
2090                        const VkDeviceCreateInfo *pCreateInfo,
2091                        const struct loader_layer_list *device_layers)
2092
2093{
2094    VkResult err;
2095
2096    if (dev == NULL)
2097        return VK_ERROR_UNKNOWN;
2098
2099    if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
2100        loader_init_layer_list(&dev->activated_layer_list);
2101    }
2102
2103    if (dev->activated_layer_list.list == NULL) {
2104        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc device activated layer list");
2105        return VK_ERROR_OUT_OF_HOST_MEMORY;
2106    }
2107
2108    /* Add any implicit layers first */
2109    loader_add_layer_implicit(
2110                VK_LAYER_TYPE_DEVICE_IMPLICIT,
2111                &dev->activated_layer_list,
2112                device_layers);
2113
2114    /* Add any layers specified via environment variable next */
2115    loader_add_layer_env(
2116                VK_LAYER_TYPE_DEVICE_EXPLICIT,
2117                "VK_DEVICE_LAYERS",
2118                &dev->activated_layer_list,
2119                device_layers);
2120
2121    /* Add layers specified by the application */
2122    err = loader_add_layer_names_to_list(
2123                &dev->activated_layer_list,
2124                pCreateInfo->layerCount,
2125                pCreateInfo->ppEnabledLayerNames,
2126                device_layers);
2127
2128    return err;
2129}
2130
2131/*
2132 * This function terminates the device chain for CreateDevice.
2133 * CreateDevice is a special case and so the loader call's
2134 * the ICD's CreateDevice before creating the chain. Since
2135 * we can't call CreateDevice twice we must terminate the
2136 * device chain with something else.
2137 */
2138static VkResult VKAPI scratch_vkCreateDevice(
2139    VkPhysicalDevice          gpu,
2140    const VkDeviceCreateInfo *pCreateInfo,
2141    VkDevice                 *pDevice)
2142{
2143    return VK_SUCCESS;
2144}
2145
2146static PFN_vkVoidFunction VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
2147{
2148    if (!strcmp(name, "vkGetDeviceProcAddr"))
2149        return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
2150    if (!strcmp(name, "vkCreateDevice"))
2151        return (PFN_vkVoidFunction) scratch_vkCreateDevice;
2152
2153    struct loader_device *found_dev;
2154    struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2155    return icd->GetDeviceProcAddr(device, name);
2156}
2157
2158static uint32_t loader_activate_device_layers(
2159        struct loader_device *dev,
2160        VkDevice device)
2161{
2162    if (!dev) {
2163        return 0;
2164    }
2165
2166    /* activate any layer libraries */
2167    void* nextObj = (void*) device;
2168    void* baseObj = nextObj;
2169    VkBaseLayerObject *nextGpuObj;
2170    PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
2171    VkBaseLayerObject *wrappedGpus;
2172
2173    if (!dev->activated_layer_list.count)
2174        return 0;
2175
2176    wrappedGpus = malloc(sizeof (VkBaseLayerObject) * dev->activated_layer_list.count);
2177    if (!wrappedGpus) {
2178        loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Gpu objects for layer");
2179        return 0;
2180    }
2181
2182    for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2183
2184        struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
2185        loader_platform_dl_handle lib_handle;
2186
2187        nextGpuObj = (wrappedGpus + i);
2188        nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
2189        nextGpuObj->baseObject = baseObj;
2190        nextGpuObj->nextObject = nextObj;
2191        nextObj = (void*) nextGpuObj;
2192
2193        char funcStr[256];
2194        snprintf(funcStr, 256, "%sGetDeviceProcAddr", layer_prop->info.layerName);
2195        lib_handle = loader_add_layer_lib("device", layer_prop);
2196        if ((nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
2197            nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2198        if (!nextGPA) {
2199            loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->info.layerName);
2200            continue;
2201        }
2202
2203        loader_log(VK_DBG_REPORT_INFO_BIT, 0,
2204                   "Insert device layer library %s (%s)",
2205                   layer_prop->info.layerName,
2206                   layer_prop->lib_info.lib_name);
2207
2208    }
2209
2210    loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2211            (VkDevice) nextObj, (VkDevice) baseObj);
2212    free(wrappedGpus);
2213
2214    return dev->activated_layer_list.count;
2215}
2216
2217VkResult loader_validate_layers(
2218        const uint32_t                  layer_count,
2219        const char * const             *ppEnabledLayerNames,
2220        struct loader_layer_list       *list)
2221{
2222    struct loader_layer_properties *prop;
2223
2224    for (uint32_t i = 0; i < layer_count; i++) {
2225        prop = loader_get_layer_property(ppEnabledLayerNames[i],
2226                                  list);
2227        if (!prop) {
2228            return VK_ERROR_INVALID_LAYER;
2229        }
2230    }
2231
2232    return VK_SUCCESS;
2233}
2234
2235VkResult loader_validate_instance_extensions(
2236                        const struct loader_extension_list *icd_exts,
2237                        const struct loader_layer_list *instance_layer,
2238                        const VkInstanceCreateInfo     *pCreateInfo)
2239{
2240    VkExtensionProperties *extension_prop;
2241    struct loader_layer_properties *layer_prop;
2242
2243    for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2244        extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2245                                                icd_exts);
2246
2247        if (extension_prop) {
2248            continue;
2249        }
2250
2251        extension_prop = NULL;
2252
2253        /* Not in global list, search layer extension lists */
2254        for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2255            layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
2256                                            instance_layer);
2257            if (!layer_prop) {
2258                /* Should NOT get here, loader_validate_layers
2259                 * should have already filtered this case out.
2260                 */
2261                continue;
2262            }
2263
2264            extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2265                                          &layer_prop->instance_extension_list);
2266            if (extension_prop) {
2267                /* Found the extension in one of the layers enabled by the app. */
2268                break;
2269            }
2270        }
2271
2272        if (!extension_prop) {
2273            /* Didn't find extension name in any of the global layers, error out */
2274            return VK_ERROR_INVALID_EXTENSION;
2275        }
2276    }
2277    return VK_SUCCESS;
2278}
2279
2280VkResult loader_validate_device_extensions(
2281                                struct loader_icd *icd,
2282                                uint32_t gpu_index,
2283                                const struct loader_layer_list *device_layer,
2284                                const VkDeviceCreateInfo *pCreateInfo)
2285{
2286    VkExtensionProperties *extension_prop;
2287    struct loader_layer_properties *layer_prop;
2288
2289    for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2290        const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2291        extension_prop = get_extension_property(extension_name,
2292                                                &icd->device_extension_cache[gpu_index]);
2293
2294        if (extension_prop) {
2295            continue;
2296        }
2297
2298        /* Not in global list, search layer extension lists */
2299        for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2300            const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
2301            layer_prop = loader_get_layer_property(layer_name,
2302                                  device_layer);
2303
2304            if (!layer_prop) {
2305                /* Should NOT get here, loader_validate_instance_layers
2306                 * should have already filtered this case out.
2307                 */
2308                continue;
2309            }
2310
2311            extension_prop = get_extension_property(extension_name,
2312                                          &layer_prop->device_extension_list);
2313            if (extension_prop) {
2314                /* Found the extension in one of the layers enabled by the app. */
2315                break;
2316            }
2317        }
2318
2319        if (!extension_prop) {
2320            /* Didn't find extension name in any of the device layers, error out */
2321            return VK_ERROR_INVALID_EXTENSION;
2322        }
2323    }
2324    return VK_SUCCESS;
2325}
2326
2327VkResult VKAPI loader_CreateInstance(
2328        const VkInstanceCreateInfo*     pCreateInfo,
2329        VkInstance*                     pInstance)
2330{
2331    struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
2332    struct loader_scanned_icds *scanned_icds;
2333    struct loader_icd *icd;
2334    VkExtensionProperties *prop;
2335    char **filtered_extension_names = NULL;
2336    VkInstanceCreateInfo icd_create_info;
2337    VkResult res = VK_SUCCESS;
2338    bool success;
2339
2340    icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2341    icd_create_info.layerCount = 0;
2342    icd_create_info.ppEnabledLayerNames = NULL;
2343    icd_create_info.pAllocCb = pCreateInfo->pAllocCb;
2344    icd_create_info.pAppInfo = pCreateInfo->pAppInfo;
2345    icd_create_info.pNext = pCreateInfo->pNext;
2346
2347    /*
2348     * NOTE: Need to filter the extensions to only those
2349     * supported by the ICD.
2350     * No ICD will advertise support for layers. An ICD
2351     * library could support a layer, but it would be
2352     * independent of the actual ICD, just in the same library.
2353     */
2354    filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2355    if (!filtered_extension_names) {
2356        return VK_ERROR_OUT_OF_HOST_MEMORY;
2357    }
2358    icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2359
2360    scanned_icds = loader.scanned_icd_list;
2361    while (scanned_icds) {
2362        icd = loader_icd_add(ptr_instance, scanned_icds);
2363        if (icd) {
2364            icd_create_info.extensionCount = 0;
2365            for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2366                prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2367                                              &ptr_instance->ext_list);
2368                if (prop) {
2369                    filtered_extension_names[icd_create_info.extensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2370                    icd_create_info.extensionCount++;
2371                }
2372            }
2373
2374            res = scanned_icds->CreateInstance(&icd_create_info,
2375                                           &(icd->instance));
2376            success = loader_icd_init_entrys(
2377                                icd,
2378                                icd->instance,
2379                                scanned_icds->GetInstanceProcAddr);
2380
2381            if (res != VK_SUCCESS || !success)
2382            {
2383                ptr_instance->icds = ptr_instance->icds->next;
2384                loader_icd_destroy(ptr_instance, icd);
2385                icd->instance = VK_NULL_HANDLE;
2386                loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2387                        "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
2388            }
2389        }
2390        scanned_icds = scanned_icds->next;
2391    }
2392
2393    /*
2394     * If no ICDs were added to instance list and res is unchanged
2395     * from it's initial value, the loader was unable to find
2396     * a suitable ICD.
2397     */
2398    if (ptr_instance->icds == NULL) {
2399        if (res == VK_SUCCESS) {
2400            return VK_ERROR_INCOMPATIBLE_DRIVER;
2401        } else {
2402            return res;
2403        }
2404    }
2405
2406    return VK_SUCCESS;
2407}
2408
2409VkResult VKAPI loader_DestroyInstance(
2410        VkInstance                                instance)
2411{
2412    struct loader_instance *ptr_instance = loader_instance(instance);
2413    struct loader_icd *icds = ptr_instance->icds;
2414    struct loader_icd *next_icd;
2415    VkResult res;
2416
2417    // Remove this instance from the list of instances:
2418    struct loader_instance *prev = NULL;
2419    struct loader_instance *next = loader.instances;
2420    while (next != NULL) {
2421        if (next == ptr_instance) {
2422            // Remove this instance from the list:
2423            if (prev)
2424                prev->next = next->next;
2425            else
2426                loader.instances = next->next;
2427            break;
2428        }
2429        prev = next;
2430        next = next->next;
2431    }
2432    if (next  == NULL) {
2433        // This must be an invalid instance handle or empty list
2434        return VK_ERROR_INVALID_HANDLE;
2435    }
2436
2437    while (icds) {
2438        if (icds->instance) {
2439            res = icds->DestroyInstance(icds->instance);
2440            if (res != VK_SUCCESS)
2441                loader_log(VK_DBG_REPORT_WARN_BIT, 0,
2442                            "ICD ignored: failed to DestroyInstance on device");
2443        }
2444        next_icd = icds->next;
2445        icds->instance = VK_NULL_HANDLE;
2446        loader_icd_destroy(ptr_instance, icds);
2447
2448        icds = next_icd;
2449    }
2450
2451
2452    loader_destroy_ext_list(&ptr_instance->ext_list);
2453    return VK_SUCCESS;
2454}
2455
2456VkResult loader_init_physical_device_info(
2457        struct loader_instance *ptr_instance)
2458{
2459    struct loader_icd *icd;
2460    uint32_t n, count = 0;
2461    VkResult res = VK_ERROR_UNKNOWN;
2462
2463    icd = ptr_instance->icds;
2464    while (icd) {
2465        res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
2466        if (res != VK_SUCCESS)
2467            return res;
2468        icd->gpu_count = n;
2469        count += n;
2470        icd = icd->next;
2471    }
2472
2473    ptr_instance->total_gpu_count = count;
2474
2475    icd = ptr_instance->icds;
2476    while (icd) {
2477
2478        n = icd->gpu_count;
2479        icd->gpus = (VkPhysicalDevice *) malloc(n * sizeof(VkPhysicalDevice));
2480        if (!icd->gpus) {
2481            /* TODO: Add cleanup code here */
2482            return VK_ERROR_OUT_OF_HOST_MEMORY;
2483        }
2484        res = icd->EnumeratePhysicalDevices(
2485                                        icd->instance,
2486                                        &n,
2487                                        icd->gpus);
2488        if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
2489
2490            for (unsigned int i = 0; i < n; i++) {
2491
2492                loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
2493
2494                if (!loader_init_ext_list(&icd->device_extension_cache[i])) {
2495                    /* TODO: Add cleanup code here */
2496                    res = VK_ERROR_OUT_OF_HOST_MEMORY;
2497                }
2498                if (res == VK_SUCCESS) {
2499
2500                    loader_add_physical_device_extensions(
2501                                icd->GetPhysicalDeviceExtensionProperties,
2502                                icd->gpus[0],
2503                                icd->scanned_icds->lib_name,
2504                                &icd->device_extension_cache[i]);
2505
2506                }
2507
2508                if (res != VK_SUCCESS) {
2509                    /* clean up any extension lists previously created before this request failed */
2510                    for (uint32_t j = 0; j < i; j++) {
2511                        loader_destroy_ext_list(&icd->device_extension_cache[i]);
2512                    }
2513
2514                    return res;
2515                }
2516            }
2517
2518            count += n;
2519        }
2520
2521        icd = icd->next;
2522    }
2523
2524    return VK_SUCCESS;
2525}
2526
2527VkResult VKAPI loader_EnumeratePhysicalDevices(
2528        VkInstance                              instance,
2529        uint32_t*                               pPhysicalDeviceCount,
2530        VkPhysicalDevice*                       pPhysicalDevices)
2531{
2532    uint32_t index = 0;
2533    struct loader_instance *ptr_instance = (struct loader_instance *) instance;
2534    struct loader_icd *icd = ptr_instance->icds;
2535
2536    if (ptr_instance->total_gpu_count == 0) {
2537        loader_init_physical_device_info(ptr_instance);
2538    }
2539
2540    *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2541    if (!pPhysicalDevices) {
2542        return VK_SUCCESS;
2543    }
2544
2545    while (icd) {
2546        assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
2547        memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
2548        index += icd->gpu_count;
2549        icd = icd->next;
2550    }
2551
2552    return VK_SUCCESS;
2553}
2554
2555VkResult VKAPI loader_GetPhysicalDeviceProperties(
2556        VkPhysicalDevice                        gpu,
2557        VkPhysicalDeviceProperties*             pProperties)
2558{
2559    uint32_t gpu_index;
2560    struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2561    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2562
2563    if (icd->GetPhysicalDeviceProperties)
2564        res = icd->GetPhysicalDeviceProperties(gpu, pProperties);
2565
2566    return res;
2567}
2568
2569VkResult VKAPI loader_GetPhysicalDeviceQueueFamilyProperties (
2570        VkPhysicalDevice                        gpu,
2571        uint32_t*                               pCount,
2572        VkQueueFamilyProperties*                pProperties)
2573{
2574    uint32_t gpu_index;
2575    struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2576    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2577
2578    if (icd->GetPhysicalDeviceQueueFamilyProperties)
2579        res = icd->GetPhysicalDeviceQueueFamilyProperties(gpu, pCount, pProperties);
2580
2581    return res;
2582}
2583
2584VkResult VKAPI loader_GetPhysicalDeviceMemoryProperties (
2585        VkPhysicalDevice gpu,
2586        VkPhysicalDeviceMemoryProperties* pProperties)
2587{
2588    uint32_t gpu_index;
2589    struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2590    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2591
2592    if (icd->GetPhysicalDeviceMemoryProperties)
2593        res = icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
2594
2595    return res;
2596}
2597
2598VkResult VKAPI loader_GetPhysicalDeviceFeatures(
2599        VkPhysicalDevice                        physicalDevice,
2600        VkPhysicalDeviceFeatures*               pFeatures)
2601{
2602    uint32_t gpu_index;
2603    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2604    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2605
2606    if (icd->GetPhysicalDeviceFeatures)
2607        res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
2608
2609    return res;
2610}
2611
2612VkResult VKAPI loader_GetPhysicalDeviceFormatProperties(
2613        VkPhysicalDevice                        physicalDevice,
2614        VkFormat                                format,
2615        VkFormatProperties*                     pFormatInfo)
2616{
2617    uint32_t gpu_index;
2618    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2619    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2620
2621    if (icd->GetPhysicalDeviceFormatProperties)
2622        res = icd->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatInfo);
2623
2624    return res;
2625}
2626
2627VkResult VKAPI loader_GetPhysicalDeviceImageFormatProperties(
2628        VkPhysicalDevice                        physicalDevice,
2629        VkFormat                                format,
2630        VkImageType                             type,
2631        VkImageTiling                           tiling,
2632        VkImageUsageFlags                       usage,
2633        VkImageFormatProperties*                pImageFormatProperties)
2634{
2635    uint32_t gpu_index;
2636    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2637    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2638
2639    if (icd->GetPhysicalDeviceImageFormatProperties)
2640        res = icd->GetPhysicalDeviceImageFormatProperties(physicalDevice, format,
2641                                type, tiling, usage, pImageFormatProperties);
2642
2643    return res;
2644}
2645
2646VkResult VKAPI loader_GetPhysicalDeviceLimits(
2647        VkPhysicalDevice                        physicalDevice,
2648        VkPhysicalDeviceLimits*                 pLimits)
2649{
2650    uint32_t gpu_index;
2651    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2652    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2653
2654    if (icd->GetPhysicalDeviceLimits)
2655        res = icd->GetPhysicalDeviceLimits(physicalDevice, pLimits);
2656
2657    return res;
2658}
2659
2660VkResult VKAPI loader_GetPhysicalDeviceSparseImageFormatProperties(
2661        VkPhysicalDevice                        physicalDevice,
2662        VkFormat                                format,
2663        VkImageType                             type,
2664        uint32_t                                samples,
2665        VkImageUsageFlags                       usage,
2666        VkImageTiling                           tiling,
2667        uint32_t*                               pNumProperties,
2668        VkSparseImageFormatProperties*          pProperties)
2669{
2670    uint32_t gpu_index;
2671    struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2672    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2673
2674    if (icd->GetPhysicalDeviceSparseImageFormatProperties)
2675        res = icd->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pNumProperties, pProperties);
2676
2677    return res;
2678}
2679
2680VkResult VKAPI loader_CreateDevice(
2681        VkPhysicalDevice                        gpu,
2682        const VkDeviceCreateInfo*               pCreateInfo,
2683        VkDevice*                               pDevice)
2684{
2685    uint32_t gpu_index;
2686    struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2687    struct loader_device *dev;
2688    VkDeviceCreateInfo device_create_info;
2689    char **filtered_extension_names = NULL;
2690    VkResult res;
2691    struct loader_layer_list device_layer_list;
2692
2693    if (!icd->CreateDevice) {
2694        return VK_ERROR_INITIALIZATION_FAILED;
2695    }
2696
2697    /* Due to implicit layers might still need to get layer list even if
2698     * layerCount == 0 and VK_DEVICE_LAYERS is unset. For now always
2699     * get layer list via loader_layer_scan(). */
2700    memset(&device_layer_list, 0, sizeof(device_layer_list));
2701    loader_layer_scan(NULL, &device_layer_list);
2702
2703    /* validate any app enabled layers are available */
2704    if (pCreateInfo->layerCount > 0) {
2705        res = loader_validate_layers(pCreateInfo->layerCount,
2706                pCreateInfo->ppEnabledLayerNames,
2707                &device_layer_list);
2708        if (res != VK_SUCCESS) {
2709            return res;
2710        }
2711    }
2712
2713    res = loader_validate_device_extensions(icd, gpu_index, &device_layer_list, pCreateInfo);
2714    if (res != VK_SUCCESS) {
2715        return res;
2716    }
2717
2718    /*
2719     * NOTE: Need to filter the extensions to only those
2720     * supported by the ICD.
2721     * No ICD will advertise support for layers. An ICD
2722     * library could support a layer, but it would be
2723     * independent of the actual ICD, just in the same library.
2724     */
2725    filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2726    if (!filtered_extension_names) {
2727        return VK_ERROR_OUT_OF_HOST_MEMORY;
2728    }
2729
2730    /* Copy user's data */
2731    memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
2732
2733    /* ICD's do not use layers */
2734    device_create_info.layerCount = 0;
2735    device_create_info.ppEnabledLayerNames = NULL;
2736
2737    device_create_info.extensionCount = 0;
2738    device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2739
2740    for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2741        const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2742        VkExtensionProperties *prop = get_extension_property(extension_name,
2743                                      &icd->device_extension_cache[gpu_index]);
2744        if (prop) {
2745            filtered_extension_names[device_create_info.extensionCount] = (char *) extension_name;
2746            device_create_info.extensionCount++;
2747        }
2748    }
2749
2750    res = icd->CreateDevice(gpu, pCreateInfo, pDevice);
2751    if (res != VK_SUCCESS) {
2752        return res;
2753    }
2754
2755    dev = loader_add_logical_device(*pDevice, &icd->logical_device_list);
2756    if (dev == NULL) {
2757        return VK_ERROR_OUT_OF_HOST_MEMORY;
2758    }
2759    PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
2760    loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
2761                                      *pDevice, *pDevice);
2762
2763    dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
2764    loader_init_dispatch(*pDevice, &dev->loader_dispatch);
2765
2766    /* activate any layers on device chain which terminates with device*/
2767    res = loader_enable_device_layers(icd, dev, pCreateInfo, &device_layer_list);
2768    if (res != VK_SUCCESS) {
2769        loader_destroy_logical_device(dev);
2770        return res;
2771    }
2772    loader_activate_device_layers(dev, *pDevice);
2773
2774    res = dev->loader_dispatch.CreateDevice(gpu, pCreateInfo, pDevice);
2775
2776    dev->loader_dispatch.CreateDevice = icd->CreateDevice;
2777
2778    return res;
2779}
2780
2781static PFN_vkVoidFunction VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName)
2782{
2783    if (instance == VK_NULL_HANDLE)
2784        return NULL;
2785
2786    void *addr;
2787    /* get entrypoint addresses that are global (in the loader)*/
2788    addr = globalGetProcAddr(pName);
2789    if (addr)
2790        return addr;
2791
2792    struct loader_instance *ptr_instance = (struct loader_instance *) instance;
2793
2794    /* return any extension global entrypoints */
2795    addr = debug_report_instance_gpa(ptr_instance, pName);
2796    if (addr) {
2797        return addr;
2798    }
2799
2800    addr = wsi_swapchain_GetInstanceProcAddr(ptr_instance, pName);
2801    if (addr) {
2802        return addr;
2803    }
2804
2805    /* return the instance dispatch table entrypoint for extensions */
2806    const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
2807    if (disp_table == NULL)
2808        return NULL;
2809
2810    addr = loader_lookup_instance_dispatch_table(disp_table, pName);
2811    if (addr)
2812        return addr;
2813
2814    return NULL;
2815}
2816
2817LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
2818{
2819    return loader_GetInstanceProcAddr(instance, pName);
2820}
2821
2822static PFN_vkVoidFunction VKAPI loader_GetDeviceProcAddr(VkDevice device, const char * pName)
2823{
2824    if (device == VK_NULL_HANDLE) {
2825        return NULL;
2826    }
2827
2828    void *addr;
2829
2830    /* for entrypoints that loader must handle (ie non-dispatchable or create object)
2831       make sure the loader entrypoint is returned */
2832    addr = loader_non_passthrough_gpa(pName);
2833    if (addr) {
2834        return addr;
2835    }
2836
2837    /* return the dispatch table entrypoint for the fastest case */
2838    const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
2839    if (disp_table == NULL)
2840        return NULL;
2841
2842    addr = loader_lookup_device_dispatch_table(disp_table, pName);
2843    if (addr)
2844        return addr;
2845    else  {
2846        if (disp_table->GetDeviceProcAddr == NULL)
2847            return NULL;
2848        return disp_table->GetDeviceProcAddr(device, pName);
2849    }
2850}
2851
2852LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
2853{
2854    return loader_GetDeviceProcAddr(device, pName);
2855}
2856
2857LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionProperties(
2858    const char*                                 pLayerName,
2859    uint32_t*                                   pCount,
2860    VkExtensionProperties*                      pProperties)
2861{
2862    struct loader_extension_list *global_ext_list;
2863    struct loader_layer_list instance_layers;
2864    struct loader_extension_list icd_extensions;
2865    uint32_t copy_size;
2866
2867    if (pCount == NULL) {
2868        return VK_ERROR_INVALID_POINTER;
2869    }
2870
2871    memset(&icd_extensions, 0, sizeof(icd_extensions));
2872    /* Scan/discover all ICD libraries in a single-threaded manner */
2873    loader_platform_thread_once(&once_icd, loader_icd_scan);
2874
2875    //TODO do we still need to lock? for loader.global_extensions
2876    loader_platform_thread_lock_mutex(&loader_lock);
2877    /* get layer libraries if needed */
2878    if (pLayerName && strlen(pLayerName) != 0) {
2879        memset(&instance_layers, 0, sizeof(instance_layers));
2880        loader_layer_scan(&instance_layers, NULL);
2881        for (uint32_t i = 0; i < instance_layers.count; i++) {
2882            struct loader_layer_properties *props = &instance_layers.list[i];
2883            if (strcmp(props->info.layerName, pLayerName) == 0) {
2884               global_ext_list = &props->instance_extension_list;
2885            }
2886        }
2887    }
2888    else {
2889        /* get extensions from all ICD's, merge so no duplicates */
2890        loader_get_icd_loader_instance_extensions(&icd_extensions);
2891        global_ext_list = &icd_extensions;
2892    }
2893
2894    if (global_ext_list == NULL) {
2895        loader_platform_thread_unlock_mutex(&loader_lock);
2896        return VK_ERROR_INVALID_LAYER;
2897    }
2898
2899    if (pProperties == NULL) {
2900        *pCount = global_ext_list->count;
2901        loader_destroy_ext_list(&icd_extensions);
2902        loader_platform_thread_unlock_mutex(&loader_lock);
2903        return VK_SUCCESS;
2904    }
2905
2906    copy_size = *pCount < global_ext_list->count ? *pCount : global_ext_list->count;
2907    for (uint32_t i = 0; i < copy_size; i++) {
2908        memcpy(&pProperties[i],
2909               &global_ext_list->list[i],
2910               sizeof(VkExtensionProperties));
2911    }
2912    *pCount = copy_size;
2913    loader_destroy_ext_list(&icd_extensions);
2914    loader_platform_thread_unlock_mutex(&loader_lock);
2915
2916    if (copy_size < global_ext_list->count) {
2917        return VK_INCOMPLETE;
2918    }
2919
2920    return VK_SUCCESS;
2921}
2922
2923LOADER_EXPORT VkResult VKAPI vkGetGlobalLayerProperties(
2924    uint32_t*                                   pCount,
2925    VkLayerProperties*                          pProperties)
2926{
2927
2928    struct loader_layer_list instance_layer_list;
2929
2930    /* Scan/discover all ICD libraries in a single-threaded manner */
2931    loader_platform_thread_once(&once_icd, loader_icd_scan);
2932
2933    uint32_t copy_size;
2934
2935    if (pCount == NULL) {
2936        return VK_ERROR_INVALID_POINTER;
2937    }
2938
2939    /* TODO: do we still need to lock */
2940    loader_platform_thread_lock_mutex(&loader_lock);
2941
2942    /* get layer libraries */
2943    memset(&instance_layer_list, 0, sizeof(instance_layer_list));
2944    loader_layer_scan(&instance_layer_list, NULL);
2945
2946    if (pProperties == NULL) {
2947        *pCount = instance_layer_list.count;
2948        loader_platform_thread_unlock_mutex(&loader_lock);
2949        return VK_SUCCESS;
2950    }
2951
2952    copy_size = (*pCount < instance_layer_list.count) ? *pCount : instance_layer_list.count;
2953    for (uint32_t i = 0; i < copy_size; i++) {
2954        memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
2955    }
2956    *pCount = copy_size;
2957
2958    loader_platform_thread_unlock_mutex(&loader_lock);
2959
2960    if (copy_size < instance_layer_list.count) {
2961        return VK_INCOMPLETE;
2962    }
2963
2964    return VK_SUCCESS;
2965}
2966
2967VkResult VKAPI loader_GetPhysicalDeviceExtensionProperties(
2968        VkPhysicalDevice                        gpu,
2969        const char*                             pLayerName,
2970        uint32_t*                               pCount,
2971        VkExtensionProperties*                  pProperties)
2972{
2973    uint32_t gpu_index;
2974    struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2975    uint32_t copy_size;
2976    struct loader_layer_list device_layers;
2977
2978    if (pCount == NULL) {
2979        return VK_ERROR_INVALID_POINTER;
2980    }
2981
2982    uint32_t count;
2983    struct loader_extension_list *dev_ext_list;
2984
2985    /* get layer libraries if needed */
2986    if (pLayerName && strlen(pLayerName) != 0) {
2987        memset(&device_layers, 0, sizeof(device_layers));
2988        loader_layer_scan(NULL, &device_layers);
2989        for (uint32_t i = 0; i < device_layers.count; i++) {
2990            struct loader_layer_properties *props = &device_layers.list[i];
2991            if (strcmp(props->info.layerName, pLayerName) == 0) {
2992               dev_ext_list = &props->device_extension_list;
2993            }
2994        }
2995    }
2996    else {
2997        dev_ext_list = &icd->device_extension_cache[gpu_index];
2998    }
2999
3000    count = dev_ext_list->count;
3001    if (pProperties == NULL) {
3002        *pCount = count;
3003        return VK_SUCCESS;
3004    }
3005
3006    copy_size = *pCount < count ? *pCount : count;
3007    for (uint32_t i = 0; i < copy_size; i++) {
3008        memcpy(&pProperties[i],
3009               &dev_ext_list->list[i],
3010               sizeof(VkExtensionProperties));
3011    }
3012    *pCount = copy_size;
3013
3014    if (copy_size < count) {
3015        return VK_INCOMPLETE;
3016    }
3017
3018    return VK_SUCCESS;
3019}
3020
3021VkResult VKAPI loader_GetPhysicalDeviceLayerProperties(
3022        VkPhysicalDevice                        gpu,
3023        uint32_t*                               pCount,
3024        VkLayerProperties*                      pProperties)
3025{
3026    uint32_t copy_size;
3027    struct loader_layer_list device_layers;
3028
3029    if (pCount == NULL) {
3030        return VK_ERROR_INVALID_POINTER;
3031    }
3032
3033    /* get layer libraries */
3034    memset(&device_layers, 0, sizeof(struct loader_layer_list));
3035    loader_layer_scan(NULL, &device_layers);
3036
3037    uint32_t count = device_layers.count;
3038
3039    if (pProperties == NULL) {
3040        *pCount = count;
3041        return VK_SUCCESS;
3042    }
3043
3044    copy_size = (*pCount < count) ? *pCount : count;
3045    for (uint32_t i = 0; i < copy_size; i++) {
3046        memcpy(&pProperties[i], &(device_layers.list[i].info), sizeof(VkLayerProperties));
3047    }
3048    *pCount = copy_size;
3049
3050    if (copy_size < count) {
3051        return VK_INCOMPLETE;
3052    }
3053
3054    return VK_SUCCESS;
3055}
3056