trampoline.c revision 7a5e4c7b7aa31bb361d14525586407d173f6dac9
1/*
2 *
3 * Copyright (c) 2015-2016 The Khronos Group Inc.
4 * Copyright (c) 2015-2016 Valve Corporation
5 * Copyright (c) 2015-2016 LunarG, Inc.
6 * Copyright (C) 2015 Google Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *     http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 * Author: Courtney Goeltzenleuchter <courtney@lunarg.com>
21 * Author: Jon Ashburn <jon@lunarg.com>
22 * Author: Tony Barbour <tony@LunarG.com>
23 * Author: Chia-I Wu <olv@lunarg.com>
24 */
25#define _GNU_SOURCE
26#include <stdlib.h>
27#include <string.h>
28
29#include "vk_loader_platform.h"
30#include "loader.h"
31#include "debug_report.h"
32#include "wsi.h"
33#include "gpa_helper.h"
34#include "table_ops.h"
35
36/* Trampoline entrypoints are in this file for core Vulkan commands */
37/**
38 * Get an instance level or global level entry point address.
39 * @param instance
40 * @param pName
41 * @return
42 *    If instance == NULL returns a global level functions only
43 *    If instance is valid returns a trampoline entry point for all dispatchable
44 * Vulkan
45 *    functions both core and extensions.
46 */
47LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
48vkGetInstanceProcAddr(VkInstance instance, const char *pName) {
49
50    void *addr;
51
52    addr = globalGetProcAddr(pName);
53    if (instance == VK_NULL_HANDLE) {
54        // get entrypoint addresses that are global (no dispatchable object)
55
56        return addr;
57    } else {
58        // if a global entrypoint return NULL
59        if (addr)
60            return NULL;
61    }
62
63    struct loader_instance *ptr_instance = loader_get_instance(instance);
64    if (ptr_instance == NULL)
65        return NULL;
66    // Return trampoline code for non-global entrypoints including any
67    // extensions.
68    // Device extensions are returned if a layer or ICD supports the extension.
69    // Instance extensions are returned if the extension is enabled and the
70    // loader
71    // or someone else supports the extension
72    return trampolineGetProcAddr(ptr_instance, pName);
73}
74
75/**
76 * Get a device level or global level entry point address.
77 * @param device
78 * @param pName
79 * @return
80 *    If device is valid, returns a device relative entry point for device level
81 *    entry points both core and extensions.
82 *    Device relative means call down the device chain.
83 */
84LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
85vkGetDeviceProcAddr(VkDevice device, const char *pName) {
86    void *addr;
87
88    /* for entrypoints that loader must handle (ie non-dispatchable or create
89       object)
90       make sure the loader entrypoint is returned */
91    addr = loader_non_passthrough_gdpa(pName);
92    if (addr) {
93        return addr;
94    }
95
96    /* Although CreateDevice is on device chain it's dispatchable object isn't
97     * a VkDevice or child of VkDevice so return NULL.
98     */
99    if (!strcmp(pName, "CreateDevice"))
100        return NULL;
101
102    /* return the dispatch table entrypoint for the fastest case */
103    const VkLayerDispatchTable *disp_table = *(VkLayerDispatchTable **)device;
104    if (disp_table == NULL)
105        return NULL;
106
107    addr = loader_lookup_device_dispatch_table(disp_table, pName);
108    if (addr)
109        return addr;
110
111    if (disp_table->GetDeviceProcAddr == NULL)
112        return NULL;
113    return disp_table->GetDeviceProcAddr(device, pName);
114}
115
116LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
117vkEnumerateInstanceExtensionProperties(const char *pLayerName,
118                                       uint32_t *pPropertyCount,
119                                       VkExtensionProperties *pProperties) {
120    struct loader_extension_list *global_ext_list = NULL;
121    struct loader_layer_list instance_layers;
122    struct loader_extension_list local_ext_list;
123    struct loader_icd_libs icd_libs;
124    uint32_t copy_size;
125
126    tls_instance = NULL;
127    memset(&local_ext_list, 0, sizeof(local_ext_list));
128    memset(&instance_layers, 0, sizeof(instance_layers));
129    loader_platform_thread_once(&once_init, loader_initialize);
130
131    /* get layer libraries if needed */
132    if (pLayerName && strlen(pLayerName) != 0) {
133        if (vk_string_validate(MaxLoaderStringLength, pLayerName) !=
134            VK_STRING_ERROR_NONE) {
135            assert(VK_FALSE && "vkEnumerateInstanceExtensionProperties:  "
136                               "pLayerName is too long or is badly formed");
137            return VK_ERROR_EXTENSION_NOT_PRESENT;
138        }
139
140        loader_layer_scan(NULL, &instance_layers);
141        if (strcmp(pLayerName, std_validation_str) == 0) {
142            struct loader_layer_list local_list;
143            memset(&local_list, 0, sizeof(local_list));
144            for (uint32_t i = 0; i < sizeof(std_validation_names) /
145                                         sizeof(std_validation_names[0]);
146                 i++) {
147                loader_find_layer_name_add_list(NULL, std_validation_names[i],
148                                                VK_LAYER_TYPE_INSTANCE_EXPLICIT,
149                                                &instance_layers, &local_list);
150            }
151            for (uint32_t i = 0; i < local_list.count; i++) {
152                struct loader_extension_list *ext_list =
153                    &local_list.list[i].instance_extension_list;
154                loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count,
155                                       ext_list->list);
156            }
157            loader_destroy_layer_list(NULL, &local_list);
158            global_ext_list = &local_ext_list;
159
160        } else {
161            for (uint32_t i = 0; i < instance_layers.count; i++) {
162                struct loader_layer_properties *props =
163                    &instance_layers.list[i];
164                if (strcmp(props->info.layerName, pLayerName) == 0) {
165                    global_ext_list = &props->instance_extension_list;
166                    break;
167                }
168            }
169        }
170    } else {
171        /* Scan/discover all ICD libraries */
172        memset(&icd_libs, 0, sizeof(struct loader_icd_libs));
173        loader_icd_scan(NULL, &icd_libs);
174        /* get extensions from all ICD's, merge so no duplicates */
175        loader_get_icd_loader_instance_extensions(NULL, &icd_libs,
176                                                  &local_ext_list);
177        loader_scanned_icd_clear(NULL, &icd_libs);
178
179        // Append implicit layers.
180        loader_implicit_layer_scan(NULL, &instance_layers);
181        for (uint32_t i = 0; i < instance_layers.count; i++) {
182            struct loader_extension_list *ext_list =
183                &instance_layers.list[i].instance_extension_list;
184            loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count,
185                                   ext_list->list);
186        }
187
188        global_ext_list = &local_ext_list;
189    }
190
191    if (global_ext_list == NULL) {
192        loader_destroy_layer_list(NULL, &instance_layers);
193        return VK_ERROR_LAYER_NOT_PRESENT;
194    }
195
196    if (pProperties == NULL) {
197        *pPropertyCount = global_ext_list->count;
198        loader_destroy_layer_list(NULL, &instance_layers);
199        loader_destroy_generic_list(
200            NULL, (struct loader_generic_list *)&local_ext_list);
201        return VK_SUCCESS;
202    }
203
204    copy_size = *pPropertyCount < global_ext_list->count
205                    ? *pPropertyCount
206                    : global_ext_list->count;
207    for (uint32_t i = 0; i < copy_size; i++) {
208        memcpy(&pProperties[i], &global_ext_list->list[i],
209               sizeof(VkExtensionProperties));
210    }
211    *pPropertyCount = copy_size;
212    loader_destroy_generic_list(NULL,
213                                (struct loader_generic_list *)&local_ext_list);
214
215    if (copy_size < global_ext_list->count) {
216        loader_destroy_layer_list(NULL, &instance_layers);
217        return VK_INCOMPLETE;
218    }
219
220    loader_destroy_layer_list(NULL, &instance_layers);
221    return VK_SUCCESS;
222}
223
224LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
225vkEnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
226                                   VkLayerProperties *pProperties) {
227
228    struct loader_layer_list instance_layer_list;
229    tls_instance = NULL;
230
231    loader_platform_thread_once(&once_init, loader_initialize);
232
233    uint32_t copy_size;
234
235    /* get layer libraries */
236    memset(&instance_layer_list, 0, sizeof(instance_layer_list));
237    loader_layer_scan(NULL, &instance_layer_list);
238
239    if (pProperties == NULL) {
240        *pPropertyCount = instance_layer_list.count;
241        loader_destroy_layer_list(NULL, &instance_layer_list);
242        return VK_SUCCESS;
243    }
244
245    copy_size = (*pPropertyCount < instance_layer_list.count)
246                    ? *pPropertyCount
247                    : instance_layer_list.count;
248    for (uint32_t i = 0; i < copy_size; i++) {
249        memcpy(&pProperties[i], &instance_layer_list.list[i].info,
250               sizeof(VkLayerProperties));
251    }
252
253    *pPropertyCount = copy_size;
254    loader_destroy_layer_list(NULL, &instance_layer_list);
255
256    if (copy_size < instance_layer_list.count) {
257        return VK_INCOMPLETE;
258    }
259
260    return VK_SUCCESS;
261}
262
263LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
264vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
265                 const VkAllocationCallbacks *pAllocator,
266                 VkInstance *pInstance) {
267    struct loader_instance *ptr_instance = NULL;
268    VkInstance created_instance = VK_NULL_HANDLE;
269    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
270
271    loader_platform_thread_once(&once_init, loader_initialize);
272
273    //TODO start handling the pAllocators again
274#if 0
275	if (pAllocator) {
276        ptr_instance = (struct loader_instance *) pAllocator->pfnAllocation(
277                           pAllocator->pUserData,
278                           sizeof(struct loader_instance),
279                           sizeof(int *),
280                           VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
281    } else {
282#endif
283    ptr_instance =
284        (struct loader_instance *)malloc(sizeof(struct loader_instance));
285    //}
286    if (ptr_instance == NULL) {
287        return VK_ERROR_OUT_OF_HOST_MEMORY;
288    }
289
290    tls_instance = ptr_instance;
291    loader_platform_thread_lock_mutex(&loader_lock);
292    memset(ptr_instance, 0, sizeof(struct loader_instance));
293#if 0
294    if (pAllocator) {
295        ptr_instance->alloc_callbacks = *pAllocator;
296    }
297#endif
298
299    /*
300     * Look for one or more debug report create info structures
301     * and setup a callback(s) for each one found.
302     */
303    ptr_instance->num_tmp_callbacks = 0;
304    ptr_instance->tmp_dbg_create_infos = NULL;
305    ptr_instance->tmp_callbacks = NULL;
306    if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator,
307                                        &ptr_instance->num_tmp_callbacks,
308                                        &ptr_instance->tmp_dbg_create_infos,
309                                        &ptr_instance->tmp_callbacks)) {
310        // One or more were found, but allocation failed.  Therefore, clean up
311        // and fail this function:
312        loader_heap_free(ptr_instance, ptr_instance);
313        loader_platform_thread_unlock_mutex(&loader_lock);
314        return VK_ERROR_OUT_OF_HOST_MEMORY;
315    } else if (ptr_instance->num_tmp_callbacks > 0) {
316        // Setup the temporary callback(s) here to catch early issues:
317        if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator,
318                                            ptr_instance->num_tmp_callbacks,
319                                            ptr_instance->tmp_dbg_create_infos,
320                                            ptr_instance->tmp_callbacks)) {
321            // Failure of setting up one or more of the callback.  Therefore,
322            // clean up and fail this function:
323            util_FreeDebugReportCreateInfos(pAllocator,
324                                            ptr_instance->tmp_dbg_create_infos,
325                                            ptr_instance->tmp_callbacks);
326            loader_heap_free(ptr_instance, ptr_instance);
327            loader_platform_thread_unlock_mutex(&loader_lock);
328            return VK_ERROR_OUT_OF_HOST_MEMORY;
329        }
330    }
331
332    /* Due to implicit layers need to get layer list even if
333     * enabledLayerCount == 0 and VK_INSTANCE_LAYERS is unset. For now always
334     * get layer list via loader_layer_scan(). */
335    memset(&ptr_instance->instance_layer_list, 0,
336           sizeof(ptr_instance->instance_layer_list));
337    loader_layer_scan(ptr_instance, &ptr_instance->instance_layer_list);
338
339    /* validate the app requested layers to be enabled */
340    if (pCreateInfo->enabledLayerCount > 0) {
341        res =
342            loader_validate_layers(ptr_instance, pCreateInfo->enabledLayerCount,
343                                   pCreateInfo->ppEnabledLayerNames,
344                                   &ptr_instance->instance_layer_list);
345        if (res != VK_SUCCESS) {
346            util_DestroyDebugReportCallbacks(ptr_instance, pAllocator,
347                                             ptr_instance->num_tmp_callbacks,
348                                             ptr_instance->tmp_callbacks);
349            util_FreeDebugReportCreateInfos(pAllocator,
350                                            ptr_instance->tmp_dbg_create_infos,
351                                            ptr_instance->tmp_callbacks);
352            loader_heap_free(ptr_instance, ptr_instance);
353            loader_platform_thread_unlock_mutex(&loader_lock);
354            return res;
355        }
356    }
357
358    /* convert any meta layers to the actual layers makes a copy of layer name*/
359    VkInstanceCreateInfo ici = *pCreateInfo;
360    loader_expand_layer_names(
361        ptr_instance, std_validation_str,
362        sizeof(std_validation_names) / sizeof(std_validation_names[0]),
363        std_validation_names, &ici.enabledLayerCount, &ici.ppEnabledLayerNames);
364
365    /* Scan/discover all ICD libraries */
366    memset(&ptr_instance->icd_libs, 0, sizeof(ptr_instance->icd_libs));
367    loader_icd_scan(ptr_instance, &ptr_instance->icd_libs);
368
369    /* get extensions from all ICD's, merge so no duplicates, then validate */
370    loader_get_icd_loader_instance_extensions(
371        ptr_instance, &ptr_instance->icd_libs, &ptr_instance->ext_list);
372    res = loader_validate_instance_extensions(
373        ptr_instance, &ptr_instance->ext_list,
374        &ptr_instance->instance_layer_list, &ici);
375    if (res != VK_SUCCESS) {
376        loader_delete_shadow_inst_layer_names(ptr_instance, pCreateInfo, &ici);
377        loader_delete_layer_properties(ptr_instance,
378                                       &ptr_instance->instance_layer_list);
379        loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
380        loader_destroy_generic_list(
381            ptr_instance,
382            (struct loader_generic_list *)&ptr_instance->ext_list);
383        util_DestroyDebugReportCallbacks(ptr_instance, pAllocator,
384                                         ptr_instance->num_tmp_callbacks,
385                                         ptr_instance->tmp_callbacks);
386        util_FreeDebugReportCreateInfos(pAllocator,
387                                        ptr_instance->tmp_dbg_create_infos,
388                                        ptr_instance->tmp_callbacks);
389        loader_platform_thread_unlock_mutex(&loader_lock);
390        loader_heap_free(ptr_instance, ptr_instance);
391        return res;
392    }
393
394    ptr_instance->disp =
395        loader_heap_alloc(ptr_instance, sizeof(VkLayerInstanceDispatchTable),
396                          VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
397    if (ptr_instance->disp == NULL) {
398        loader_delete_shadow_inst_layer_names(ptr_instance, pCreateInfo, &ici);
399
400        loader_delete_layer_properties(ptr_instance,
401                                       &ptr_instance->instance_layer_list);
402        loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
403        loader_destroy_generic_list(
404            ptr_instance,
405            (struct loader_generic_list *)&ptr_instance->ext_list);
406        util_DestroyDebugReportCallbacks(ptr_instance, pAllocator,
407                                         ptr_instance->num_tmp_callbacks,
408                                         ptr_instance->tmp_callbacks);
409        util_FreeDebugReportCreateInfos(pAllocator,
410                                        ptr_instance->tmp_dbg_create_infos,
411                                        ptr_instance->tmp_callbacks);
412        loader_platform_thread_unlock_mutex(&loader_lock);
413        loader_heap_free(ptr_instance, ptr_instance);
414        return VK_ERROR_OUT_OF_HOST_MEMORY;
415    }
416    memcpy(ptr_instance->disp, &instance_disp, sizeof(instance_disp));
417    ptr_instance->next = loader.instances;
418    loader.instances = ptr_instance;
419
420    /* activate any layers on instance chain */
421    res = loader_enable_instance_layers(ptr_instance, &ici,
422                                        &ptr_instance->instance_layer_list);
423    if (res != VK_SUCCESS) {
424        loader_delete_shadow_inst_layer_names(ptr_instance, pCreateInfo, &ici);
425        loader_delete_layer_properties(ptr_instance,
426                                       &ptr_instance->instance_layer_list);
427        loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
428        loader_destroy_generic_list(
429            ptr_instance,
430            (struct loader_generic_list *)&ptr_instance->ext_list);
431        loader.instances = ptr_instance->next;
432        util_DestroyDebugReportCallbacks(ptr_instance, pAllocator,
433                                         ptr_instance->num_tmp_callbacks,
434                                         ptr_instance->tmp_callbacks);
435        util_FreeDebugReportCreateInfos(pAllocator,
436                                        ptr_instance->tmp_dbg_create_infos,
437                                        ptr_instance->tmp_callbacks);
438        loader_platform_thread_unlock_mutex(&loader_lock);
439        loader_heap_free(ptr_instance, ptr_instance->disp);
440        loader_heap_free(ptr_instance, ptr_instance);
441        return res;
442    }
443
444    created_instance = (VkInstance)ptr_instance;
445    res = loader_create_instance_chain(&ici, pAllocator, ptr_instance,
446                                       &created_instance);
447
448    if (res == VK_SUCCESS) {
449        wsi_create_instance(ptr_instance, &ici);
450        debug_report_create_instance(ptr_instance, &ici);
451
452        *pInstance = created_instance;
453
454        /*
455         * Finally have the layers in place and everyone has seen
456         * the CreateInstance command go by. This allows the layer's
457         * GetInstanceProcAddr functions to return valid extension functions
458         * if enabled.
459         */
460        loader_activate_instance_layer_extensions(ptr_instance, *pInstance);
461    } else {
462        // TODO: cleanup here.
463    }
464
465    /* Remove temporary debug_report callback */
466    util_DestroyDebugReportCallbacks(ptr_instance, pAllocator,
467                                     ptr_instance->num_tmp_callbacks,
468                                     ptr_instance->tmp_callbacks);
469    loader_delete_shadow_inst_layer_names(ptr_instance, pCreateInfo, &ici);
470    loader_platform_thread_unlock_mutex(&loader_lock);
471    return res;
472}
473
474LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
475vkDestroyInstance(VkInstance instance,
476                  const VkAllocationCallbacks *pAllocator) {
477    const VkLayerInstanceDispatchTable *disp;
478    struct loader_instance *ptr_instance = NULL;
479    bool callback_setup = false;
480
481    if (instance == VK_NULL_HANDLE) {
482        return;
483    }
484
485    disp = loader_get_instance_dispatch(instance);
486
487    loader_platform_thread_lock_mutex(&loader_lock);
488
489    ptr_instance = loader_get_instance(instance);
490
491    if (ptr_instance->num_tmp_callbacks > 0) {
492        // Setup the temporary callback(s) here to catch cleanup issues:
493        if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator,
494                                             ptr_instance->num_tmp_callbacks,
495                                             ptr_instance->tmp_dbg_create_infos,
496                                             ptr_instance->tmp_callbacks)) {
497            callback_setup = true;
498        }
499    }
500
501    disp->DestroyInstance(instance, pAllocator);
502
503    loader_deactivate_layers(ptr_instance, &ptr_instance->activated_layer_list);
504    if (ptr_instance->phys_devs)
505        loader_heap_free(ptr_instance, ptr_instance->phys_devs);
506    if (callback_setup) {
507        util_DestroyDebugReportCallbacks(ptr_instance, pAllocator,
508                                         ptr_instance->num_tmp_callbacks,
509                                         ptr_instance->tmp_callbacks);
510        util_FreeDebugReportCreateInfos(pAllocator,
511                                        ptr_instance->tmp_dbg_create_infos,
512                                        ptr_instance->tmp_callbacks);
513    }
514    loader_heap_free(ptr_instance, ptr_instance->disp);
515    loader_heap_free(ptr_instance, ptr_instance);
516    loader_platform_thread_unlock_mutex(&loader_lock);
517}
518
519LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
520vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
521                           VkPhysicalDevice *pPhysicalDevices) {
522    const VkLayerInstanceDispatchTable *disp;
523    VkResult res;
524    uint32_t count, i;
525    struct loader_instance *inst;
526    disp = loader_get_instance_dispatch(instance);
527
528    loader_platform_thread_lock_mutex(&loader_lock);
529    res = disp->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount,
530                                         pPhysicalDevices);
531
532    if (res != VK_SUCCESS && res != VK_INCOMPLETE) {
533        loader_platform_thread_unlock_mutex(&loader_lock);
534        return res;
535    }
536
537    if (!pPhysicalDevices) {
538        loader_platform_thread_unlock_mutex(&loader_lock);
539        return res;
540    }
541
542    // wrap the PhysDev object for loader usage, return wrapped objects
543    inst = loader_get_instance(instance);
544    if (!inst) {
545        loader_platform_thread_unlock_mutex(&loader_lock);
546        return VK_ERROR_INITIALIZATION_FAILED;
547    }
548    count = (inst->total_gpu_count < *pPhysicalDeviceCount)
549                ? inst->total_gpu_count
550                : *pPhysicalDeviceCount;
551    *pPhysicalDeviceCount = count;
552    if (!inst->phys_devs) {
553        inst->phys_devs =
554            (struct loader_physical_device_tramp *)loader_heap_alloc(
555                inst, inst->total_gpu_count *
556                          sizeof(struct loader_physical_device_tramp),
557                VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
558    }
559    if (!inst->phys_devs) {
560        loader_platform_thread_unlock_mutex(&loader_lock);
561        return VK_ERROR_OUT_OF_HOST_MEMORY;
562    }
563
564    for (i = 0; i < count; i++) {
565
566        // initialize the loader's physicalDevice object
567        loader_set_dispatch((void *)&inst->phys_devs[i], inst->disp);
568        inst->phys_devs[i].this_instance = inst;
569        inst->phys_devs[i].phys_dev = pPhysicalDevices[i];
570
571        // copy wrapped object into Application provided array
572        pPhysicalDevices[i] = (VkPhysicalDevice)&inst->phys_devs[i];
573    }
574    loader_platform_thread_unlock_mutex(&loader_lock);
575    return res;
576}
577
578LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
579vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
580                            VkPhysicalDeviceFeatures *pFeatures) {
581    const VkLayerInstanceDispatchTable *disp;
582    VkPhysicalDevice unwrapped_phys_dev =
583        loader_unwrap_physical_device(physicalDevice);
584    disp = loader_get_instance_dispatch(physicalDevice);
585    disp->GetPhysicalDeviceFeatures(unwrapped_phys_dev, pFeatures);
586}
587
588LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
589vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
590                                    VkFormat format,
591                                    VkFormatProperties *pFormatInfo) {
592    const VkLayerInstanceDispatchTable *disp;
593    VkPhysicalDevice unwrapped_pd =
594        loader_unwrap_physical_device(physicalDevice);
595    disp = loader_get_instance_dispatch(physicalDevice);
596    disp->GetPhysicalDeviceFormatProperties(unwrapped_pd, format, pFormatInfo);
597}
598
599LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
600vkGetPhysicalDeviceImageFormatProperties(
601    VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
602    VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
603    VkImageFormatProperties *pImageFormatProperties) {
604    const VkLayerInstanceDispatchTable *disp;
605    VkPhysicalDevice unwrapped_phys_dev =
606        loader_unwrap_physical_device(physicalDevice);
607    disp = loader_get_instance_dispatch(physicalDevice);
608    return disp->GetPhysicalDeviceImageFormatProperties(
609        unwrapped_phys_dev, format, type, tiling, usage, flags,
610        pImageFormatProperties);
611}
612
613LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
614vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
615                              VkPhysicalDeviceProperties *pProperties) {
616    const VkLayerInstanceDispatchTable *disp;
617    VkPhysicalDevice unwrapped_phys_dev =
618        loader_unwrap_physical_device(physicalDevice);
619    disp = loader_get_instance_dispatch(physicalDevice);
620    disp->GetPhysicalDeviceProperties(unwrapped_phys_dev, pProperties);
621}
622
623LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
624vkGetPhysicalDeviceQueueFamilyProperties(
625    VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
626    VkQueueFamilyProperties *pQueueProperties) {
627    const VkLayerInstanceDispatchTable *disp;
628    VkPhysicalDevice unwrapped_phys_dev =
629        loader_unwrap_physical_device(physicalDevice);
630    disp = loader_get_instance_dispatch(physicalDevice);
631    disp->GetPhysicalDeviceQueueFamilyProperties(
632        unwrapped_phys_dev, pQueueFamilyPropertyCount, pQueueProperties);
633}
634
635LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
636    VkPhysicalDevice physicalDevice,
637    VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
638    const VkLayerInstanceDispatchTable *disp;
639    VkPhysicalDevice unwrapped_phys_dev =
640        loader_unwrap_physical_device(physicalDevice);
641    disp = loader_get_instance_dispatch(physicalDevice);
642    disp->GetPhysicalDeviceMemoryProperties(unwrapped_phys_dev,
643                                            pMemoryProperties);
644}
645
646LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
647vkCreateDevice(VkPhysicalDevice physicalDevice,
648               const VkDeviceCreateInfo *pCreateInfo,
649               const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
650    VkResult res;
651    struct loader_physical_device_tramp *phys_dev;
652    struct loader_device *dev;
653    struct loader_instance *inst;
654
655    assert(pCreateInfo->queueCreateInfoCount >= 1);
656
657    loader_platform_thread_lock_mutex(&loader_lock);
658
659    phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
660    inst = (struct loader_instance *)phys_dev->this_instance;
661
662    /* Get the physical device (ICD) extensions  */
663    struct loader_extension_list icd_exts;
664    if (!loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts,
665                                  sizeof(VkExtensionProperties))) {
666        loader_platform_thread_unlock_mutex(&loader_lock);
667        return VK_ERROR_OUT_OF_HOST_MEMORY;
668    }
669
670    res = loader_add_device_extensions(
671        inst, inst->disp->EnumerateDeviceExtensionProperties,
672        phys_dev->phys_dev, "Unknown", &icd_exts);
673    if (res != VK_SUCCESS) {
674        loader_platform_thread_unlock_mutex(&loader_lock);
675        return res;
676    }
677
678    /* make sure requested extensions to be enabled are supported */
679    res = loader_validate_device_extensions(phys_dev, &inst->activated_layer_list,
680                                            &icd_exts, pCreateInfo);
681    if (res != VK_SUCCESS) {
682        loader_platform_thread_unlock_mutex(&loader_lock);
683        return res;
684    }
685
686    dev = loader_create_logical_device(inst);
687    if (dev == NULL) {
688        loader_platform_thread_unlock_mutex(&loader_lock);
689        return VK_ERROR_OUT_OF_HOST_MEMORY;
690    }
691
692    /* copy the instance layer list into the device */
693    dev->activated_layer_list.capacity = inst->activated_layer_list.capacity;
694    dev->activated_layer_list.count = inst->activated_layer_list.count;
695    dev->activated_layer_list.list = loader_heap_alloc(inst,
696                            inst->activated_layer_list.capacity,
697                            VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
698    if (dev->activated_layer_list.list == NULL) {
699        loader_platform_thread_unlock_mutex(&loader_lock);
700        return VK_ERROR_OUT_OF_HOST_MEMORY;
701    }
702    memcpy(dev->activated_layer_list.list, inst->activated_layer_list.list,
703            sizeof(*dev->activated_layer_list.list) * dev->activated_layer_list.count);
704
705
706    res = loader_create_device_chain(phys_dev, pCreateInfo, pAllocator, inst, dev);
707    if (res != VK_SUCCESS) {
708        loader_platform_thread_unlock_mutex(&loader_lock);
709        return res;
710    }
711
712    *pDevice = dev->device;
713
714    /* initialize any device extension dispatch entry's from the instance list*/
715    loader_init_dispatch_dev_ext(inst, dev);
716
717    /* initialize WSI device extensions as part of core dispatch since loader
718     * has
719     * dedicated trampoline code for these*/
720    loader_init_device_extension_dispatch_table(
721        &dev->loader_dispatch,
722        dev->loader_dispatch.core_dispatch.GetDeviceProcAddr, *pDevice);
723
724    loader_platform_thread_unlock_mutex(&loader_lock);
725    return res;
726}
727
728LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
729vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
730    const VkLayerDispatchTable *disp;
731    struct loader_device *dev;
732
733    if (device == VK_NULL_HANDLE) {
734        return;
735    }
736
737    loader_platform_thread_lock_mutex(&loader_lock);
738
739    struct loader_icd *icd = loader_get_icd_and_device(device, &dev);
740    const struct loader_instance *inst = icd->this_instance;
741    disp = loader_get_dispatch(device);
742
743    disp->DestroyDevice(device, pAllocator);
744    dev->device = NULL;
745    loader_remove_logical_device(inst, icd, dev);
746
747    loader_platform_thread_unlock_mutex(&loader_lock);
748}
749
750LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
751vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
752                                     const char *pLayerName,
753                                     uint32_t *pPropertyCount,
754                                     VkExtensionProperties *pProperties) {
755    VkResult res = VK_SUCCESS;
756    struct loader_physical_device_tramp *phys_dev;
757    phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
758
759    loader_platform_thread_lock_mutex(&loader_lock);
760
761    /* If pLayerName == NULL, then querying ICD extensions, pass this call
762       down the instance chain which will terminate in the ICD. This allows
763       layers to filter the extensions coming back up the chain.
764       If pLayerName != NULL then get layer extensions from manifest file.  */
765    if (pLayerName == NULL || strlen(pLayerName) == 0) {
766        const VkLayerInstanceDispatchTable *disp;
767
768        disp = loader_get_instance_dispatch(physicalDevice);
769        res = disp->EnumerateDeviceExtensionProperties(
770            phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
771    } else {
772
773        uint32_t count;
774        uint32_t copy_size;
775        const struct loader_instance *inst = phys_dev->this_instance;
776        struct loader_device_extension_list *dev_ext_list = NULL;
777        struct loader_device_extension_list local_ext_list;
778        memset(&local_ext_list, 0, sizeof(local_ext_list));
779        if (vk_string_validate(MaxLoaderStringLength, pLayerName) ==
780            VK_STRING_ERROR_NONE) {
781            if (strcmp(pLayerName, std_validation_str) == 0) {
782                struct loader_layer_list local_list;
783                memset(&local_list, 0, sizeof(local_list));
784                for (uint32_t i = 0; i < sizeof(std_validation_names) /
785                                             sizeof(std_validation_names[0]);
786                     i++) {
787                    loader_find_layer_name_add_list(
788                        NULL, std_validation_names[i],
789                        VK_LAYER_TYPE_INSTANCE_EXPLICIT, &inst->instance_layer_list,
790                        &local_list);
791                }
792                for (uint32_t i = 0; i < local_list.count; i++) {
793                    struct loader_device_extension_list *ext_list =
794                        &local_list.list[i].device_extension_list;
795                    for (uint32_t j = 0; j < ext_list->count; j++) {
796                        loader_add_to_dev_ext_list(NULL, &local_ext_list,
797                                                   &ext_list->list[j].props, 0,
798                                                   NULL);
799                    }
800                }
801                dev_ext_list = &local_ext_list;
802
803            } else {
804                for (uint32_t i = 0; i < inst->instance_layer_list.count; i++) {
805                    struct loader_layer_properties *props =
806                        &inst->instance_layer_list.list[i];
807                    if (strcmp(props->info.layerName, pLayerName) == 0) {
808                        dev_ext_list = &props->device_extension_list;
809                    }
810                }
811            }
812
813            count = (dev_ext_list == NULL) ? 0 : dev_ext_list->count;
814            if (pProperties == NULL) {
815                *pPropertyCount = count;
816                loader_destroy_generic_list(
817                    inst, (struct loader_generic_list *)&local_ext_list);
818                loader_platform_thread_unlock_mutex(&loader_lock);
819                return VK_SUCCESS;
820            }
821
822            copy_size = *pPropertyCount < count ? *pPropertyCount : count;
823            for (uint32_t i = 0; i < copy_size; i++) {
824                memcpy(&pProperties[i], &dev_ext_list->list[i].props,
825                       sizeof(VkExtensionProperties));
826            }
827            *pPropertyCount = copy_size;
828
829            loader_destroy_generic_list(
830                inst, (struct loader_generic_list *)&local_ext_list);
831            if (copy_size < count) {
832                loader_platform_thread_unlock_mutex(&loader_lock);
833                return VK_INCOMPLETE;
834            }
835        } else {
836            loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
837                       "vkEnumerateDeviceExtensionProperties:  pLayerName "
838                       "is too long or is badly formed");
839            loader_platform_thread_unlock_mutex(&loader_lock);
840            return VK_ERROR_EXTENSION_NOT_PRESENT;
841        }
842    }
843
844    loader_platform_thread_unlock_mutex(&loader_lock);
845    return res;
846}
847
848LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
849vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
850                                 uint32_t *pPropertyCount,
851                                 VkLayerProperties *pProperties) {
852    uint32_t copy_size;
853    struct loader_physical_device_tramp *phys_dev;
854    struct loader_layer_list *enabled_layers, layers_list;
855    uint32_t std_val_count = sizeof(std_validation_names) /
856                                sizeof(std_validation_names[0]);
857    memset(&layers_list, 0, sizeof(layers_list));
858    loader_platform_thread_lock_mutex(&loader_lock);
859
860    /* Don't dispatch this call down the instance chain, want all device layers
861       enumerated and instance chain may not contain all device layers */
862    // TODO re-evaluate the above statement we maybe able to start calling
863    // down the chain
864
865    phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
866    const struct loader_instance *inst = phys_dev->this_instance;
867
868    uint32_t count = inst->activated_layer_list.count;
869    if (inst->activated_layers_are_std_val)
870        count = count - std_val_count + 1;
871    if (pProperties == NULL) {
872        *pPropertyCount = count;
873        loader_platform_thread_unlock_mutex(&loader_lock);
874        return VK_SUCCESS;
875    }
876    /* make sure to enumerate standard_validation if that is what was used
877     at the instance layer enablement */
878    if (inst->activated_layers_are_std_val) {
879        enabled_layers = &layers_list;
880        enabled_layers->count = count;
881        enabled_layers->capacity = enabled_layers->count *
882                                 sizeof(struct loader_layer_properties);
883        enabled_layers->list = loader_heap_alloc(inst, enabled_layers->capacity,
884                                VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
885        if (!enabled_layers->list)
886            return VK_ERROR_OUT_OF_HOST_MEMORY;
887
888        uint32_t j = 0;
889        for (uint32_t i = 0; i < inst->activated_layer_list.count; j++) {
890
891            if (loader_find_layer_name_array(
892                    inst->activated_layer_list.list[i].info.layerName,
893                    std_val_count, std_validation_names)) {
894                struct loader_layer_properties props;
895                loader_init_std_validation_props(&props);
896                loader_copy_layer_properties(inst,
897                                             &enabled_layers->list[j], &props);
898                i += std_val_count;
899            }
900            else {
901                loader_copy_layer_properties(inst,
902                                         &enabled_layers->list[j],
903                                         &inst->activated_layer_list.list[i++]);
904            }
905        }
906    }
907    else {
908        enabled_layers = (struct loader_layer_list *) &inst->activated_layer_list;
909    }
910
911
912    copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
913    for (uint32_t i = 0; i < copy_size; i++) {
914        memcpy(&pProperties[i], &(enabled_layers->list[i].info),
915               sizeof(VkLayerProperties));
916    }
917    *pPropertyCount = copy_size;
918
919    if (inst->activated_layers_are_std_val)
920        loader_delete_layer_properties(inst, enabled_layers);
921    if (copy_size < count) {
922        loader_platform_thread_unlock_mutex(&loader_lock);
923        return VK_INCOMPLETE;
924    }
925
926    loader_platform_thread_unlock_mutex(&loader_lock);
927    return VK_SUCCESS;
928}
929
930LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
931vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex,
932                 VkQueue *pQueue) {
933    const VkLayerDispatchTable *disp;
934
935    disp = loader_get_dispatch(device);
936
937    disp->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
938    loader_set_dispatch(*pQueue, disp);
939}
940
941LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
942vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
943              VkFence fence) {
944    const VkLayerDispatchTable *disp;
945
946    disp = loader_get_dispatch(queue);
947
948    return disp->QueueSubmit(queue, submitCount, pSubmits, fence);
949}
950
951LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue) {
952    const VkLayerDispatchTable *disp;
953
954    disp = loader_get_dispatch(queue);
955
956    return disp->QueueWaitIdle(queue);
957}
958
959LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device) {
960    const VkLayerDispatchTable *disp;
961
962    disp = loader_get_dispatch(device);
963
964    return disp->DeviceWaitIdle(device);
965}
966
967LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
968vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
969                 const VkAllocationCallbacks *pAllocator,
970                 VkDeviceMemory *pMemory) {
971    const VkLayerDispatchTable *disp;
972
973    disp = loader_get_dispatch(device);
974
975    return disp->AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
976}
977
978LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
979vkFreeMemory(VkDevice device, VkDeviceMemory mem,
980             const VkAllocationCallbacks *pAllocator) {
981    const VkLayerDispatchTable *disp;
982
983    disp = loader_get_dispatch(device);
984
985    disp->FreeMemory(device, mem, pAllocator);
986}
987
988LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
989vkMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset,
990            VkDeviceSize size, VkFlags flags, void **ppData) {
991    const VkLayerDispatchTable *disp;
992
993    disp = loader_get_dispatch(device);
994
995    return disp->MapMemory(device, mem, offset, size, flags, ppData);
996}
997
998LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
999vkUnmapMemory(VkDevice device, VkDeviceMemory mem) {
1000    const VkLayerDispatchTable *disp;
1001
1002    disp = loader_get_dispatch(device);
1003
1004    disp->UnmapMemory(device, mem);
1005}
1006
1007LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1008vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
1009                          const VkMappedMemoryRange *pMemoryRanges) {
1010    const VkLayerDispatchTable *disp;
1011
1012    disp = loader_get_dispatch(device);
1013
1014    return disp->FlushMappedMemoryRanges(device, memoryRangeCount,
1015                                         pMemoryRanges);
1016}
1017
1018LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1019vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
1020                               const VkMappedMemoryRange *pMemoryRanges) {
1021    const VkLayerDispatchTable *disp;
1022
1023    disp = loader_get_dispatch(device);
1024
1025    return disp->InvalidateMappedMemoryRanges(device, memoryRangeCount,
1026                                              pMemoryRanges);
1027}
1028
1029LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1030vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory,
1031                            VkDeviceSize *pCommittedMemoryInBytes) {
1032    const VkLayerDispatchTable *disp;
1033
1034    disp = loader_get_dispatch(device);
1035
1036    disp->GetDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
1037}
1038
1039LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1040vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem,
1041                   VkDeviceSize offset) {
1042    const VkLayerDispatchTable *disp;
1043
1044    disp = loader_get_dispatch(device);
1045
1046    return disp->BindBufferMemory(device, buffer, mem, offset);
1047}
1048
1049LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1050vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem,
1051                  VkDeviceSize offset) {
1052    const VkLayerDispatchTable *disp;
1053
1054    disp = loader_get_dispatch(device);
1055
1056    return disp->BindImageMemory(device, image, mem, offset);
1057}
1058
1059LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1060vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
1061                              VkMemoryRequirements *pMemoryRequirements) {
1062    const VkLayerDispatchTable *disp;
1063
1064    disp = loader_get_dispatch(device);
1065
1066    disp->GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
1067}
1068
1069LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1070vkGetImageMemoryRequirements(VkDevice device, VkImage image,
1071                             VkMemoryRequirements *pMemoryRequirements) {
1072    const VkLayerDispatchTable *disp;
1073
1074    disp = loader_get_dispatch(device);
1075
1076    disp->GetImageMemoryRequirements(device, image, pMemoryRequirements);
1077}
1078
1079LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements(
1080    VkDevice device, VkImage image, uint32_t *pSparseMemoryRequirementCount,
1081    VkSparseImageMemoryRequirements *pSparseMemoryRequirements) {
1082    const VkLayerDispatchTable *disp;
1083
1084    disp = loader_get_dispatch(device);
1085
1086    disp->GetImageSparseMemoryRequirements(device, image,
1087                                           pSparseMemoryRequirementCount,
1088                                           pSparseMemoryRequirements);
1089}
1090
1091LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1092vkGetPhysicalDeviceSparseImageFormatProperties(
1093    VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
1094    VkSampleCountFlagBits samples, VkImageUsageFlags usage,
1095    VkImageTiling tiling, uint32_t *pPropertyCount,
1096    VkSparseImageFormatProperties *pProperties) {
1097    const VkLayerInstanceDispatchTable *disp;
1098    VkPhysicalDevice unwrapped_phys_dev =
1099        loader_unwrap_physical_device(physicalDevice);
1100    disp = loader_get_instance_dispatch(physicalDevice);
1101
1102    disp->GetPhysicalDeviceSparseImageFormatProperties(
1103        unwrapped_phys_dev, format, type, samples, usage, tiling,
1104        pPropertyCount, pProperties);
1105}
1106
1107LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1108vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount,
1109                  const VkBindSparseInfo *pBindInfo, VkFence fence) {
1110    const VkLayerDispatchTable *disp;
1111
1112    disp = loader_get_dispatch(queue);
1113
1114    return disp->QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
1115}
1116
1117LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1118vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo,
1119              const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
1120    const VkLayerDispatchTable *disp;
1121
1122    disp = loader_get_dispatch(device);
1123
1124    return disp->CreateFence(device, pCreateInfo, pAllocator, pFence);
1125}
1126
1127LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1128vkDestroyFence(VkDevice device, VkFence fence,
1129               const VkAllocationCallbacks *pAllocator) {
1130    const VkLayerDispatchTable *disp;
1131
1132    disp = loader_get_dispatch(device);
1133
1134    disp->DestroyFence(device, fence, pAllocator);
1135}
1136
1137LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1138vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
1139    const VkLayerDispatchTable *disp;
1140
1141    disp = loader_get_dispatch(device);
1142
1143    return disp->ResetFences(device, fenceCount, pFences);
1144}
1145
1146LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1147vkGetFenceStatus(VkDevice device, VkFence fence) {
1148    const VkLayerDispatchTable *disp;
1149
1150    disp = loader_get_dispatch(device);
1151
1152    return disp->GetFenceStatus(device, fence);
1153}
1154
1155LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1156vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences,
1157                VkBool32 waitAll, uint64_t timeout) {
1158    const VkLayerDispatchTable *disp;
1159
1160    disp = loader_get_dispatch(device);
1161
1162    return disp->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
1163}
1164
1165LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1166vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
1167                  const VkAllocationCallbacks *pAllocator,
1168                  VkSemaphore *pSemaphore) {
1169    const VkLayerDispatchTable *disp;
1170
1171    disp = loader_get_dispatch(device);
1172
1173    return disp->CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
1174}
1175
1176LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1177vkDestroySemaphore(VkDevice device, VkSemaphore semaphore,
1178                   const VkAllocationCallbacks *pAllocator) {
1179    const VkLayerDispatchTable *disp;
1180
1181    disp = loader_get_dispatch(device);
1182
1183    disp->DestroySemaphore(device, semaphore, pAllocator);
1184}
1185
1186LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1187vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo,
1188              const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
1189    const VkLayerDispatchTable *disp;
1190
1191    disp = loader_get_dispatch(device);
1192
1193    return disp->CreateEvent(device, pCreateInfo, pAllocator, pEvent);
1194}
1195
1196LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1197vkDestroyEvent(VkDevice device, VkEvent event,
1198               const VkAllocationCallbacks *pAllocator) {
1199    const VkLayerDispatchTable *disp;
1200
1201    disp = loader_get_dispatch(device);
1202
1203    disp->DestroyEvent(device, event, pAllocator);
1204}
1205
1206LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1207vkGetEventStatus(VkDevice device, VkEvent event) {
1208    const VkLayerDispatchTable *disp;
1209
1210    disp = loader_get_dispatch(device);
1211
1212    return disp->GetEventStatus(device, event);
1213}
1214
1215LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1216vkSetEvent(VkDevice device, VkEvent event) {
1217    const VkLayerDispatchTable *disp;
1218
1219    disp = loader_get_dispatch(device);
1220
1221    return disp->SetEvent(device, event);
1222}
1223
1224LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1225vkResetEvent(VkDevice device, VkEvent event) {
1226    const VkLayerDispatchTable *disp;
1227
1228    disp = loader_get_dispatch(device);
1229
1230    return disp->ResetEvent(device, event);
1231}
1232
1233LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1234vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
1235                  const VkAllocationCallbacks *pAllocator,
1236                  VkQueryPool *pQueryPool) {
1237    const VkLayerDispatchTable *disp;
1238
1239    disp = loader_get_dispatch(device);
1240
1241    return disp->CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
1242}
1243
1244LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1245vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool,
1246                   const VkAllocationCallbacks *pAllocator) {
1247    const VkLayerDispatchTable *disp;
1248
1249    disp = loader_get_dispatch(device);
1250
1251    disp->DestroyQueryPool(device, queryPool, pAllocator);
1252}
1253
1254LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1255vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool,
1256                      uint32_t firstQuery, uint32_t queryCount, size_t dataSize,
1257                      void *pData, VkDeviceSize stride,
1258                      VkQueryResultFlags flags) {
1259    const VkLayerDispatchTable *disp;
1260
1261    disp = loader_get_dispatch(device);
1262
1263    return disp->GetQueryPoolResults(device, queryPool, firstQuery, queryCount,
1264                                     dataSize, pData, stride, flags);
1265}
1266
1267LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1268vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
1269               const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
1270    const VkLayerDispatchTable *disp;
1271
1272    disp = loader_get_dispatch(device);
1273
1274    return disp->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
1275}
1276
1277LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1278vkDestroyBuffer(VkDevice device, VkBuffer buffer,
1279                const VkAllocationCallbacks *pAllocator) {
1280    const VkLayerDispatchTable *disp;
1281
1282    disp = loader_get_dispatch(device);
1283
1284    disp->DestroyBuffer(device, buffer, pAllocator);
1285}
1286
1287LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1288vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
1289                   const VkAllocationCallbacks *pAllocator,
1290                   VkBufferView *pView) {
1291    const VkLayerDispatchTable *disp;
1292
1293    disp = loader_get_dispatch(device);
1294
1295    return disp->CreateBufferView(device, pCreateInfo, pAllocator, pView);
1296}
1297
1298LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1299vkDestroyBufferView(VkDevice device, VkBufferView bufferView,
1300                    const VkAllocationCallbacks *pAllocator) {
1301    const VkLayerDispatchTable *disp;
1302
1303    disp = loader_get_dispatch(device);
1304
1305    disp->DestroyBufferView(device, bufferView, pAllocator);
1306}
1307
1308LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1309vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
1310              const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
1311    const VkLayerDispatchTable *disp;
1312
1313    disp = loader_get_dispatch(device);
1314
1315    return disp->CreateImage(device, pCreateInfo, pAllocator, pImage);
1316}
1317
1318LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1319vkDestroyImage(VkDevice device, VkImage image,
1320               const VkAllocationCallbacks *pAllocator) {
1321    const VkLayerDispatchTable *disp;
1322
1323    disp = loader_get_dispatch(device);
1324
1325    disp->DestroyImage(device, image, pAllocator);
1326}
1327
1328LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1329vkGetImageSubresourceLayout(VkDevice device, VkImage image,
1330                            const VkImageSubresource *pSubresource,
1331                            VkSubresourceLayout *pLayout) {
1332    const VkLayerDispatchTable *disp;
1333
1334    disp = loader_get_dispatch(device);
1335
1336    disp->GetImageSubresourceLayout(device, image, pSubresource, pLayout);
1337}
1338
1339LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1340vkCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
1341                  const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
1342    const VkLayerDispatchTable *disp;
1343
1344    disp = loader_get_dispatch(device);
1345
1346    return disp->CreateImageView(device, pCreateInfo, pAllocator, pView);
1347}
1348
1349LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1350vkDestroyImageView(VkDevice device, VkImageView imageView,
1351                   const VkAllocationCallbacks *pAllocator) {
1352    const VkLayerDispatchTable *disp;
1353
1354    disp = loader_get_dispatch(device);
1355
1356    disp->DestroyImageView(device, imageView, pAllocator);
1357}
1358
1359LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1360vkCreateShaderModule(VkDevice device,
1361                     const VkShaderModuleCreateInfo *pCreateInfo,
1362                     const VkAllocationCallbacks *pAllocator,
1363                     VkShaderModule *pShader) {
1364    const VkLayerDispatchTable *disp;
1365
1366    disp = loader_get_dispatch(device);
1367
1368    return disp->CreateShaderModule(device, pCreateInfo, pAllocator, pShader);
1369}
1370
1371LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1372vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule,
1373                      const VkAllocationCallbacks *pAllocator) {
1374    const VkLayerDispatchTable *disp;
1375
1376    disp = loader_get_dispatch(device);
1377
1378    disp->DestroyShaderModule(device, shaderModule, pAllocator);
1379}
1380
1381LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1382vkCreatePipelineCache(VkDevice device,
1383                      const VkPipelineCacheCreateInfo *pCreateInfo,
1384                      const VkAllocationCallbacks *pAllocator,
1385                      VkPipelineCache *pPipelineCache) {
1386    const VkLayerDispatchTable *disp;
1387
1388    disp = loader_get_dispatch(device);
1389
1390    return disp->CreatePipelineCache(device, pCreateInfo, pAllocator,
1391                                     pPipelineCache);
1392}
1393
1394LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1395vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
1396                       const VkAllocationCallbacks *pAllocator) {
1397    const VkLayerDispatchTable *disp;
1398
1399    disp = loader_get_dispatch(device);
1400
1401    disp->DestroyPipelineCache(device, pipelineCache, pAllocator);
1402}
1403
1404LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1405vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache,
1406                       size_t *pDataSize, void *pData) {
1407    const VkLayerDispatchTable *disp;
1408
1409    disp = loader_get_dispatch(device);
1410
1411    return disp->GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
1412}
1413
1414LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1415vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache,
1416                      uint32_t srcCacheCount,
1417                      const VkPipelineCache *pSrcCaches) {
1418    const VkLayerDispatchTable *disp;
1419
1420    disp = loader_get_dispatch(device);
1421
1422    return disp->MergePipelineCaches(device, dstCache, srcCacheCount,
1423                                     pSrcCaches);
1424}
1425
1426LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1427vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache,
1428                          uint32_t createInfoCount,
1429                          const VkGraphicsPipelineCreateInfo *pCreateInfos,
1430                          const VkAllocationCallbacks *pAllocator,
1431                          VkPipeline *pPipelines) {
1432    const VkLayerDispatchTable *disp;
1433
1434    disp = loader_get_dispatch(device);
1435
1436    return disp->CreateGraphicsPipelines(device, pipelineCache, createInfoCount,
1437                                         pCreateInfos, pAllocator, pPipelines);
1438}
1439
1440LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1441vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache,
1442                         uint32_t createInfoCount,
1443                         const VkComputePipelineCreateInfo *pCreateInfos,
1444                         const VkAllocationCallbacks *pAllocator,
1445                         VkPipeline *pPipelines) {
1446    const VkLayerDispatchTable *disp;
1447
1448    disp = loader_get_dispatch(device);
1449
1450    return disp->CreateComputePipelines(device, pipelineCache, createInfoCount,
1451                                        pCreateInfos, pAllocator, pPipelines);
1452}
1453
1454LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1455vkDestroyPipeline(VkDevice device, VkPipeline pipeline,
1456                  const VkAllocationCallbacks *pAllocator) {
1457    const VkLayerDispatchTable *disp;
1458
1459    disp = loader_get_dispatch(device);
1460
1461    disp->DestroyPipeline(device, pipeline, pAllocator);
1462}
1463
1464LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1465vkCreatePipelineLayout(VkDevice device,
1466                       const VkPipelineLayoutCreateInfo *pCreateInfo,
1467                       const VkAllocationCallbacks *pAllocator,
1468                       VkPipelineLayout *pPipelineLayout) {
1469    const VkLayerDispatchTable *disp;
1470
1471    disp = loader_get_dispatch(device);
1472
1473    return disp->CreatePipelineLayout(device, pCreateInfo, pAllocator,
1474                                      pPipelineLayout);
1475}
1476
1477LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1478vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout,
1479                        const VkAllocationCallbacks *pAllocator) {
1480    const VkLayerDispatchTable *disp;
1481
1482    disp = loader_get_dispatch(device);
1483
1484    disp->DestroyPipelineLayout(device, pipelineLayout, pAllocator);
1485}
1486
1487LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1488vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
1489                const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
1490    const VkLayerDispatchTable *disp;
1491
1492    disp = loader_get_dispatch(device);
1493
1494    return disp->CreateSampler(device, pCreateInfo, pAllocator, pSampler);
1495}
1496
1497LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1498vkDestroySampler(VkDevice device, VkSampler sampler,
1499                 const VkAllocationCallbacks *pAllocator) {
1500    const VkLayerDispatchTable *disp;
1501
1502    disp = loader_get_dispatch(device);
1503
1504    disp->DestroySampler(device, sampler, pAllocator);
1505}
1506
1507LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1508vkCreateDescriptorSetLayout(VkDevice device,
1509                            const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
1510                            const VkAllocationCallbacks *pAllocator,
1511                            VkDescriptorSetLayout *pSetLayout) {
1512    const VkLayerDispatchTable *disp;
1513
1514    disp = loader_get_dispatch(device);
1515
1516    return disp->CreateDescriptorSetLayout(device, pCreateInfo, pAllocator,
1517                                           pSetLayout);
1518}
1519
1520LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1521vkDestroyDescriptorSetLayout(VkDevice device,
1522                             VkDescriptorSetLayout descriptorSetLayout,
1523                             const VkAllocationCallbacks *pAllocator) {
1524    const VkLayerDispatchTable *disp;
1525
1526    disp = loader_get_dispatch(device);
1527
1528    disp->DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
1529}
1530
1531LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1532vkCreateDescriptorPool(VkDevice device,
1533                       const VkDescriptorPoolCreateInfo *pCreateInfo,
1534                       const VkAllocationCallbacks *pAllocator,
1535                       VkDescriptorPool *pDescriptorPool) {
1536    const VkLayerDispatchTable *disp;
1537
1538    disp = loader_get_dispatch(device);
1539
1540    return disp->CreateDescriptorPool(device, pCreateInfo, pAllocator,
1541                                      pDescriptorPool);
1542}
1543
1544LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1545vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
1546                        const VkAllocationCallbacks *pAllocator) {
1547    const VkLayerDispatchTable *disp;
1548
1549    disp = loader_get_dispatch(device);
1550
1551    disp->DestroyDescriptorPool(device, descriptorPool, pAllocator);
1552}
1553
1554LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1555vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
1556                      VkDescriptorPoolResetFlags flags) {
1557    const VkLayerDispatchTable *disp;
1558
1559    disp = loader_get_dispatch(device);
1560
1561    return disp->ResetDescriptorPool(device, descriptorPool, flags);
1562}
1563
1564LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1565vkAllocateDescriptorSets(VkDevice device,
1566                         const VkDescriptorSetAllocateInfo *pAllocateInfo,
1567                         VkDescriptorSet *pDescriptorSets) {
1568    const VkLayerDispatchTable *disp;
1569
1570    disp = loader_get_dispatch(device);
1571
1572    return disp->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
1573}
1574
1575LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1576vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
1577                     uint32_t descriptorSetCount,
1578                     const VkDescriptorSet *pDescriptorSets) {
1579    const VkLayerDispatchTable *disp;
1580
1581    disp = loader_get_dispatch(device);
1582
1583    return disp->FreeDescriptorSets(device, descriptorPool, descriptorSetCount,
1584                                    pDescriptorSets);
1585}
1586
1587LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1588vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
1589                       const VkWriteDescriptorSet *pDescriptorWrites,
1590                       uint32_t descriptorCopyCount,
1591                       const VkCopyDescriptorSet *pDescriptorCopies) {
1592    const VkLayerDispatchTable *disp;
1593
1594    disp = loader_get_dispatch(device);
1595
1596    disp->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites,
1597                               descriptorCopyCount, pDescriptorCopies);
1598}
1599
1600LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1601vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
1602                    const VkAllocationCallbacks *pAllocator,
1603                    VkFramebuffer *pFramebuffer) {
1604    const VkLayerDispatchTable *disp;
1605
1606    disp = loader_get_dispatch(device);
1607
1608    return disp->CreateFramebuffer(device, pCreateInfo, pAllocator,
1609                                   pFramebuffer);
1610}
1611
1612LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1613vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer,
1614                     const VkAllocationCallbacks *pAllocator) {
1615    const VkLayerDispatchTable *disp;
1616
1617    disp = loader_get_dispatch(device);
1618
1619    disp->DestroyFramebuffer(device, framebuffer, pAllocator);
1620}
1621
1622LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1623vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
1624                   const VkAllocationCallbacks *pAllocator,
1625                   VkRenderPass *pRenderPass) {
1626    const VkLayerDispatchTable *disp;
1627
1628    disp = loader_get_dispatch(device);
1629
1630    return disp->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
1631}
1632
1633LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1634vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
1635                    const VkAllocationCallbacks *pAllocator) {
1636    const VkLayerDispatchTable *disp;
1637
1638    disp = loader_get_dispatch(device);
1639
1640    disp->DestroyRenderPass(device, renderPass, pAllocator);
1641}
1642
1643LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1644vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass,
1645                           VkExtent2D *pGranularity) {
1646    const VkLayerDispatchTable *disp;
1647
1648    disp = loader_get_dispatch(device);
1649
1650    disp->GetRenderAreaGranularity(device, renderPass, pGranularity);
1651}
1652
1653LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1654vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
1655                    const VkAllocationCallbacks *pAllocator,
1656                    VkCommandPool *pCommandPool) {
1657    const VkLayerDispatchTable *disp;
1658
1659    disp = loader_get_dispatch(device);
1660
1661    return disp->CreateCommandPool(device, pCreateInfo, pAllocator,
1662                                   pCommandPool);
1663}
1664
1665LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1666vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
1667                     const VkAllocationCallbacks *pAllocator) {
1668    const VkLayerDispatchTable *disp;
1669
1670    disp = loader_get_dispatch(device);
1671
1672    disp->DestroyCommandPool(device, commandPool, pAllocator);
1673}
1674
1675LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1676vkResetCommandPool(VkDevice device, VkCommandPool commandPool,
1677                   VkCommandPoolResetFlags flags) {
1678    const VkLayerDispatchTable *disp;
1679
1680    disp = loader_get_dispatch(device);
1681
1682    return disp->ResetCommandPool(device, commandPool, flags);
1683}
1684
1685LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1686vkAllocateCommandBuffers(VkDevice device,
1687                         const VkCommandBufferAllocateInfo *pAllocateInfo,
1688                         VkCommandBuffer *pCommandBuffers) {
1689    const VkLayerDispatchTable *disp;
1690    VkResult res;
1691
1692    disp = loader_get_dispatch(device);
1693
1694    res = disp->AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
1695    if (res == VK_SUCCESS) {
1696        for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
1697            if (pCommandBuffers[i]) {
1698                loader_init_dispatch(pCommandBuffers[i], disp);
1699            }
1700        }
1701    }
1702
1703    return res;
1704}
1705
1706LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1707vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
1708                     uint32_t commandBufferCount,
1709                     const VkCommandBuffer *pCommandBuffers) {
1710    const VkLayerDispatchTable *disp;
1711
1712    disp = loader_get_dispatch(device);
1713
1714    disp->FreeCommandBuffers(device, commandPool, commandBufferCount,
1715                             pCommandBuffers);
1716}
1717
1718LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1719vkBeginCommandBuffer(VkCommandBuffer commandBuffer,
1720                     const VkCommandBufferBeginInfo *pBeginInfo) {
1721    const VkLayerDispatchTable *disp;
1722
1723    disp = loader_get_dispatch(commandBuffer);
1724
1725    return disp->BeginCommandBuffer(commandBuffer, pBeginInfo);
1726}
1727
1728LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1729vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
1730    const VkLayerDispatchTable *disp;
1731
1732    disp = loader_get_dispatch(commandBuffer);
1733
1734    return disp->EndCommandBuffer(commandBuffer);
1735}
1736
1737LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1738vkResetCommandBuffer(VkCommandBuffer commandBuffer,
1739                     VkCommandBufferResetFlags flags) {
1740    const VkLayerDispatchTable *disp;
1741
1742    disp = loader_get_dispatch(commandBuffer);
1743
1744    return disp->ResetCommandBuffer(commandBuffer, flags);
1745}
1746
1747LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1748vkCmdBindPipeline(VkCommandBuffer commandBuffer,
1749                  VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
1750    const VkLayerDispatchTable *disp;
1751
1752    disp = loader_get_dispatch(commandBuffer);
1753
1754    disp->CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
1755}
1756
1757LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1758vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport,
1759                 uint32_t viewportCount, const VkViewport *pViewports) {
1760    const VkLayerDispatchTable *disp;
1761
1762    disp = loader_get_dispatch(commandBuffer);
1763
1764    disp->CmdSetViewport(commandBuffer, firstViewport, viewportCount,
1765                         pViewports);
1766}
1767
1768LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1769vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor,
1770                uint32_t scissorCount, const VkRect2D *pScissors) {
1771    const VkLayerDispatchTable *disp;
1772
1773    disp = loader_get_dispatch(commandBuffer);
1774
1775    disp->CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
1776}
1777
1778LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1779vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
1780    const VkLayerDispatchTable *disp;
1781
1782    disp = loader_get_dispatch(commandBuffer);
1783
1784    disp->CmdSetLineWidth(commandBuffer, lineWidth);
1785}
1786
1787LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1788vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor,
1789                  float depthBiasClamp, float depthBiasSlopeFactor) {
1790    const VkLayerDispatchTable *disp;
1791
1792    disp = loader_get_dispatch(commandBuffer);
1793
1794    disp->CmdSetDepthBias(commandBuffer, depthBiasConstantFactor,
1795                          depthBiasClamp, depthBiasSlopeFactor);
1796}
1797
1798LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1799vkCmdSetBlendConstants(VkCommandBuffer commandBuffer,
1800                       const float blendConstants[4]) {
1801    const VkLayerDispatchTable *disp;
1802
1803    disp = loader_get_dispatch(commandBuffer);
1804
1805    disp->CmdSetBlendConstants(commandBuffer, blendConstants);
1806}
1807
1808LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1809vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds,
1810                    float maxDepthBounds) {
1811    const VkLayerDispatchTable *disp;
1812
1813    disp = loader_get_dispatch(commandBuffer);
1814
1815    disp->CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
1816}
1817
1818LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1819vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
1820                           VkStencilFaceFlags faceMask, uint32_t compareMask) {
1821    const VkLayerDispatchTable *disp;
1822
1823    disp = loader_get_dispatch(commandBuffer);
1824
1825    disp->CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
1826}
1827
1828LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1829vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
1830                         VkStencilFaceFlags faceMask, uint32_t writeMask) {
1831    const VkLayerDispatchTable *disp;
1832
1833    disp = loader_get_dispatch(commandBuffer);
1834
1835    disp->CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
1836}
1837
1838LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1839vkCmdSetStencilReference(VkCommandBuffer commandBuffer,
1840                         VkStencilFaceFlags faceMask, uint32_t reference) {
1841    const VkLayerDispatchTable *disp;
1842
1843    disp = loader_get_dispatch(commandBuffer);
1844
1845    disp->CmdSetStencilReference(commandBuffer, faceMask, reference);
1846}
1847
1848LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets(
1849    VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
1850    VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount,
1851    const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount,
1852    const uint32_t *pDynamicOffsets) {
1853    const VkLayerDispatchTable *disp;
1854
1855    disp = loader_get_dispatch(commandBuffer);
1856
1857    disp->CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout,
1858                                firstSet, descriptorSetCount, pDescriptorSets,
1859                                dynamicOffsetCount, pDynamicOffsets);
1860}
1861
1862LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1863vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer,
1864                     VkDeviceSize offset, VkIndexType indexType) {
1865    const VkLayerDispatchTable *disp;
1866
1867    disp = loader_get_dispatch(commandBuffer);
1868
1869    disp->CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
1870}
1871
1872LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1873vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
1874                       uint32_t bindingCount, const VkBuffer *pBuffers,
1875                       const VkDeviceSize *pOffsets) {
1876    const VkLayerDispatchTable *disp;
1877
1878    disp = loader_get_dispatch(commandBuffer);
1879
1880    disp->CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount,
1881                               pBuffers, pOffsets);
1882}
1883
1884LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1885vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount,
1886          uint32_t instanceCount, uint32_t firstVertex,
1887          uint32_t firstInstance) {
1888    const VkLayerDispatchTable *disp;
1889
1890    disp = loader_get_dispatch(commandBuffer);
1891
1892    disp->CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex,
1893                  firstInstance);
1894}
1895
1896LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1897vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
1898                 uint32_t instanceCount, uint32_t firstIndex,
1899                 int32_t vertexOffset, uint32_t firstInstance) {
1900    const VkLayerDispatchTable *disp;
1901
1902    disp = loader_get_dispatch(commandBuffer);
1903
1904    disp->CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex,
1905                         vertexOffset, firstInstance);
1906}
1907
1908LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1909vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
1910                  VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
1911    const VkLayerDispatchTable *disp;
1912
1913    disp = loader_get_dispatch(commandBuffer);
1914
1915    disp->CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
1916}
1917
1918LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1919vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
1920                         VkDeviceSize offset, uint32_t drawCount,
1921                         uint32_t stride) {
1922    const VkLayerDispatchTable *disp;
1923
1924    disp = loader_get_dispatch(commandBuffer);
1925
1926    disp->CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount,
1927                                 stride);
1928}
1929
1930LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1931vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y,
1932              uint32_t z) {
1933    const VkLayerDispatchTable *disp;
1934
1935    disp = loader_get_dispatch(commandBuffer);
1936
1937    disp->CmdDispatch(commandBuffer, x, y, z);
1938}
1939
1940LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1941vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
1942                      VkDeviceSize offset) {
1943    const VkLayerDispatchTable *disp;
1944
1945    disp = loader_get_dispatch(commandBuffer);
1946
1947    disp->CmdDispatchIndirect(commandBuffer, buffer, offset);
1948}
1949
1950LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1951vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
1952                VkBuffer dstBuffer, uint32_t regionCount,
1953                const VkBufferCopy *pRegions) {
1954    const VkLayerDispatchTable *disp;
1955
1956    disp = loader_get_dispatch(commandBuffer);
1957
1958    disp->CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount,
1959                        pRegions);
1960}
1961
1962LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1963vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage,
1964               VkImageLayout srcImageLayout, VkImage dstImage,
1965               VkImageLayout dstImageLayout, uint32_t regionCount,
1966               const VkImageCopy *pRegions) {
1967    const VkLayerDispatchTable *disp;
1968
1969    disp = loader_get_dispatch(commandBuffer);
1970
1971    disp->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage,
1972                       dstImageLayout, regionCount, pRegions);
1973}
1974
1975LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1976vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage,
1977               VkImageLayout srcImageLayout, VkImage dstImage,
1978               VkImageLayout dstImageLayout, uint32_t regionCount,
1979               const VkImageBlit *pRegions, VkFilter filter) {
1980    const VkLayerDispatchTable *disp;
1981
1982    disp = loader_get_dispatch(commandBuffer);
1983
1984    disp->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage,
1985                       dstImageLayout, regionCount, pRegions, filter);
1986}
1987
1988LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
1989vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
1990                       VkImage dstImage, VkImageLayout dstImageLayout,
1991                       uint32_t regionCount,
1992                       const VkBufferImageCopy *pRegions) {
1993    const VkLayerDispatchTable *disp;
1994
1995    disp = loader_get_dispatch(commandBuffer);
1996
1997    disp->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage,
1998                               dstImageLayout, regionCount, pRegions);
1999}
2000
2001LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2002vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
2003                       VkImageLayout srcImageLayout, VkBuffer dstBuffer,
2004                       uint32_t regionCount,
2005                       const VkBufferImageCopy *pRegions) {
2006    const VkLayerDispatchTable *disp;
2007
2008    disp = loader_get_dispatch(commandBuffer);
2009
2010    disp->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout,
2011                               dstBuffer, regionCount, pRegions);
2012}
2013
2014LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2015vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
2016                  VkDeviceSize dstOffset, VkDeviceSize dataSize,
2017                  const uint32_t *pData) {
2018    const VkLayerDispatchTable *disp;
2019
2020    disp = loader_get_dispatch(commandBuffer);
2021
2022    disp->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
2023}
2024
2025LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2026vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
2027                VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
2028    const VkLayerDispatchTable *disp;
2029
2030    disp = loader_get_dispatch(commandBuffer);
2031
2032    disp->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
2033}
2034
2035LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2036vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
2037                     VkImageLayout imageLayout, const VkClearColorValue *pColor,
2038                     uint32_t rangeCount,
2039                     const VkImageSubresourceRange *pRanges) {
2040    const VkLayerDispatchTable *disp;
2041
2042    disp = loader_get_dispatch(commandBuffer);
2043
2044    disp->CmdClearColorImage(commandBuffer, image, imageLayout, pColor,
2045                             rangeCount, pRanges);
2046}
2047
2048LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2049vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image,
2050                            VkImageLayout imageLayout,
2051                            const VkClearDepthStencilValue *pDepthStencil,
2052                            uint32_t rangeCount,
2053                            const VkImageSubresourceRange *pRanges) {
2054    const VkLayerDispatchTable *disp;
2055
2056    disp = loader_get_dispatch(commandBuffer);
2057
2058    disp->CmdClearDepthStencilImage(commandBuffer, image, imageLayout,
2059                                    pDepthStencil, rangeCount, pRanges);
2060}
2061
2062LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2063vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
2064                      const VkClearAttachment *pAttachments, uint32_t rectCount,
2065                      const VkClearRect *pRects) {
2066    const VkLayerDispatchTable *disp;
2067
2068    disp = loader_get_dispatch(commandBuffer);
2069
2070    disp->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments,
2071                              rectCount, pRects);
2072}
2073
2074LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2075vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage,
2076                  VkImageLayout srcImageLayout, VkImage dstImage,
2077                  VkImageLayout dstImageLayout, uint32_t regionCount,
2078                  const VkImageResolve *pRegions) {
2079    const VkLayerDispatchTable *disp;
2080
2081    disp = loader_get_dispatch(commandBuffer);
2082
2083    disp->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage,
2084                          dstImageLayout, regionCount, pRegions);
2085}
2086
2087LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2088vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event,
2089              VkPipelineStageFlags stageMask) {
2090    const VkLayerDispatchTable *disp;
2091
2092    disp = loader_get_dispatch(commandBuffer);
2093
2094    disp->CmdSetEvent(commandBuffer, event, stageMask);
2095}
2096
2097LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2098vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event,
2099                VkPipelineStageFlags stageMask) {
2100    const VkLayerDispatchTable *disp;
2101
2102    disp = loader_get_dispatch(commandBuffer);
2103
2104    disp->CmdResetEvent(commandBuffer, event, stageMask);
2105}
2106
2107LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2108vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount,
2109                const VkEvent *pEvents, VkPipelineStageFlags sourceStageMask,
2110                VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount,
2111                const VkMemoryBarrier *pMemoryBarriers,
2112                uint32_t bufferMemoryBarrierCount,
2113                const VkBufferMemoryBarrier *pBufferMemoryBarriers,
2114                uint32_t imageMemoryBarrierCount,
2115                const VkImageMemoryBarrier *pImageMemoryBarriers) {
2116    const VkLayerDispatchTable *disp;
2117
2118    disp = loader_get_dispatch(commandBuffer);
2119
2120    disp->CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask,
2121                        dstStageMask, memoryBarrierCount, pMemoryBarriers,
2122                        bufferMemoryBarrierCount, pBufferMemoryBarriers,
2123                        imageMemoryBarrierCount, pImageMemoryBarriers);
2124}
2125
2126LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(
2127    VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
2128    VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
2129    uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
2130    uint32_t bufferMemoryBarrierCount,
2131    const VkBufferMemoryBarrier *pBufferMemoryBarriers,
2132    uint32_t imageMemoryBarrierCount,
2133    const VkImageMemoryBarrier *pImageMemoryBarriers) {
2134    const VkLayerDispatchTable *disp;
2135
2136    disp = loader_get_dispatch(commandBuffer);
2137
2138    disp->CmdPipelineBarrier(
2139        commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
2140        memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
2141        pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
2142}
2143
2144LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2145vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
2146                uint32_t slot, VkFlags flags) {
2147    const VkLayerDispatchTable *disp;
2148
2149    disp = loader_get_dispatch(commandBuffer);
2150
2151    disp->CmdBeginQuery(commandBuffer, queryPool, slot, flags);
2152}
2153
2154LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2155vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
2156              uint32_t slot) {
2157    const VkLayerDispatchTable *disp;
2158
2159    disp = loader_get_dispatch(commandBuffer);
2160
2161    disp->CmdEndQuery(commandBuffer, queryPool, slot);
2162}
2163
2164LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2165vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
2166                    uint32_t firstQuery, uint32_t queryCount) {
2167    const VkLayerDispatchTable *disp;
2168
2169    disp = loader_get_dispatch(commandBuffer);
2170
2171    disp->CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
2172}
2173
2174LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2175vkCmdWriteTimestamp(VkCommandBuffer commandBuffer,
2176                    VkPipelineStageFlagBits pipelineStage,
2177                    VkQueryPool queryPool, uint32_t slot) {
2178    const VkLayerDispatchTable *disp;
2179
2180    disp = loader_get_dispatch(commandBuffer);
2181
2182    disp->CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
2183}
2184
2185LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2186vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
2187                          uint32_t firstQuery, uint32_t queryCount,
2188                          VkBuffer dstBuffer, VkDeviceSize dstOffset,
2189                          VkDeviceSize stride, VkFlags flags) {
2190    const VkLayerDispatchTable *disp;
2191
2192    disp = loader_get_dispatch(commandBuffer);
2193
2194    disp->CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery,
2195                                  queryCount, dstBuffer, dstOffset, stride,
2196                                  flags);
2197}
2198
2199LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2200vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
2201                   VkShaderStageFlags stageFlags, uint32_t offset,
2202                   uint32_t size, const void *pValues) {
2203    const VkLayerDispatchTable *disp;
2204
2205    disp = loader_get_dispatch(commandBuffer);
2206
2207    disp->CmdPushConstants(commandBuffer, layout, stageFlags, offset, size,
2208                           pValues);
2209}
2210
2211LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2212vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
2213                     const VkRenderPassBeginInfo *pRenderPassBegin,
2214                     VkSubpassContents contents) {
2215    const VkLayerDispatchTable *disp;
2216
2217    disp = loader_get_dispatch(commandBuffer);
2218
2219    disp->CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
2220}
2221
2222LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2223vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
2224    const VkLayerDispatchTable *disp;
2225
2226    disp = loader_get_dispatch(commandBuffer);
2227
2228    disp->CmdNextSubpass(commandBuffer, contents);
2229}
2230
2231LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2232vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
2233    const VkLayerDispatchTable *disp;
2234
2235    disp = loader_get_dispatch(commandBuffer);
2236
2237    disp->CmdEndRenderPass(commandBuffer);
2238}
2239
2240LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
2241vkCmdExecuteCommands(VkCommandBuffer commandBuffer,
2242                     uint32_t commandBuffersCount,
2243                     const VkCommandBuffer *pCommandBuffers) {
2244    const VkLayerDispatchTable *disp;
2245
2246    disp = loader_get_dispatch(commandBuffer);
2247
2248    disp->CmdExecuteCommands(commandBuffer, commandBuffersCount,
2249                             pCommandBuffers);
2250}
2251