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