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