vulkan: initial loader and null driver

Change-Id: Id5ebb5f01e61e9b114990f49c64c88fbbb7b730e
(cherry picked from commit 4df205cdfc61e66de774ba50be9ef59a08cf88bb)
diff --git a/vulkan/.clang-format b/vulkan/.clang-format
new file mode 100644
index 0000000..563cd9a
--- /dev/null
+++ b/vulkan/.clang-format
@@ -0,0 +1,2 @@
+BasedOnStyle: Chromium
+IndentWidth: 4
diff --git a/vulkan/api/templates/vulkan_common.tmpl b/vulkan/api/templates/vulkan_common.tmpl
index 8c27c02..135c835 100644
--- a/vulkan/api/templates/vulkan_common.tmpl
+++ b/vulkan/api/templates/vulkan_common.tmpl
@@ -199,3 +199,24 @@
     {{Global $d.Name $d.Expression}}
   {{end}}
 {{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Given a function, return "Global", "Instance", or "Device" depending on which
+  dispatch table the function belongs to.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Vtbl#VkInstance"      }}Instance{{end}}
+{{define "Vtbl#VkPhysicalDevice"}}Instance{{end}}
+{{define "Vtbl#VkDevice"        }}Device{{end}}
+{{define "Vtbl#VkQueue"         }}Device{{end}}
+{{define "Vtbl#VkCmdBuffer"     }}Device{{end}}
+{{define "Vtbl_Default"         }}Global{{end}}
+{{define "Vtbl"}}
+  {{AssertType $ "Function"}}
+
+  {{range $i, $p := $.CallParameters}}
+    {{if not $i}}{{Node "Vtbl" $p}}{{end}}
+  {{end}}
+{{end}}
diff --git a/vulkan/include/hardware/hwvulkan.h b/vulkan/include/hardware/hwvulkan.h
new file mode 100644
index 0000000..91dd41e
--- /dev/null
+++ b/vulkan/include/hardware/hwvulkan.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWVULKAN_H
+#define ANDROID_HWVULKAN_H
+
+#include <hardware/hardware.h>
+#include <vulkan/vulkan.h>
+
+__BEGIN_DECLS
+
+#define HWVULKAN_HARDWARE_MODULE_ID "vulkan"
+
+#define HWVULKAN_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1)
+#define HWVULKAN_DEVICE_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION_2(0, 1, 0)
+
+#define HWVULKAN_DEVICE_0 "vk0"
+
+typedef struct hwvulkan_module_t {
+    struct hw_module_t common;
+} hwvulkan_module_t;
+
+/* Dispatchable Vulkan object handles must be pointers, which must point to
+ * instances of hwvulkan_dispatch_t (potentially followed by additional
+ * implementation-defined data). On return from the creation function, the
+ * 'magic' field must contain HWVULKAN_DISPATCH_MAGIC; the loader will overwrite
+ * the 'vtbl' field.
+ */
+#if defined(__LP64__)
+#define HWVULKAN_DISPATCH_MAGIC UINT64_C(0xCA11AB1E00C0DE00)
+#elif defined(__ILP32__)
+#define HWVULKAN_DISPATCH_MAGIC UINT32_C(0xCA11AB1E)
+#else
+#error "unknown pointer size?!"
+#endif
+
+typedef union {
+    uintptr_t magic;
+    const void* vtbl;
+} hwvulkan_dispatch_t;
+
+/* A hwvulkan_device_t corresponds to an ICD on other systems. Currently there
+ * can only be one on a system (HWVULKAN_DEVICE_0). It is opened once per
+ * process when the Vulkan API is first used; the hw_device_t::close() function
+ * is never called. Any non-trivial resource allocation should be done when
+ * the VkInstance is created rather than when the hwvulkan_device_t is opened.
+ */
+typedef struct hwvulkan_device_t {
+    struct hw_device_t common;
+
+    PFN_vkGetGlobalExtensionProperties GetGlobalExtensionProperties;
+    PFN_vkCreateInstance CreateInstance;
+    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+} hwvulkan_device_t;
+
+__END_DECLS
+
+#endif  // ANDROID_HWVULKAN_H
diff --git a/vulkan/include/vulkan/vk_platform.h b/vulkan/include/vulkan/vk_platform.h
new file mode 100644
index 0000000..7ba8d77
--- /dev/null
+++ b/vulkan/include/vulkan/vk_platform.h
@@ -0,0 +1,90 @@
+//
+// File: vk_platform.h
+//
+/*
+** Copyright (c) 2014-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+
+#ifndef __VK_PLATFORM_H__
+#define __VK_PLATFORM_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*
+***************************************************************************************************
+*   Platform-specific directives and type declarations
+***************************************************************************************************
+*/
+
+#if defined(_WIN32)
+    // On Windows, VKAPI should equate to the __stdcall convention
+    #define VKAPI   __stdcall
+#elif defined(__GNUC__)
+    // On other platforms using GCC, VKAPI stays undefined
+    #define VKAPI
+#else
+    // Unsupported Platform!
+    #error "Unsupported OS Platform detected!"
+#endif
+
+#include <stddef.h>
+
+#if !defined(VK_NO_STDINT_H)
+    #if defined(_MSC_VER) && (_MSC_VER < 1600)
+        typedef signed   __int8  int8_t;
+        typedef unsigned __int8  uint8_t;
+        typedef signed   __int16 int16_t;
+        typedef unsigned __int16 uint16_t;
+        typedef signed   __int32 int32_t;
+        typedef unsigned __int32 uint32_t;
+        typedef signed   __int64 int64_t;
+        typedef unsigned __int64 uint64_t;
+    #else
+        #include <stdint.h>
+    #endif
+#endif // !defined(VK_NO_STDINT_H)
+
+typedef uint64_t   VkDeviceSize;
+typedef uint32_t   VkBool32;
+
+typedef uint32_t   VkSampleMask;
+typedef uint32_t   VkFlags;
+
+#if (UINTPTR_MAX >= UINT64_MAX)
+    #define VK_UINTPTRLEAST64_MAX UINTPTR_MAX
+
+    typedef uintptr_t VkUintPtrLeast64;
+#else
+    #define VK_UINTPTRLEAST64_MAX UINT64_MAX
+
+    typedef uint64_t  VkUintPtrLeast64;
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // __VK_PLATFORM_H__
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
new file mode 100644
index 0000000..9877233
--- /dev/null
+++ b/vulkan/include/vulkan/vulkan.h
@@ -0,0 +1,3054 @@
+#ifndef __vulkan_h_
+#define __vulkan_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#define VK_VERSION_1_0 1
+#include "vk_platform.h"
+
+#define VK_MAKE_VERSION(major, minor, patch) \
+    ((major << 22) | (minor << 12) | patch)
+
+// Vulkan API version supported by this file
+#define VK_API_VERSION VK_MAKE_VERSION(0, 138, 2)
+
+
+#define VK_DEFINE_HANDLE(obj) typedef struct obj##_T* obj;
+
+
+#if defined(__cplusplus)
+    #if (_MSC_VER >= 1800 || __cplusplus >= 201103L)
+        // The bool operator only works if there are no implicit conversions from an obj to
+        // a bool-compatible type, which can then be used to unintentionally violate type safety.
+        // C++11 and above supports the "explicit" keyword on conversion operators to stop this
+        // from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
+        // the object handle as a bool in expressions like:
+        //     if (obj) vkDestroy(obj);
+        #define VK_NONDISP_HANDLE_OPERATOR_BOOL() explicit operator bool() const { return handle != 0; }
+    #else
+        #define VK_NONDISP_HANDLE_OPERATOR_BOOL()
+    #endif
+    #define VK_DEFINE_NONDISP_HANDLE(obj) \
+        struct obj { \
+            obj() : handle(0) { } \
+            obj(uint64_t x) : handle(x) { } \
+            obj& operator =(uint64_t x) { handle = x; return *this; } \
+            bool operator==(const obj& other) const { return handle == other.handle; } \
+            bool operator!=(const obj& other) const { return handle != other.handle; } \
+            bool operator!() const { return !handle; } \
+            VK_NONDISP_HANDLE_OPERATOR_BOOL() \
+            uint64_t handle; \
+        };
+#else
+    #define VK_DEFINE_NONDISP_HANDLE(obj) typedef struct obj##_T { uint64_t handle; } obj;
+#endif
+        
+
+
+#define VK_LOD_CLAMP_NONE                 MAX_FLOAT
+#define VK_LAST_MIP_LEVEL                 UINT32_MAX
+#define VK_LAST_ARRAY_SLICE               UINT32_MAX
+#define VK_WHOLE_SIZE                     UINT64_MAX
+#define VK_ATTACHMENT_UNUSED              UINT32_MAX
+#define VK_TRUE                           1
+#define VK_FALSE                          0
+#define VK_NULL_HANDLE                    0
+#define VK_MAX_PHYSICAL_DEVICE_NAME       256
+#define VK_UUID_LENGTH                    16
+#define VK_MAX_MEMORY_TYPES               32
+#define VK_MAX_MEMORY_HEAPS               16
+#define VK_MAX_EXTENSION_NAME             256
+#define VK_MAX_DESCRIPTION                256
+
+VK_DEFINE_HANDLE(VkInstance)
+VK_DEFINE_HANDLE(VkPhysicalDevice)
+VK_DEFINE_HANDLE(VkDevice)
+VK_DEFINE_HANDLE(VkQueue)
+VK_DEFINE_HANDLE(VkCmdBuffer)
+VK_DEFINE_NONDISP_HANDLE(VkFence)
+VK_DEFINE_NONDISP_HANDLE(VkDeviceMemory)
+VK_DEFINE_NONDISP_HANDLE(VkBuffer)
+VK_DEFINE_NONDISP_HANDLE(VkImage)
+VK_DEFINE_NONDISP_HANDLE(VkSemaphore)
+VK_DEFINE_NONDISP_HANDLE(VkEvent)
+VK_DEFINE_NONDISP_HANDLE(VkQueryPool)
+VK_DEFINE_NONDISP_HANDLE(VkBufferView)
+VK_DEFINE_NONDISP_HANDLE(VkImageView)
+VK_DEFINE_NONDISP_HANDLE(VkAttachmentView)
+VK_DEFINE_NONDISP_HANDLE(VkShaderModule)
+VK_DEFINE_NONDISP_HANDLE(VkShader)
+VK_DEFINE_NONDISP_HANDLE(VkPipelineCache)
+VK_DEFINE_NONDISP_HANDLE(VkPipelineLayout)
+VK_DEFINE_NONDISP_HANDLE(VkRenderPass)
+VK_DEFINE_NONDISP_HANDLE(VkPipeline)
+VK_DEFINE_NONDISP_HANDLE(VkDescriptorSetLayout)
+VK_DEFINE_NONDISP_HANDLE(VkSampler)
+VK_DEFINE_NONDISP_HANDLE(VkDescriptorPool)
+VK_DEFINE_NONDISP_HANDLE(VkDescriptorSet)
+VK_DEFINE_NONDISP_HANDLE(VkDynamicViewportState)
+VK_DEFINE_NONDISP_HANDLE(VkDynamicRasterState)
+VK_DEFINE_NONDISP_HANDLE(VkDynamicColorBlendState)
+VK_DEFINE_NONDISP_HANDLE(VkDynamicDepthStencilState)
+VK_DEFINE_NONDISP_HANDLE(VkFramebuffer)
+VK_DEFINE_NONDISP_HANDLE(VkCmdPool)
+
+
+typedef enum {
+    VK_SUCCESS = 0,
+    VK_UNSUPPORTED = 1,
+    VK_NOT_READY = 2,
+    VK_TIMEOUT = 3,
+    VK_EVENT_SET = 4,
+    VK_EVENT_RESET = 5,
+    VK_INCOMPLETE = 6,
+    VK_ERROR_UNKNOWN = -1,
+    VK_ERROR_UNAVAILABLE = -2,
+    VK_ERROR_INITIALIZATION_FAILED = -3,
+    VK_ERROR_OUT_OF_HOST_MEMORY = -4,
+    VK_ERROR_OUT_OF_DEVICE_MEMORY = -5,
+    VK_ERROR_DEVICE_ALREADY_CREATED = -6,
+    VK_ERROR_DEVICE_LOST = -7,
+    VK_ERROR_INVALID_POINTER = -8,
+    VK_ERROR_INVALID_VALUE = -9,
+    VK_ERROR_INVALID_HANDLE = -10,
+    VK_ERROR_INVALID_ORDINAL = -11,
+    VK_ERROR_INVALID_MEMORY_SIZE = -12,
+    VK_ERROR_INVALID_EXTENSION = -13,
+    VK_ERROR_INVALID_FLAGS = -14,
+    VK_ERROR_INVALID_ALIGNMENT = -15,
+    VK_ERROR_INVALID_FORMAT = -16,
+    VK_ERROR_INVALID_IMAGE = -17,
+    VK_ERROR_INVALID_DESCRIPTOR_SET_DATA = -18,
+    VK_ERROR_INVALID_QUEUE_TYPE = -19,
+    VK_ERROR_UNSUPPORTED_SHADER_IL_VERSION = -20,
+    VK_ERROR_BAD_SHADER_CODE = -21,
+    VK_ERROR_BAD_PIPELINE_DATA = -22,
+    VK_ERROR_NOT_MAPPABLE = -23,
+    VK_ERROR_MEMORY_MAP_FAILED = -24,
+    VK_ERROR_MEMORY_UNMAP_FAILED = -25,
+    VK_ERROR_INCOMPATIBLE_DEVICE = -26,
+    VK_ERROR_INCOMPATIBLE_DRIVER = -27,
+    VK_ERROR_INCOMPLETE_COMMAND_BUFFER = -28,
+    VK_ERROR_BUILDING_COMMAND_BUFFER = -29,
+    VK_ERROR_MEMORY_NOT_BOUND = -30,
+    VK_ERROR_INCOMPATIBLE_QUEUE = -31,
+    VK_ERROR_INVALID_LAYER = -32,
+    VK_RESULT_BEGIN_RANGE = VK_ERROR_INVALID_LAYER,
+    VK_RESULT_END_RANGE = VK_INCOMPLETE,
+    VK_RESULT_NUM = (VK_INCOMPLETE - VK_ERROR_INVALID_LAYER + 1),
+    VK_RESULT_MAX_ENUM = 0x7FFFFFFF
+} VkResult;
+
+typedef enum {
+    VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
+    VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 1,
+    VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO = 2,
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 3,
+    VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO = 4,
+    VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 5,
+    VK_STRUCTURE_TYPE_SHADER_CREATE_INFO = 6,
+    VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 7,
+    VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 8,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 9,
+    VK_STRUCTURE_TYPE_DYNAMIC_VIEWPORT_STATE_CREATE_INFO = 10,
+    VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO = 11,
+    VK_STRUCTURE_TYPE_DYNAMIC_COLOR_BLEND_STATE_CREATE_INFO = 12,
+    VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO = 13,
+    VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO = 14,
+    VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 15,
+    VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 16,
+    VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 17,
+    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 18,
+    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 19,
+    VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 20,
+    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 21,
+    VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 22,
+    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 23,
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 24,
+    VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO = 25,
+    VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 26,
+    VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 27,
+    VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 28,
+    VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 29,
+    VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 30,
+    VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 31,
+    VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 32,
+    VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO = 33,
+    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 34,
+    VK_STRUCTURE_TYPE_MEMORY_BARRIER = 35,
+    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 36,
+    VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 37,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 38,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 39,
+    VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 40,
+    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 41,
+    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 42,
+    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 43,
+    VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 44,
+    VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION = 45,
+    VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION = 46,
+    VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY = 47,
+    VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 48,
+    VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO = 49,
+    VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+    VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,
+    VK_STRUCTURE_TYPE_NUM = (VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
+    VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkStructureType;
+
+typedef enum {
+    VK_SYSTEM_ALLOC_TYPE_API_OBJECT = 0,
+    VK_SYSTEM_ALLOC_TYPE_INTERNAL = 1,
+    VK_SYSTEM_ALLOC_TYPE_INTERNAL_TEMP = 2,
+    VK_SYSTEM_ALLOC_TYPE_INTERNAL_SHADER = 3,
+    VK_SYSTEM_ALLOC_TYPE_DEBUG = 4,
+    VK_SYSTEM_ALLOC_TYPE_BEGIN_RANGE = VK_SYSTEM_ALLOC_TYPE_API_OBJECT,
+    VK_SYSTEM_ALLOC_TYPE_END_RANGE = VK_SYSTEM_ALLOC_TYPE_DEBUG,
+    VK_SYSTEM_ALLOC_TYPE_NUM = (VK_SYSTEM_ALLOC_TYPE_DEBUG - VK_SYSTEM_ALLOC_TYPE_API_OBJECT + 1),
+    VK_SYSTEM_ALLOC_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkSystemAllocType;
+
+typedef enum {
+    VK_FORMAT_UNDEFINED = 0,
+    VK_FORMAT_R4G4_UNORM = 1,
+    VK_FORMAT_R4G4_USCALED = 2,
+    VK_FORMAT_R4G4B4A4_UNORM = 3,
+    VK_FORMAT_R4G4B4A4_USCALED = 4,
+    VK_FORMAT_R5G6B5_UNORM = 5,
+    VK_FORMAT_R5G6B5_USCALED = 6,
+    VK_FORMAT_R5G5B5A1_UNORM = 7,
+    VK_FORMAT_R5G5B5A1_USCALED = 8,
+    VK_FORMAT_R8_UNORM = 9,
+    VK_FORMAT_R8_SNORM = 10,
+    VK_FORMAT_R8_USCALED = 11,
+    VK_FORMAT_R8_SSCALED = 12,
+    VK_FORMAT_R8_UINT = 13,
+    VK_FORMAT_R8_SINT = 14,
+    VK_FORMAT_R8_SRGB = 15,
+    VK_FORMAT_R8G8_UNORM = 16,
+    VK_FORMAT_R8G8_SNORM = 17,
+    VK_FORMAT_R8G8_USCALED = 18,
+    VK_FORMAT_R8G8_SSCALED = 19,
+    VK_FORMAT_R8G8_UINT = 20,
+    VK_FORMAT_R8G8_SINT = 21,
+    VK_FORMAT_R8G8_SRGB = 22,
+    VK_FORMAT_R8G8B8_UNORM = 23,
+    VK_FORMAT_R8G8B8_SNORM = 24,
+    VK_FORMAT_R8G8B8_USCALED = 25,
+    VK_FORMAT_R8G8B8_SSCALED = 26,
+    VK_FORMAT_R8G8B8_UINT = 27,
+    VK_FORMAT_R8G8B8_SINT = 28,
+    VK_FORMAT_R8G8B8_SRGB = 29,
+    VK_FORMAT_R8G8B8A8_UNORM = 30,
+    VK_FORMAT_R8G8B8A8_SNORM = 31,
+    VK_FORMAT_R8G8B8A8_USCALED = 32,
+    VK_FORMAT_R8G8B8A8_SSCALED = 33,
+    VK_FORMAT_R8G8B8A8_UINT = 34,
+    VK_FORMAT_R8G8B8A8_SINT = 35,
+    VK_FORMAT_R8G8B8A8_SRGB = 36,
+    VK_FORMAT_R10G10B10A2_UNORM = 37,
+    VK_FORMAT_R10G10B10A2_SNORM = 38,
+    VK_FORMAT_R10G10B10A2_USCALED = 39,
+    VK_FORMAT_R10G10B10A2_SSCALED = 40,
+    VK_FORMAT_R10G10B10A2_UINT = 41,
+    VK_FORMAT_R10G10B10A2_SINT = 42,
+    VK_FORMAT_R16_UNORM = 43,
+    VK_FORMAT_R16_SNORM = 44,
+    VK_FORMAT_R16_USCALED = 45,
+    VK_FORMAT_R16_SSCALED = 46,
+    VK_FORMAT_R16_UINT = 47,
+    VK_FORMAT_R16_SINT = 48,
+    VK_FORMAT_R16_SFLOAT = 49,
+    VK_FORMAT_R16G16_UNORM = 50,
+    VK_FORMAT_R16G16_SNORM = 51,
+    VK_FORMAT_R16G16_USCALED = 52,
+    VK_FORMAT_R16G16_SSCALED = 53,
+    VK_FORMAT_R16G16_UINT = 54,
+    VK_FORMAT_R16G16_SINT = 55,
+    VK_FORMAT_R16G16_SFLOAT = 56,
+    VK_FORMAT_R16G16B16_UNORM = 57,
+    VK_FORMAT_R16G16B16_SNORM = 58,
+    VK_FORMAT_R16G16B16_USCALED = 59,
+    VK_FORMAT_R16G16B16_SSCALED = 60,
+    VK_FORMAT_R16G16B16_UINT = 61,
+    VK_FORMAT_R16G16B16_SINT = 62,
+    VK_FORMAT_R16G16B16_SFLOAT = 63,
+    VK_FORMAT_R16G16B16A16_UNORM = 64,
+    VK_FORMAT_R16G16B16A16_SNORM = 65,
+    VK_FORMAT_R16G16B16A16_USCALED = 66,
+    VK_FORMAT_R16G16B16A16_SSCALED = 67,
+    VK_FORMAT_R16G16B16A16_UINT = 68,
+    VK_FORMAT_R16G16B16A16_SINT = 69,
+    VK_FORMAT_R16G16B16A16_SFLOAT = 70,
+    VK_FORMAT_R32_UINT = 71,
+    VK_FORMAT_R32_SINT = 72,
+    VK_FORMAT_R32_SFLOAT = 73,
+    VK_FORMAT_R32G32_UINT = 74,
+    VK_FORMAT_R32G32_SINT = 75,
+    VK_FORMAT_R32G32_SFLOAT = 76,
+    VK_FORMAT_R32G32B32_UINT = 77,
+    VK_FORMAT_R32G32B32_SINT = 78,
+    VK_FORMAT_R32G32B32_SFLOAT = 79,
+    VK_FORMAT_R32G32B32A32_UINT = 80,
+    VK_FORMAT_R32G32B32A32_SINT = 81,
+    VK_FORMAT_R32G32B32A32_SFLOAT = 82,
+    VK_FORMAT_R64_SFLOAT = 83,
+    VK_FORMAT_R64G64_SFLOAT = 84,
+    VK_FORMAT_R64G64B64_SFLOAT = 85,
+    VK_FORMAT_R64G64B64A64_SFLOAT = 86,
+    VK_FORMAT_R11G11B10_UFLOAT = 87,
+    VK_FORMAT_R9G9B9E5_UFLOAT = 88,
+    VK_FORMAT_D16_UNORM = 89,
+    VK_FORMAT_D24_UNORM = 90,
+    VK_FORMAT_D32_SFLOAT = 91,
+    VK_FORMAT_S8_UINT = 92,
+    VK_FORMAT_D16_UNORM_S8_UINT = 93,
+    VK_FORMAT_D24_UNORM_S8_UINT = 94,
+    VK_FORMAT_D32_SFLOAT_S8_UINT = 95,
+    VK_FORMAT_BC1_RGB_UNORM = 96,
+    VK_FORMAT_BC1_RGB_SRGB = 97,
+    VK_FORMAT_BC1_RGBA_UNORM = 98,
+    VK_FORMAT_BC1_RGBA_SRGB = 99,
+    VK_FORMAT_BC2_UNORM = 100,
+    VK_FORMAT_BC2_SRGB = 101,
+    VK_FORMAT_BC3_UNORM = 102,
+    VK_FORMAT_BC3_SRGB = 103,
+    VK_FORMAT_BC4_UNORM = 104,
+    VK_FORMAT_BC4_SNORM = 105,
+    VK_FORMAT_BC5_UNORM = 106,
+    VK_FORMAT_BC5_SNORM = 107,
+    VK_FORMAT_BC6H_UFLOAT = 108,
+    VK_FORMAT_BC6H_SFLOAT = 109,
+    VK_FORMAT_BC7_UNORM = 110,
+    VK_FORMAT_BC7_SRGB = 111,
+    VK_FORMAT_ETC2_R8G8B8_UNORM = 112,
+    VK_FORMAT_ETC2_R8G8B8_SRGB = 113,
+    VK_FORMAT_ETC2_R8G8B8A1_UNORM = 114,
+    VK_FORMAT_ETC2_R8G8B8A1_SRGB = 115,
+    VK_FORMAT_ETC2_R8G8B8A8_UNORM = 116,
+    VK_FORMAT_ETC2_R8G8B8A8_SRGB = 117,
+    VK_FORMAT_EAC_R11_UNORM = 118,
+    VK_FORMAT_EAC_R11_SNORM = 119,
+    VK_FORMAT_EAC_R11G11_UNORM = 120,
+    VK_FORMAT_EAC_R11G11_SNORM = 121,
+    VK_FORMAT_ASTC_4x4_UNORM = 122,
+    VK_FORMAT_ASTC_4x4_SRGB = 123,
+    VK_FORMAT_ASTC_5x4_UNORM = 124,
+    VK_FORMAT_ASTC_5x4_SRGB = 125,
+    VK_FORMAT_ASTC_5x5_UNORM = 126,
+    VK_FORMAT_ASTC_5x5_SRGB = 127,
+    VK_FORMAT_ASTC_6x5_UNORM = 128,
+    VK_FORMAT_ASTC_6x5_SRGB = 129,
+    VK_FORMAT_ASTC_6x6_UNORM = 130,
+    VK_FORMAT_ASTC_6x6_SRGB = 131,
+    VK_FORMAT_ASTC_8x5_UNORM = 132,
+    VK_FORMAT_ASTC_8x5_SRGB = 133,
+    VK_FORMAT_ASTC_8x6_UNORM = 134,
+    VK_FORMAT_ASTC_8x6_SRGB = 135,
+    VK_FORMAT_ASTC_8x8_UNORM = 136,
+    VK_FORMAT_ASTC_8x8_SRGB = 137,
+    VK_FORMAT_ASTC_10x5_UNORM = 138,
+    VK_FORMAT_ASTC_10x5_SRGB = 139,
+    VK_FORMAT_ASTC_10x6_UNORM = 140,
+    VK_FORMAT_ASTC_10x6_SRGB = 141,
+    VK_FORMAT_ASTC_10x8_UNORM = 142,
+    VK_FORMAT_ASTC_10x8_SRGB = 143,
+    VK_FORMAT_ASTC_10x10_UNORM = 144,
+    VK_FORMAT_ASTC_10x10_SRGB = 145,
+    VK_FORMAT_ASTC_12x10_UNORM = 146,
+    VK_FORMAT_ASTC_12x10_SRGB = 147,
+    VK_FORMAT_ASTC_12x12_UNORM = 148,
+    VK_FORMAT_ASTC_12x12_SRGB = 149,
+    VK_FORMAT_B4G4R4A4_UNORM = 150,
+    VK_FORMAT_B5G5R5A1_UNORM = 151,
+    VK_FORMAT_B5G6R5_UNORM = 152,
+    VK_FORMAT_B5G6R5_USCALED = 153,
+    VK_FORMAT_B8G8R8_UNORM = 154,
+    VK_FORMAT_B8G8R8_SNORM = 155,
+    VK_FORMAT_B8G8R8_USCALED = 156,
+    VK_FORMAT_B8G8R8_SSCALED = 157,
+    VK_FORMAT_B8G8R8_UINT = 158,
+    VK_FORMAT_B8G8R8_SINT = 159,
+    VK_FORMAT_B8G8R8_SRGB = 160,
+    VK_FORMAT_B8G8R8A8_UNORM = 161,
+    VK_FORMAT_B8G8R8A8_SNORM = 162,
+    VK_FORMAT_B8G8R8A8_USCALED = 163,
+    VK_FORMAT_B8G8R8A8_SSCALED = 164,
+    VK_FORMAT_B8G8R8A8_UINT = 165,
+    VK_FORMAT_B8G8R8A8_SINT = 166,
+    VK_FORMAT_B8G8R8A8_SRGB = 167,
+    VK_FORMAT_B10G10R10A2_UNORM = 168,
+    VK_FORMAT_B10G10R10A2_SNORM = 169,
+    VK_FORMAT_B10G10R10A2_USCALED = 170,
+    VK_FORMAT_B10G10R10A2_SSCALED = 171,
+    VK_FORMAT_B10G10R10A2_UINT = 172,
+    VK_FORMAT_B10G10R10A2_SINT = 173,
+    VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED,
+    VK_FORMAT_END_RANGE = VK_FORMAT_B10G10R10A2_SINT,
+    VK_FORMAT_NUM = (VK_FORMAT_B10G10R10A2_SINT - VK_FORMAT_UNDEFINED + 1),
+    VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
+} VkFormat;
+
+typedef enum {
+    VK_IMAGE_TYPE_1D = 0,
+    VK_IMAGE_TYPE_2D = 1,
+    VK_IMAGE_TYPE_3D = 2,
+    VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D,
+    VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D,
+    VK_IMAGE_TYPE_NUM = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1),
+    VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkImageType;
+
+typedef enum {
+    VK_IMAGE_TILING_LINEAR = 0,
+    VK_IMAGE_TILING_OPTIMAL = 1,
+    VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_LINEAR,
+    VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_OPTIMAL,
+    VK_IMAGE_TILING_NUM = (VK_IMAGE_TILING_OPTIMAL - VK_IMAGE_TILING_LINEAR + 1),
+    VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF
+} VkImageTiling;
+
+typedef enum {
+    VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
+    VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
+    VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
+    VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
+    VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
+    VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER,
+    VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU,
+    VK_PHYSICAL_DEVICE_TYPE_NUM = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1),
+    VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkPhysicalDeviceType;
+
+typedef enum {
+    VK_IMAGE_ASPECT_COLOR = 0,
+    VK_IMAGE_ASPECT_DEPTH = 1,
+    VK_IMAGE_ASPECT_STENCIL = 2,
+    VK_IMAGE_ASPECT_METADATA = 3,
+    VK_IMAGE_ASPECT_BEGIN_RANGE = VK_IMAGE_ASPECT_COLOR,
+    VK_IMAGE_ASPECT_END_RANGE = VK_IMAGE_ASPECT_METADATA,
+    VK_IMAGE_ASPECT_NUM = (VK_IMAGE_ASPECT_METADATA - VK_IMAGE_ASPECT_COLOR + 1),
+    VK_IMAGE_ASPECT_MAX_ENUM = 0x7FFFFFFF
+} VkImageAspect;
+
+typedef enum {
+    VK_QUERY_TYPE_OCCLUSION = 0,
+    VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
+    VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
+    VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_PIPELINE_STATISTICS,
+    VK_QUERY_TYPE_NUM = (VK_QUERY_TYPE_PIPELINE_STATISTICS - VK_QUERY_TYPE_OCCLUSION + 1),
+    VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkQueryType;
+
+typedef enum {
+    VK_SHARING_MODE_EXCLUSIVE = 0,
+    VK_SHARING_MODE_CONCURRENT = 1,
+    VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE,
+    VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT,
+    VK_SHARING_MODE_NUM = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1),
+    VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSharingMode;
+
+typedef enum {
+    VK_BUFFER_VIEW_TYPE_RAW = 0,
+    VK_BUFFER_VIEW_TYPE_FORMATTED = 1,
+    VK_BUFFER_VIEW_TYPE_BEGIN_RANGE = VK_BUFFER_VIEW_TYPE_RAW,
+    VK_BUFFER_VIEW_TYPE_END_RANGE = VK_BUFFER_VIEW_TYPE_FORMATTED,
+    VK_BUFFER_VIEW_TYPE_NUM = (VK_BUFFER_VIEW_TYPE_FORMATTED - VK_BUFFER_VIEW_TYPE_RAW + 1),
+    VK_BUFFER_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkBufferViewType;
+
+typedef enum {
+    VK_IMAGE_VIEW_TYPE_1D = 0,
+    VK_IMAGE_VIEW_TYPE_2D = 1,
+    VK_IMAGE_VIEW_TYPE_3D = 2,
+    VK_IMAGE_VIEW_TYPE_CUBE = 3,
+    VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4,
+    VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5,
+    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6,
+    VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D,
+    VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
+    VK_IMAGE_VIEW_TYPE_NUM = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1),
+    VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkImageViewType;
+
+typedef enum {
+    VK_CHANNEL_SWIZZLE_ZERO = 0,
+    VK_CHANNEL_SWIZZLE_ONE = 1,
+    VK_CHANNEL_SWIZZLE_R = 2,
+    VK_CHANNEL_SWIZZLE_G = 3,
+    VK_CHANNEL_SWIZZLE_B = 4,
+    VK_CHANNEL_SWIZZLE_A = 5,
+    VK_CHANNEL_SWIZZLE_BEGIN_RANGE = VK_CHANNEL_SWIZZLE_ZERO,
+    VK_CHANNEL_SWIZZLE_END_RANGE = VK_CHANNEL_SWIZZLE_A,
+    VK_CHANNEL_SWIZZLE_NUM = (VK_CHANNEL_SWIZZLE_A - VK_CHANNEL_SWIZZLE_ZERO + 1),
+    VK_CHANNEL_SWIZZLE_MAX_ENUM = 0x7FFFFFFF
+} VkChannelSwizzle;
+
+typedef enum {
+    VK_SHADER_STAGE_VERTEX = 0,
+    VK_SHADER_STAGE_TESS_CONTROL = 1,
+    VK_SHADER_STAGE_TESS_EVALUATION = 2,
+    VK_SHADER_STAGE_GEOMETRY = 3,
+    VK_SHADER_STAGE_FRAGMENT = 4,
+    VK_SHADER_STAGE_COMPUTE = 5,
+    VK_SHADER_STAGE_BEGIN_RANGE = VK_SHADER_STAGE_VERTEX,
+    VK_SHADER_STAGE_END_RANGE = VK_SHADER_STAGE_COMPUTE,
+    VK_SHADER_STAGE_NUM = (VK_SHADER_STAGE_COMPUTE - VK_SHADER_STAGE_VERTEX + 1),
+    VK_SHADER_STAGE_MAX_ENUM = 0x7FFFFFFF
+} VkShaderStage;
+
+typedef enum {
+    VK_VERTEX_INPUT_STEP_RATE_VERTEX = 0,
+    VK_VERTEX_INPUT_STEP_RATE_INSTANCE = 1,
+    VK_VERTEX_INPUT_STEP_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_STEP_RATE_VERTEX,
+    VK_VERTEX_INPUT_STEP_RATE_END_RANGE = VK_VERTEX_INPUT_STEP_RATE_INSTANCE,
+    VK_VERTEX_INPUT_STEP_RATE_NUM = (VK_VERTEX_INPUT_STEP_RATE_INSTANCE - VK_VERTEX_INPUT_STEP_RATE_VERTEX + 1),
+    VK_VERTEX_INPUT_STEP_RATE_MAX_ENUM = 0x7FFFFFFF
+} VkVertexInputStepRate;
+
+typedef enum {
+    VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0,
+    VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1,
+    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5,
+    VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ = 6,
+    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ = 7,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ = 8,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ = 9,
+    VK_PRIMITIVE_TOPOLOGY_PATCH = 10,
+    VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
+    VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH,
+    VK_PRIMITIVE_TOPOLOGY_NUM = (VK_PRIMITIVE_TOPOLOGY_PATCH - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1),
+    VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF
+} VkPrimitiveTopology;
+
+typedef enum {
+    VK_FILL_MODE_POINTS = 0,
+    VK_FILL_MODE_WIREFRAME = 1,
+    VK_FILL_MODE_SOLID = 2,
+    VK_FILL_MODE_BEGIN_RANGE = VK_FILL_MODE_POINTS,
+    VK_FILL_MODE_END_RANGE = VK_FILL_MODE_SOLID,
+    VK_FILL_MODE_NUM = (VK_FILL_MODE_SOLID - VK_FILL_MODE_POINTS + 1),
+    VK_FILL_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkFillMode;
+
+typedef enum {
+    VK_CULL_MODE_NONE = 0,
+    VK_CULL_MODE_FRONT = 1,
+    VK_CULL_MODE_BACK = 2,
+    VK_CULL_MODE_FRONT_AND_BACK = 3,
+    VK_CULL_MODE_BEGIN_RANGE = VK_CULL_MODE_NONE,
+    VK_CULL_MODE_END_RANGE = VK_CULL_MODE_FRONT_AND_BACK,
+    VK_CULL_MODE_NUM = (VK_CULL_MODE_FRONT_AND_BACK - VK_CULL_MODE_NONE + 1),
+    VK_CULL_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkCullMode;
+
+typedef enum {
+    VK_FRONT_FACE_CCW = 0,
+    VK_FRONT_FACE_CW = 1,
+    VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_CCW,
+    VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CW,
+    VK_FRONT_FACE_NUM = (VK_FRONT_FACE_CW - VK_FRONT_FACE_CCW + 1),
+    VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF
+} VkFrontFace;
+
+typedef enum {
+    VK_COMPARE_OP_NEVER = 0,
+    VK_COMPARE_OP_LESS = 1,
+    VK_COMPARE_OP_EQUAL = 2,
+    VK_COMPARE_OP_LESS_EQUAL = 3,
+    VK_COMPARE_OP_GREATER = 4,
+    VK_COMPARE_OP_NOT_EQUAL = 5,
+    VK_COMPARE_OP_GREATER_EQUAL = 6,
+    VK_COMPARE_OP_ALWAYS = 7,
+    VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER,
+    VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS,
+    VK_COMPARE_OP_NUM = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1),
+    VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF
+} VkCompareOp;
+
+typedef enum {
+    VK_STENCIL_OP_KEEP = 0,
+    VK_STENCIL_OP_ZERO = 1,
+    VK_STENCIL_OP_REPLACE = 2,
+    VK_STENCIL_OP_INC_CLAMP = 3,
+    VK_STENCIL_OP_DEC_CLAMP = 4,
+    VK_STENCIL_OP_INVERT = 5,
+    VK_STENCIL_OP_INC_WRAP = 6,
+    VK_STENCIL_OP_DEC_WRAP = 7,
+    VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP,
+    VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DEC_WRAP,
+    VK_STENCIL_OP_NUM = (VK_STENCIL_OP_DEC_WRAP - VK_STENCIL_OP_KEEP + 1),
+    VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF
+} VkStencilOp;
+
+typedef enum {
+    VK_LOGIC_OP_CLEAR = 0,
+    VK_LOGIC_OP_AND = 1,
+    VK_LOGIC_OP_AND_REVERSE = 2,
+    VK_LOGIC_OP_COPY = 3,
+    VK_LOGIC_OP_AND_INVERTED = 4,
+    VK_LOGIC_OP_NOOP = 5,
+    VK_LOGIC_OP_XOR = 6,
+    VK_LOGIC_OP_OR = 7,
+    VK_LOGIC_OP_NOR = 8,
+    VK_LOGIC_OP_EQUIV = 9,
+    VK_LOGIC_OP_INVERT = 10,
+    VK_LOGIC_OP_OR_REVERSE = 11,
+    VK_LOGIC_OP_COPY_INVERTED = 12,
+    VK_LOGIC_OP_OR_INVERTED = 13,
+    VK_LOGIC_OP_NAND = 14,
+    VK_LOGIC_OP_SET = 15,
+    VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR,
+    VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET,
+    VK_LOGIC_OP_NUM = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1),
+    VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF
+} VkLogicOp;
+
+typedef enum {
+    VK_BLEND_ZERO = 0,
+    VK_BLEND_ONE = 1,
+    VK_BLEND_SRC_COLOR = 2,
+    VK_BLEND_ONE_MINUS_SRC_COLOR = 3,
+    VK_BLEND_DEST_COLOR = 4,
+    VK_BLEND_ONE_MINUS_DEST_COLOR = 5,
+    VK_BLEND_SRC_ALPHA = 6,
+    VK_BLEND_ONE_MINUS_SRC_ALPHA = 7,
+    VK_BLEND_DEST_ALPHA = 8,
+    VK_BLEND_ONE_MINUS_DEST_ALPHA = 9,
+    VK_BLEND_CONSTANT_COLOR = 10,
+    VK_BLEND_ONE_MINUS_CONSTANT_COLOR = 11,
+    VK_BLEND_CONSTANT_ALPHA = 12,
+    VK_BLEND_ONE_MINUS_CONSTANT_ALPHA = 13,
+    VK_BLEND_SRC_ALPHA_SATURATE = 14,
+    VK_BLEND_SRC1_COLOR = 15,
+    VK_BLEND_ONE_MINUS_SRC1_COLOR = 16,
+    VK_BLEND_SRC1_ALPHA = 17,
+    VK_BLEND_ONE_MINUS_SRC1_ALPHA = 18,
+    VK_BLEND_BEGIN_RANGE = VK_BLEND_ZERO,
+    VK_BLEND_END_RANGE = VK_BLEND_ONE_MINUS_SRC1_ALPHA,
+    VK_BLEND_NUM = (VK_BLEND_ONE_MINUS_SRC1_ALPHA - VK_BLEND_ZERO + 1),
+    VK_BLEND_MAX_ENUM = 0x7FFFFFFF
+} VkBlend;
+
+typedef enum {
+    VK_BLEND_OP_ADD = 0,
+    VK_BLEND_OP_SUBTRACT = 1,
+    VK_BLEND_OP_REVERSE_SUBTRACT = 2,
+    VK_BLEND_OP_MIN = 3,
+    VK_BLEND_OP_MAX = 4,
+    VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD,
+    VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX,
+    VK_BLEND_OP_NUM = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1),
+    VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF
+} VkBlendOp;
+
+typedef enum {
+    VK_TEX_FILTER_NEAREST = 0,
+    VK_TEX_FILTER_LINEAR = 1,
+    VK_TEX_FILTER_BEGIN_RANGE = VK_TEX_FILTER_NEAREST,
+    VK_TEX_FILTER_END_RANGE = VK_TEX_FILTER_LINEAR,
+    VK_TEX_FILTER_NUM = (VK_TEX_FILTER_LINEAR - VK_TEX_FILTER_NEAREST + 1),
+    VK_TEX_FILTER_MAX_ENUM = 0x7FFFFFFF
+} VkTexFilter;
+
+typedef enum {
+    VK_TEX_MIPMAP_MODE_BASE = 0,
+    VK_TEX_MIPMAP_MODE_NEAREST = 1,
+    VK_TEX_MIPMAP_MODE_LINEAR = 2,
+    VK_TEX_MIPMAP_MODE_BEGIN_RANGE = VK_TEX_MIPMAP_MODE_BASE,
+    VK_TEX_MIPMAP_MODE_END_RANGE = VK_TEX_MIPMAP_MODE_LINEAR,
+    VK_TEX_MIPMAP_MODE_NUM = (VK_TEX_MIPMAP_MODE_LINEAR - VK_TEX_MIPMAP_MODE_BASE + 1),
+    VK_TEX_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkTexMipmapMode;
+
+typedef enum {
+    VK_TEX_ADDRESS_WRAP = 0,
+    VK_TEX_ADDRESS_MIRROR = 1,
+    VK_TEX_ADDRESS_CLAMP = 2,
+    VK_TEX_ADDRESS_MIRROR_ONCE = 3,
+    VK_TEX_ADDRESS_CLAMP_BORDER = 4,
+    VK_TEX_ADDRESS_BEGIN_RANGE = VK_TEX_ADDRESS_WRAP,
+    VK_TEX_ADDRESS_END_RANGE = VK_TEX_ADDRESS_CLAMP_BORDER,
+    VK_TEX_ADDRESS_NUM = (VK_TEX_ADDRESS_CLAMP_BORDER - VK_TEX_ADDRESS_WRAP + 1),
+    VK_TEX_ADDRESS_MAX_ENUM = 0x7FFFFFFF
+} VkTexAddress;
+
+typedef enum {
+    VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
+    VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1,
+    VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
+    VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
+    VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
+    VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
+    VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+    VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE,
+    VK_BORDER_COLOR_NUM = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1),
+    VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF
+} VkBorderColor;
+
+typedef enum {
+    VK_DESCRIPTOR_TYPE_SAMPLER = 0,
+    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1,
+    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2,
+    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3,
+    VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4,
+    VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5,
+    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6,
+    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
+    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
+    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
+    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+    VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
+    VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+    VK_DESCRIPTOR_TYPE_NUM = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
+    VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorType;
+
+typedef enum {
+    VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT = 0,
+    VK_DESCRIPTOR_POOL_USAGE_DYNAMIC = 1,
+    VK_DESCRIPTOR_POOL_USAGE_BEGIN_RANGE = VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT,
+    VK_DESCRIPTOR_POOL_USAGE_END_RANGE = VK_DESCRIPTOR_POOL_USAGE_DYNAMIC,
+    VK_DESCRIPTOR_POOL_USAGE_NUM = (VK_DESCRIPTOR_POOL_USAGE_DYNAMIC - VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT + 1),
+    VK_DESCRIPTOR_POOL_USAGE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorPoolUsage;
+
+typedef enum {
+    VK_DESCRIPTOR_SET_USAGE_ONE_SHOT = 0,
+    VK_DESCRIPTOR_SET_USAGE_STATIC = 1,
+    VK_DESCRIPTOR_SET_USAGE_BEGIN_RANGE = VK_DESCRIPTOR_SET_USAGE_ONE_SHOT,
+    VK_DESCRIPTOR_SET_USAGE_END_RANGE = VK_DESCRIPTOR_SET_USAGE_STATIC,
+    VK_DESCRIPTOR_SET_USAGE_NUM = (VK_DESCRIPTOR_SET_USAGE_STATIC - VK_DESCRIPTOR_SET_USAGE_ONE_SHOT + 1),
+    VK_DESCRIPTOR_SET_USAGE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorSetUsage;
+
+typedef enum {
+    VK_IMAGE_LAYOUT_UNDEFINED = 0,
+    VK_IMAGE_LAYOUT_GENERAL = 1,
+    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2,
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3,
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4,
+    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5,
+    VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL = 6,
+    VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL = 7,
+    VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
+    VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
+    VK_IMAGE_LAYOUT_NUM = (VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL - VK_IMAGE_LAYOUT_UNDEFINED + 1),
+    VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF
+} VkImageLayout;
+
+typedef enum {
+    VK_ATTACHMENT_LOAD_OP_LOAD = 0,
+    VK_ATTACHMENT_LOAD_OP_CLEAR = 1,
+    VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2,
+    VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD,
+    VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+    VK_ATTACHMENT_LOAD_OP_NUM = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1),
+    VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF
+} VkAttachmentLoadOp;
+
+typedef enum {
+    VK_ATTACHMENT_STORE_OP_STORE = 0,
+    VK_ATTACHMENT_STORE_OP_DONT_CARE = 1,
+    VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE,
+    VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+    VK_ATTACHMENT_STORE_OP_NUM = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1),
+    VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF
+} VkAttachmentStoreOp;
+
+typedef enum {
+    VK_PIPELINE_BIND_POINT_COMPUTE = 0,
+    VK_PIPELINE_BIND_POINT_GRAPHICS = 1,
+    VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE,
+    VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS,
+    VK_PIPELINE_BIND_POINT_NUM = (VK_PIPELINE_BIND_POINT_GRAPHICS - VK_PIPELINE_BIND_POINT_COMPUTE + 1),
+    VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineBindPoint;
+
+typedef enum {
+    VK_CMD_BUFFER_LEVEL_PRIMARY = 0,
+    VK_CMD_BUFFER_LEVEL_SECONDARY = 1,
+    VK_CMD_BUFFER_LEVEL_BEGIN_RANGE = VK_CMD_BUFFER_LEVEL_PRIMARY,
+    VK_CMD_BUFFER_LEVEL_END_RANGE = VK_CMD_BUFFER_LEVEL_SECONDARY,
+    VK_CMD_BUFFER_LEVEL_NUM = (VK_CMD_BUFFER_LEVEL_SECONDARY - VK_CMD_BUFFER_LEVEL_PRIMARY + 1),
+    VK_CMD_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF
+} VkCmdBufferLevel;
+
+typedef enum {
+    VK_INDEX_TYPE_UINT16 = 0,
+    VK_INDEX_TYPE_UINT32 = 1,
+    VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16,
+    VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32,
+    VK_INDEX_TYPE_NUM = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1),
+    VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkIndexType;
+
+typedef enum {
+    VK_TIMESTAMP_TYPE_TOP = 0,
+    VK_TIMESTAMP_TYPE_BOTTOM = 1,
+    VK_TIMESTAMP_TYPE_BEGIN_RANGE = VK_TIMESTAMP_TYPE_TOP,
+    VK_TIMESTAMP_TYPE_END_RANGE = VK_TIMESTAMP_TYPE_BOTTOM,
+    VK_TIMESTAMP_TYPE_NUM = (VK_TIMESTAMP_TYPE_BOTTOM - VK_TIMESTAMP_TYPE_TOP + 1),
+    VK_TIMESTAMP_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkTimestampType;
+
+typedef enum {
+    VK_RENDER_PASS_CONTENTS_INLINE = 0,
+    VK_RENDER_PASS_CONTENTS_SECONDARY_CMD_BUFFERS = 1,
+    VK_RENDER_PASS_CONTENTS_BEGIN_RANGE = VK_RENDER_PASS_CONTENTS_INLINE,
+    VK_RENDER_PASS_CONTENTS_END_RANGE = VK_RENDER_PASS_CONTENTS_SECONDARY_CMD_BUFFERS,
+    VK_RENDER_PASS_CONTENTS_NUM = (VK_RENDER_PASS_CONTENTS_SECONDARY_CMD_BUFFERS - VK_RENDER_PASS_CONTENTS_INLINE + 1),
+    VK_RENDER_PASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
+} VkRenderPassContents;
+
+
+typedef enum {
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001,
+    VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002,
+    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004,
+    VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008,
+    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010,
+    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020,
+    VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040,
+    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080,
+    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100,
+    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200,
+    VK_FORMAT_FEATURE_CONVERSION_BIT = 0x00000400,
+} VkFormatFeatureFlagBits;
+typedef VkFlags VkFormatFeatureFlags;
+
+typedef enum {
+    VK_IMAGE_USAGE_GENERAL = 0,
+    VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT = 0x00000001,
+    VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT = 0x00000002,
+    VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,
+    VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,
+    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,
+    VK_IMAGE_USAGE_DEPTH_STENCIL_BIT = 0x00000020,
+    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
+    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
+} VkImageUsageFlagBits;
+typedef VkFlags VkImageUsageFlags;
+
+typedef enum {
+    VK_QUEUE_GRAPHICS_BIT = 0x00000001,
+    VK_QUEUE_COMPUTE_BIT = 0x00000002,
+    VK_QUEUE_DMA_BIT = 0x00000004,
+    VK_QUEUE_SPARSE_MEMMGR_BIT = 0x00000008,
+    VK_QUEUE_EXTENDED_BIT = 0x40000000,
+} VkQueueFlagBits;
+typedef VkFlags VkQueueFlags;
+
+typedef enum {
+    VK_MEMORY_PROPERTY_DEVICE_ONLY = 0,
+    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000001,
+    VK_MEMORY_PROPERTY_HOST_NON_COHERENT_BIT = 0x00000002,
+    VK_MEMORY_PROPERTY_HOST_UNCACHED_BIT = 0x00000004,
+    VK_MEMORY_PROPERTY_HOST_WRITE_COMBINED_BIT = 0x00000008,
+    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+} VkMemoryPropertyFlagBits;
+typedef VkFlags VkMemoryPropertyFlags;
+
+typedef enum {
+    VK_MEMORY_HEAP_HOST_LOCAL = 0x00000001,
+} VkMemoryHeapFlagBits;
+typedef VkFlags VkMemoryHeapFlags;
+
+typedef enum {
+    VK_DEVICE_CREATE_VALIDATION_BIT = 0x00000001,
+} VkDeviceCreateFlagBits;
+typedef VkFlags VkDeviceCreateFlags;
+typedef VkFlags VkMemoryMapFlags;
+
+typedef enum {
+    VK_SPARSE_IMAGE_FMT_SINGLE_MIPTAIL_BIT = 0x00000001,
+    VK_SPARSE_IMAGE_FMT_ALIGNED_MIP_SIZE_BIT = 0x00000002,
+    VK_SPARSE_IMAGE_FMT_NONSTD_BLOCK_SIZE_BIT = 0x00000004,
+} VkSparseImageFormatFlagBits;
+typedef VkFlags VkSparseImageFormatFlags;
+
+typedef enum {
+    VK_SPARSE_MEMORY_BIND_REPLICATE_64KIB_BLOCK_BIT = 0x00000001,
+} VkSparseMemoryBindFlagBits;
+typedef VkFlags VkSparseMemoryBindFlags;
+
+typedef enum {
+    VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
+} VkFenceCreateFlagBits;
+typedef VkFlags VkFenceCreateFlags;
+typedef VkFlags VkSemaphoreCreateFlags;
+typedef VkFlags VkEventCreateFlags;
+
+typedef enum {
+    VK_QUERY_PIPELINE_STATISTIC_IA_VERTICES_BIT = 0x00000001,
+    VK_QUERY_PIPELINE_STATISTIC_IA_PRIMITIVES_BIT = 0x00000002,
+    VK_QUERY_PIPELINE_STATISTIC_VS_INVOCATIONS_BIT = 0x00000004,
+    VK_QUERY_PIPELINE_STATISTIC_GS_INVOCATIONS_BIT = 0x00000008,
+    VK_QUERY_PIPELINE_STATISTIC_GS_PRIMITIVES_BIT = 0x00000010,
+    VK_QUERY_PIPELINE_STATISTIC_C_INVOCATIONS_BIT = 0x00000020,
+    VK_QUERY_PIPELINE_STATISTIC_C_PRIMITIVES_BIT = 0x00000040,
+    VK_QUERY_PIPELINE_STATISTIC_FS_INVOCATIONS_BIT = 0x00000080,
+    VK_QUERY_PIPELINE_STATISTIC_TCS_PATCHES_BIT = 0x00000100,
+    VK_QUERY_PIPELINE_STATISTIC_TES_INVOCATIONS_BIT = 0x00000200,
+    VK_QUERY_PIPELINE_STATISTIC_CS_INVOCATIONS_BIT = 0x00000400,
+} VkQueryPipelineStatisticFlagBits;
+typedef VkFlags VkQueryPipelineStatisticFlags;
+
+typedef enum {
+    VK_QUERY_RESULT_DEFAULT = 0,
+    VK_QUERY_RESULT_64_BIT = 0x00000001,
+    VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
+    VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
+    VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
+} VkQueryResultFlagBits;
+typedef VkFlags VkQueryResultFlags;
+
+typedef enum {
+    VK_BUFFER_USAGE_GENERAL = 0,
+    VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT = 0x00000001,
+    VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT = 0x00000002,
+    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004,
+    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008,
+    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010,
+    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020,
+    VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
+    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
+    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
+} VkBufferUsageFlagBits;
+typedef VkFlags VkBufferUsageFlags;
+
+typedef enum {
+    VK_BUFFER_CREATE_SPARSE_BIT = 0x00000001,
+    VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+    VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+} VkBufferCreateFlagBits;
+typedef VkFlags VkBufferCreateFlags;
+
+typedef enum {
+    VK_IMAGE_CREATE_SPARSE_BIT = 0x00000001,
+    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+    VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+    VK_IMAGE_CREATE_INVARIANT_DATA_BIT = 0x00000008,
+    VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000010,
+    VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000020,
+} VkImageCreateFlagBits;
+typedef VkFlags VkImageCreateFlags;
+
+typedef enum {
+    VK_ATTACHMENT_VIEW_CREATE_READ_ONLY_DEPTH_BIT = 0x00000001,
+    VK_ATTACHMENT_VIEW_CREATE_READ_ONLY_STENCIL_BIT = 0x00000002,
+} VkAttachmentViewCreateFlagBits;
+typedef VkFlags VkAttachmentViewCreateFlags;
+typedef VkFlags VkShaderModuleCreateFlags;
+typedef VkFlags VkShaderCreateFlags;
+
+typedef enum {
+    VK_CHANNEL_R_BIT = 0x00000001,
+    VK_CHANNEL_G_BIT = 0x00000002,
+    VK_CHANNEL_B_BIT = 0x00000004,
+    VK_CHANNEL_A_BIT = 0x00000008,
+} VkChannelFlagBits;
+typedef VkFlags VkChannelFlags;
+
+typedef enum {
+    VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
+    VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
+    VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
+} VkPipelineCreateFlagBits;
+typedef VkFlags VkPipelineCreateFlags;
+
+typedef enum {
+    VK_SHADER_STAGE_VERTEX_BIT = 0x00000001,
+    VK_SHADER_STAGE_TESS_CONTROL_BIT = 0x00000002,
+    VK_SHADER_STAGE_TESS_EVALUATION_BIT = 0x00000004,
+    VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008,
+    VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010,
+    VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
+    VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+} VkShaderStageFlagBits;
+typedef VkFlags VkShaderStageFlags;
+
+typedef enum {
+    VK_SUBPASS_DESCRIPTION_NO_OVERDRAW_BIT = 0x00000001,
+} VkSubpassDescriptionFlagBits;
+typedef VkFlags VkSubpassDescriptionFlags;
+
+typedef enum {
+    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
+    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
+    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
+    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
+    VK_PIPELINE_STAGE_TESS_CONTROL_SHADER_BIT = 0x00000010,
+    VK_PIPELINE_STAGE_TESS_EVALUATION_SHADER_BIT = 0x00000020,
+    VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
+    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
+    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
+    VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
+    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
+    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
+    VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
+    VK_PIPELINE_STAGE_TRANSITION_BIT = 0x00002000,
+    VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
+    VK_PIPELINE_STAGE_ALL_GRAPHICS = 0x000007FF,
+    VK_PIPELINE_STAGE_ALL_GPU_COMMANDS = 0x00003FFF,
+} VkPipelineStageFlagBits;
+typedef VkFlags VkPipelineStageFlags;
+
+typedef enum {
+    VK_MEMORY_OUTPUT_HOST_WRITE_BIT = 0x00000001,
+    VK_MEMORY_OUTPUT_SHADER_WRITE_BIT = 0x00000002,
+    VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT = 0x00000004,
+    VK_MEMORY_OUTPUT_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000008,
+    VK_MEMORY_OUTPUT_TRANSFER_BIT = 0x00000010,
+} VkMemoryOutputFlagBits;
+typedef VkFlags VkMemoryOutputFlags;
+
+typedef enum {
+    VK_MEMORY_INPUT_HOST_READ_BIT = 0x00000001,
+    VK_MEMORY_INPUT_INDIRECT_COMMAND_BIT = 0x00000002,
+    VK_MEMORY_INPUT_INDEX_FETCH_BIT = 0x00000004,
+    VK_MEMORY_INPUT_VERTEX_ATTRIBUTE_FETCH_BIT = 0x00000008,
+    VK_MEMORY_INPUT_UNIFORM_READ_BIT = 0x00000010,
+    VK_MEMORY_INPUT_SHADER_READ_BIT = 0x00000020,
+    VK_MEMORY_INPUT_COLOR_ATTACHMENT_BIT = 0x00000040,
+    VK_MEMORY_INPUT_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000080,
+    VK_MEMORY_INPUT_INPUT_ATTACHMENT_BIT = 0x00000100,
+    VK_MEMORY_INPUT_TRANSFER_BIT = 0x00000200,
+} VkMemoryInputFlagBits;
+typedef VkFlags VkMemoryInputFlags;
+
+typedef enum {
+    VK_CMD_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
+    VK_CMD_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
+} VkCmdPoolCreateFlagBits;
+typedef VkFlags VkCmdPoolCreateFlags;
+
+typedef enum {
+    VK_CMD_POOL_RESET_RELEASE_RESOURCES = 0x00000001,
+} VkCmdPoolResetFlagBits;
+typedef VkFlags VkCmdPoolResetFlags;
+typedef VkFlags VkCmdBufferCreateFlags;
+
+typedef enum {
+    VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT = 0x00000001,
+    VK_CMD_BUFFER_OPTIMIZE_PIPELINE_SWITCH_BIT = 0x00000002,
+    VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT = 0x00000004,
+    VK_CMD_BUFFER_OPTIMIZE_DESCRIPTOR_SET_SWITCH_BIT = 0x00000008,
+    VK_CMD_BUFFER_OPTIMIZE_NO_SIMULTANEOUS_USE_BIT = 0x00000010,
+} VkCmdBufferOptimizeFlagBits;
+typedef VkFlags VkCmdBufferOptimizeFlags;
+
+typedef enum {
+    VK_CMD_BUFFER_RESET_RELEASE_RESOURCES = 0x00000001,
+} VkCmdBufferResetFlagBits;
+typedef VkFlags VkCmdBufferResetFlags;
+
+typedef enum {
+    VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001,
+    VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
+    VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
+    VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
+} VkImageAspectFlagBits;
+typedef VkFlags VkImageAspectFlags;
+
+typedef enum {
+    VK_QUERY_CONTROL_CONSERVATIVE_BIT = 0x00000001,
+} VkQueryControlFlagBits;
+typedef VkFlags VkQueryControlFlags;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    const char*                                 pAppName;
+    uint32_t                                    appVersion;
+    const char*                                 pEngineName;
+    uint32_t                                    engineVersion;
+    uint32_t                                    apiVersion;
+} VkApplicationInfo;
+
+typedef void* (VKAPI *PFN_vkAllocFunction)(
+    void*                           pUserData,
+    size_t                          size,
+    size_t                          alignment,
+    VkSystemAllocType               allocType);
+
+typedef void (VKAPI *PFN_vkFreeFunction)(
+    void*                           pUserData,
+    void*                           pMem);
+
+typedef struct {
+    void*                                       pUserData;
+    PFN_vkAllocFunction                         pfnAlloc;
+    PFN_vkFreeFunction                          pfnFree;
+} VkAllocCallbacks;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    const VkApplicationInfo*                    pAppInfo;
+    const VkAllocCallbacks*                     pAllocCb;
+    uint32_t                                    layerCount;
+    const char*const*                           ppEnabledLayerNames;
+    uint32_t                                    extensionCount;
+    const char*const*                           ppEnabledExtensionNames;
+} VkInstanceCreateInfo;
+
+typedef struct {
+    VkBool32                                    robustBufferAccess;
+    VkBool32                                    fullDrawIndexUint32;
+    VkBool32                                    imageCubeArray;
+    VkBool32                                    independentBlend;
+    VkBool32                                    geometryShader;
+    VkBool32                                    tessellationShader;
+    VkBool32                                    sampleRateShading;
+    VkBool32                                    dualSourceBlend;
+    VkBool32                                    logicOp;
+    VkBool32                                    instancedDrawIndirect;
+    VkBool32                                    depthClip;
+    VkBool32                                    depthBiasClamp;
+    VkBool32                                    fillModeNonSolid;
+    VkBool32                                    depthBounds;
+    VkBool32                                    wideLines;
+    VkBool32                                    largePoints;
+    VkBool32                                    textureCompressionETC2;
+    VkBool32                                    textureCompressionASTC_LDR;
+    VkBool32                                    textureCompressionBC;
+    VkBool32                                    pipelineStatisticsQuery;
+    VkBool32                                    vertexSideEffects;
+    VkBool32                                    tessellationSideEffects;
+    VkBool32                                    geometrySideEffects;
+    VkBool32                                    fragmentSideEffects;
+    VkBool32                                    shaderTessellationPointSize;
+    VkBool32                                    shaderGeometryPointSize;
+    VkBool32                                    shaderTextureGatherExtended;
+    VkBool32                                    shaderStorageImageExtendedFormats;
+    VkBool32                                    shaderStorageImageMultisample;
+    VkBool32                                    shaderStorageBufferArrayConstantIndexing;
+    VkBool32                                    shaderStorageImageArrayConstantIndexing;
+    VkBool32                                    shaderUniformBufferArrayDynamicIndexing;
+    VkBool32                                    shaderSampledImageArrayDynamicIndexing;
+    VkBool32                                    shaderStorageBufferArrayDynamicIndexing;
+    VkBool32                                    shaderStorageImageArrayDynamicIndexing;
+    VkBool32                                    shaderClipDistance;
+    VkBool32                                    shaderCullDistance;
+    VkBool32                                    shaderFloat64;
+    VkBool32                                    shaderInt64;
+    VkBool32                                    shaderFloat16;
+    VkBool32                                    shaderInt16;
+    VkBool32                                    shaderResourceResidency;
+    VkBool32                                    shaderResourceMinLOD;
+    VkBool32                                    sparse;
+    VkBool32                                    sparseResidencyBuffer;
+    VkBool32                                    sparseResidencyImage2D;
+    VkBool32                                    sparseResidencyImage3D;
+    VkBool32                                    sparseResidency2Samples;
+    VkBool32                                    sparseResidency4Samples;
+    VkBool32                                    sparseResidency8Samples;
+    VkBool32                                    sparseResidency16Samples;
+    VkBool32                                    sparseResidencyStandard2DBlockShape;
+    VkBool32                                    sparseResidencyStandard2DMSBlockShape;
+    VkBool32                                    sparseResidencyStandard3DBlockShape;
+    VkBool32                                    sparseResidencyAlignedMipSize;
+    VkBool32                                    sparseResidencyNonResident;
+    VkBool32                                    sparseResidencyNonResidentStrict;
+    VkBool32                                    sparseResidencyAliased;
+} VkPhysicalDeviceFeatures;
+
+typedef struct {
+    VkFormatFeatureFlags                        linearTilingFeatures;
+    VkFormatFeatureFlags                        optimalTilingFeatures;
+} VkFormatProperties;
+
+typedef struct {
+    uint64_t                                    maxResourceSize;
+    uint32_t                                    maxSamples;
+} VkImageFormatProperties;
+
+typedef struct {
+    uint32_t                                    maxImageDimension1D;
+    uint32_t                                    maxImageDimension2D;
+    uint32_t                                    maxImageDimension3D;
+    uint32_t                                    maxImageDimensionCube;
+    uint32_t                                    maxImageArrayLayers;
+    uint32_t                                    maxTexelBufferSize;
+    uint32_t                                    maxUniformBufferSize;
+    uint32_t                                    maxStorageBufferSize;
+    uint32_t                                    maxPushConstantsSize;
+    uint32_t                                    maxMemoryAllocationCount;
+    VkDeviceSize                                bufferImageGranularity;
+    uint32_t                                    maxBoundDescriptorSets;
+    uint32_t                                    maxDescriptorSets;
+    uint32_t                                    maxPerStageDescriptorSamplers;
+    uint32_t                                    maxPerStageDescriptorUniformBuffers;
+    uint32_t                                    maxPerStageDescriptorStorageBuffers;
+    uint32_t                                    maxPerStageDescriptorSampledImages;
+    uint32_t                                    maxPerStageDescriptorStorageImages;
+    uint32_t                                    maxDescriptorSetSamplers;
+    uint32_t                                    maxDescriptorSetUniformBuffers;
+    uint32_t                                    maxDescriptorSetStorageBuffers;
+    uint32_t                                    maxDescriptorSetSampledImages;
+    uint32_t                                    maxDescriptorSetStorageImages;
+    uint32_t                                    maxVertexInputAttributes;
+    uint32_t                                    maxVertexInputAttributeOffset;
+    uint32_t                                    maxVertexInputBindingStride;
+    uint32_t                                    maxVertexOutputComponents;
+    uint32_t                                    maxTessGenLevel;
+    uint32_t                                    maxTessPatchSize;
+    uint32_t                                    maxTessControlPerVertexInputComponents;
+    uint32_t                                    maxTessControlPerVertexOutputComponents;
+    uint32_t                                    maxTessControlPerPatchOutputComponents;
+    uint32_t                                    maxTessControlTotalOutputComponents;
+    uint32_t                                    maxTessEvaluationInputComponents;
+    uint32_t                                    maxTessEvaluationOutputComponents;
+    uint32_t                                    maxGeometryShaderInvocations;
+    uint32_t                                    maxGeometryInputComponents;
+    uint32_t                                    maxGeometryOutputComponents;
+    uint32_t                                    maxGeometryOutputVertices;
+    uint32_t                                    maxGeometryTotalOutputComponents;
+    uint32_t                                    maxFragmentInputComponents;
+    uint32_t                                    maxFragmentOutputBuffers;
+    uint32_t                                    maxFragmentDualSourceBuffers;
+    uint32_t                                    maxFragmentCombinedOutputResources;
+    uint32_t                                    maxComputeSharedMemorySize;
+    uint32_t                                    maxComputeWorkGroupCount[3];
+    uint32_t                                    maxComputeWorkGroupInvocations;
+    uint32_t                                    maxComputeWorkGroupSize[3];
+    uint32_t                                    subPixelPrecisionBits;
+    uint32_t                                    subTexelPrecisionBits;
+    uint32_t                                    mipmapPrecisionBits;
+    uint32_t                                    maxDrawIndexedIndexValue;
+    uint32_t                                    maxDrawIndirectInstanceCount;
+    VkBool32                                    primitiveRestartForPatches;
+    float                                       maxSamplerLodBias;
+    float                                       maxSamplerAnisotropy;
+    uint32_t                                    maxViewports;
+    uint32_t                                    maxDynamicViewportStates;
+    uint32_t                                    maxViewportDimensions[2];
+    float                                       viewportBoundsRange[2];
+    uint32_t                                    viewportSubPixelBits;
+    uint32_t                                    minMemoryMapAlignment;
+    uint32_t                                    minTexelBufferOffsetAlignment;
+    uint32_t                                    minUniformBufferOffsetAlignment;
+    uint32_t                                    minStorageBufferOffsetAlignment;
+    uint32_t                                    minTexelOffset;
+    uint32_t                                    maxTexelOffset;
+    uint32_t                                    minTexelGatherOffset;
+    uint32_t                                    maxTexelGatherOffset;
+    float                                       minInterpolationOffset;
+    float                                       maxInterpolationOffset;
+    uint32_t                                    subPixelInterpolationOffsetBits;
+    uint32_t                                    maxFramebufferWidth;
+    uint32_t                                    maxFramebufferHeight;
+    uint32_t                                    maxFramebufferLayers;
+    uint32_t                                    maxFramebufferColorSamples;
+    uint32_t                                    maxFramebufferDepthSamples;
+    uint32_t                                    maxFramebufferStencilSamples;
+    uint32_t                                    maxColorAttachments;
+    uint32_t                                    maxSampledImageColorSamples;
+    uint32_t                                    maxSampledImageDepthSamples;
+    uint32_t                                    maxSampledImageIntegerSamples;
+    uint32_t                                    maxStorageImageSamples;
+    uint32_t                                    maxSampleMaskWords;
+    uint64_t                                    timestampFrequency;
+    uint32_t                                    maxClipDistances;
+    uint32_t                                    maxCullDistances;
+    uint32_t                                    maxCombinedClipAndCullDistances;
+    float                                       pointSizeRange[2];
+    float                                       lineWidthRange[2];
+    float                                       pointSizeGranularity;
+    float                                       lineWidthGranularity;
+} VkPhysicalDeviceLimits;
+
+typedef struct {
+    uint32_t                                    apiVersion;
+    uint32_t                                    driverVersion;
+    uint32_t                                    vendorId;
+    uint32_t                                    deviceId;
+    VkPhysicalDeviceType                        deviceType;
+    char                                        deviceName[VK_MAX_PHYSICAL_DEVICE_NAME];
+    uint8_t                                     pipelineCacheUUID[VK_UUID_LENGTH];
+} VkPhysicalDeviceProperties;
+
+typedef struct {
+    VkQueueFlags                                queueFlags;
+    uint32_t                                    queueCount;
+    VkBool32                                    supportsTimestamps;
+} VkPhysicalDeviceQueueProperties;
+
+typedef struct {
+    VkMemoryPropertyFlags                       propertyFlags;
+    uint32_t                                    heapIndex;
+} VkMemoryType;
+
+typedef struct {
+    VkDeviceSize                                size;
+    VkMemoryHeapFlags                           flags;
+} VkMemoryHeap;
+
+typedef struct {
+    uint32_t                                    memoryTypeCount;
+    VkMemoryType                                memoryTypes[VK_MAX_MEMORY_TYPES];
+    uint32_t                                    memoryHeapCount;
+    VkMemoryHeap                                memoryHeaps[VK_MAX_MEMORY_HEAPS];
+} VkPhysicalDeviceMemoryProperties;
+
+typedef void (VKAPI *PFN_vkVoidFunction)(void);
+typedef struct {
+    uint32_t                                    queueFamilyIndex;
+    uint32_t                                    queueCount;
+} VkDeviceQueueCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    queueRecordCount;
+    const VkDeviceQueueCreateInfo*              pRequestedQueues;
+    uint32_t                                    layerCount;
+    const char*const*                           ppEnabledLayerNames;
+    uint32_t                                    extensionCount;
+    const char*const*                           ppEnabledExtensionNames;
+    const VkPhysicalDeviceFeatures*             pEnabledFeatures;
+    VkDeviceCreateFlags                         flags;
+} VkDeviceCreateInfo;
+
+typedef struct {
+    char                                        extName[VK_MAX_EXTENSION_NAME];
+    uint32_t                                    specVersion;
+} VkExtensionProperties;
+
+typedef struct {
+    char                                        layerName[VK_MAX_EXTENSION_NAME];
+    uint32_t                                    specVersion;
+    uint32_t                                    implVersion;
+    char                                        description[VK_MAX_DESCRIPTION];
+} VkLayerProperties;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkDeviceSize                                allocationSize;
+    uint32_t                                    memoryTypeIndex;
+} VkMemoryAllocInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkDeviceMemory                              mem;
+    VkDeviceSize                                offset;
+    VkDeviceSize                                size;
+} VkMappedMemoryRange;
+
+typedef struct {
+    VkDeviceSize                                size;
+    VkDeviceSize                                alignment;
+    uint32_t                                    memoryTypeBits;
+} VkMemoryRequirements;
+
+typedef struct {
+    int32_t                                     width;
+    int32_t                                     height;
+    int32_t                                     depth;
+} VkExtent3D;
+
+typedef struct {
+    VkImageAspect                               aspect;
+    VkExtent3D                                  imageGranularity;
+    VkSparseImageFormatFlags                    flags;
+} VkSparseImageFormatProperties;
+
+typedef struct {
+    VkSparseImageFormatProperties               formatProps;
+    uint32_t                                    imageMipTailStartLOD;
+    VkDeviceSize                                imageMipTailSize;
+    VkDeviceSize                                imageMipTailOffset;
+    VkDeviceSize                                imageMipTailStride;
+} VkSparseImageMemoryRequirements;
+
+typedef struct {
+    VkDeviceSize                                rangeOffset;
+    VkDeviceSize                                rangeSize;
+    VkDeviceSize                                memOffset;
+    VkDeviceMemory                              mem;
+    VkSparseMemoryBindFlags                     flags;
+} VkSparseMemoryBindInfo;
+
+typedef struct {
+    VkImageAspect                               aspect;
+    uint32_t                                    mipLevel;
+    uint32_t                                    arraySlice;
+} VkImageSubresource;
+
+typedef struct {
+    int32_t                                     x;
+    int32_t                                     y;
+    int32_t                                     z;
+} VkOffset3D;
+
+typedef struct {
+    VkImageSubresource                          subresource;
+    VkOffset3D                                  offset;
+    VkExtent3D                                  extent;
+    VkDeviceSize                                memOffset;
+    VkDeviceMemory                              mem;
+    VkSparseMemoryBindFlags                     flags;
+} VkSparseImageMemoryBindInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkFenceCreateFlags                          flags;
+} VkFenceCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkSemaphoreCreateFlags                      flags;
+} VkSemaphoreCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkEventCreateFlags                          flags;
+} VkEventCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkQueryType                                 queryType;
+    uint32_t                                    slots;
+    VkQueryPipelineStatisticFlags               pipelineStatistics;
+} VkQueryPoolCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkDeviceSize                                size;
+    VkBufferUsageFlags                          usage;
+    VkBufferCreateFlags                         flags;
+    VkSharingMode                               sharingMode;
+    uint32_t                                    queueFamilyCount;
+    const uint32_t*                             pQueueFamilyIndices;
+} VkBufferCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkBuffer                                    buffer;
+    VkBufferViewType                            viewType;
+    VkFormat                                    format;
+    VkDeviceSize                                offset;
+    VkDeviceSize                                range;
+} VkBufferViewCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkImageType                                 imageType;
+    VkFormat                                    format;
+    VkExtent3D                                  extent;
+    uint32_t                                    mipLevels;
+    uint32_t                                    arraySize;
+    uint32_t                                    samples;
+    VkImageTiling                               tiling;
+    VkImageUsageFlags                           usage;
+    VkImageCreateFlags                          flags;
+    VkSharingMode                               sharingMode;
+    uint32_t                                    queueFamilyCount;
+    const uint32_t*                             pQueueFamilyIndices;
+} VkImageCreateInfo;
+
+typedef struct {
+    VkDeviceSize                                offset;
+    VkDeviceSize                                size;
+    VkDeviceSize                                rowPitch;
+    VkDeviceSize                                depthPitch;
+} VkSubresourceLayout;
+
+typedef struct {
+    VkChannelSwizzle                            r;
+    VkChannelSwizzle                            g;
+    VkChannelSwizzle                            b;
+    VkChannelSwizzle                            a;
+} VkChannelMapping;
+
+typedef struct {
+    VkImageAspect                               aspect;
+    uint32_t                                    baseMipLevel;
+    uint32_t                                    mipLevels;
+    uint32_t                                    baseArraySlice;
+    uint32_t                                    arraySize;
+} VkImageSubresourceRange;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkImage                                     image;
+    VkImageViewType                             viewType;
+    VkFormat                                    format;
+    VkChannelMapping                            channels;
+    VkImageSubresourceRange                     subresourceRange;
+} VkImageViewCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkImage                                     image;
+    VkFormat                                    format;
+    uint32_t                                    mipLevel;
+    uint32_t                                    baseArraySlice;
+    uint32_t                                    arraySize;
+    VkAttachmentViewCreateFlags                 flags;
+} VkAttachmentViewCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    size_t                                      codeSize;
+    const void*                                 pCode;
+    VkShaderModuleCreateFlags                   flags;
+} VkShaderModuleCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkShaderModule                              module;
+    const char*                                 pName;
+    VkShaderCreateFlags                         flags;
+} VkShaderCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    size_t                                      initialSize;
+    const void*                                 initialData;
+    size_t                                      maxSize;
+} VkPipelineCacheCreateInfo;
+
+typedef struct {
+    uint32_t                                    constantId;
+    size_t                                      size;
+    uint32_t                                    offset;
+} VkSpecializationMapEntry;
+
+typedef struct {
+    uint32_t                                    mapEntryCount;
+    const VkSpecializationMapEntry*             pMap;
+    size_t                                      dataSize;
+    const void*                                 pData;
+} VkSpecializationInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkShaderStage                               stage;
+    VkShader                                    shader;
+    const VkSpecializationInfo*                 pSpecializationInfo;
+} VkPipelineShaderStageCreateInfo;
+
+typedef struct {
+    uint32_t                                    binding;
+    uint32_t                                    strideInBytes;
+    VkVertexInputStepRate                       stepRate;
+} VkVertexInputBindingDescription;
+
+typedef struct {
+    uint32_t                                    location;
+    uint32_t                                    binding;
+    VkFormat                                    format;
+    uint32_t                                    offsetInBytes;
+} VkVertexInputAttributeDescription;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    bindingCount;
+    const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
+    uint32_t                                    attributeCount;
+    const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
+} VkPipelineVertexInputStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkPrimitiveTopology                         topology;
+    VkBool32                                    primitiveRestartEnable;
+} VkPipelineInputAssemblyStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    patchControlPoints;
+} VkPipelineTessellationStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    viewportCount;
+} VkPipelineViewportStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkBool32                                    depthClipEnable;
+    VkBool32                                    rasterizerDiscardEnable;
+    VkFillMode                                  fillMode;
+    VkCullMode                                  cullMode;
+    VkFrontFace                                 frontFace;
+} VkPipelineRasterStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    rasterSamples;
+    VkBool32                                    sampleShadingEnable;
+    float                                       minSampleShading;
+    VkSampleMask                                sampleMask;
+} VkPipelineMultisampleStateCreateInfo;
+
+typedef struct {
+    VkStencilOp                                 stencilFailOp;
+    VkStencilOp                                 stencilPassOp;
+    VkStencilOp                                 stencilDepthFailOp;
+    VkCompareOp                                 stencilCompareOp;
+} VkStencilOpState;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkBool32                                    depthTestEnable;
+    VkBool32                                    depthWriteEnable;
+    VkCompareOp                                 depthCompareOp;
+    VkBool32                                    depthBoundsEnable;
+    VkBool32                                    stencilTestEnable;
+    VkStencilOpState                            front;
+    VkStencilOpState                            back;
+} VkPipelineDepthStencilStateCreateInfo;
+
+typedef struct {
+    VkBool32                                    blendEnable;
+    VkBlend                                     srcBlendColor;
+    VkBlend                                     destBlendColor;
+    VkBlendOp                                   blendOpColor;
+    VkBlend                                     srcBlendAlpha;
+    VkBlend                                     destBlendAlpha;
+    VkBlendOp                                   blendOpAlpha;
+    VkChannelFlags                              channelWriteMask;
+} VkPipelineColorBlendAttachmentState;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkBool32                                    alphaToCoverageEnable;
+    VkBool32                                    logicOpEnable;
+    VkLogicOp                                   logicOp;
+    uint32_t                                    attachmentCount;
+    const VkPipelineColorBlendAttachmentState*  pAttachments;
+} VkPipelineColorBlendStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    stageCount;
+    const VkPipelineShaderStageCreateInfo*      pStages;
+    const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+    const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
+    const VkPipelineTessellationStateCreateInfo* pTessellationState;
+    const VkPipelineViewportStateCreateInfo*    pViewportState;
+    const VkPipelineRasterStateCreateInfo*      pRasterState;
+    const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
+    const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
+    const VkPipelineColorBlendStateCreateInfo*  pColorBlendState;
+    VkPipelineCreateFlags                       flags;
+    VkPipelineLayout                            layout;
+    VkRenderPass                                renderPass;
+    uint32_t                                    subpass;
+    VkPipeline                                  basePipelineHandle;
+    int32_t                                     basePipelineIndex;
+} VkGraphicsPipelineCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkPipelineShaderStageCreateInfo             cs;
+    VkPipelineCreateFlags                       flags;
+    VkPipelineLayout                            layout;
+    VkPipeline                                  basePipelineHandle;
+    int32_t                                     basePipelineIndex;
+} VkComputePipelineCreateInfo;
+
+typedef struct {
+    VkShaderStageFlags                          stageFlags;
+    uint32_t                                    start;
+    uint32_t                                    length;
+} VkPushConstantRange;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    descriptorSetCount;
+    const VkDescriptorSetLayout*                pSetLayouts;
+    uint32_t                                    pushConstantRangeCount;
+    const VkPushConstantRange*                  pPushConstantRanges;
+} VkPipelineLayoutCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkTexFilter                                 magFilter;
+    VkTexFilter                                 minFilter;
+    VkTexMipmapMode                             mipMode;
+    VkTexAddress                                addressU;
+    VkTexAddress                                addressV;
+    VkTexAddress                                addressW;
+    float                                       mipLodBias;
+    float                                       maxAnisotropy;
+    VkBool32                                    compareEnable;
+    VkCompareOp                                 compareOp;
+    float                                       minLod;
+    float                                       maxLod;
+    VkBorderColor                               borderColor;
+} VkSamplerCreateInfo;
+
+typedef struct {
+    VkDescriptorType                            descriptorType;
+    uint32_t                                    arraySize;
+    VkShaderStageFlags                          stageFlags;
+    const VkSampler*                            pImmutableSamplers;
+} VkDescriptorSetLayoutBinding;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    count;
+    const VkDescriptorSetLayoutBinding*         pBinding;
+} VkDescriptorSetLayoutCreateInfo;
+
+typedef struct {
+    VkDescriptorType                            type;
+    uint32_t                                    count;
+} VkDescriptorTypeCount;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    count;
+    const VkDescriptorTypeCount*                pTypeCount;
+} VkDescriptorPoolCreateInfo;
+
+typedef struct {
+    VkBufferView                                bufferView;
+    VkSampler                                   sampler;
+    VkImageView                                 imageView;
+    VkAttachmentView                            attachmentView;
+    VkImageLayout                               imageLayout;
+} VkDescriptorInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkDescriptorSet                             destSet;
+    uint32_t                                    destBinding;
+    uint32_t                                    destArrayElement;
+    uint32_t                                    count;
+    VkDescriptorType                            descriptorType;
+    const VkDescriptorInfo*                     pDescriptors;
+} VkWriteDescriptorSet;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkDescriptorSet                             srcSet;
+    uint32_t                                    srcBinding;
+    uint32_t                                    srcArrayElement;
+    VkDescriptorSet                             destSet;
+    uint32_t                                    destBinding;
+    uint32_t                                    destArrayElement;
+    uint32_t                                    count;
+} VkCopyDescriptorSet;
+
+typedef struct {
+    float                                       originX;
+    float                                       originY;
+    float                                       width;
+    float                                       height;
+    float                                       minDepth;
+    float                                       maxDepth;
+} VkViewport;
+
+typedef struct {
+    int32_t                                     x;
+    int32_t                                     y;
+} VkOffset2D;
+
+typedef struct {
+    int32_t                                     width;
+    int32_t                                     height;
+} VkExtent2D;
+
+typedef struct {
+    VkOffset2D                                  offset;
+    VkExtent2D                                  extent;
+} VkRect2D;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    viewportAndScissorCount;
+    const VkViewport*                           pViewports;
+    const VkRect2D*                             pScissors;
+} VkDynamicViewportStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    float                                       depthBias;
+    float                                       depthBiasClamp;
+    float                                       slopeScaledDepthBias;
+    float                                       lineWidth;
+} VkDynamicRasterStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    float                                       blendConst[4];
+} VkDynamicColorBlendStateCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    float                                       minDepthBounds;
+    float                                       maxDepthBounds;
+    uint32_t                                    stencilReadMask;
+    uint32_t                                    stencilWriteMask;
+    uint32_t                                    stencilFrontRef;
+    uint32_t                                    stencilBackRef;
+} VkDynamicDepthStencilStateCreateInfo;
+
+typedef struct {
+    VkAttachmentView                            view;
+    VkImageLayout                               layout;
+} VkAttachmentBindInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkRenderPass                                renderPass;
+    uint32_t                                    attachmentCount;
+    const VkAttachmentBindInfo*                 pAttachments;
+    uint32_t                                    width;
+    uint32_t                                    height;
+    uint32_t                                    layers;
+} VkFramebufferCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkFormat                                    format;
+    uint32_t                                    samples;
+    VkAttachmentLoadOp                          loadOp;
+    VkAttachmentStoreOp                         storeOp;
+    VkAttachmentLoadOp                          stencilLoadOp;
+    VkAttachmentStoreOp                         stencilStoreOp;
+    VkImageLayout                               initialLayout;
+    VkImageLayout                               finalLayout;
+} VkAttachmentDescription;
+
+typedef struct {
+    uint32_t                                    attachment;
+    VkImageLayout                               layout;
+} VkAttachmentReference;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkPipelineBindPoint                         pipelineBindPoint;
+    VkSubpassDescriptionFlags                   flags;
+    uint32_t                                    inputCount;
+    const VkAttachmentReference*                inputAttachments;
+    uint32_t                                    colorCount;
+    const VkAttachmentReference*                colorAttachments;
+    const VkAttachmentReference*                resolveAttachments;
+    VkAttachmentReference                       depthStencilAttachment;
+    uint32_t                                    preserveCount;
+    const VkAttachmentReference*                preserveAttachments;
+} VkSubpassDescription;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    srcSubpass;
+    uint32_t                                    destSubpass;
+    VkPipelineStageFlags                        srcStageMask;
+    VkPipelineStageFlags                        destStageMask;
+    VkMemoryOutputFlags                         outputMask;
+    VkMemoryInputFlags                          inputMask;
+    VkBool32                                    byRegion;
+} VkSubpassDependency;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    attachmentCount;
+    const VkAttachmentDescription*              pAttachments;
+    uint32_t                                    subpassCount;
+    const VkSubpassDescription*                 pSubpasses;
+    uint32_t                                    dependencyCount;
+    const VkSubpassDependency*                  pDependencies;
+} VkRenderPassCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    queueFamilyIndex;
+    VkCmdPoolCreateFlags                        flags;
+} VkCmdPoolCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkCmdPool                                   cmdPool;
+    VkCmdBufferLevel                            level;
+    VkCmdBufferCreateFlags                      flags;
+} VkCmdBufferCreateInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkCmdBufferOptimizeFlags                    flags;
+    VkRenderPass                                renderPass;
+    VkFramebuffer                               framebuffer;
+} VkCmdBufferBeginInfo;
+
+typedef struct {
+    VkDeviceSize                                srcOffset;
+    VkDeviceSize                                destOffset;
+    VkDeviceSize                                copySize;
+} VkBufferCopy;
+
+typedef struct {
+    VkImageSubresource                          srcSubresource;
+    VkOffset3D                                  srcOffset;
+    VkImageSubresource                          destSubresource;
+    VkOffset3D                                  destOffset;
+    VkExtent3D                                  extent;
+} VkImageCopy;
+
+typedef struct {
+    VkImageSubresource                          srcSubresource;
+    VkOffset3D                                  srcOffset;
+    VkExtent3D                                  srcExtent;
+    VkImageSubresource                          destSubresource;
+    VkOffset3D                                  destOffset;
+    VkExtent3D                                  destExtent;
+} VkImageBlit;
+
+typedef struct {
+    VkDeviceSize                                bufferOffset;
+    uint32_t                                    bufferRowLength;
+    uint32_t                                    bufferImageHeight;
+    VkImageSubresource                          imageSubresource;
+    VkOffset3D                                  imageOffset;
+    VkExtent3D                                  imageExtent;
+} VkBufferImageCopy;
+
+typedef union {
+    float                                       f32[4];
+    int32_t                                     s32[4];
+    uint32_t                                    u32[4];
+} VkClearColorValue;
+
+typedef struct {
+    VkOffset3D                                  offset;
+    VkExtent3D                                  extent;
+} VkRect3D;
+
+typedef struct {
+    VkImageSubresource                          srcSubresource;
+    VkOffset3D                                  srcOffset;
+    VkImageSubresource                          destSubresource;
+    VkOffset3D                                  destOffset;
+    VkExtent3D                                  extent;
+} VkImageResolve;
+
+typedef struct {
+    float                                       depth;
+    uint32_t                                    stencil;
+} VkClearDepthStencilValue;
+
+typedef union {
+    VkClearColorValue                           color;
+    VkClearDepthStencilValue                    ds;
+} VkClearValue;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkRenderPass                                renderPass;
+    VkFramebuffer                               framebuffer;
+    VkRect2D                                    renderArea;
+    uint32_t                                    attachmentCount;
+    const VkClearValue*                         pAttachmentClearValues;
+} VkRenderPassBeginInfo;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkMemoryOutputFlags                         outputMask;
+    VkMemoryInputFlags                          inputMask;
+    uint32_t                                    srcQueueFamilyIndex;
+    uint32_t                                    destQueueFamilyIndex;
+    VkBuffer                                    buffer;
+    VkDeviceSize                                offset;
+    VkDeviceSize                                size;
+} VkBufferMemoryBarrier;
+
+typedef struct {
+    uint32_t                                    x;
+    uint32_t                                    y;
+    uint32_t                                    z;
+} VkDispatchIndirectCmd;
+
+typedef struct {
+    uint32_t                                    indexCount;
+    uint32_t                                    instanceCount;
+    uint32_t                                    firstIndex;
+    int32_t                                     vertexOffset;
+    uint32_t                                    firstInstance;
+} VkDrawIndexedIndirectCmd;
+
+typedef struct {
+    uint32_t                                    vertexCount;
+    uint32_t                                    instanceCount;
+    uint32_t                                    firstVertex;
+    uint32_t                                    firstInstance;
+} VkDrawIndirectCmd;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkMemoryOutputFlags                         outputMask;
+    VkMemoryInputFlags                          inputMask;
+    VkImageLayout                               oldLayout;
+    VkImageLayout                               newLayout;
+    uint32_t                                    srcQueueFamilyIndex;
+    uint32_t                                    destQueueFamilyIndex;
+    VkImage                                     image;
+    VkImageSubresourceRange                     subresourceRange;
+} VkImageMemoryBarrier;
+
+typedef struct {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkMemoryOutputFlags                         outputMask;
+    VkMemoryInputFlags                          inputMask;
+} VkMemoryBarrier;
+
+
+typedef VkResult (VKAPI *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance);
+typedef VkResult (VKAPI *PFN_vkDestroyInstance)(VkInstance instance);
+typedef VkResult (VKAPI *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageFormatProperties* pImageFormatProperties);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceLimits)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceLimits* pLimits);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceQueueCount)(VkPhysicalDevice physicalDevice, uint32_t* pCount);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceQueueProperties)(VkPhysicalDevice physicalDevice, uint32_t count, VkPhysicalDeviceQueueProperties* pQueueProperties);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+typedef PFN_vkVoidFunction (VKAPI *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName);
+typedef PFN_vkVoidFunction (VKAPI *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName);
+typedef VkResult (VKAPI *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice);
+typedef VkResult (VKAPI *PFN_vkDestroyDevice)(VkDevice device);
+typedef VkResult (VKAPI *PFN_vkGetGlobalExtensionProperties)(const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties);
+typedef VkResult (VKAPI *PFN_vkGetGlobalLayerProperties)(uint32_t* pCount, VkLayerProperties* pProperties);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pCount, VkLayerProperties* pProperties);
+typedef VkResult (VKAPI *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+typedef VkResult (VKAPI *PFN_vkQueueSubmit)(VkQueue queue, uint32_t cmdBufferCount, const VkCmdBuffer* pCmdBuffers, VkFence fence);
+typedef VkResult (VKAPI *PFN_vkQueueWaitIdle)(VkQueue queue);
+typedef VkResult (VKAPI *PFN_vkDeviceWaitIdle)(VkDevice device);
+typedef VkResult (VKAPI *PFN_vkAllocMemory)(VkDevice device, const VkMemoryAllocInfo* pAllocInfo, VkDeviceMemory* pMem);
+typedef VkResult (VKAPI *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory mem);
+typedef VkResult (VKAPI *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);
+typedef VkResult (VKAPI *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory mem);
+typedef VkResult (VKAPI *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges);
+typedef VkResult (VKAPI *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges);
+typedef VkResult (VKAPI *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes);
+typedef VkResult (VKAPI *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset);
+typedef VkResult (VKAPI *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset);
+typedef VkResult (VKAPI *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements);
+typedef VkResult (VKAPI *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
+typedef VkResult (VKAPI *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pNumRequirements, VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, uint32_t samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pNumProperties, VkSparseImageFormatProperties* pProperties);
+typedef VkResult (VKAPI *PFN_vkQueueBindSparseBufferMemory)(VkQueue queue, VkBuffer buffer, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo);
+typedef VkResult (VKAPI *PFN_vkQueueBindSparseImageOpaqueMemory)(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo);
+typedef VkResult (VKAPI *PFN_vkQueueBindSparseImageMemory)(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseImageMemoryBindInfo* pBindInfo);
+typedef VkResult (VKAPI *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, VkFence* pFence);
+typedef VkResult (VKAPI *PFN_vkDestroyFence)(VkDevice device, VkFence fence);
+typedef VkResult (VKAPI *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences);
+typedef VkResult (VKAPI *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence);
+typedef VkResult (VKAPI *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout);
+typedef VkResult (VKAPI *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, VkSemaphore* pSemaphore);
+typedef VkResult (VKAPI *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore);
+typedef VkResult (VKAPI *PFN_vkQueueSignalSemaphore)(VkQueue queue, VkSemaphore semaphore);
+typedef VkResult (VKAPI *PFN_vkQueueWaitSemaphore)(VkQueue queue, VkSemaphore semaphore);
+typedef VkResult (VKAPI *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, VkEvent* pEvent);
+typedef VkResult (VKAPI *PFN_vkDestroyEvent)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI *PFN_vkGetEventStatus)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI *PFN_vkSetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI *PFN_vkResetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, VkQueryPool* pQueryPool);
+typedef VkResult (VKAPI *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool);
+typedef VkResult (VKAPI *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, size_t* pDataSize, void* pData, VkQueryResultFlags flags);
+typedef VkResult (VKAPI *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, VkBuffer* pBuffer);
+typedef VkResult (VKAPI *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer);
+typedef VkResult (VKAPI *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, VkBufferView* pView);
+typedef VkResult (VKAPI *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView);
+typedef VkResult (VKAPI *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage);
+typedef VkResult (VKAPI *PFN_vkDestroyImage)(VkDevice device, VkImage image);
+typedef VkResult (VKAPI *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
+typedef VkResult (VKAPI *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, VkImageView* pView);
+typedef VkResult (VKAPI *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView);
+typedef VkResult (VKAPI *PFN_vkCreateAttachmentView)(VkDevice device, const VkAttachmentViewCreateInfo* pCreateInfo, VkAttachmentView* pView);
+typedef VkResult (VKAPI *PFN_vkDestroyAttachmentView)(VkDevice device, VkAttachmentView attachmentView);
+typedef VkResult (VKAPI *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* pShaderModule);
+typedef VkResult (VKAPI *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule);
+typedef VkResult (VKAPI *PFN_vkCreateShader)(VkDevice device, const VkShaderCreateInfo* pCreateInfo, VkShader* pShader);
+typedef VkResult (VKAPI *PFN_vkDestroyShader)(VkDevice device, VkShader shader);
+typedef VkResult (VKAPI *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, VkPipelineCache* pPipelineCache);
+typedef VkResult (VKAPI *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache);
+typedef size_t (VKAPI *PFN_vkGetPipelineCacheSize)(VkDevice device, VkPipelineCache pipelineCache);
+typedef VkResult (VKAPI *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, void* pData);
+typedef VkResult (VKAPI *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache destCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches);
+typedef VkResult (VKAPI *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkGraphicsPipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines);
+typedef VkResult (VKAPI *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkComputePipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines);
+typedef VkResult (VKAPI *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline);
+typedef VkResult (VKAPI *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, VkPipelineLayout* pPipelineLayout);
+typedef VkResult (VKAPI *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout);
+typedef VkResult (VKAPI *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, VkSampler* pSampler);
+typedef VkResult (VKAPI *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler);
+typedef VkResult (VKAPI *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayout* pSetLayout);
+typedef VkResult (VKAPI *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout);
+typedef VkResult (VKAPI *PFN_vkCreateDescriptorPool)(VkDevice device, VkDescriptorPoolUsage poolUsage, uint32_t maxSets, const VkDescriptorPoolCreateInfo* pCreateInfo, VkDescriptorPool* pDescriptorPool);
+typedef VkResult (VKAPI *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool);
+typedef VkResult (VKAPI *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool);
+typedef VkResult (VKAPI *PFN_vkAllocDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorSetUsage setUsage, uint32_t count, const VkDescriptorSetLayout* pSetLayouts, VkDescriptorSet* pDescriptorSets, uint32_t* pCount);
+typedef VkResult (VKAPI *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets);
+typedef VkResult (VKAPI *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies);
+typedef VkResult (VKAPI *PFN_vkCreateDynamicViewportState)(VkDevice device, const VkDynamicViewportStateCreateInfo* pCreateInfo, VkDynamicViewportState* pState);
+typedef VkResult (VKAPI *PFN_vkDestroyDynamicViewportState)(VkDevice device, VkDynamicViewportState dynamicViewportState);
+typedef VkResult (VKAPI *PFN_vkCreateDynamicRasterState)(VkDevice device, const VkDynamicRasterStateCreateInfo* pCreateInfo, VkDynamicRasterState* pState);
+typedef VkResult (VKAPI *PFN_vkDestroyDynamicRasterState)(VkDevice device, VkDynamicRasterState dynamicRasterState);
+typedef VkResult (VKAPI *PFN_vkCreateDynamicColorBlendState)(VkDevice device, const VkDynamicColorBlendStateCreateInfo* pCreateInfo, VkDynamicColorBlendState* pState);
+typedef VkResult (VKAPI *PFN_vkDestroyDynamicColorBlendState)(VkDevice device, VkDynamicColorBlendState dynamicColorBlendState);
+typedef VkResult (VKAPI *PFN_vkCreateDynamicDepthStencilState)(VkDevice device, const VkDynamicDepthStencilStateCreateInfo* pCreateInfo, VkDynamicDepthStencilState* pState);
+typedef VkResult (VKAPI *PFN_vkDestroyDynamicDepthStencilState)(VkDevice device, VkDynamicDepthStencilState dynamicDepthStencilState);
+typedef VkResult (VKAPI *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, VkFramebuffer* pFramebuffer);
+typedef VkResult (VKAPI *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer);
+typedef VkResult (VKAPI *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, VkRenderPass* pRenderPass);
+typedef VkResult (VKAPI *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass);
+typedef VkResult (VKAPI *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+typedef VkResult (VKAPI *PFN_vkCreateCommandPool)(VkDevice device, const VkCmdPoolCreateInfo* pCreateInfo, VkCmdPool* pCmdPool);
+typedef VkResult (VKAPI *PFN_vkDestroyCommandPool)(VkDevice device, VkCmdPool cmdPool);
+typedef VkResult (VKAPI *PFN_vkResetCommandPool)(VkDevice device, VkCmdPool cmdPool, VkCmdPoolResetFlags flags);
+typedef VkResult (VKAPI *PFN_vkCreateCommandBuffer)(VkDevice device, const VkCmdBufferCreateInfo* pCreateInfo, VkCmdBuffer* pCmdBuffer);
+typedef VkResult (VKAPI *PFN_vkDestroyCommandBuffer)(VkDevice device, VkCmdBuffer commandBuffer);
+typedef VkResult (VKAPI *PFN_vkBeginCommandBuffer)(VkCmdBuffer cmdBuffer, const VkCmdBufferBeginInfo* pBeginInfo);
+typedef VkResult (VKAPI *PFN_vkEndCommandBuffer)(VkCmdBuffer cmdBuffer);
+typedef VkResult (VKAPI *PFN_vkResetCommandBuffer)(VkCmdBuffer cmdBuffer, VkCmdBufferResetFlags flags);
+typedef void (VKAPI *PFN_vkCmdBindPipeline)(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+typedef void (VKAPI *PFN_vkCmdBindDynamicViewportState)(VkCmdBuffer cmdBuffer, VkDynamicViewportState dynamicViewportState);
+typedef void (VKAPI *PFN_vkCmdBindDynamicRasterState)(VkCmdBuffer cmdBuffer, VkDynamicRasterState dynamicRasterState);
+typedef void (VKAPI *PFN_vkCmdBindDynamicColorBlendState)(VkCmdBuffer cmdBuffer, VkDynamicColorBlendState dynamicColorBlendState);
+typedef void (VKAPI *PFN_vkCmdBindDynamicDepthStencilState)(VkCmdBuffer cmdBuffer, VkDynamicDepthStencilState dynamicDepthStencilState);
+typedef void (VKAPI *PFN_vkCmdBindDescriptorSets)(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets);
+typedef void (VKAPI *PFN_vkCmdBindIndexBuffer)(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
+typedef void (VKAPI *PFN_vkCmdBindVertexBuffers)(VkCmdBuffer cmdBuffer, uint32_t startBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets);
+typedef void (VKAPI *PFN_vkCmdDraw)(VkCmdBuffer cmdBuffer, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount);
+typedef void (VKAPI *PFN_vkCmdDrawIndexed)(VkCmdBuffer cmdBuffer, uint32_t firstIndex, uint32_t indexCount, int32_t vertexOffset, uint32_t firstInstance, uint32_t instanceCount);
+typedef void (VKAPI *PFN_vkCmdDrawIndirect)(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride);
+typedef void (VKAPI *PFN_vkCmdDrawIndexedIndirect)(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride);
+typedef void (VKAPI *PFN_vkCmdDispatch)(VkCmdBuffer cmdBuffer, uint32_t x, uint32_t y, uint32_t z);
+typedef void (VKAPI *PFN_vkCmdDispatchIndirect)(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset);
+typedef void (VKAPI *PFN_vkCmdCopyBuffer)(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkBuffer destBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
+typedef void (VKAPI *PFN_vkCmdCopyImage)(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
+typedef void (VKAPI *PFN_vkCmdBlitImage)(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkTexFilter filter);
+typedef void (VKAPI *PFN_vkCmdCopyBufferToImage)(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+typedef void (VKAPI *PFN_vkCmdCopyImageToBuffer)(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer destBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+typedef void (VKAPI *PFN_vkCmdUpdateBuffer)(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize dataSize, const uint32_t* pData);
+typedef void (VKAPI *PFN_vkCmdFillBuffer)(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize fillSize, uint32_t data);
+typedef void (VKAPI *PFN_vkCmdClearColorImage)(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+typedef void (VKAPI *PFN_vkCmdClearDepthStencilImage)(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+typedef void (VKAPI *PFN_vkCmdClearColorAttachment)(VkCmdBuffer cmdBuffer, uint32_t colorAttachment, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rectCount, const VkRect3D* pRects);
+typedef void (VKAPI *PFN_vkCmdClearDepthStencilAttachment)(VkCmdBuffer cmdBuffer, VkImageAspectFlags imageAspectMask, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rectCount, const VkRect3D* pRects);
+typedef void (VKAPI *PFN_vkCmdResolveImage)(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageResolve* pRegions);
+typedef void (VKAPI *PFN_vkCmdSetEvent)(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (VKAPI *PFN_vkCmdResetEvent)(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (VKAPI *PFN_vkCmdWaitEvents)(VkCmdBuffer cmdBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, uint32_t memBarrierCount, const void* const* ppMemBarriers);
+typedef void (VKAPI *PFN_vkCmdPipelineBarrier)(VkCmdBuffer cmdBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, VkBool32 byRegion, uint32_t memBarrierCount, const void* const* ppMemBarriers);
+typedef void (VKAPI *PFN_vkCmdBeginQuery)(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags);
+typedef void (VKAPI *PFN_vkCmdEndQuery)(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot);
+typedef void (VKAPI *PFN_vkCmdResetQueryPool)(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount);
+typedef void (VKAPI *PFN_vkCmdWriteTimestamp)(VkCmdBuffer cmdBuffer, VkTimestampType timestampType, VkBuffer destBuffer, VkDeviceSize destOffset);
+typedef void (VKAPI *PFN_vkCmdCopyQueryPoolResults)(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize destStride, VkQueryResultFlags flags);
+typedef void (VKAPI *PFN_vkCmdPushConstants)(VkCmdBuffer cmdBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t start, uint32_t length, const void* values);
+typedef void (VKAPI *PFN_vkCmdBeginRenderPass)(VkCmdBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkRenderPassContents contents);
+typedef void (VKAPI *PFN_vkCmdNextSubpass)(VkCmdBuffer cmdBuffer, VkRenderPassContents contents);
+typedef void (VKAPI *PFN_vkCmdEndRenderPass)(VkCmdBuffer cmdBuffer);
+typedef void (VKAPI *PFN_vkCmdExecuteCommands)(VkCmdBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCmdBuffer* pCmdBuffers);
+
+#ifdef VK_PROTOTYPES
+VkResult VKAPI vkCreateInstance(
+    const VkInstanceCreateInfo*                 pCreateInfo,
+    VkInstance*                                 pInstance);
+
+VkResult VKAPI vkDestroyInstance(
+    VkInstance                                  instance);
+
+VkResult VKAPI vkEnumeratePhysicalDevices(
+    VkInstance                                  instance,
+    uint32_t*                                   pPhysicalDeviceCount,
+    VkPhysicalDevice*                           pPhysicalDevices);
+
+VkResult VKAPI vkGetPhysicalDeviceFeatures(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceFeatures*                   pFeatures);
+
+VkResult VKAPI vkGetPhysicalDeviceFormatProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkFormatProperties*                         pFormatProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceImageFormatProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkImageType                                 type,
+    VkImageTiling                               tiling,
+    VkImageUsageFlags                           usage,
+    VkImageFormatProperties*                    pImageFormatProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceLimits(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceLimits*                     pLimits);
+
+VkResult VKAPI vkGetPhysicalDeviceProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceProperties*                 pProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceQueueCount(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pCount);
+
+VkResult VKAPI vkGetPhysicalDeviceQueueProperties(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    count,
+    VkPhysicalDeviceQueueProperties*            pQueueProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceMemoryProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceMemoryProperties*           pMemoryProperties);
+
+PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(
+    VkInstance                                  instance,
+    const char*                                 pName);
+
+PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(
+    VkDevice                                    device,
+    const char*                                 pName);
+
+VkResult VKAPI vkCreateDevice(
+    VkPhysicalDevice                            physicalDevice,
+    const VkDeviceCreateInfo*                   pCreateInfo,
+    VkDevice*                                   pDevice);
+
+VkResult VKAPI vkDestroyDevice(
+    VkDevice                                    device);
+
+VkResult VKAPI vkGetGlobalExtensionProperties(
+    const char*                                 pLayerName,
+    uint32_t*                                   pCount,
+    VkExtensionProperties*                      pProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceExtensionProperties(
+    VkPhysicalDevice                            physicalDevice,
+    const char*                                 pLayerName,
+    uint32_t*                                   pCount,
+    VkExtensionProperties*                      pProperties);
+
+VkResult VKAPI vkGetGlobalLayerProperties(
+    uint32_t*                                   pCount,
+    VkLayerProperties*                          pProperties);
+
+VkResult VKAPI vkGetPhysicalDeviceLayerProperties(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pCount,
+    VkLayerProperties*                          pProperties);
+
+VkResult VKAPI vkGetDeviceQueue(
+    VkDevice                                    device,
+    uint32_t                                    queueFamilyIndex,
+    uint32_t                                    queueIndex,
+    VkQueue*                                    pQueue);
+
+VkResult VKAPI vkQueueSubmit(
+    VkQueue                                     queue,
+    uint32_t                                    cmdBufferCount,
+    const VkCmdBuffer*                          pCmdBuffers,
+    VkFence                                     fence);
+
+VkResult VKAPI vkQueueWaitIdle(
+    VkQueue                                     queue);
+
+VkResult VKAPI vkDeviceWaitIdle(
+    VkDevice                                    device);
+
+VkResult VKAPI vkAllocMemory(
+    VkDevice                                    device,
+    const VkMemoryAllocInfo*                    pAllocInfo,
+    VkDeviceMemory*                             pMem);
+
+VkResult VKAPI vkFreeMemory(
+    VkDevice                                    device,
+    VkDeviceMemory                              mem);
+
+VkResult VKAPI vkMapMemory(
+    VkDevice                                    device,
+    VkDeviceMemory                              mem,
+    VkDeviceSize                                offset,
+    VkDeviceSize                                size,
+    VkMemoryMapFlags                            flags,
+    void**                                      ppData);
+
+VkResult VKAPI vkUnmapMemory(
+    VkDevice                                    device,
+    VkDeviceMemory                              mem);
+
+VkResult VKAPI vkFlushMappedMemoryRanges(
+    VkDevice                                    device,
+    uint32_t                                    memRangeCount,
+    const VkMappedMemoryRange*                  pMemRanges);
+
+VkResult VKAPI vkInvalidateMappedMemoryRanges(
+    VkDevice                                    device,
+    uint32_t                                    memRangeCount,
+    const VkMappedMemoryRange*                  pMemRanges);
+
+VkResult VKAPI vkGetDeviceMemoryCommitment(
+    VkDevice                                    device,
+    VkDeviceMemory                              memory,
+    VkDeviceSize*                               pCommittedMemoryInBytes);
+
+VkResult VKAPI vkBindBufferMemory(
+    VkDevice                                    device,
+    VkBuffer                                    buffer,
+    VkDeviceMemory                              mem,
+    VkDeviceSize                                memOffset);
+
+VkResult VKAPI vkBindImageMemory(
+    VkDevice                                    device,
+    VkImage                                     image,
+    VkDeviceMemory                              mem,
+    VkDeviceSize                                memOffset);
+
+VkResult VKAPI vkGetBufferMemoryRequirements(
+    VkDevice                                    device,
+    VkBuffer                                    buffer,
+    VkMemoryRequirements*                       pMemoryRequirements);
+
+VkResult VKAPI vkGetImageMemoryRequirements(
+    VkDevice                                    device,
+    VkImage                                     image,
+    VkMemoryRequirements*                       pMemoryRequirements);
+
+VkResult VKAPI vkGetImageSparseMemoryRequirements(
+    VkDevice                                    device,
+    VkImage                                     image,
+    uint32_t*                                   pNumRequirements,
+    VkSparseImageMemoryRequirements*            pSparseMemoryRequirements);
+
+VkResult VKAPI vkGetPhysicalDeviceSparseImageFormatProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkImageType                                 type,
+    uint32_t                                    samples,
+    VkImageUsageFlags                           usage,
+    VkImageTiling                               tiling,
+    uint32_t*                                   pNumProperties,
+    VkSparseImageFormatProperties*              pProperties);
+
+VkResult VKAPI vkQueueBindSparseBufferMemory(
+    VkQueue                                     queue,
+    VkBuffer                                    buffer,
+    uint32_t                                    numBindings,
+    const VkSparseMemoryBindInfo*               pBindInfo);
+
+VkResult VKAPI vkQueueBindSparseImageOpaqueMemory(
+    VkQueue                                     queue,
+    VkImage                                     image,
+    uint32_t                                    numBindings,
+    const VkSparseMemoryBindInfo*               pBindInfo);
+
+VkResult VKAPI vkQueueBindSparseImageMemory(
+    VkQueue                                     queue,
+    VkImage                                     image,
+    uint32_t                                    numBindings,
+    const VkSparseImageMemoryBindInfo*          pBindInfo);
+
+VkResult VKAPI vkCreateFence(
+    VkDevice                                    device,
+    const VkFenceCreateInfo*                    pCreateInfo,
+    VkFence*                                    pFence);
+
+VkResult VKAPI vkDestroyFence(
+    VkDevice                                    device,
+    VkFence                                     fence);
+
+VkResult VKAPI vkResetFences(
+    VkDevice                                    device,
+    uint32_t                                    fenceCount,
+    const VkFence*                              pFences);
+
+VkResult VKAPI vkGetFenceStatus(
+    VkDevice                                    device,
+    VkFence                                     fence);
+
+VkResult VKAPI vkWaitForFences(
+    VkDevice                                    device,
+    uint32_t                                    fenceCount,
+    const VkFence*                              pFences,
+    VkBool32                                    waitAll,
+    uint64_t                                    timeout);
+
+VkResult VKAPI vkCreateSemaphore(
+    VkDevice                                    device,
+    const VkSemaphoreCreateInfo*                pCreateInfo,
+    VkSemaphore*                                pSemaphore);
+
+VkResult VKAPI vkDestroySemaphore(
+    VkDevice                                    device,
+    VkSemaphore                                 semaphore);
+
+VkResult VKAPI vkQueueSignalSemaphore(
+    VkQueue                                     queue,
+    VkSemaphore                                 semaphore);
+
+VkResult VKAPI vkQueueWaitSemaphore(
+    VkQueue                                     queue,
+    VkSemaphore                                 semaphore);
+
+VkResult VKAPI vkCreateEvent(
+    VkDevice                                    device,
+    const VkEventCreateInfo*                    pCreateInfo,
+    VkEvent*                                    pEvent);
+
+VkResult VKAPI vkDestroyEvent(
+    VkDevice                                    device,
+    VkEvent                                     event);
+
+VkResult VKAPI vkGetEventStatus(
+    VkDevice                                    device,
+    VkEvent                                     event);
+
+VkResult VKAPI vkSetEvent(
+    VkDevice                                    device,
+    VkEvent                                     event);
+
+VkResult VKAPI vkResetEvent(
+    VkDevice                                    device,
+    VkEvent                                     event);
+
+VkResult VKAPI vkCreateQueryPool(
+    VkDevice                                    device,
+    const VkQueryPoolCreateInfo*                pCreateInfo,
+    VkQueryPool*                                pQueryPool);
+
+VkResult VKAPI vkDestroyQueryPool(
+    VkDevice                                    device,
+    VkQueryPool                                 queryPool);
+
+VkResult VKAPI vkGetQueryPoolResults(
+    VkDevice                                    device,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    startQuery,
+    uint32_t                                    queryCount,
+    size_t*                                     pDataSize,
+    void*                                       pData,
+    VkQueryResultFlags                          flags);
+
+VkResult VKAPI vkCreateBuffer(
+    VkDevice                                    device,
+    const VkBufferCreateInfo*                   pCreateInfo,
+    VkBuffer*                                   pBuffer);
+
+VkResult VKAPI vkDestroyBuffer(
+    VkDevice                                    device,
+    VkBuffer                                    buffer);
+
+VkResult VKAPI vkCreateBufferView(
+    VkDevice                                    device,
+    const VkBufferViewCreateInfo*               pCreateInfo,
+    VkBufferView*                               pView);
+
+VkResult VKAPI vkDestroyBufferView(
+    VkDevice                                    device,
+    VkBufferView                                bufferView);
+
+VkResult VKAPI vkCreateImage(
+    VkDevice                                    device,
+    const VkImageCreateInfo*                    pCreateInfo,
+    VkImage*                                    pImage);
+
+VkResult VKAPI vkDestroyImage(
+    VkDevice                                    device,
+    VkImage                                     image);
+
+VkResult VKAPI vkGetImageSubresourceLayout(
+    VkDevice                                    device,
+    VkImage                                     image,
+    const VkImageSubresource*                   pSubresource,
+    VkSubresourceLayout*                        pLayout);
+
+VkResult VKAPI vkCreateImageView(
+    VkDevice                                    device,
+    const VkImageViewCreateInfo*                pCreateInfo,
+    VkImageView*                                pView);
+
+VkResult VKAPI vkDestroyImageView(
+    VkDevice                                    device,
+    VkImageView                                 imageView);
+
+VkResult VKAPI vkCreateAttachmentView(
+    VkDevice                                    device,
+    const VkAttachmentViewCreateInfo*           pCreateInfo,
+    VkAttachmentView*                           pView);
+
+VkResult VKAPI vkDestroyAttachmentView(
+    VkDevice                                    device,
+    VkAttachmentView                            attachmentView);
+
+VkResult VKAPI vkCreateShaderModule(
+    VkDevice                                    device,
+    const VkShaderModuleCreateInfo*             pCreateInfo,
+    VkShaderModule*                             pShaderModule);
+
+VkResult VKAPI vkDestroyShaderModule(
+    VkDevice                                    device,
+    VkShaderModule                              shaderModule);
+
+VkResult VKAPI vkCreateShader(
+    VkDevice                                    device,
+    const VkShaderCreateInfo*                   pCreateInfo,
+    VkShader*                                   pShader);
+
+VkResult VKAPI vkDestroyShader(
+    VkDevice                                    device,
+    VkShader                                    shader);
+
+VkResult VKAPI vkCreatePipelineCache(
+    VkDevice                                    device,
+    const VkPipelineCacheCreateInfo*            pCreateInfo,
+    VkPipelineCache*                            pPipelineCache);
+
+VkResult VKAPI vkDestroyPipelineCache(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache);
+
+size_t VKAPI vkGetPipelineCacheSize(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache);
+
+VkResult VKAPI vkGetPipelineCacheData(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    void*                                       pData);
+
+VkResult VKAPI vkMergePipelineCaches(
+    VkDevice                                    device,
+    VkPipelineCache                             destCache,
+    uint32_t                                    srcCacheCount,
+    const VkPipelineCache*                      pSrcCaches);
+
+VkResult VKAPI vkCreateGraphicsPipelines(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    uint32_t                                    count,
+    const VkGraphicsPipelineCreateInfo*         pCreateInfos,
+    VkPipeline*                                 pPipelines);
+
+VkResult VKAPI vkCreateComputePipelines(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    uint32_t                                    count,
+    const VkComputePipelineCreateInfo*          pCreateInfos,
+    VkPipeline*                                 pPipelines);
+
+VkResult VKAPI vkDestroyPipeline(
+    VkDevice                                    device,
+    VkPipeline                                  pipeline);
+
+VkResult VKAPI vkCreatePipelineLayout(
+    VkDevice                                    device,
+    const VkPipelineLayoutCreateInfo*           pCreateInfo,
+    VkPipelineLayout*                           pPipelineLayout);
+
+VkResult VKAPI vkDestroyPipelineLayout(
+    VkDevice                                    device,
+    VkPipelineLayout                            pipelineLayout);
+
+VkResult VKAPI vkCreateSampler(
+    VkDevice                                    device,
+    const VkSamplerCreateInfo*                  pCreateInfo,
+    VkSampler*                                  pSampler);
+
+VkResult VKAPI vkDestroySampler(
+    VkDevice                                    device,
+    VkSampler                                   sampler);
+
+VkResult VKAPI vkCreateDescriptorSetLayout(
+    VkDevice                                    device,
+    const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
+    VkDescriptorSetLayout*                      pSetLayout);
+
+VkResult VKAPI vkDestroyDescriptorSetLayout(
+    VkDevice                                    device,
+    VkDescriptorSetLayout                       descriptorSetLayout);
+
+VkResult VKAPI vkCreateDescriptorPool(
+    VkDevice                                    device,
+    VkDescriptorPoolUsage                       poolUsage,
+    uint32_t                                    maxSets,
+    const VkDescriptorPoolCreateInfo*           pCreateInfo,
+    VkDescriptorPool*                           pDescriptorPool);
+
+VkResult VKAPI vkDestroyDescriptorPool(
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool);
+
+VkResult VKAPI vkResetDescriptorPool(
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool);
+
+VkResult VKAPI vkAllocDescriptorSets(
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool,
+    VkDescriptorSetUsage                        setUsage,
+    uint32_t                                    count,
+    const VkDescriptorSetLayout*                pSetLayouts,
+    VkDescriptorSet*                            pDescriptorSets,
+    uint32_t*                                   pCount);
+
+VkResult VKAPI vkFreeDescriptorSets(
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool,
+    uint32_t                                    count,
+    const VkDescriptorSet*                      pDescriptorSets);
+
+VkResult VKAPI vkUpdateDescriptorSets(
+    VkDevice                                    device,
+    uint32_t                                    writeCount,
+    const VkWriteDescriptorSet*                 pDescriptorWrites,
+    uint32_t                                    copyCount,
+    const VkCopyDescriptorSet*                  pDescriptorCopies);
+
+VkResult VKAPI vkCreateDynamicViewportState(
+    VkDevice                                    device,
+    const VkDynamicViewportStateCreateInfo*     pCreateInfo,
+    VkDynamicViewportState*                     pState);
+
+VkResult VKAPI vkDestroyDynamicViewportState(
+    VkDevice                                    device,
+    VkDynamicViewportState                      dynamicViewportState);
+
+VkResult VKAPI vkCreateDynamicRasterState(
+    VkDevice                                    device,
+    const VkDynamicRasterStateCreateInfo*       pCreateInfo,
+    VkDynamicRasterState*                       pState);
+
+VkResult VKAPI vkDestroyDynamicRasterState(
+    VkDevice                                    device,
+    VkDynamicRasterState                        dynamicRasterState);
+
+VkResult VKAPI vkCreateDynamicColorBlendState(
+    VkDevice                                    device,
+    const VkDynamicColorBlendStateCreateInfo*   pCreateInfo,
+    VkDynamicColorBlendState*                   pState);
+
+VkResult VKAPI vkDestroyDynamicColorBlendState(
+    VkDevice                                    device,
+    VkDynamicColorBlendState                    dynamicColorBlendState);
+
+VkResult VKAPI vkCreateDynamicDepthStencilState(
+    VkDevice                                    device,
+    const VkDynamicDepthStencilStateCreateInfo* pCreateInfo,
+    VkDynamicDepthStencilState*                 pState);
+
+VkResult VKAPI vkDestroyDynamicDepthStencilState(
+    VkDevice                                    device,
+    VkDynamicDepthStencilState                  dynamicDepthStencilState);
+
+VkResult VKAPI vkCreateFramebuffer(
+    VkDevice                                    device,
+    const VkFramebufferCreateInfo*              pCreateInfo,
+    VkFramebuffer*                              pFramebuffer);
+
+VkResult VKAPI vkDestroyFramebuffer(
+    VkDevice                                    device,
+    VkFramebuffer                               framebuffer);
+
+VkResult VKAPI vkCreateRenderPass(
+    VkDevice                                    device,
+    const VkRenderPassCreateInfo*               pCreateInfo,
+    VkRenderPass*                               pRenderPass);
+
+VkResult VKAPI vkDestroyRenderPass(
+    VkDevice                                    device,
+    VkRenderPass                                renderPass);
+
+VkResult VKAPI vkGetRenderAreaGranularity(
+    VkDevice                                    device,
+    VkRenderPass                                renderPass,
+    VkExtent2D*                                 pGranularity);
+
+VkResult VKAPI vkCreateCommandPool(
+    VkDevice                                    device,
+    const VkCmdPoolCreateInfo*                  pCreateInfo,
+    VkCmdPool*                                  pCmdPool);
+
+VkResult VKAPI vkDestroyCommandPool(
+    VkDevice                                    device,
+    VkCmdPool                                   cmdPool);
+
+VkResult VKAPI vkResetCommandPool(
+    VkDevice                                    device,
+    VkCmdPool                                   cmdPool,
+    VkCmdPoolResetFlags                         flags);
+
+VkResult VKAPI vkCreateCommandBuffer(
+    VkDevice                                    device,
+    const VkCmdBufferCreateInfo*                pCreateInfo,
+    VkCmdBuffer*                                pCmdBuffer);
+
+VkResult VKAPI vkDestroyCommandBuffer(
+    VkDevice                                    device,
+    VkCmdBuffer                                 commandBuffer);
+
+VkResult VKAPI vkBeginCommandBuffer(
+    VkCmdBuffer                                 cmdBuffer,
+    const VkCmdBufferBeginInfo*                 pBeginInfo);
+
+VkResult VKAPI vkEndCommandBuffer(
+    VkCmdBuffer                                 cmdBuffer);
+
+VkResult VKAPI vkResetCommandBuffer(
+    VkCmdBuffer                                 cmdBuffer,
+    VkCmdBufferResetFlags                       flags);
+
+void VKAPI vkCmdBindPipeline(
+    VkCmdBuffer                                 cmdBuffer,
+    VkPipelineBindPoint                         pipelineBindPoint,
+    VkPipeline                                  pipeline);
+
+void VKAPI vkCmdBindDynamicViewportState(
+    VkCmdBuffer                                 cmdBuffer,
+    VkDynamicViewportState                      dynamicViewportState);
+
+void VKAPI vkCmdBindDynamicRasterState(
+    VkCmdBuffer                                 cmdBuffer,
+    VkDynamicRasterState                        dynamicRasterState);
+
+void VKAPI vkCmdBindDynamicColorBlendState(
+    VkCmdBuffer                                 cmdBuffer,
+    VkDynamicColorBlendState                    dynamicColorBlendState);
+
+void VKAPI vkCmdBindDynamicDepthStencilState(
+    VkCmdBuffer                                 cmdBuffer,
+    VkDynamicDepthStencilState                  dynamicDepthStencilState);
+
+void VKAPI vkCmdBindDescriptorSets(
+    VkCmdBuffer                                 cmdBuffer,
+    VkPipelineBindPoint                         pipelineBindPoint,
+    VkPipelineLayout                            layout,
+    uint32_t                                    firstSet,
+    uint32_t                                    setCount,
+    const VkDescriptorSet*                      pDescriptorSets,
+    uint32_t                                    dynamicOffsetCount,
+    const uint32_t*                             pDynamicOffsets);
+
+void VKAPI vkCmdBindIndexBuffer(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    VkIndexType                                 indexType);
+
+void VKAPI vkCmdBindVertexBuffers(
+    VkCmdBuffer                                 cmdBuffer,
+    uint32_t                                    startBinding,
+    uint32_t                                    bindingCount,
+    const VkBuffer*                             pBuffers,
+    const VkDeviceSize*                         pOffsets);
+
+void VKAPI vkCmdDraw(
+    VkCmdBuffer                                 cmdBuffer,
+    uint32_t                                    firstVertex,
+    uint32_t                                    vertexCount,
+    uint32_t                                    firstInstance,
+    uint32_t                                    instanceCount);
+
+void VKAPI vkCmdDrawIndexed(
+    VkCmdBuffer                                 cmdBuffer,
+    uint32_t                                    firstIndex,
+    uint32_t                                    indexCount,
+    int32_t                                     vertexOffset,
+    uint32_t                                    firstInstance,
+    uint32_t                                    instanceCount);
+
+void VKAPI vkCmdDrawIndirect(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    uint32_t                                    count,
+    uint32_t                                    stride);
+
+void VKAPI vkCmdDrawIndexedIndirect(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    uint32_t                                    count,
+    uint32_t                                    stride);
+
+void VKAPI vkCmdDispatch(
+    VkCmdBuffer                                 cmdBuffer,
+    uint32_t                                    x,
+    uint32_t                                    y,
+    uint32_t                                    z);
+
+void VKAPI vkCmdDispatchIndirect(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset);
+
+void VKAPI vkCmdCopyBuffer(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    srcBuffer,
+    VkBuffer                                    destBuffer,
+    uint32_t                                    regionCount,
+    const VkBufferCopy*                         pRegions);
+
+void VKAPI vkCmdCopyImage(
+    VkCmdBuffer                                 cmdBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkImage                                     destImage,
+    VkImageLayout                               destImageLayout,
+    uint32_t                                    regionCount,
+    const VkImageCopy*                          pRegions);
+
+void VKAPI vkCmdBlitImage(
+    VkCmdBuffer                                 cmdBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkImage                                     destImage,
+    VkImageLayout                               destImageLayout,
+    uint32_t                                    regionCount,
+    const VkImageBlit*                          pRegions,
+    VkTexFilter                                 filter);
+
+void VKAPI vkCmdCopyBufferToImage(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    srcBuffer,
+    VkImage                                     destImage,
+    VkImageLayout                               destImageLayout,
+    uint32_t                                    regionCount,
+    const VkBufferImageCopy*                    pRegions);
+
+void VKAPI vkCmdCopyImageToBuffer(
+    VkCmdBuffer                                 cmdBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkBuffer                                    destBuffer,
+    uint32_t                                    regionCount,
+    const VkBufferImageCopy*                    pRegions);
+
+void VKAPI vkCmdUpdateBuffer(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    destBuffer,
+    VkDeviceSize                                destOffset,
+    VkDeviceSize                                dataSize,
+    const uint32_t*                             pData);
+
+void VKAPI vkCmdFillBuffer(
+    VkCmdBuffer                                 cmdBuffer,
+    VkBuffer                                    destBuffer,
+    VkDeviceSize                                destOffset,
+    VkDeviceSize                                fillSize,
+    uint32_t                                    data);
+
+void VKAPI vkCmdClearColorImage(
+    VkCmdBuffer                                 cmdBuffer,
+    VkImage                                     image,
+    VkImageLayout                               imageLayout,
+    const VkClearColorValue*                    pColor,
+    uint32_t                                    rangeCount,
+    const VkImageSubresourceRange*              pRanges);
+
+void VKAPI vkCmdClearDepthStencilImage(
+    VkCmdBuffer                                 cmdBuffer,
+    VkImage                                     image,
+    VkImageLayout                               imageLayout,
+    float                                       depth,
+    uint32_t                                    stencil,
+    uint32_t                                    rangeCount,
+    const VkImageSubresourceRange*              pRanges);
+
+void VKAPI vkCmdClearColorAttachment(
+    VkCmdBuffer                                 cmdBuffer,
+    uint32_t                                    colorAttachment,
+    VkImageLayout                               imageLayout,
+    const VkClearColorValue*                    pColor,
+    uint32_t                                    rectCount,
+    const VkRect3D*                             pRects);
+
+void VKAPI vkCmdClearDepthStencilAttachment(
+    VkCmdBuffer                                 cmdBuffer,
+    VkImageAspectFlags                          imageAspectMask,
+    VkImageLayout                               imageLayout,
+    float                                       depth,
+    uint32_t                                    stencil,
+    uint32_t                                    rectCount,
+    const VkRect3D*                             pRects);
+
+void VKAPI vkCmdResolveImage(
+    VkCmdBuffer                                 cmdBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkImage                                     destImage,
+    VkImageLayout                               destImageLayout,
+    uint32_t                                    regionCount,
+    const VkImageResolve*                       pRegions);
+
+void VKAPI vkCmdSetEvent(
+    VkCmdBuffer                                 cmdBuffer,
+    VkEvent                                     event,
+    VkPipelineStageFlags                        stageMask);
+
+void VKAPI vkCmdResetEvent(
+    VkCmdBuffer                                 cmdBuffer,
+    VkEvent                                     event,
+    VkPipelineStageFlags                        stageMask);
+
+void VKAPI vkCmdWaitEvents(
+    VkCmdBuffer                                 cmdBuffer,
+    uint32_t                                    eventCount,
+    const VkEvent*                              pEvents,
+    VkPipelineStageFlags                        srcStageMask,
+    VkPipelineStageFlags                        destStageMask,
+    uint32_t                                    memBarrierCount,
+    const void* const*                          ppMemBarriers);
+
+void VKAPI vkCmdPipelineBarrier(
+    VkCmdBuffer                                 cmdBuffer,
+    VkPipelineStageFlags                        srcStageMask,
+    VkPipelineStageFlags                        destStageMask,
+    VkBool32                                    byRegion,
+    uint32_t                                    memBarrierCount,
+    const void* const*                          ppMemBarriers);
+
+void VKAPI vkCmdBeginQuery(
+    VkCmdBuffer                                 cmdBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    slot,
+    VkQueryControlFlags                         flags);
+
+void VKAPI vkCmdEndQuery(
+    VkCmdBuffer                                 cmdBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    slot);
+
+void VKAPI vkCmdResetQueryPool(
+    VkCmdBuffer                                 cmdBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    startQuery,
+    uint32_t                                    queryCount);
+
+void VKAPI vkCmdWriteTimestamp(
+    VkCmdBuffer                                 cmdBuffer,
+    VkTimestampType                             timestampType,
+    VkBuffer                                    destBuffer,
+    VkDeviceSize                                destOffset);
+
+void VKAPI vkCmdCopyQueryPoolResults(
+    VkCmdBuffer                                 cmdBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    startQuery,
+    uint32_t                                    queryCount,
+    VkBuffer                                    destBuffer,
+    VkDeviceSize                                destOffset,
+    VkDeviceSize                                destStride,
+    VkQueryResultFlags                          flags);
+
+void VKAPI vkCmdPushConstants(
+    VkCmdBuffer                                 cmdBuffer,
+    VkPipelineLayout                            layout,
+    VkShaderStageFlags                          stageFlags,
+    uint32_t                                    start,
+    uint32_t                                    length,
+    const void*                                 values);
+
+void VKAPI vkCmdBeginRenderPass(
+    VkCmdBuffer                                 cmdBuffer,
+    const VkRenderPassBeginInfo*                pRenderPassBegin,
+    VkRenderPassContents                        contents);
+
+void VKAPI vkCmdNextSubpass(
+    VkCmdBuffer                                 cmdBuffer,
+    VkRenderPassContents                        contents);
+
+void VKAPI vkCmdEndRenderPass(
+    VkCmdBuffer                                 cmdBuffer);
+
+void VKAPI vkCmdExecuteCommands(
+    VkCmdBuffer                                 cmdBuffer,
+    uint32_t                                    cmdBuffersCount,
+    const VkCmdBuffer*                          pCmdBuffers);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
new file mode 100644
index 0000000..c26b01f
--- /dev/null
+++ b/vulkan/libvulkan/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
+LOCAL_CFLAGS += -DLOG_TAG=\"vulkan\"
+LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef
+LOCAL_CPPFLAGS := -std=c++1y \
+	-Wno-c++98-compat-pedantic \
+	-Wno-exit-time-destructors \
+	-Wno-c99-extensions
+
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include
+
+LOCAL_SRC_FILES := \
+	entry.cpp \
+	get_proc_addr.cpp \
+	loader.cpp
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_SHARED_LIBRARIES := libhardware liblog
+
+LOCAL_MODULE := libvulkan
+include $(BUILD_SHARED_LIBRARY)
diff --git a/vulkan/libvulkan/entry.cpp b/vulkan/libvulkan/entry.cpp
new file mode 100644
index 0000000..7bfaaf2
--- /dev/null
+++ b/vulkan/libvulkan/entry.cpp
@@ -0,0 +1,802 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+// This file is generated. Do not edit manually!
+// To regenerate: $ apic template ../api/vulkan.api entry.cpp.tmpl
+// Requires apic from https://android.googlesource.com/platform/tools/gpu/.
+
+#include "loader.h"
+using namespace vulkan;
+
+// clang-format off
+
+namespace {
+    inline const InstanceVtbl& GetVtbl(VkInstance instance) {
+        return **reinterpret_cast<InstanceVtbl**>(instance);
+    }
+    inline const InstanceVtbl& GetVtbl(VkPhysicalDevice physicalDevice) {
+        return **reinterpret_cast<InstanceVtbl**>(physicalDevice);
+    }
+    inline const DeviceVtbl& GetVtbl(VkDevice device) {
+        return **reinterpret_cast<DeviceVtbl**>(device);
+    }
+    inline const DeviceVtbl& GetVtbl(VkQueue queue) {
+        return **reinterpret_cast<DeviceVtbl**>(queue);
+    }
+    inline const DeviceVtbl& GetVtbl(VkCmdBuffer cmdBuffer) {
+        return **reinterpret_cast<DeviceVtbl**>(cmdBuffer);
+    }
+} // namespace
+
+__attribute__((visibility("default")))
+VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance) {
+    return vulkan::CreateInstance(pCreateInfo, pInstance);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyInstance(VkInstance instance) {
+    return GetVtbl(instance).DestroyInstance(instance);
+}
+
+__attribute__((visibility("default")))
+VkResult vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
+    return GetVtbl(instance).EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
+}
+
+__attribute__((visibility("default")))
+PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* pName) {
+    return vulkan::GetDeviceProcAddr(device, pName);
+}
+
+__attribute__((visibility("default")))
+PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
+    return vulkan::GetInstanceProcAddr(instance, pName);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceProperties(physicalDevice, pProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceQueueCount(VkPhysicalDevice physicalDevice, uint32_t* pCount) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceQueueCount(physicalDevice, pCount);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceQueueProperties(VkPhysicalDevice physicalDevice, uint32_t count, VkPhysicalDeviceQueueProperties* pQueueProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceQueueProperties(physicalDevice, count, pQueueProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageFormatProperties* pImageFormatProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, pImageFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceLimits(VkPhysicalDevice physicalDevice, VkPhysicalDeviceLimits* pLimits) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceLimits(physicalDevice, pLimits);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice) {
+    return GetVtbl(physicalDevice).CreateDevice(physicalDevice, pCreateInfo, pDevice);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyDevice(VkDevice device) {
+    return vulkan::DestroyDevice(device);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetGlobalLayerProperties(uint32_t* pCount, VkLayerProperties* pProperties) {
+    return vulkan::GetGlobalLayerProperties(pCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetGlobalExtensionProperties(const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties) {
+    return vulkan::GetGlobalExtensionProperties(pLayerName, pCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pCount, VkLayerProperties* pProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceLayerProperties(physicalDevice, pCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) {
+    return vulkan::GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
+}
+
+__attribute__((visibility("default")))
+VkResult vkQueueSubmit(VkQueue queue, uint32_t cmdBufferCount, const VkCmdBuffer* pCmdBuffers, VkFence fence) {
+    return GetVtbl(queue).QueueSubmit(queue, cmdBufferCount, pCmdBuffers, fence);
+}
+
+__attribute__((visibility("default")))
+VkResult vkQueueWaitIdle(VkQueue queue) {
+    return GetVtbl(queue).QueueWaitIdle(queue);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDeviceWaitIdle(VkDevice device) {
+    return GetVtbl(device).DeviceWaitIdle(device);
+}
+
+__attribute__((visibility("default")))
+VkResult vkAllocMemory(VkDevice device, const VkMemoryAllocInfo* pAllocInfo, VkDeviceMemory* pMem) {
+    return GetVtbl(device).AllocMemory(device, pAllocInfo, pMem);
+}
+
+__attribute__((visibility("default")))
+VkResult vkFreeMemory(VkDevice device, VkDeviceMemory mem) {
+    return GetVtbl(device).FreeMemory(device, mem);
+}
+
+__attribute__((visibility("default")))
+VkResult vkMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
+    return GetVtbl(device).MapMemory(device, mem, offset, size, flags, ppData);
+}
+
+__attribute__((visibility("default")))
+VkResult vkUnmapMemory(VkDevice device, VkDeviceMemory mem) {
+    return GetVtbl(device).UnmapMemory(device, mem);
+}
+
+__attribute__((visibility("default")))
+VkResult vkFlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
+    return GetVtbl(device).FlushMappedMemoryRanges(device, memRangeCount, pMemRanges);
+}
+
+__attribute__((visibility("default")))
+VkResult vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
+    return GetVtbl(device).InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) {
+    return GetVtbl(device).GetDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) {
+    return GetVtbl(device).GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VkResult vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset) {
+    return GetVtbl(device).BindBufferMemory(device, buffer, mem, memOffset);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) {
+    return GetVtbl(device).GetImageMemoryRequirements(device, image, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VkResult vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset) {
+    return GetVtbl(device).BindImageMemory(device, image, mem, memOffset);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pNumRequirements, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
+    return GetVtbl(device).GetImageSparseMemoryRequirements(device, image, pNumRequirements, pSparseMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, uint32_t samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pNumProperties, VkSparseImageFormatProperties* pProperties) {
+    return GetVtbl(physicalDevice).GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pNumProperties, pProperties);
+}
+
+__attribute__((visibility("default")))
+VkResult vkQueueBindSparseBufferMemory(VkQueue queue, VkBuffer buffer, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) {
+    return GetVtbl(queue).QueueBindSparseBufferMemory(queue, buffer, numBindings, pBindInfo);
+}
+
+__attribute__((visibility("default")))
+VkResult vkQueueBindSparseImageOpaqueMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) {
+    return GetVtbl(queue).QueueBindSparseImageOpaqueMemory(queue, image, numBindings, pBindInfo);
+}
+
+__attribute__((visibility("default")))
+VkResult vkQueueBindSparseImageMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseImageMemoryBindInfo* pBindInfo) {
+    return GetVtbl(queue).QueueBindSparseImageMemory(queue, image, numBindings, pBindInfo);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo, VkFence* pFence) {
+    return GetVtbl(device).CreateFence(device, pCreateInfo, pFence);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyFence(VkDevice device, VkFence fence) {
+    return GetVtbl(device).DestroyFence(device, fence);
+}
+
+__attribute__((visibility("default")))
+VkResult vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
+    return GetVtbl(device).ResetFences(device, fenceCount, pFences);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetFenceStatus(VkDevice device, VkFence fence) {
+    return GetVtbl(device).GetFenceStatus(device, fence);
+}
+
+__attribute__((visibility("default")))
+VkResult vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
+    return GetVtbl(device).WaitForFences(device, fenceCount, pFences, waitAll, timeout);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, VkSemaphore* pSemaphore) {
+    return GetVtbl(device).CreateSemaphore(device, pCreateInfo, pSemaphore);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroySemaphore(VkDevice device, VkSemaphore semaphore) {
+    return GetVtbl(device).DestroySemaphore(device, semaphore);
+}
+
+__attribute__((visibility("default")))
+VkResult vkQueueSignalSemaphore(VkQueue queue, VkSemaphore semaphore) {
+    return GetVtbl(queue).QueueSignalSemaphore(queue, semaphore);
+}
+
+__attribute__((visibility("default")))
+VkResult vkQueueWaitSemaphore(VkQueue queue, VkSemaphore semaphore) {
+    return GetVtbl(queue).QueueWaitSemaphore(queue, semaphore);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, VkEvent* pEvent) {
+    return GetVtbl(device).CreateEvent(device, pCreateInfo, pEvent);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyEvent(VkDevice device, VkEvent event) {
+    return GetVtbl(device).DestroyEvent(device, event);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetEventStatus(VkDevice device, VkEvent event) {
+    return GetVtbl(device).GetEventStatus(device, event);
+}
+
+__attribute__((visibility("default")))
+VkResult vkSetEvent(VkDevice device, VkEvent event) {
+    return GetVtbl(device).SetEvent(device, event);
+}
+
+__attribute__((visibility("default")))
+VkResult vkResetEvent(VkDevice device, VkEvent event) {
+    return GetVtbl(device).ResetEvent(device, event);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, VkQueryPool* pQueryPool) {
+    return GetVtbl(device).CreateQueryPool(device, pCreateInfo, pQueryPool);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool) {
+    return GetVtbl(device).DestroyQueryPool(device, queryPool);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, size_t* pDataSize, void* pData, VkQueryResultFlags flags) {
+    return GetVtbl(device).GetQueryPoolResults(device, queryPool, startQuery, queryCount, pDataSize, pData, flags);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, VkBuffer* pBuffer) {
+    return GetVtbl(device).CreateBuffer(device, pCreateInfo, pBuffer);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyBuffer(VkDevice device, VkBuffer buffer) {
+    return GetVtbl(device).DestroyBuffer(device, buffer);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, VkBufferView* pView) {
+    return GetVtbl(device).CreateBufferView(device, pCreateInfo, pView);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyBufferView(VkDevice device, VkBufferView bufferView) {
+    return GetVtbl(device).DestroyBufferView(device, bufferView);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage) {
+    return GetVtbl(device).CreateImage(device, pCreateInfo, pImage);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyImage(VkDevice device, VkImage image) {
+    return GetVtbl(device).DestroyImage(device, image);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
+    return GetVtbl(device).GetImageSubresourceLayout(device, image, pSubresource, pLayout);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, VkImageView* pView) {
+    return GetVtbl(device).CreateImageView(device, pCreateInfo, pView);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyImageView(VkDevice device, VkImageView imageView) {
+    return GetVtbl(device).DestroyImageView(device, imageView);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateAttachmentView(VkDevice device, const VkAttachmentViewCreateInfo* pCreateInfo, VkAttachmentView* pView) {
+    return GetVtbl(device).CreateAttachmentView(device, pCreateInfo, pView);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyAttachmentView(VkDevice device, VkAttachmentView attachmentView) {
+    return GetVtbl(device).DestroyAttachmentView(device, attachmentView);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* pShaderModule) {
+    return GetVtbl(device).CreateShaderModule(device, pCreateInfo, pShaderModule);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule) {
+    return GetVtbl(device).DestroyShaderModule(device, shaderModule);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateShader(VkDevice device, const VkShaderCreateInfo* pCreateInfo, VkShader* pShader) {
+    return GetVtbl(device).CreateShader(device, pCreateInfo, pShader);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyShader(VkDevice device, VkShader shader) {
+    return GetVtbl(device).DestroyShader(device, shader);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, VkPipelineCache* pPipelineCache) {
+    return GetVtbl(device).CreatePipelineCache(device, pCreateInfo, pPipelineCache);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache) {
+    return GetVtbl(device).DestroyPipelineCache(device, pipelineCache);
+}
+
+__attribute__((visibility("default")))
+size_t vkGetPipelineCacheSize(VkDevice device, VkPipelineCache pipelineCache) {
+    return GetVtbl(device).GetPipelineCacheSize(device, pipelineCache);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, void* pData) {
+    return GetVtbl(device).GetPipelineCacheData(device, pipelineCache, pData);
+}
+
+__attribute__((visibility("default")))
+VkResult vkMergePipelineCaches(VkDevice device, VkPipelineCache destCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) {
+    return GetVtbl(device).MergePipelineCaches(device, destCache, srcCacheCount, pSrcCaches);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkGraphicsPipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines) {
+    return GetVtbl(device).CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pPipelines);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkComputePipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines) {
+    return GetVtbl(device).CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pPipelines);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyPipeline(VkDevice device, VkPipeline pipeline) {
+    return GetVtbl(device).DestroyPipeline(device, pipeline);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, VkPipelineLayout* pPipelineLayout) {
+    return GetVtbl(device).CreatePipelineLayout(device, pCreateInfo, pPipelineLayout);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout) {
+    return GetVtbl(device).DestroyPipelineLayout(device, pipelineLayout);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, VkSampler* pSampler) {
+    return GetVtbl(device).CreateSampler(device, pCreateInfo, pSampler);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroySampler(VkDevice device, VkSampler sampler) {
+    return GetVtbl(device).DestroySampler(device, sampler);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayout* pSetLayout) {
+    return GetVtbl(device).CreateDescriptorSetLayout(device, pCreateInfo, pSetLayout);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout) {
+    return GetVtbl(device).DestroyDescriptorSetLayout(device, descriptorSetLayout);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateDescriptorPool(VkDevice device, VkDescriptorPoolUsage poolUsage, uint32_t maxSets, const VkDescriptorPoolCreateInfo* pCreateInfo, VkDescriptorPool* pDescriptorPool) {
+    return GetVtbl(device).CreateDescriptorPool(device, poolUsage, maxSets, pCreateInfo, pDescriptorPool);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool) {
+    return GetVtbl(device).DestroyDescriptorPool(device, descriptorPool);
+}
+
+__attribute__((visibility("default")))
+VkResult vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool) {
+    return GetVtbl(device).ResetDescriptorPool(device, descriptorPool);
+}
+
+__attribute__((visibility("default")))
+VkResult vkAllocDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorSetUsage setUsage, uint32_t count, const VkDescriptorSetLayout* pSetLayouts, VkDescriptorSet* pDescriptorSets, uint32_t* pCount) {
+    return GetVtbl(device).AllocDescriptorSets(device, descriptorPool, setUsage, count, pSetLayouts, pDescriptorSets, pCount);
+}
+
+__attribute__((visibility("default")))
+VkResult vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets) {
+    return GetVtbl(device).FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
+}
+
+__attribute__((visibility("default")))
+VkResult vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies) {
+    return GetVtbl(device).UpdateDescriptorSets(device, writeCount, pDescriptorWrites, copyCount, pDescriptorCopies);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateDynamicViewportState(VkDevice device, const VkDynamicViewportStateCreateInfo* pCreateInfo, VkDynamicViewportState* pState) {
+    return GetVtbl(device).CreateDynamicViewportState(device, pCreateInfo, pState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyDynamicViewportState(VkDevice device, VkDynamicViewportState dynamicViewportState) {
+    return GetVtbl(device).DestroyDynamicViewportState(device, dynamicViewportState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateDynamicRasterState(VkDevice device, const VkDynamicRasterStateCreateInfo* pCreateInfo, VkDynamicRasterState* pState) {
+    return GetVtbl(device).CreateDynamicRasterState(device, pCreateInfo, pState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyDynamicRasterState(VkDevice device, VkDynamicRasterState dynamicRasterState) {
+    return GetVtbl(device).DestroyDynamicRasterState(device, dynamicRasterState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateDynamicColorBlendState(VkDevice device, const VkDynamicColorBlendStateCreateInfo* pCreateInfo, VkDynamicColorBlendState* pState) {
+    return GetVtbl(device).CreateDynamicColorBlendState(device, pCreateInfo, pState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyDynamicColorBlendState(VkDevice device, VkDynamicColorBlendState dynamicColorBlendState) {
+    return GetVtbl(device).DestroyDynamicColorBlendState(device, dynamicColorBlendState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateDynamicDepthStencilState(VkDevice device, const VkDynamicDepthStencilStateCreateInfo* pCreateInfo, VkDynamicDepthStencilState* pState) {
+    return GetVtbl(device).CreateDynamicDepthStencilState(device, pCreateInfo, pState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyDynamicDepthStencilState(VkDevice device, VkDynamicDepthStencilState dynamicDepthStencilState) {
+    return GetVtbl(device).DestroyDynamicDepthStencilState(device, dynamicDepthStencilState);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, VkFramebuffer* pFramebuffer) {
+    return GetVtbl(device).CreateFramebuffer(device, pCreateInfo, pFramebuffer);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer) {
+    return GetVtbl(device).DestroyFramebuffer(device, framebuffer);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, VkRenderPass* pRenderPass) {
+    return GetVtbl(device).CreateRenderPass(device, pCreateInfo, pRenderPass);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass) {
+    return GetVtbl(device).DestroyRenderPass(device, renderPass);
+}
+
+__attribute__((visibility("default")))
+VkResult vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) {
+    return GetVtbl(device).GetRenderAreaGranularity(device, renderPass, pGranularity);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateCommandPool(VkDevice device, const VkCmdPoolCreateInfo* pCreateInfo, VkCmdPool* pCmdPool) {
+    return GetVtbl(device).CreateCommandPool(device, pCreateInfo, pCmdPool);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyCommandPool(VkDevice device, VkCmdPool cmdPool) {
+    return GetVtbl(device).DestroyCommandPool(device, cmdPool);
+}
+
+__attribute__((visibility("default")))
+VkResult vkResetCommandPool(VkDevice device, VkCmdPool cmdPool, VkCmdPoolResetFlags flags) {
+    return GetVtbl(device).ResetCommandPool(device, cmdPool, flags);
+}
+
+__attribute__((visibility("default")))
+VkResult vkCreateCommandBuffer(VkDevice device, const VkCmdBufferCreateInfo* pCreateInfo, VkCmdBuffer* pCmdBuffer) {
+    return GetVtbl(device).CreateCommandBuffer(device, pCreateInfo, pCmdBuffer);
+}
+
+__attribute__((visibility("default")))
+VkResult vkDestroyCommandBuffer(VkDevice device, VkCmdBuffer commandBuffer) {
+    return GetVtbl(device).DestroyCommandBuffer(device, commandBuffer);
+}
+
+__attribute__((visibility("default")))
+VkResult vkBeginCommandBuffer(VkCmdBuffer cmdBuffer, const VkCmdBufferBeginInfo* pBeginInfo) {
+    return GetVtbl(cmdBuffer).BeginCommandBuffer(cmdBuffer, pBeginInfo);
+}
+
+__attribute__((visibility("default")))
+VkResult vkEndCommandBuffer(VkCmdBuffer cmdBuffer) {
+    return GetVtbl(cmdBuffer).EndCommandBuffer(cmdBuffer);
+}
+
+__attribute__((visibility("default")))
+VkResult vkResetCommandBuffer(VkCmdBuffer cmdBuffer, VkCmdBufferResetFlags flags) {
+    return GetVtbl(cmdBuffer).ResetCommandBuffer(cmdBuffer, flags);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindPipeline(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
+    GetVtbl(cmdBuffer).CmdBindPipeline(cmdBuffer, pipelineBindPoint, pipeline);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindDynamicViewportState(VkCmdBuffer cmdBuffer, VkDynamicViewportState dynamicViewportState) {
+    GetVtbl(cmdBuffer).CmdBindDynamicViewportState(cmdBuffer, dynamicViewportState);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindDynamicRasterState(VkCmdBuffer cmdBuffer, VkDynamicRasterState dynamicRasterState) {
+    GetVtbl(cmdBuffer).CmdBindDynamicRasterState(cmdBuffer, dynamicRasterState);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindDynamicColorBlendState(VkCmdBuffer cmdBuffer, VkDynamicColorBlendState dynamicColorBlendState) {
+    GetVtbl(cmdBuffer).CmdBindDynamicColorBlendState(cmdBuffer, dynamicColorBlendState);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindDynamicDepthStencilState(VkCmdBuffer cmdBuffer, VkDynamicDepthStencilState dynamicDepthStencilState) {
+    GetVtbl(cmdBuffer).CmdBindDynamicDepthStencilState(cmdBuffer, dynamicDepthStencilState);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindDescriptorSets(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
+    GetVtbl(cmdBuffer).CmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, layout, firstSet, setCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindIndexBuffer(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
+    GetVtbl(cmdBuffer).CmdBindIndexBuffer(cmdBuffer, buffer, offset, indexType);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBindVertexBuffers(VkCmdBuffer cmdBuffer, uint32_t startBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) {
+    GetVtbl(cmdBuffer).CmdBindVertexBuffers(cmdBuffer, startBinding, bindingCount, pBuffers, pOffsets);
+}
+
+__attribute__((visibility("default")))
+void vkCmdDraw(VkCmdBuffer cmdBuffer, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) {
+    GetVtbl(cmdBuffer).CmdDraw(cmdBuffer, firstVertex, vertexCount, firstInstance, instanceCount);
+}
+
+__attribute__((visibility("default")))
+void vkCmdDrawIndexed(VkCmdBuffer cmdBuffer, uint32_t firstIndex, uint32_t indexCount, int32_t vertexOffset, uint32_t firstInstance, uint32_t instanceCount) {
+    GetVtbl(cmdBuffer).CmdDrawIndexed(cmdBuffer, firstIndex, indexCount, vertexOffset, firstInstance, instanceCount);
+}
+
+__attribute__((visibility("default")))
+void vkCmdDrawIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+    GetVtbl(cmdBuffer).CmdDrawIndirect(cmdBuffer, buffer, offset, count, stride);
+}
+
+__attribute__((visibility("default")))
+void vkCmdDrawIndexedIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+    GetVtbl(cmdBuffer).CmdDrawIndexedIndirect(cmdBuffer, buffer, offset, count, stride);
+}
+
+__attribute__((visibility("default")))
+void vkCmdDispatch(VkCmdBuffer cmdBuffer, uint32_t x, uint32_t y, uint32_t z) {
+    GetVtbl(cmdBuffer).CmdDispatch(cmdBuffer, x, y, z);
+}
+
+__attribute__((visibility("default")))
+void vkCmdDispatchIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset) {
+    GetVtbl(cmdBuffer).CmdDispatchIndirect(cmdBuffer, buffer, offset);
+}
+
+__attribute__((visibility("default")))
+void vkCmdCopyBuffer(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkBuffer destBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) {
+    GetVtbl(cmdBuffer).CmdCopyBuffer(cmdBuffer, srcBuffer, destBuffer, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+void vkCmdCopyImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageCopy* pRegions) {
+    GetVtbl(cmdBuffer).CmdCopyImage(cmdBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBlitImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkTexFilter filter) {
+    GetVtbl(cmdBuffer).CmdBlitImage(cmdBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions, filter);
+}
+
+__attribute__((visibility("default")))
+void vkCmdCopyBufferToImage(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+    GetVtbl(cmdBuffer).CmdCopyBufferToImage(cmdBuffer, srcBuffer, destImage, destImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+void vkCmdCopyImageToBuffer(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer destBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+    GetVtbl(cmdBuffer).CmdCopyImageToBuffer(cmdBuffer, srcImage, srcImageLayout, destBuffer, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+void vkCmdUpdateBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize dataSize, const uint32_t* pData) {
+    GetVtbl(cmdBuffer).CmdUpdateBuffer(cmdBuffer, destBuffer, destOffset, dataSize, pData);
+}
+
+__attribute__((visibility("default")))
+void vkCmdFillBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize fillSize, uint32_t data) {
+    GetVtbl(cmdBuffer).CmdFillBuffer(cmdBuffer, destBuffer, destOffset, fillSize, data);
+}
+
+__attribute__((visibility("default")))
+void vkCmdClearColorImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+    GetVtbl(cmdBuffer).CmdClearColorImage(cmdBuffer, image, imageLayout, pColor, rangeCount, pRanges);
+}
+
+__attribute__((visibility("default")))
+void vkCmdClearDepthStencilImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+    GetVtbl(cmdBuffer).CmdClearDepthStencilImage(cmdBuffer, image, imageLayout, depth, stencil, rangeCount, pRanges);
+}
+
+__attribute__((visibility("default")))
+void vkCmdClearColorAttachment(VkCmdBuffer cmdBuffer, uint32_t colorAttachment, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rectCount, const VkRect3D* pRects) {
+    GetVtbl(cmdBuffer).CmdClearColorAttachment(cmdBuffer, colorAttachment, imageLayout, pColor, rectCount, pRects);
+}
+
+__attribute__((visibility("default")))
+void vkCmdClearDepthStencilAttachment(VkCmdBuffer cmdBuffer, VkImageAspectFlags imageAspectMask, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rectCount, const VkRect3D* pRects) {
+    GetVtbl(cmdBuffer).CmdClearDepthStencilAttachment(cmdBuffer, imageAspectMask, imageLayout, depth, stencil, rectCount, pRects);
+}
+
+__attribute__((visibility("default")))
+void vkCmdResolveImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageResolve* pRegions) {
+    GetVtbl(cmdBuffer).CmdResolveImage(cmdBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+void vkCmdSetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+    GetVtbl(cmdBuffer).CmdSetEvent(cmdBuffer, event, stageMask);
+}
+
+__attribute__((visibility("default")))
+void vkCmdResetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+    GetVtbl(cmdBuffer).CmdResetEvent(cmdBuffer, event, stageMask);
+}
+
+__attribute__((visibility("default")))
+void vkCmdWaitEvents(VkCmdBuffer cmdBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
+    GetVtbl(cmdBuffer).CmdWaitEvents(cmdBuffer, eventCount, pEvents, srcStageMask, destStageMask, memBarrierCount, ppMemBarriers);
+}
+
+__attribute__((visibility("default")))
+void vkCmdPipelineBarrier(VkCmdBuffer cmdBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, VkBool32 byRegion, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
+    GetVtbl(cmdBuffer).CmdPipelineBarrier(cmdBuffer, srcStageMask, destStageMask, byRegion, memBarrierCount, ppMemBarriers);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBeginQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags) {
+    GetVtbl(cmdBuffer).CmdBeginQuery(cmdBuffer, queryPool, slot, flags);
+}
+
+__attribute__((visibility("default")))
+void vkCmdEndQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot) {
+    GetVtbl(cmdBuffer).CmdEndQuery(cmdBuffer, queryPool, slot);
+}
+
+__attribute__((visibility("default")))
+void vkCmdResetQueryPool(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount) {
+    GetVtbl(cmdBuffer).CmdResetQueryPool(cmdBuffer, queryPool, startQuery, queryCount);
+}
+
+__attribute__((visibility("default")))
+void vkCmdWriteTimestamp(VkCmdBuffer cmdBuffer, VkTimestampType timestampType, VkBuffer destBuffer, VkDeviceSize destOffset) {
+    GetVtbl(cmdBuffer).CmdWriteTimestamp(cmdBuffer, timestampType, destBuffer, destOffset);
+}
+
+__attribute__((visibility("default")))
+void vkCmdCopyQueryPoolResults(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize destStride, VkQueryResultFlags flags) {
+    GetVtbl(cmdBuffer).CmdCopyQueryPoolResults(cmdBuffer, queryPool, startQuery, queryCount, destBuffer, destOffset, destStride, flags);
+}
+
+__attribute__((visibility("default")))
+void vkCmdPushConstants(VkCmdBuffer cmdBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t start, uint32_t length, const void* values) {
+    GetVtbl(cmdBuffer).CmdPushConstants(cmdBuffer, layout, stageFlags, start, length, values);
+}
+
+__attribute__((visibility("default")))
+void vkCmdBeginRenderPass(VkCmdBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkRenderPassContents contents) {
+    GetVtbl(cmdBuffer).CmdBeginRenderPass(cmdBuffer, pRenderPassBegin, contents);
+}
+
+__attribute__((visibility("default")))
+void vkCmdNextSubpass(VkCmdBuffer cmdBuffer, VkRenderPassContents contents) {
+    GetVtbl(cmdBuffer).CmdNextSubpass(cmdBuffer, contents);
+}
+
+__attribute__((visibility("default")))
+void vkCmdEndRenderPass(VkCmdBuffer cmdBuffer) {
+    GetVtbl(cmdBuffer).CmdEndRenderPass(cmdBuffer);
+}
+
+__attribute__((visibility("default")))
+void vkCmdExecuteCommands(VkCmdBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCmdBuffer* pCmdBuffers) {
+    GetVtbl(cmdBuffer).CmdExecuteCommands(cmdBuffer, cmdBuffersCount, pCmdBuffers);
+}
diff --git a/vulkan/libvulkan/entry.cpp.tmpl b/vulkan/libvulkan/entry.cpp.tmpl
new file mode 100644
index 0000000..249f8fd
--- /dev/null
+++ b/vulkan/libvulkan/entry.cpp.tmpl
@@ -0,0 +1,145 @@
+{{Include "../api/templates/vulkan_common.tmpl"}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "entry.cpp" | Reflow 4 | Write "entry.cpp"}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Entry point
+-------------------------------------------------------------------------------
+*/}}
+{{define "entry.cpp"}}
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */

+// This file is generated. Do not edit manually!
+// To regenerate: $ apic template ../api/vulkan.api entry.cpp.tmpl
+// Requires apic from https://android.googlesource.com/platform/tools/gpu/.

+#include "loader.h"
+using namespace vulkan;

+// clang-format off

+namespace {
+    inline const InstanceVtbl& GetVtbl(VkInstance instance) {
+        return **reinterpret_cast<InstanceVtbl**>(instance);
+    }
+    inline const InstanceVtbl& GetVtbl(VkPhysicalDevice physicalDevice) {
+        return **reinterpret_cast<InstanceVtbl**>(physicalDevice);
+    }
+    inline const DeviceVtbl& GetVtbl(VkDevice device) {
+        return **reinterpret_cast<DeviceVtbl**>(device);
+    }
+    inline const DeviceVtbl& GetVtbl(VkQueue queue) {
+        return **reinterpret_cast<DeviceVtbl**>(queue);
+    }
+    inline const DeviceVtbl& GetVtbl(VkCmdBuffer cmdBuffer) {
+        return **reinterpret_cast<DeviceVtbl**>(cmdBuffer);
+    }
+} // namespace

+  {{range $f := AllCommands $}}
+    {{if not (GetAnnotation $f "pfn")}}
+      __attribute__((visibility("default")))
+      {{if eq (Macro "IsSpecialEntry" $f.Name) "true"}}
+        {{Macro "EmitSpecialEntry" $f}}
+      {{else}}
+        {{Macro "EmitEntry" $f}}
+      {{end}}
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Decides whether an entrypoint needs special-case handling. Emits the string
+  "true" if so, nothing otherwise.
+-------------------------------------------------------------------------------
+*/}}
+{{define "IsSpecialEntry"}}
+  {{/* TODO: figure out how to do this in a cleaner or at least multi-line way */}}
+  {{if or (eq $ "vkGetInstanceProcAddr") (or (eq $ "vkGetDeviceProcAddr") (or (eq $ "vkGetDeviceQueue") (eq $ "vkDestroyDevice")))}}
+    true
+  {{end}}
+{{end}}
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the entrypoint definition for the specified command, which always
+  dispatches statically because the function requires special-case handling.
+-------------------------------------------------------------------------------
+*/}}
+{{define "EmitSpecialEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{Node "Type" $.Return}} {{Macro "FunctionName" $}}({{Macro "Parameters" $}}) {
+    {{if not (IsVoid $.Return.Type)}}return §{{end}}
+    vulkan::{{TrimPrefix "vk" $.Name}}({{Macro "Arguments" $}});
+  }
+  ¶
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the entrypoint definition for the specified command. If the first
+  parameter is a handle to dispatchable object, it dispatches the call through
+  the object's function table. Otherwise, it dispatches statically.
+-------------------------------------------------------------------------------
+*/}}
+{{define "EmitEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{Node "Type" $.Return}} {{Macro "FunctionName" $}}({{Macro "Parameters" $}}) {
+    {{if not (IsVoid $.Return.Type)}}return §{{end}}
+    {{Macro "Dispatch" $}}{{TrimPrefix "vk" $.Name}}({{Macro "Arguments" $}});
+  }
+  ¶
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emit the dispatch lookup for a function based on its first parameter.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Dispatch#VkInstance"      }}GetVtbl({{$.Node.Name}}).{{end}}
+{{define "Dispatch#VkPhysicalDevice"}}GetVtbl({{$.Node.Name}}).{{end}}
+{{define "Dispatch#VkDevice"        }}GetVtbl({{$.Node.Name}}).{{end}}
+{{define "Dispatch#VkQueue"         }}GetVtbl({{$.Node.Name}}).{{end}}
+{{define "Dispatch#VkCmdBuffer"     }}GetVtbl({{$.Node.Name}}).{{end}}
+{{define "Dispatch_Default"         }}vulkan::{{end}}
+{{define "Dispatch"}}
+  {{AssertType $ "Function"}}
+
+  {{range $i, $p := $.CallParameters}}
+    {{if not $i}}{{Node "Dispatch" $p}}{{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a comma-separated list of C parameter names for the given command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Arguments"}}
+  {{AssertType $ "Function"}}
+
+  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
+{{end}}
diff --git a/vulkan/libvulkan/get_proc_addr.cpp b/vulkan/libvulkan/get_proc_addr.cpp
new file mode 100644
index 0000000..5f05f0e
--- /dev/null
+++ b/vulkan/libvulkan/get_proc_addr.cpp
@@ -0,0 +1,1167 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+// This file is generated. Do not edit manually!
+// To regenerate: $ apic template ../api/vulkan.api get_proc_addr.cpp.tmpl
+// Requires apic from https://android.googlesource.com/platform/tools/gpu/.
+
+#include <algorithm>
+#include <log/log.h>
+#include "loader.h"
+using namespace vulkan;
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+namespace {
+
+struct NameProcEntry {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};
+
+struct NameOffsetEntry {
+    const char* name;
+    size_t offset;
+};
+
+template <typename TEntry, size_t N>
+const TEntry* FindProcEntry(const TEntry(&table)[N], const char* name) {
+    auto entry = std::lower_bound(
+        table, table + N, name,
+        [](const TEntry& e, const char* n) { return strcmp(e.name, n) < 0; });
+    if (entry != (table + N) && strcmp(entry->name, name) == 0)
+        return entry;
+    return nullptr;
+}
+
+const NameProcEntry kInstanceProcTbl[] = {
+    // clang-format off
+    {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDevice)},
+    {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyInstance)},
+    {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(vkEnumeratePhysicalDevices)},
+    {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr)},
+    {"vkGetPhysicalDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceExtensionProperties)},
+    {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceFeatures)},
+    {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceFormatProperties)},
+    {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceImageFormatProperties)},
+    {"vkGetPhysicalDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceLayerProperties)},
+    {"vkGetPhysicalDeviceLimits", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceLimits)},
+    {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceMemoryProperties)},
+    {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceProperties)},
+    {"vkGetPhysicalDeviceQueueCount", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceQueueCount)},
+    {"vkGetPhysicalDeviceQueueProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceQueueProperties)},
+    {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSparseImageFormatProperties)},
+    // clang-format on
+};
+
+const NameProcEntry kDeviceProcTbl[] = {
+    // clang-format off
+    {"vkAllocDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkAllocDescriptorSets)},
+    {"vkAllocMemory", reinterpret_cast<PFN_vkVoidFunction>(vkAllocMemory)},
+    {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkBeginCommandBuffer)},
+    {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindBufferMemory)},
+    {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindImageMemory)},
+    {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginQuery)},
+    {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginRenderPass)},
+    {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDescriptorSets)},
+    {"vkCmdBindDynamicColorBlendState", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDynamicColorBlendState)},
+    {"vkCmdBindDynamicDepthStencilState", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDynamicDepthStencilState)},
+    {"vkCmdBindDynamicRasterState", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDynamicRasterState)},
+    {"vkCmdBindDynamicViewportState", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDynamicViewportState)},
+    {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindIndexBuffer)},
+    {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindPipeline)},
+    {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindVertexBuffers)},
+    {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBlitImage)},
+    {"vkCmdClearColorAttachment", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearColorAttachment)},
+    {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearColorImage)},
+    {"vkCmdClearDepthStencilAttachment", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearDepthStencilAttachment)},
+    {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearDepthStencilImage)},
+    {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBuffer)},
+    {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBufferToImage)},
+    {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImage)},
+    {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImageToBuffer)},
+    {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyQueryPoolResults)},
+    {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatch)},
+    {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatchIndirect)},
+    {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDraw)},
+    {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexed)},
+    {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexedIndirect)},
+    {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndirect)},
+    {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndQuery)},
+    {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndRenderPass)},
+    {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(vkCmdExecuteCommands)},
+    {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdFillBuffer)},
+    {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdNextSubpass)},
+    {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPipelineBarrier)},
+    {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPushConstants)},
+    {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetEvent)},
+    {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetQueryPool)},
+    {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResolveImage)},
+    {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetEvent)},
+    {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdUpdateBuffer)},
+    {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWaitEvents)},
+    {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWriteTimestamp)},
+    {"vkCreateAttachmentView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateAttachmentView)},
+    {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBuffer)},
+    {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBufferView)},
+    {"vkCreateCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateCommandBuffer)},
+    {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateCommandPool)},
+    {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateComputePipelines)},
+    {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorPool)},
+    {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorSetLayout)},
+    {"vkCreateDynamicColorBlendState", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDynamicColorBlendState)},
+    {"vkCreateDynamicDepthStencilState", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDynamicDepthStencilState)},
+    {"vkCreateDynamicRasterState", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDynamicRasterState)},
+    {"vkCreateDynamicViewportState", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDynamicViewportState)},
+    {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCreateEvent)},
+    {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFence)},
+    {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFramebuffer)},
+    {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateGraphicsPipelines)},
+    {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImage)},
+    {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImageView)},
+    {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineCache)},
+    {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineLayout)},
+    {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateQueryPool)},
+    {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCreateRenderPass)},
+    {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSampler)},
+    {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSemaphore)},
+    {"vkCreateShader", reinterpret_cast<PFN_vkVoidFunction>(vkCreateShader)},
+    {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkCreateShaderModule)},
+    {"vkDestroyAttachmentView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyAttachmentView)},
+    {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBuffer)},
+    {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBufferView)},
+    {"vkDestroyCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyCommandBuffer)},
+    {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyCommandPool)},
+    {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorPool)},
+    {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorSetLayout)},
+    {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDevice)},
+    {"vkDestroyDynamicColorBlendState", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDynamicColorBlendState)},
+    {"vkDestroyDynamicDepthStencilState", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDynamicDepthStencilState)},
+    {"vkDestroyDynamicRasterState", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDynamicRasterState)},
+    {"vkDestroyDynamicViewportState", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDynamicViewportState)},
+    {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyEvent)},
+    {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFence)},
+    {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFramebuffer)},
+    {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImage)},
+    {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImageView)},
+    {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipeline)},
+    {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineCache)},
+    {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineLayout)},
+    {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyQueryPool)},
+    {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyRenderPass)},
+    {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySampler)},
+    {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySemaphore)},
+    {"vkDestroyShader", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyShader)},
+    {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyShaderModule)},
+    {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkDeviceWaitIdle)},
+    {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkEndCommandBuffer)},
+    {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkFlushMappedMemoryRanges)},
+    {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkFreeDescriptorSets)},
+    {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(vkFreeMemory)},
+    {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetBufferMemoryRequirements)},
+    {"vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceMemoryCommitment)},
+    {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr)},
+    {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue)},
+    {"vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetEventStatus)},
+    {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetFenceStatus)},
+    {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageMemoryRequirements)},
+    {"vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSparseMemoryRequirements)},
+    {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSubresourceLayout)},
+    {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(vkGetPipelineCacheData)},
+    {"vkGetPipelineCacheSize", reinterpret_cast<PFN_vkVoidFunction>(vkGetPipelineCacheSize)},
+    {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkGetQueryPoolResults)},
+    {"vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(vkGetRenderAreaGranularity)},
+    {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkInvalidateMappedMemoryRanges)},
+    {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkMapMemory)},
+    {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(vkMergePipelineCaches)},
+    {"vkQueueBindSparseBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(vkQueueBindSparseBufferMemory)},
+    {"vkQueueBindSparseImageMemory", reinterpret_cast<PFN_vkVoidFunction>(vkQueueBindSparseImageMemory)},
+    {"vkQueueBindSparseImageOpaqueMemory", reinterpret_cast<PFN_vkVoidFunction>(vkQueueBindSparseImageOpaqueMemory)},
+    {"vkQueueSignalSemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkQueueSignalSemaphore)},
+    {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(vkQueueSubmit)},
+    {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkQueueWaitIdle)},
+    {"vkQueueWaitSemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkQueueWaitSemaphore)},
+    {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandBuffer)},
+    {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandPool)},
+    {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetDescriptorPool)},
+    {"vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkResetEvent)},
+    {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(vkResetFences)},
+    {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkSetEvent)},
+    {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkUnmapMemory)},
+    {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkUpdateDescriptorSets)},
+    {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(vkWaitForFences)},
+    // clang-format on
+};
+
+const NameOffsetEntry kInstanceOffsetTbl[] = {
+    // clang-format off
+    {"vkCreateDevice", offsetof(InstanceVtbl, CreateDevice)},
+    {"vkDestroyInstance", offsetof(InstanceVtbl, DestroyInstance)},
+    {"vkEnumeratePhysicalDevices", offsetof(InstanceVtbl, EnumeratePhysicalDevices)},
+    {"vkGetInstanceProcAddr", offsetof(InstanceVtbl, GetInstanceProcAddr)},
+    {"vkGetPhysicalDeviceExtensionProperties", offsetof(InstanceVtbl, GetPhysicalDeviceExtensionProperties)},
+    {"vkGetPhysicalDeviceFeatures", offsetof(InstanceVtbl, GetPhysicalDeviceFeatures)},
+    {"vkGetPhysicalDeviceFormatProperties", offsetof(InstanceVtbl, GetPhysicalDeviceFormatProperties)},
+    {"vkGetPhysicalDeviceImageFormatProperties", offsetof(InstanceVtbl, GetPhysicalDeviceImageFormatProperties)},
+    {"vkGetPhysicalDeviceLayerProperties", offsetof(InstanceVtbl, GetPhysicalDeviceLayerProperties)},
+    {"vkGetPhysicalDeviceLimits", offsetof(InstanceVtbl, GetPhysicalDeviceLimits)},
+    {"vkGetPhysicalDeviceMemoryProperties", offsetof(InstanceVtbl, GetPhysicalDeviceMemoryProperties)},
+    {"vkGetPhysicalDeviceProperties", offsetof(InstanceVtbl, GetPhysicalDeviceProperties)},
+    {"vkGetPhysicalDeviceQueueCount", offsetof(InstanceVtbl, GetPhysicalDeviceQueueCount)},
+    {"vkGetPhysicalDeviceQueueProperties", offsetof(InstanceVtbl, GetPhysicalDeviceQueueProperties)},
+    {"vkGetPhysicalDeviceSparseImageFormatProperties", offsetof(InstanceVtbl, GetPhysicalDeviceSparseImageFormatProperties)},
+    // clang-format on
+};
+
+const NameOffsetEntry kDeviceOffsetTbl[] = {
+    // clang-format off
+    {"vkAllocDescriptorSets", offsetof(DeviceVtbl, AllocDescriptorSets)},
+    {"vkAllocMemory", offsetof(DeviceVtbl, AllocMemory)},
+    {"vkBeginCommandBuffer", offsetof(DeviceVtbl, BeginCommandBuffer)},
+    {"vkBindBufferMemory", offsetof(DeviceVtbl, BindBufferMemory)},
+    {"vkBindImageMemory", offsetof(DeviceVtbl, BindImageMemory)},
+    {"vkCmdBeginQuery", offsetof(DeviceVtbl, CmdBeginQuery)},
+    {"vkCmdBeginRenderPass", offsetof(DeviceVtbl, CmdBeginRenderPass)},
+    {"vkCmdBindDescriptorSets", offsetof(DeviceVtbl, CmdBindDescriptorSets)},
+    {"vkCmdBindDynamicColorBlendState", offsetof(DeviceVtbl, CmdBindDynamicColorBlendState)},
+    {"vkCmdBindDynamicDepthStencilState", offsetof(DeviceVtbl, CmdBindDynamicDepthStencilState)},
+    {"vkCmdBindDynamicRasterState", offsetof(DeviceVtbl, CmdBindDynamicRasterState)},
+    {"vkCmdBindDynamicViewportState", offsetof(DeviceVtbl, CmdBindDynamicViewportState)},
+    {"vkCmdBindIndexBuffer", offsetof(DeviceVtbl, CmdBindIndexBuffer)},
+    {"vkCmdBindPipeline", offsetof(DeviceVtbl, CmdBindPipeline)},
+    {"vkCmdBindVertexBuffers", offsetof(DeviceVtbl, CmdBindVertexBuffers)},
+    {"vkCmdBlitImage", offsetof(DeviceVtbl, CmdBlitImage)},
+    {"vkCmdClearColorAttachment", offsetof(DeviceVtbl, CmdClearColorAttachment)},
+    {"vkCmdClearColorImage", offsetof(DeviceVtbl, CmdClearColorImage)},
+    {"vkCmdClearDepthStencilAttachment", offsetof(DeviceVtbl, CmdClearDepthStencilAttachment)},
+    {"vkCmdClearDepthStencilImage", offsetof(DeviceVtbl, CmdClearDepthStencilImage)},
+    {"vkCmdCopyBuffer", offsetof(DeviceVtbl, CmdCopyBuffer)},
+    {"vkCmdCopyBufferToImage", offsetof(DeviceVtbl, CmdCopyBufferToImage)},
+    {"vkCmdCopyImage", offsetof(DeviceVtbl, CmdCopyImage)},
+    {"vkCmdCopyImageToBuffer", offsetof(DeviceVtbl, CmdCopyImageToBuffer)},
+    {"vkCmdCopyQueryPoolResults", offsetof(DeviceVtbl, CmdCopyQueryPoolResults)},
+    {"vkCmdDispatch", offsetof(DeviceVtbl, CmdDispatch)},
+    {"vkCmdDispatchIndirect", offsetof(DeviceVtbl, CmdDispatchIndirect)},
+    {"vkCmdDraw", offsetof(DeviceVtbl, CmdDraw)},
+    {"vkCmdDrawIndexed", offsetof(DeviceVtbl, CmdDrawIndexed)},
+    {"vkCmdDrawIndexedIndirect", offsetof(DeviceVtbl, CmdDrawIndexedIndirect)},
+    {"vkCmdDrawIndirect", offsetof(DeviceVtbl, CmdDrawIndirect)},
+    {"vkCmdEndQuery", offsetof(DeviceVtbl, CmdEndQuery)},
+    {"vkCmdEndRenderPass", offsetof(DeviceVtbl, CmdEndRenderPass)},
+    {"vkCmdExecuteCommands", offsetof(DeviceVtbl, CmdExecuteCommands)},
+    {"vkCmdFillBuffer", offsetof(DeviceVtbl, CmdFillBuffer)},
+    {"vkCmdNextSubpass", offsetof(DeviceVtbl, CmdNextSubpass)},
+    {"vkCmdPipelineBarrier", offsetof(DeviceVtbl, CmdPipelineBarrier)},
+    {"vkCmdPushConstants", offsetof(DeviceVtbl, CmdPushConstants)},
+    {"vkCmdResetEvent", offsetof(DeviceVtbl, CmdResetEvent)},
+    {"vkCmdResetQueryPool", offsetof(DeviceVtbl, CmdResetQueryPool)},
+    {"vkCmdResolveImage", offsetof(DeviceVtbl, CmdResolveImage)},
+    {"vkCmdSetEvent", offsetof(DeviceVtbl, CmdSetEvent)},
+    {"vkCmdUpdateBuffer", offsetof(DeviceVtbl, CmdUpdateBuffer)},
+    {"vkCmdWaitEvents", offsetof(DeviceVtbl, CmdWaitEvents)},
+    {"vkCmdWriteTimestamp", offsetof(DeviceVtbl, CmdWriteTimestamp)},
+    {"vkCreateAttachmentView", offsetof(DeviceVtbl, CreateAttachmentView)},
+    {"vkCreateBuffer", offsetof(DeviceVtbl, CreateBuffer)},
+    {"vkCreateBufferView", offsetof(DeviceVtbl, CreateBufferView)},
+    {"vkCreateCommandBuffer", offsetof(DeviceVtbl, CreateCommandBuffer)},
+    {"vkCreateCommandPool", offsetof(DeviceVtbl, CreateCommandPool)},
+    {"vkCreateComputePipelines", offsetof(DeviceVtbl, CreateComputePipelines)},
+    {"vkCreateDescriptorPool", offsetof(DeviceVtbl, CreateDescriptorPool)},
+    {"vkCreateDescriptorSetLayout", offsetof(DeviceVtbl, CreateDescriptorSetLayout)},
+    {"vkCreateDynamicColorBlendState", offsetof(DeviceVtbl, CreateDynamicColorBlendState)},
+    {"vkCreateDynamicDepthStencilState", offsetof(DeviceVtbl, CreateDynamicDepthStencilState)},
+    {"vkCreateDynamicRasterState", offsetof(DeviceVtbl, CreateDynamicRasterState)},
+    {"vkCreateDynamicViewportState", offsetof(DeviceVtbl, CreateDynamicViewportState)},
+    {"vkCreateEvent", offsetof(DeviceVtbl, CreateEvent)},
+    {"vkCreateFence", offsetof(DeviceVtbl, CreateFence)},
+    {"vkCreateFramebuffer", offsetof(DeviceVtbl, CreateFramebuffer)},
+    {"vkCreateGraphicsPipelines", offsetof(DeviceVtbl, CreateGraphicsPipelines)},
+    {"vkCreateImage", offsetof(DeviceVtbl, CreateImage)},
+    {"vkCreateImageView", offsetof(DeviceVtbl, CreateImageView)},
+    {"vkCreatePipelineCache", offsetof(DeviceVtbl, CreatePipelineCache)},
+    {"vkCreatePipelineLayout", offsetof(DeviceVtbl, CreatePipelineLayout)},
+    {"vkCreateQueryPool", offsetof(DeviceVtbl, CreateQueryPool)},
+    {"vkCreateRenderPass", offsetof(DeviceVtbl, CreateRenderPass)},
+    {"vkCreateSampler", offsetof(DeviceVtbl, CreateSampler)},
+    {"vkCreateSemaphore", offsetof(DeviceVtbl, CreateSemaphore)},
+    {"vkCreateShader", offsetof(DeviceVtbl, CreateShader)},
+    {"vkCreateShaderModule", offsetof(DeviceVtbl, CreateShaderModule)},
+    {"vkDestroyAttachmentView", offsetof(DeviceVtbl, DestroyAttachmentView)},
+    {"vkDestroyBuffer", offsetof(DeviceVtbl, DestroyBuffer)},
+    {"vkDestroyBufferView", offsetof(DeviceVtbl, DestroyBufferView)},
+    {"vkDestroyCommandBuffer", offsetof(DeviceVtbl, DestroyCommandBuffer)},
+    {"vkDestroyCommandPool", offsetof(DeviceVtbl, DestroyCommandPool)},
+    {"vkDestroyDescriptorPool", offsetof(DeviceVtbl, DestroyDescriptorPool)},
+    {"vkDestroyDescriptorSetLayout", offsetof(DeviceVtbl, DestroyDescriptorSetLayout)},
+    {"vkDestroyDevice", offsetof(DeviceVtbl, DestroyDevice)},
+    {"vkDestroyDynamicColorBlendState", offsetof(DeviceVtbl, DestroyDynamicColorBlendState)},
+    {"vkDestroyDynamicDepthStencilState", offsetof(DeviceVtbl, DestroyDynamicDepthStencilState)},
+    {"vkDestroyDynamicRasterState", offsetof(DeviceVtbl, DestroyDynamicRasterState)},
+    {"vkDestroyDynamicViewportState", offsetof(DeviceVtbl, DestroyDynamicViewportState)},
+    {"vkDestroyEvent", offsetof(DeviceVtbl, DestroyEvent)},
+    {"vkDestroyFence", offsetof(DeviceVtbl, DestroyFence)},
+    {"vkDestroyFramebuffer", offsetof(DeviceVtbl, DestroyFramebuffer)},
+    {"vkDestroyImage", offsetof(DeviceVtbl, DestroyImage)},
+    {"vkDestroyImageView", offsetof(DeviceVtbl, DestroyImageView)},
+    {"vkDestroyPipeline", offsetof(DeviceVtbl, DestroyPipeline)},
+    {"vkDestroyPipelineCache", offsetof(DeviceVtbl, DestroyPipelineCache)},
+    {"vkDestroyPipelineLayout", offsetof(DeviceVtbl, DestroyPipelineLayout)},
+    {"vkDestroyQueryPool", offsetof(DeviceVtbl, DestroyQueryPool)},
+    {"vkDestroyRenderPass", offsetof(DeviceVtbl, DestroyRenderPass)},
+    {"vkDestroySampler", offsetof(DeviceVtbl, DestroySampler)},
+    {"vkDestroySemaphore", offsetof(DeviceVtbl, DestroySemaphore)},
+    {"vkDestroyShader", offsetof(DeviceVtbl, DestroyShader)},
+    {"vkDestroyShaderModule", offsetof(DeviceVtbl, DestroyShaderModule)},
+    {"vkDeviceWaitIdle", offsetof(DeviceVtbl, DeviceWaitIdle)},
+    {"vkEndCommandBuffer", offsetof(DeviceVtbl, EndCommandBuffer)},
+    {"vkFlushMappedMemoryRanges", offsetof(DeviceVtbl, FlushMappedMemoryRanges)},
+    {"vkFreeDescriptorSets", offsetof(DeviceVtbl, FreeDescriptorSets)},
+    {"vkFreeMemory", offsetof(DeviceVtbl, FreeMemory)},
+    {"vkGetBufferMemoryRequirements", offsetof(DeviceVtbl, GetBufferMemoryRequirements)},
+    {"vkGetDeviceMemoryCommitment", offsetof(DeviceVtbl, GetDeviceMemoryCommitment)},
+    {"vkGetDeviceProcAddr", offsetof(DeviceVtbl, GetDeviceProcAddr)},
+    {"vkGetDeviceQueue", offsetof(DeviceVtbl, GetDeviceQueue)},
+    {"vkGetEventStatus", offsetof(DeviceVtbl, GetEventStatus)},
+    {"vkGetFenceStatus", offsetof(DeviceVtbl, GetFenceStatus)},
+    {"vkGetImageMemoryRequirements", offsetof(DeviceVtbl, GetImageMemoryRequirements)},
+    {"vkGetImageSparseMemoryRequirements", offsetof(DeviceVtbl, GetImageSparseMemoryRequirements)},
+    {"vkGetImageSubresourceLayout", offsetof(DeviceVtbl, GetImageSubresourceLayout)},
+    {"vkGetPipelineCacheData", offsetof(DeviceVtbl, GetPipelineCacheData)},
+    {"vkGetPipelineCacheSize", offsetof(DeviceVtbl, GetPipelineCacheSize)},
+    {"vkGetQueryPoolResults", offsetof(DeviceVtbl, GetQueryPoolResults)},
+    {"vkGetRenderAreaGranularity", offsetof(DeviceVtbl, GetRenderAreaGranularity)},
+    {"vkInvalidateMappedMemoryRanges", offsetof(DeviceVtbl, InvalidateMappedMemoryRanges)},
+    {"vkMapMemory", offsetof(DeviceVtbl, MapMemory)},
+    {"vkMergePipelineCaches", offsetof(DeviceVtbl, MergePipelineCaches)},
+    {"vkQueueBindSparseBufferMemory", offsetof(DeviceVtbl, QueueBindSparseBufferMemory)},
+    {"vkQueueBindSparseImageMemory", offsetof(DeviceVtbl, QueueBindSparseImageMemory)},
+    {"vkQueueBindSparseImageOpaqueMemory", offsetof(DeviceVtbl, QueueBindSparseImageOpaqueMemory)},
+    {"vkQueueSignalSemaphore", offsetof(DeviceVtbl, QueueSignalSemaphore)},
+    {"vkQueueSubmit", offsetof(DeviceVtbl, QueueSubmit)},
+    {"vkQueueWaitIdle", offsetof(DeviceVtbl, QueueWaitIdle)},
+    {"vkQueueWaitSemaphore", offsetof(DeviceVtbl, QueueWaitSemaphore)},
+    {"vkResetCommandBuffer", offsetof(DeviceVtbl, ResetCommandBuffer)},
+    {"vkResetCommandPool", offsetof(DeviceVtbl, ResetCommandPool)},
+    {"vkResetDescriptorPool", offsetof(DeviceVtbl, ResetDescriptorPool)},
+    {"vkResetEvent", offsetof(DeviceVtbl, ResetEvent)},
+    {"vkResetFences", offsetof(DeviceVtbl, ResetFences)},
+    {"vkSetEvent", offsetof(DeviceVtbl, SetEvent)},
+    {"vkUnmapMemory", offsetof(DeviceVtbl, UnmapMemory)},
+    {"vkUpdateDescriptorSets", offsetof(DeviceVtbl, UpdateDescriptorSets)},
+    {"vkWaitForFences", offsetof(DeviceVtbl, WaitForFences)},
+    // clang-format on
+};
+
+}  // namespace
+
+namespace vulkan {
+
+PFN_vkVoidFunction GetGlobalInstanceProcAddr(const char* name) {
+    if (strcmp(name, "vkGetDeviceProcAddr") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr);
+    const NameProcEntry* entry = FindProcEntry(kInstanceProcTbl, name);
+    return entry ? entry->proc : nullptr;
+}
+
+PFN_vkVoidFunction GetGlobalDeviceProcAddr(const char* name) {
+    const NameProcEntry* entry = FindProcEntry(kDeviceProcTbl, name);
+    return entry ? entry->proc : nullptr;
+}
+
+PFN_vkVoidFunction GetSpecificInstanceProcAddr(const InstanceVtbl* vtbl,
+                                               const char* name) {
+    const NameOffsetEntry* entry = FindProcEntry(kInstanceOffsetTbl, name);
+    if (!entry)
+        return nullptr;
+    const unsigned char* base = reinterpret_cast<const unsigned char*>(vtbl);
+    return reinterpret_cast<PFN_vkVoidFunction>(
+        const_cast<unsigned char*>(base) + entry->offset);
+}
+
+PFN_vkVoidFunction GetSpecificDeviceProcAddr(const DeviceVtbl* vtbl,
+                                             const char* name) {
+    const NameOffsetEntry* entry = FindProcEntry(kDeviceOffsetTbl, name);
+    if (!entry)
+        return nullptr;
+    const unsigned char* base = reinterpret_cast<const unsigned char*>(vtbl);
+    return reinterpret_cast<PFN_vkVoidFunction>(
+        const_cast<unsigned char*>(base) + entry->offset);
+}
+
+bool LoadInstanceVtbl(VkInstance instance,
+                      PFN_vkGetInstanceProcAddr get_proc_addr,
+                      InstanceVtbl& vtbl) {
+    bool success = true;
+    // clang-format off
+    vtbl.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(get_proc_addr(instance, "vkDestroyInstance"));
+    if (UNLIKELY(!vtbl.DestroyInstance)) {
+        ALOGE("missing instance proc: %s", "vkDestroyInstance");
+        success = false;
+    }
+    vtbl.EnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(get_proc_addr(instance, "vkEnumeratePhysicalDevices"));
+    if (UNLIKELY(!vtbl.EnumeratePhysicalDevices)) {
+        ALOGE("missing instance proc: %s", "vkEnumeratePhysicalDevices");
+        success = false;
+    }
+    vtbl.GetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(get_proc_addr(instance, "vkGetInstanceProcAddr"));
+    if (UNLIKELY(!vtbl.GetInstanceProcAddr)) {
+        ALOGE("missing instance proc: %s", "vkGetInstanceProcAddr");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceProperties");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceQueueCount = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueCount>(get_proc_addr(instance, "vkGetPhysicalDeviceQueueCount"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceQueueCount)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceQueueCount");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceQueueProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceQueueProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceQueueProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceQueueProperties");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceMemoryProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceMemoryProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceMemoryProperties");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceFeatures = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(get_proc_addr(instance, "vkGetPhysicalDeviceFeatures"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceFeatures)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceFeatures");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceFormatProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceFormatProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceFormatProperties");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceImageFormatProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceImageFormatProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceImageFormatProperties");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceLimits = reinterpret_cast<PFN_vkGetPhysicalDeviceLimits>(get_proc_addr(instance, "vkGetPhysicalDeviceLimits"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceLimits)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceLimits");
+        success = false;
+    }
+    vtbl.CreateDevice = reinterpret_cast<PFN_vkCreateDevice>(get_proc_addr(instance, "vkCreateDevice"));
+    if (UNLIKELY(!vtbl.CreateDevice)) {
+        ALOGE("missing instance proc: %s", "vkCreateDevice");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceLayerProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceLayerProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceLayerProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceLayerProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceLayerProperties");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceExtensionProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceExtensionProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceExtensionProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceExtensionProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceExtensionProperties");
+        success = false;
+    }
+    vtbl.GetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties"));
+    if (UNLIKELY(!vtbl.GetPhysicalDeviceSparseImageFormatProperties)) {
+        ALOGE("missing instance proc: %s", "vkGetPhysicalDeviceSparseImageFormatProperties");
+        success = false;
+    }
+    // clang-format on
+    return success;
+}
+
+bool LoadDeviceVtbl(VkDevice device,
+                    PFN_vkGetDeviceProcAddr get_proc_addr,
+                    DeviceVtbl& vtbl) {
+    bool success = true;
+    // clang-format off
+    vtbl.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(device, "vkGetDeviceProcAddr"));
+    if (UNLIKELY(!vtbl.GetDeviceProcAddr)) {
+        ALOGE("missing device proc: %s", "vkGetDeviceProcAddr");
+        success = false;
+    }
+    vtbl.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(get_proc_addr(device, "vkDestroyDevice"));
+    if (UNLIKELY(!vtbl.DestroyDevice)) {
+        ALOGE("missing device proc: %s", "vkDestroyDevice");
+        success = false;
+    }
+    vtbl.GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(get_proc_addr(device, "vkGetDeviceQueue"));
+    if (UNLIKELY(!vtbl.GetDeviceQueue)) {
+        ALOGE("missing device proc: %s", "vkGetDeviceQueue");
+        success = false;
+    }
+    vtbl.QueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(get_proc_addr(device, "vkQueueSubmit"));
+    if (UNLIKELY(!vtbl.QueueSubmit)) {
+        ALOGE("missing device proc: %s", "vkQueueSubmit");
+        success = false;
+    }
+    vtbl.QueueWaitIdle = reinterpret_cast<PFN_vkQueueWaitIdle>(get_proc_addr(device, "vkQueueWaitIdle"));
+    if (UNLIKELY(!vtbl.QueueWaitIdle)) {
+        ALOGE("missing device proc: %s", "vkQueueWaitIdle");
+        success = false;
+    }
+    vtbl.DeviceWaitIdle = reinterpret_cast<PFN_vkDeviceWaitIdle>(get_proc_addr(device, "vkDeviceWaitIdle"));
+    if (UNLIKELY(!vtbl.DeviceWaitIdle)) {
+        ALOGE("missing device proc: %s", "vkDeviceWaitIdle");
+        success = false;
+    }
+    vtbl.AllocMemory = reinterpret_cast<PFN_vkAllocMemory>(get_proc_addr(device, "vkAllocMemory"));
+    if (UNLIKELY(!vtbl.AllocMemory)) {
+        ALOGE("missing device proc: %s", "vkAllocMemory");
+        success = false;
+    }
+    vtbl.FreeMemory = reinterpret_cast<PFN_vkFreeMemory>(get_proc_addr(device, "vkFreeMemory"));
+    if (UNLIKELY(!vtbl.FreeMemory)) {
+        ALOGE("missing device proc: %s", "vkFreeMemory");
+        success = false;
+    }
+    vtbl.MapMemory = reinterpret_cast<PFN_vkMapMemory>(get_proc_addr(device, "vkMapMemory"));
+    if (UNLIKELY(!vtbl.MapMemory)) {
+        ALOGE("missing device proc: %s", "vkMapMemory");
+        success = false;
+    }
+    vtbl.UnmapMemory = reinterpret_cast<PFN_vkUnmapMemory>(get_proc_addr(device, "vkUnmapMemory"));
+    if (UNLIKELY(!vtbl.UnmapMemory)) {
+        ALOGE("missing device proc: %s", "vkUnmapMemory");
+        success = false;
+    }
+    vtbl.FlushMappedMemoryRanges = reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(get_proc_addr(device, "vkFlushMappedMemoryRanges"));
+    if (UNLIKELY(!vtbl.FlushMappedMemoryRanges)) {
+        ALOGE("missing device proc: %s", "vkFlushMappedMemoryRanges");
+        success = false;
+    }
+    vtbl.InvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(get_proc_addr(device, "vkInvalidateMappedMemoryRanges"));
+    if (UNLIKELY(!vtbl.InvalidateMappedMemoryRanges)) {
+        ALOGE("missing device proc: %s", "vkInvalidateMappedMemoryRanges");
+        success = false;
+    }
+    vtbl.GetDeviceMemoryCommitment = reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(get_proc_addr(device, "vkGetDeviceMemoryCommitment"));
+    if (UNLIKELY(!vtbl.GetDeviceMemoryCommitment)) {
+        ALOGE("missing device proc: %s", "vkGetDeviceMemoryCommitment");
+        success = false;
+    }
+    vtbl.GetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(get_proc_addr(device, "vkGetBufferMemoryRequirements"));
+    if (UNLIKELY(!vtbl.GetBufferMemoryRequirements)) {
+        ALOGE("missing device proc: %s", "vkGetBufferMemoryRequirements");
+        success = false;
+    }
+    vtbl.BindBufferMemory = reinterpret_cast<PFN_vkBindBufferMemory>(get_proc_addr(device, "vkBindBufferMemory"));
+    if (UNLIKELY(!vtbl.BindBufferMemory)) {
+        ALOGE("missing device proc: %s", "vkBindBufferMemory");
+        success = false;
+    }
+    vtbl.GetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>(get_proc_addr(device, "vkGetImageMemoryRequirements"));
+    if (UNLIKELY(!vtbl.GetImageMemoryRequirements)) {
+        ALOGE("missing device proc: %s", "vkGetImageMemoryRequirements");
+        success = false;
+    }
+    vtbl.BindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>(get_proc_addr(device, "vkBindImageMemory"));
+    if (UNLIKELY(!vtbl.BindImageMemory)) {
+        ALOGE("missing device proc: %s", "vkBindImageMemory");
+        success = false;
+    }
+    vtbl.GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(get_proc_addr(device, "vkGetImageSparseMemoryRequirements"));
+    if (UNLIKELY(!vtbl.GetImageSparseMemoryRequirements)) {
+        ALOGE("missing device proc: %s", "vkGetImageSparseMemoryRequirements");
+        success = false;
+    }
+    vtbl.QueueBindSparseBufferMemory = reinterpret_cast<PFN_vkQueueBindSparseBufferMemory>(get_proc_addr(device, "vkQueueBindSparseBufferMemory"));
+    if (UNLIKELY(!vtbl.QueueBindSparseBufferMemory)) {
+        ALOGE("missing device proc: %s", "vkQueueBindSparseBufferMemory");
+        success = false;
+    }
+    vtbl.QueueBindSparseImageOpaqueMemory = reinterpret_cast<PFN_vkQueueBindSparseImageOpaqueMemory>(get_proc_addr(device, "vkQueueBindSparseImageOpaqueMemory"));
+    if (UNLIKELY(!vtbl.QueueBindSparseImageOpaqueMemory)) {
+        ALOGE("missing device proc: %s", "vkQueueBindSparseImageOpaqueMemory");
+        success = false;
+    }
+    vtbl.QueueBindSparseImageMemory = reinterpret_cast<PFN_vkQueueBindSparseImageMemory>(get_proc_addr(device, "vkQueueBindSparseImageMemory"));
+    if (UNLIKELY(!vtbl.QueueBindSparseImageMemory)) {
+        ALOGE("missing device proc: %s", "vkQueueBindSparseImageMemory");
+        success = false;
+    }
+    vtbl.CreateFence = reinterpret_cast<PFN_vkCreateFence>(get_proc_addr(device, "vkCreateFence"));
+    if (UNLIKELY(!vtbl.CreateFence)) {
+        ALOGE("missing device proc: %s", "vkCreateFence");
+        success = false;
+    }
+    vtbl.DestroyFence = reinterpret_cast<PFN_vkDestroyFence>(get_proc_addr(device, "vkDestroyFence"));
+    if (UNLIKELY(!vtbl.DestroyFence)) {
+        ALOGE("missing device proc: %s", "vkDestroyFence");
+        success = false;
+    }
+    vtbl.ResetFences = reinterpret_cast<PFN_vkResetFences>(get_proc_addr(device, "vkResetFences"));
+    if (UNLIKELY(!vtbl.ResetFences)) {
+        ALOGE("missing device proc: %s", "vkResetFences");
+        success = false;
+    }
+    vtbl.GetFenceStatus = reinterpret_cast<PFN_vkGetFenceStatus>(get_proc_addr(device, "vkGetFenceStatus"));
+    if (UNLIKELY(!vtbl.GetFenceStatus)) {
+        ALOGE("missing device proc: %s", "vkGetFenceStatus");
+        success = false;
+    }
+    vtbl.WaitForFences = reinterpret_cast<PFN_vkWaitForFences>(get_proc_addr(device, "vkWaitForFences"));
+    if (UNLIKELY(!vtbl.WaitForFences)) {
+        ALOGE("missing device proc: %s", "vkWaitForFences");
+        success = false;
+    }
+    vtbl.CreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>(get_proc_addr(device, "vkCreateSemaphore"));
+    if (UNLIKELY(!vtbl.CreateSemaphore)) {
+        ALOGE("missing device proc: %s", "vkCreateSemaphore");
+        success = false;
+    }
+    vtbl.DestroySemaphore = reinterpret_cast<PFN_vkDestroySemaphore>(get_proc_addr(device, "vkDestroySemaphore"));
+    if (UNLIKELY(!vtbl.DestroySemaphore)) {
+        ALOGE("missing device proc: %s", "vkDestroySemaphore");
+        success = false;
+    }
+    vtbl.QueueSignalSemaphore = reinterpret_cast<PFN_vkQueueSignalSemaphore>(get_proc_addr(device, "vkQueueSignalSemaphore"));
+    if (UNLIKELY(!vtbl.QueueSignalSemaphore)) {
+        ALOGE("missing device proc: %s", "vkQueueSignalSemaphore");
+        success = false;
+    }
+    vtbl.QueueWaitSemaphore = reinterpret_cast<PFN_vkQueueWaitSemaphore>(get_proc_addr(device, "vkQueueWaitSemaphore"));
+    if (UNLIKELY(!vtbl.QueueWaitSemaphore)) {
+        ALOGE("missing device proc: %s", "vkQueueWaitSemaphore");
+        success = false;
+    }
+    vtbl.CreateEvent = reinterpret_cast<PFN_vkCreateEvent>(get_proc_addr(device, "vkCreateEvent"));
+    if (UNLIKELY(!vtbl.CreateEvent)) {
+        ALOGE("missing device proc: %s", "vkCreateEvent");
+        success = false;
+    }
+    vtbl.DestroyEvent = reinterpret_cast<PFN_vkDestroyEvent>(get_proc_addr(device, "vkDestroyEvent"));
+    if (UNLIKELY(!vtbl.DestroyEvent)) {
+        ALOGE("missing device proc: %s", "vkDestroyEvent");
+        success = false;
+    }
+    vtbl.GetEventStatus = reinterpret_cast<PFN_vkGetEventStatus>(get_proc_addr(device, "vkGetEventStatus"));
+    if (UNLIKELY(!vtbl.GetEventStatus)) {
+        ALOGE("missing device proc: %s", "vkGetEventStatus");
+        success = false;
+    }
+    vtbl.SetEvent = reinterpret_cast<PFN_vkSetEvent>(get_proc_addr(device, "vkSetEvent"));
+    if (UNLIKELY(!vtbl.SetEvent)) {
+        ALOGE("missing device proc: %s", "vkSetEvent");
+        success = false;
+    }
+    vtbl.ResetEvent = reinterpret_cast<PFN_vkResetEvent>(get_proc_addr(device, "vkResetEvent"));
+    if (UNLIKELY(!vtbl.ResetEvent)) {
+        ALOGE("missing device proc: %s", "vkResetEvent");
+        success = false;
+    }
+    vtbl.CreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(get_proc_addr(device, "vkCreateQueryPool"));
+    if (UNLIKELY(!vtbl.CreateQueryPool)) {
+        ALOGE("missing device proc: %s", "vkCreateQueryPool");
+        success = false;
+    }
+    vtbl.DestroyQueryPool = reinterpret_cast<PFN_vkDestroyQueryPool>(get_proc_addr(device, "vkDestroyQueryPool"));
+    if (UNLIKELY(!vtbl.DestroyQueryPool)) {
+        ALOGE("missing device proc: %s", "vkDestroyQueryPool");
+        success = false;
+    }
+    vtbl.GetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(get_proc_addr(device, "vkGetQueryPoolResults"));
+    if (UNLIKELY(!vtbl.GetQueryPoolResults)) {
+        ALOGE("missing device proc: %s", "vkGetQueryPoolResults");
+        success = false;
+    }
+    vtbl.CreateBuffer = reinterpret_cast<PFN_vkCreateBuffer>(get_proc_addr(device, "vkCreateBuffer"));
+    if (UNLIKELY(!vtbl.CreateBuffer)) {
+        ALOGE("missing device proc: %s", "vkCreateBuffer");
+        success = false;
+    }
+    vtbl.DestroyBuffer = reinterpret_cast<PFN_vkDestroyBuffer>(get_proc_addr(device, "vkDestroyBuffer"));
+    if (UNLIKELY(!vtbl.DestroyBuffer)) {
+        ALOGE("missing device proc: %s", "vkDestroyBuffer");
+        success = false;
+    }
+    vtbl.CreateBufferView = reinterpret_cast<PFN_vkCreateBufferView>(get_proc_addr(device, "vkCreateBufferView"));
+    if (UNLIKELY(!vtbl.CreateBufferView)) {
+        ALOGE("missing device proc: %s", "vkCreateBufferView");
+        success = false;
+    }
+    vtbl.DestroyBufferView = reinterpret_cast<PFN_vkDestroyBufferView>(get_proc_addr(device, "vkDestroyBufferView"));
+    if (UNLIKELY(!vtbl.DestroyBufferView)) {
+        ALOGE("missing device proc: %s", "vkDestroyBufferView");
+        success = false;
+    }
+    vtbl.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(device, "vkCreateImage"));
+    if (UNLIKELY(!vtbl.CreateImage)) {
+        ALOGE("missing device proc: %s", "vkCreateImage");
+        success = false;
+    }
+    vtbl.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(device, "vkDestroyImage"));
+    if (UNLIKELY(!vtbl.DestroyImage)) {
+        ALOGE("missing device proc: %s", "vkDestroyImage");
+        success = false;
+    }
+    vtbl.GetImageSubresourceLayout = reinterpret_cast<PFN_vkGetImageSubresourceLayout>(get_proc_addr(device, "vkGetImageSubresourceLayout"));
+    if (UNLIKELY(!vtbl.GetImageSubresourceLayout)) {
+        ALOGE("missing device proc: %s", "vkGetImageSubresourceLayout");
+        success = false;
+    }
+    vtbl.CreateImageView = reinterpret_cast<PFN_vkCreateImageView>(get_proc_addr(device, "vkCreateImageView"));
+    if (UNLIKELY(!vtbl.CreateImageView)) {
+        ALOGE("missing device proc: %s", "vkCreateImageView");
+        success = false;
+    }
+    vtbl.DestroyImageView = reinterpret_cast<PFN_vkDestroyImageView>(get_proc_addr(device, "vkDestroyImageView"));
+    if (UNLIKELY(!vtbl.DestroyImageView)) {
+        ALOGE("missing device proc: %s", "vkDestroyImageView");
+        success = false;
+    }
+    vtbl.CreateAttachmentView = reinterpret_cast<PFN_vkCreateAttachmentView>(get_proc_addr(device, "vkCreateAttachmentView"));
+    if (UNLIKELY(!vtbl.CreateAttachmentView)) {
+        ALOGE("missing device proc: %s", "vkCreateAttachmentView");
+        success = false;
+    }
+    vtbl.DestroyAttachmentView = reinterpret_cast<PFN_vkDestroyAttachmentView>(get_proc_addr(device, "vkDestroyAttachmentView"));
+    if (UNLIKELY(!vtbl.DestroyAttachmentView)) {
+        ALOGE("missing device proc: %s", "vkDestroyAttachmentView");
+        success = false;
+    }
+    vtbl.CreateShaderModule = reinterpret_cast<PFN_vkCreateShaderModule>(get_proc_addr(device, "vkCreateShaderModule"));
+    if (UNLIKELY(!vtbl.CreateShaderModule)) {
+        ALOGE("missing device proc: %s", "vkCreateShaderModule");
+        success = false;
+    }
+    vtbl.DestroyShaderModule = reinterpret_cast<PFN_vkDestroyShaderModule>(get_proc_addr(device, "vkDestroyShaderModule"));
+    if (UNLIKELY(!vtbl.DestroyShaderModule)) {
+        ALOGE("missing device proc: %s", "vkDestroyShaderModule");
+        success = false;
+    }
+    vtbl.CreateShader = reinterpret_cast<PFN_vkCreateShader>(get_proc_addr(device, "vkCreateShader"));
+    if (UNLIKELY(!vtbl.CreateShader)) {
+        ALOGE("missing device proc: %s", "vkCreateShader");
+        success = false;
+    }
+    vtbl.DestroyShader = reinterpret_cast<PFN_vkDestroyShader>(get_proc_addr(device, "vkDestroyShader"));
+    if (UNLIKELY(!vtbl.DestroyShader)) {
+        ALOGE("missing device proc: %s", "vkDestroyShader");
+        success = false;
+    }
+    vtbl.CreatePipelineCache = reinterpret_cast<PFN_vkCreatePipelineCache>(get_proc_addr(device, "vkCreatePipelineCache"));
+    if (UNLIKELY(!vtbl.CreatePipelineCache)) {
+        ALOGE("missing device proc: %s", "vkCreatePipelineCache");
+        success = false;
+    }
+    vtbl.DestroyPipelineCache = reinterpret_cast<PFN_vkDestroyPipelineCache>(get_proc_addr(device, "vkDestroyPipelineCache"));
+    if (UNLIKELY(!vtbl.DestroyPipelineCache)) {
+        ALOGE("missing device proc: %s", "vkDestroyPipelineCache");
+        success = false;
+    }
+    vtbl.GetPipelineCacheSize = reinterpret_cast<PFN_vkGetPipelineCacheSize>(get_proc_addr(device, "vkGetPipelineCacheSize"));
+    if (UNLIKELY(!vtbl.GetPipelineCacheSize)) {
+        ALOGE("missing device proc: %s", "vkGetPipelineCacheSize");
+        success = false;
+    }
+    vtbl.GetPipelineCacheData = reinterpret_cast<PFN_vkGetPipelineCacheData>(get_proc_addr(device, "vkGetPipelineCacheData"));
+    if (UNLIKELY(!vtbl.GetPipelineCacheData)) {
+        ALOGE("missing device proc: %s", "vkGetPipelineCacheData");
+        success = false;
+    }
+    vtbl.MergePipelineCaches = reinterpret_cast<PFN_vkMergePipelineCaches>(get_proc_addr(device, "vkMergePipelineCaches"));
+    if (UNLIKELY(!vtbl.MergePipelineCaches)) {
+        ALOGE("missing device proc: %s", "vkMergePipelineCaches");
+        success = false;
+    }
+    vtbl.CreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(get_proc_addr(device, "vkCreateGraphicsPipelines"));
+    if (UNLIKELY(!vtbl.CreateGraphicsPipelines)) {
+        ALOGE("missing device proc: %s", "vkCreateGraphicsPipelines");
+        success = false;
+    }
+    vtbl.CreateComputePipelines = reinterpret_cast<PFN_vkCreateComputePipelines>(get_proc_addr(device, "vkCreateComputePipelines"));
+    if (UNLIKELY(!vtbl.CreateComputePipelines)) {
+        ALOGE("missing device proc: %s", "vkCreateComputePipelines");
+        success = false;
+    }
+    vtbl.DestroyPipeline = reinterpret_cast<PFN_vkDestroyPipeline>(get_proc_addr(device, "vkDestroyPipeline"));
+    if (UNLIKELY(!vtbl.DestroyPipeline)) {
+        ALOGE("missing device proc: %s", "vkDestroyPipeline");
+        success = false;
+    }
+    vtbl.CreatePipelineLayout = reinterpret_cast<PFN_vkCreatePipelineLayout>(get_proc_addr(device, "vkCreatePipelineLayout"));
+    if (UNLIKELY(!vtbl.CreatePipelineLayout)) {
+        ALOGE("missing device proc: %s", "vkCreatePipelineLayout");
+        success = false;
+    }
+    vtbl.DestroyPipelineLayout = reinterpret_cast<PFN_vkDestroyPipelineLayout>(get_proc_addr(device, "vkDestroyPipelineLayout"));
+    if (UNLIKELY(!vtbl.DestroyPipelineLayout)) {
+        ALOGE("missing device proc: %s", "vkDestroyPipelineLayout");
+        success = false;
+    }
+    vtbl.CreateSampler = reinterpret_cast<PFN_vkCreateSampler>(get_proc_addr(device, "vkCreateSampler"));
+    if (UNLIKELY(!vtbl.CreateSampler)) {
+        ALOGE("missing device proc: %s", "vkCreateSampler");
+        success = false;
+    }
+    vtbl.DestroySampler = reinterpret_cast<PFN_vkDestroySampler>(get_proc_addr(device, "vkDestroySampler"));
+    if (UNLIKELY(!vtbl.DestroySampler)) {
+        ALOGE("missing device proc: %s", "vkDestroySampler");
+        success = false;
+    }
+    vtbl.CreateDescriptorSetLayout = reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(get_proc_addr(device, "vkCreateDescriptorSetLayout"));
+    if (UNLIKELY(!vtbl.CreateDescriptorSetLayout)) {
+        ALOGE("missing device proc: %s", "vkCreateDescriptorSetLayout");
+        success = false;
+    }
+    vtbl.DestroyDescriptorSetLayout = reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(get_proc_addr(device, "vkDestroyDescriptorSetLayout"));
+    if (UNLIKELY(!vtbl.DestroyDescriptorSetLayout)) {
+        ALOGE("missing device proc: %s", "vkDestroyDescriptorSetLayout");
+        success = false;
+    }
+    vtbl.CreateDescriptorPool = reinterpret_cast<PFN_vkCreateDescriptorPool>(get_proc_addr(device, "vkCreateDescriptorPool"));
+    if (UNLIKELY(!vtbl.CreateDescriptorPool)) {
+        ALOGE("missing device proc: %s", "vkCreateDescriptorPool");
+        success = false;
+    }
+    vtbl.DestroyDescriptorPool = reinterpret_cast<PFN_vkDestroyDescriptorPool>(get_proc_addr(device, "vkDestroyDescriptorPool"));
+    if (UNLIKELY(!vtbl.DestroyDescriptorPool)) {
+        ALOGE("missing device proc: %s", "vkDestroyDescriptorPool");
+        success = false;
+    }
+    vtbl.ResetDescriptorPool = reinterpret_cast<PFN_vkResetDescriptorPool>(get_proc_addr(device, "vkResetDescriptorPool"));
+    if (UNLIKELY(!vtbl.ResetDescriptorPool)) {
+        ALOGE("missing device proc: %s", "vkResetDescriptorPool");
+        success = false;
+    }
+    vtbl.AllocDescriptorSets = reinterpret_cast<PFN_vkAllocDescriptorSets>(get_proc_addr(device, "vkAllocDescriptorSets"));
+    if (UNLIKELY(!vtbl.AllocDescriptorSets)) {
+        ALOGE("missing device proc: %s", "vkAllocDescriptorSets");
+        success = false;
+    }
+    vtbl.FreeDescriptorSets = reinterpret_cast<PFN_vkFreeDescriptorSets>(get_proc_addr(device, "vkFreeDescriptorSets"));
+    if (UNLIKELY(!vtbl.FreeDescriptorSets)) {
+        ALOGE("missing device proc: %s", "vkFreeDescriptorSets");
+        success = false;
+    }
+    vtbl.UpdateDescriptorSets = reinterpret_cast<PFN_vkUpdateDescriptorSets>(get_proc_addr(device, "vkUpdateDescriptorSets"));
+    if (UNLIKELY(!vtbl.UpdateDescriptorSets)) {
+        ALOGE("missing device proc: %s", "vkUpdateDescriptorSets");
+        success = false;
+    }
+    vtbl.CreateDynamicViewportState = reinterpret_cast<PFN_vkCreateDynamicViewportState>(get_proc_addr(device, "vkCreateDynamicViewportState"));
+    if (UNLIKELY(!vtbl.CreateDynamicViewportState)) {
+        ALOGE("missing device proc: %s", "vkCreateDynamicViewportState");
+        success = false;
+    }
+    vtbl.DestroyDynamicViewportState = reinterpret_cast<PFN_vkDestroyDynamicViewportState>(get_proc_addr(device, "vkDestroyDynamicViewportState"));
+    if (UNLIKELY(!vtbl.DestroyDynamicViewportState)) {
+        ALOGE("missing device proc: %s", "vkDestroyDynamicViewportState");
+        success = false;
+    }
+    vtbl.CreateDynamicRasterState = reinterpret_cast<PFN_vkCreateDynamicRasterState>(get_proc_addr(device, "vkCreateDynamicRasterState"));
+    if (UNLIKELY(!vtbl.CreateDynamicRasterState)) {
+        ALOGE("missing device proc: %s", "vkCreateDynamicRasterState");
+        success = false;
+    }
+    vtbl.DestroyDynamicRasterState = reinterpret_cast<PFN_vkDestroyDynamicRasterState>(get_proc_addr(device, "vkDestroyDynamicRasterState"));
+    if (UNLIKELY(!vtbl.DestroyDynamicRasterState)) {
+        ALOGE("missing device proc: %s", "vkDestroyDynamicRasterState");
+        success = false;
+    }
+    vtbl.CreateDynamicColorBlendState = reinterpret_cast<PFN_vkCreateDynamicColorBlendState>(get_proc_addr(device, "vkCreateDynamicColorBlendState"));
+    if (UNLIKELY(!vtbl.CreateDynamicColorBlendState)) {
+        ALOGE("missing device proc: %s", "vkCreateDynamicColorBlendState");
+        success = false;
+    }
+    vtbl.DestroyDynamicColorBlendState = reinterpret_cast<PFN_vkDestroyDynamicColorBlendState>(get_proc_addr(device, "vkDestroyDynamicColorBlendState"));
+    if (UNLIKELY(!vtbl.DestroyDynamicColorBlendState)) {
+        ALOGE("missing device proc: %s", "vkDestroyDynamicColorBlendState");
+        success = false;
+    }
+    vtbl.CreateDynamicDepthStencilState = reinterpret_cast<PFN_vkCreateDynamicDepthStencilState>(get_proc_addr(device, "vkCreateDynamicDepthStencilState"));
+    if (UNLIKELY(!vtbl.CreateDynamicDepthStencilState)) {
+        ALOGE("missing device proc: %s", "vkCreateDynamicDepthStencilState");
+        success = false;
+    }
+    vtbl.DestroyDynamicDepthStencilState = reinterpret_cast<PFN_vkDestroyDynamicDepthStencilState>(get_proc_addr(device, "vkDestroyDynamicDepthStencilState"));
+    if (UNLIKELY(!vtbl.DestroyDynamicDepthStencilState)) {
+        ALOGE("missing device proc: %s", "vkDestroyDynamicDepthStencilState");
+        success = false;
+    }
+    vtbl.CreateFramebuffer = reinterpret_cast<PFN_vkCreateFramebuffer>(get_proc_addr(device, "vkCreateFramebuffer"));
+    if (UNLIKELY(!vtbl.CreateFramebuffer)) {
+        ALOGE("missing device proc: %s", "vkCreateFramebuffer");
+        success = false;
+    }
+    vtbl.DestroyFramebuffer = reinterpret_cast<PFN_vkDestroyFramebuffer>(get_proc_addr(device, "vkDestroyFramebuffer"));
+    if (UNLIKELY(!vtbl.DestroyFramebuffer)) {
+        ALOGE("missing device proc: %s", "vkDestroyFramebuffer");
+        success = false;
+    }
+    vtbl.CreateRenderPass = reinterpret_cast<PFN_vkCreateRenderPass>(get_proc_addr(device, "vkCreateRenderPass"));
+    if (UNLIKELY(!vtbl.CreateRenderPass)) {
+        ALOGE("missing device proc: %s", "vkCreateRenderPass");
+        success = false;
+    }
+    vtbl.DestroyRenderPass = reinterpret_cast<PFN_vkDestroyRenderPass>(get_proc_addr(device, "vkDestroyRenderPass"));
+    if (UNLIKELY(!vtbl.DestroyRenderPass)) {
+        ALOGE("missing device proc: %s", "vkDestroyRenderPass");
+        success = false;
+    }
+    vtbl.GetRenderAreaGranularity = reinterpret_cast<PFN_vkGetRenderAreaGranularity>(get_proc_addr(device, "vkGetRenderAreaGranularity"));
+    if (UNLIKELY(!vtbl.GetRenderAreaGranularity)) {
+        ALOGE("missing device proc: %s", "vkGetRenderAreaGranularity");
+        success = false;
+    }
+    vtbl.CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(get_proc_addr(device, "vkCreateCommandPool"));
+    if (UNLIKELY(!vtbl.CreateCommandPool)) {
+        ALOGE("missing device proc: %s", "vkCreateCommandPool");
+        success = false;
+    }
+    vtbl.DestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(get_proc_addr(device, "vkDestroyCommandPool"));
+    if (UNLIKELY(!vtbl.DestroyCommandPool)) {
+        ALOGE("missing device proc: %s", "vkDestroyCommandPool");
+        success = false;
+    }
+    vtbl.ResetCommandPool = reinterpret_cast<PFN_vkResetCommandPool>(get_proc_addr(device, "vkResetCommandPool"));
+    if (UNLIKELY(!vtbl.ResetCommandPool)) {
+        ALOGE("missing device proc: %s", "vkResetCommandPool");
+        success = false;
+    }
+    vtbl.CreateCommandBuffer = reinterpret_cast<PFN_vkCreateCommandBuffer>(get_proc_addr(device, "vkCreateCommandBuffer"));
+    if (UNLIKELY(!vtbl.CreateCommandBuffer)) {
+        ALOGE("missing device proc: %s", "vkCreateCommandBuffer");
+        success = false;
+    }
+    vtbl.DestroyCommandBuffer = reinterpret_cast<PFN_vkDestroyCommandBuffer>(get_proc_addr(device, "vkDestroyCommandBuffer"));
+    if (UNLIKELY(!vtbl.DestroyCommandBuffer)) {
+        ALOGE("missing device proc: %s", "vkDestroyCommandBuffer");
+        success = false;
+    }
+    vtbl.BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(get_proc_addr(device, "vkBeginCommandBuffer"));
+    if (UNLIKELY(!vtbl.BeginCommandBuffer)) {
+        ALOGE("missing device proc: %s", "vkBeginCommandBuffer");
+        success = false;
+    }
+    vtbl.EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(get_proc_addr(device, "vkEndCommandBuffer"));
+    if (UNLIKELY(!vtbl.EndCommandBuffer)) {
+        ALOGE("missing device proc: %s", "vkEndCommandBuffer");
+        success = false;
+    }
+    vtbl.ResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(get_proc_addr(device, "vkResetCommandBuffer"));
+    if (UNLIKELY(!vtbl.ResetCommandBuffer)) {
+        ALOGE("missing device proc: %s", "vkResetCommandBuffer");
+        success = false;
+    }
+    vtbl.CmdBindPipeline = reinterpret_cast<PFN_vkCmdBindPipeline>(get_proc_addr(device, "vkCmdBindPipeline"));
+    if (UNLIKELY(!vtbl.CmdBindPipeline)) {
+        ALOGE("missing device proc: %s", "vkCmdBindPipeline");
+        success = false;
+    }
+    vtbl.CmdBindDynamicViewportState = reinterpret_cast<PFN_vkCmdBindDynamicViewportState>(get_proc_addr(device, "vkCmdBindDynamicViewportState"));
+    if (UNLIKELY(!vtbl.CmdBindDynamicViewportState)) {
+        ALOGE("missing device proc: %s", "vkCmdBindDynamicViewportState");
+        success = false;
+    }
+    vtbl.CmdBindDynamicRasterState = reinterpret_cast<PFN_vkCmdBindDynamicRasterState>(get_proc_addr(device, "vkCmdBindDynamicRasterState"));
+    if (UNLIKELY(!vtbl.CmdBindDynamicRasterState)) {
+        ALOGE("missing device proc: %s", "vkCmdBindDynamicRasterState");
+        success = false;
+    }
+    vtbl.CmdBindDynamicColorBlendState = reinterpret_cast<PFN_vkCmdBindDynamicColorBlendState>(get_proc_addr(device, "vkCmdBindDynamicColorBlendState"));
+    if (UNLIKELY(!vtbl.CmdBindDynamicColorBlendState)) {
+        ALOGE("missing device proc: %s", "vkCmdBindDynamicColorBlendState");
+        success = false;
+    }
+    vtbl.CmdBindDynamicDepthStencilState = reinterpret_cast<PFN_vkCmdBindDynamicDepthStencilState>(get_proc_addr(device, "vkCmdBindDynamicDepthStencilState"));
+    if (UNLIKELY(!vtbl.CmdBindDynamicDepthStencilState)) {
+        ALOGE("missing device proc: %s", "vkCmdBindDynamicDepthStencilState");
+        success = false;
+    }
+    vtbl.CmdBindDescriptorSets = reinterpret_cast<PFN_vkCmdBindDescriptorSets>(get_proc_addr(device, "vkCmdBindDescriptorSets"));
+    if (UNLIKELY(!vtbl.CmdBindDescriptorSets)) {
+        ALOGE("missing device proc: %s", "vkCmdBindDescriptorSets");
+        success = false;
+    }
+    vtbl.CmdBindIndexBuffer = reinterpret_cast<PFN_vkCmdBindIndexBuffer>(get_proc_addr(device, "vkCmdBindIndexBuffer"));
+    if (UNLIKELY(!vtbl.CmdBindIndexBuffer)) {
+        ALOGE("missing device proc: %s", "vkCmdBindIndexBuffer");
+        success = false;
+    }
+    vtbl.CmdBindVertexBuffers = reinterpret_cast<PFN_vkCmdBindVertexBuffers>(get_proc_addr(device, "vkCmdBindVertexBuffers"));
+    if (UNLIKELY(!vtbl.CmdBindVertexBuffers)) {
+        ALOGE("missing device proc: %s", "vkCmdBindVertexBuffers");
+        success = false;
+    }
+    vtbl.CmdDraw = reinterpret_cast<PFN_vkCmdDraw>(get_proc_addr(device, "vkCmdDraw"));
+    if (UNLIKELY(!vtbl.CmdDraw)) {
+        ALOGE("missing device proc: %s", "vkCmdDraw");
+        success = false;
+    }
+    vtbl.CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(get_proc_addr(device, "vkCmdDrawIndexed"));
+    if (UNLIKELY(!vtbl.CmdDrawIndexed)) {
+        ALOGE("missing device proc: %s", "vkCmdDrawIndexed");
+        success = false;
+    }
+    vtbl.CmdDrawIndirect = reinterpret_cast<PFN_vkCmdDrawIndirect>(get_proc_addr(device, "vkCmdDrawIndirect"));
+    if (UNLIKELY(!vtbl.CmdDrawIndirect)) {
+        ALOGE("missing device proc: %s", "vkCmdDrawIndirect");
+        success = false;
+    }
+    vtbl.CmdDrawIndexedIndirect = reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(get_proc_addr(device, "vkCmdDrawIndexedIndirect"));
+    if (UNLIKELY(!vtbl.CmdDrawIndexedIndirect)) {
+        ALOGE("missing device proc: %s", "vkCmdDrawIndexedIndirect");
+        success = false;
+    }
+    vtbl.CmdDispatch = reinterpret_cast<PFN_vkCmdDispatch>(get_proc_addr(device, "vkCmdDispatch"));
+    if (UNLIKELY(!vtbl.CmdDispatch)) {
+        ALOGE("missing device proc: %s", "vkCmdDispatch");
+        success = false;
+    }
+    vtbl.CmdDispatchIndirect = reinterpret_cast<PFN_vkCmdDispatchIndirect>(get_proc_addr(device, "vkCmdDispatchIndirect"));
+    if (UNLIKELY(!vtbl.CmdDispatchIndirect)) {
+        ALOGE("missing device proc: %s", "vkCmdDispatchIndirect");
+        success = false;
+    }
+    vtbl.CmdCopyBuffer = reinterpret_cast<PFN_vkCmdCopyBuffer>(get_proc_addr(device, "vkCmdCopyBuffer"));
+    if (UNLIKELY(!vtbl.CmdCopyBuffer)) {
+        ALOGE("missing device proc: %s", "vkCmdCopyBuffer");
+        success = false;
+    }
+    vtbl.CmdCopyImage = reinterpret_cast<PFN_vkCmdCopyImage>(get_proc_addr(device, "vkCmdCopyImage"));
+    if (UNLIKELY(!vtbl.CmdCopyImage)) {
+        ALOGE("missing device proc: %s", "vkCmdCopyImage");
+        success = false;
+    }
+    vtbl.CmdBlitImage = reinterpret_cast<PFN_vkCmdBlitImage>(get_proc_addr(device, "vkCmdBlitImage"));
+    if (UNLIKELY(!vtbl.CmdBlitImage)) {
+        ALOGE("missing device proc: %s", "vkCmdBlitImage");
+        success = false;
+    }
+    vtbl.CmdCopyBufferToImage = reinterpret_cast<PFN_vkCmdCopyBufferToImage>(get_proc_addr(device, "vkCmdCopyBufferToImage"));
+    if (UNLIKELY(!vtbl.CmdCopyBufferToImage)) {
+        ALOGE("missing device proc: %s", "vkCmdCopyBufferToImage");
+        success = false;
+    }
+    vtbl.CmdCopyImageToBuffer = reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(get_proc_addr(device, "vkCmdCopyImageToBuffer"));
+    if (UNLIKELY(!vtbl.CmdCopyImageToBuffer)) {
+        ALOGE("missing device proc: %s", "vkCmdCopyImageToBuffer");
+        success = false;
+    }
+    vtbl.CmdUpdateBuffer = reinterpret_cast<PFN_vkCmdUpdateBuffer>(get_proc_addr(device, "vkCmdUpdateBuffer"));
+    if (UNLIKELY(!vtbl.CmdUpdateBuffer)) {
+        ALOGE("missing device proc: %s", "vkCmdUpdateBuffer");
+        success = false;
+    }
+    vtbl.CmdFillBuffer = reinterpret_cast<PFN_vkCmdFillBuffer>(get_proc_addr(device, "vkCmdFillBuffer"));
+    if (UNLIKELY(!vtbl.CmdFillBuffer)) {
+        ALOGE("missing device proc: %s", "vkCmdFillBuffer");
+        success = false;
+    }
+    vtbl.CmdClearColorImage = reinterpret_cast<PFN_vkCmdClearColorImage>(get_proc_addr(device, "vkCmdClearColorImage"));
+    if (UNLIKELY(!vtbl.CmdClearColorImage)) {
+        ALOGE("missing device proc: %s", "vkCmdClearColorImage");
+        success = false;
+    }
+    vtbl.CmdClearDepthStencilImage = reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(get_proc_addr(device, "vkCmdClearDepthStencilImage"));
+    if (UNLIKELY(!vtbl.CmdClearDepthStencilImage)) {
+        ALOGE("missing device proc: %s", "vkCmdClearDepthStencilImage");
+        success = false;
+    }
+    vtbl.CmdClearColorAttachment = reinterpret_cast<PFN_vkCmdClearColorAttachment>(get_proc_addr(device, "vkCmdClearColorAttachment"));
+    if (UNLIKELY(!vtbl.CmdClearColorAttachment)) {
+        ALOGE("missing device proc: %s", "vkCmdClearColorAttachment");
+        success = false;
+    }
+    vtbl.CmdClearDepthStencilAttachment = reinterpret_cast<PFN_vkCmdClearDepthStencilAttachment>(get_proc_addr(device, "vkCmdClearDepthStencilAttachment"));
+    if (UNLIKELY(!vtbl.CmdClearDepthStencilAttachment)) {
+        ALOGE("missing device proc: %s", "vkCmdClearDepthStencilAttachment");
+        success = false;
+    }
+    vtbl.CmdResolveImage = reinterpret_cast<PFN_vkCmdResolveImage>(get_proc_addr(device, "vkCmdResolveImage"));
+    if (UNLIKELY(!vtbl.CmdResolveImage)) {
+        ALOGE("missing device proc: %s", "vkCmdResolveImage");
+        success = false;
+    }
+    vtbl.CmdSetEvent = reinterpret_cast<PFN_vkCmdSetEvent>(get_proc_addr(device, "vkCmdSetEvent"));
+    if (UNLIKELY(!vtbl.CmdSetEvent)) {
+        ALOGE("missing device proc: %s", "vkCmdSetEvent");
+        success = false;
+    }
+    vtbl.CmdResetEvent = reinterpret_cast<PFN_vkCmdResetEvent>(get_proc_addr(device, "vkCmdResetEvent"));
+    if (UNLIKELY(!vtbl.CmdResetEvent)) {
+        ALOGE("missing device proc: %s", "vkCmdResetEvent");
+        success = false;
+    }
+    vtbl.CmdWaitEvents = reinterpret_cast<PFN_vkCmdWaitEvents>(get_proc_addr(device, "vkCmdWaitEvents"));
+    if (UNLIKELY(!vtbl.CmdWaitEvents)) {
+        ALOGE("missing device proc: %s", "vkCmdWaitEvents");
+        success = false;
+    }
+    vtbl.CmdPipelineBarrier = reinterpret_cast<PFN_vkCmdPipelineBarrier>(get_proc_addr(device, "vkCmdPipelineBarrier"));
+    if (UNLIKELY(!vtbl.CmdPipelineBarrier)) {
+        ALOGE("missing device proc: %s", "vkCmdPipelineBarrier");
+        success = false;
+    }
+    vtbl.CmdBeginQuery = reinterpret_cast<PFN_vkCmdBeginQuery>(get_proc_addr(device, "vkCmdBeginQuery"));
+    if (UNLIKELY(!vtbl.CmdBeginQuery)) {
+        ALOGE("missing device proc: %s", "vkCmdBeginQuery");
+        success = false;
+    }
+    vtbl.CmdEndQuery = reinterpret_cast<PFN_vkCmdEndQuery>(get_proc_addr(device, "vkCmdEndQuery"));
+    if (UNLIKELY(!vtbl.CmdEndQuery)) {
+        ALOGE("missing device proc: %s", "vkCmdEndQuery");
+        success = false;
+    }
+    vtbl.CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(get_proc_addr(device, "vkCmdResetQueryPool"));
+    if (UNLIKELY(!vtbl.CmdResetQueryPool)) {
+        ALOGE("missing device proc: %s", "vkCmdResetQueryPool");
+        success = false;
+    }
+    vtbl.CmdWriteTimestamp = reinterpret_cast<PFN_vkCmdWriteTimestamp>(get_proc_addr(device, "vkCmdWriteTimestamp"));
+    if (UNLIKELY(!vtbl.CmdWriteTimestamp)) {
+        ALOGE("missing device proc: %s", "vkCmdWriteTimestamp");
+        success = false;
+    }
+    vtbl.CmdCopyQueryPoolResults = reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(get_proc_addr(device, "vkCmdCopyQueryPoolResults"));
+    if (UNLIKELY(!vtbl.CmdCopyQueryPoolResults)) {
+        ALOGE("missing device proc: %s", "vkCmdCopyQueryPoolResults");
+        success = false;
+    }
+    vtbl.CmdPushConstants = reinterpret_cast<PFN_vkCmdPushConstants>(get_proc_addr(device, "vkCmdPushConstants"));
+    if (UNLIKELY(!vtbl.CmdPushConstants)) {
+        ALOGE("missing device proc: %s", "vkCmdPushConstants");
+        success = false;
+    }
+    vtbl.CmdBeginRenderPass = reinterpret_cast<PFN_vkCmdBeginRenderPass>(get_proc_addr(device, "vkCmdBeginRenderPass"));
+    if (UNLIKELY(!vtbl.CmdBeginRenderPass)) {
+        ALOGE("missing device proc: %s", "vkCmdBeginRenderPass");
+        success = false;
+    }
+    vtbl.CmdNextSubpass = reinterpret_cast<PFN_vkCmdNextSubpass>(get_proc_addr(device, "vkCmdNextSubpass"));
+    if (UNLIKELY(!vtbl.CmdNextSubpass)) {
+        ALOGE("missing device proc: %s", "vkCmdNextSubpass");
+        success = false;
+    }
+    vtbl.CmdEndRenderPass = reinterpret_cast<PFN_vkCmdEndRenderPass>(get_proc_addr(device, "vkCmdEndRenderPass"));
+    if (UNLIKELY(!vtbl.CmdEndRenderPass)) {
+        ALOGE("missing device proc: %s", "vkCmdEndRenderPass");
+        success = false;
+    }
+    vtbl.CmdExecuteCommands = reinterpret_cast<PFN_vkCmdExecuteCommands>(get_proc_addr(device, "vkCmdExecuteCommands"));
+    if (UNLIKELY(!vtbl.CmdExecuteCommands)) {
+        ALOGE("missing device proc: %s", "vkCmdExecuteCommands");
+        success = false;
+    }
+    // clang-format on
+    return success;
+}
+
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/get_proc_addr.cpp.tmpl b/vulkan/libvulkan/get_proc_addr.cpp.tmpl
new file mode 100644
index 0000000..d4ced56
--- /dev/null
+++ b/vulkan/libvulkan/get_proc_addr.cpp.tmpl
@@ -0,0 +1,180 @@
+{{Include "../api/templates/vulkan_common.tmpl"}}
+{{Global "clang-format" (Strings "clang-format" "-style=file")}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "get_proc_addr.cpp" | Format (Global "clang-format") | Write "get_proc_addr.cpp"}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Entry point
+-------------------------------------------------------------------------------
+*/}}
+{{define "get_proc_addr.cpp"}}
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */

+// This file is generated. Do not edit manually!
+// To regenerate: $ apic template ../api/vulkan.api get_proc_addr.cpp.tmpl
+// Requires apic from https://android.googlesource.com/platform/tools/gpu/.

+#include <algorithm>
+#include <log/log.h>
+#include "loader.h"
+using namespace vulkan;

+#define UNLIKELY(expr) __builtin_expect((expr), 0)

+namespace {

+struct NameProcEntry {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};

+struct NameOffsetEntry {
+    const char* name;
+    size_t offset;
+};

+template <typename TEntry, size_t N>
+const TEntry* FindProcEntry(const TEntry(&table)[N], const char* name) {
+    auto entry = std::lower_bound(
+        table, table + N, name,
+        [](const TEntry& e, const char* n) { return strcmp(e.name, n) < 0; });
+    if (entry != (table + N) && strcmp(entry->name, name) == 0)
+        return entry;
+    return nullptr;
+}

+const NameProcEntry kInstanceProcTbl[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if eq (Macro "Vtbl" $f) "Instance"}}
+      {"{{Macro "FunctionName" $f}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "FunctionName" $f}})},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+const NameProcEntry kDeviceProcTbl[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if eq (Macro "Vtbl" $f) "Device"}}
+      {"{{Macro "FunctionName" $f}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "FunctionName" $f}})},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+const NameOffsetEntry kInstanceOffsetTbl[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if eq (Macro "Vtbl" $f) "Instance"}}
+      {"{{Macro "FunctionName" $f}}", offsetof(InstanceVtbl, {{TrimPrefix "vk" (Macro "FunctionName" $f)}})},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+const NameOffsetEntry kDeviceOffsetTbl[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if eq (Macro "Vtbl" $f) "Device"}}
+      {"{{Macro "FunctionName" $f}}", offsetof(DeviceVtbl, {{TrimPrefix "vk" (Macro "FunctionName" $f)}})},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+} // namespace

+namespace vulkan {

+PFN_vkVoidFunction GetGlobalInstanceProcAddr(const char* name) {
+    if (strcmp(name, "vkGetDeviceProcAddr") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr);
+    const NameProcEntry* entry = FindProcEntry(kInstanceProcTbl, name);
+    return entry ? entry->proc : nullptr;
+}

+PFN_vkVoidFunction GetGlobalDeviceProcAddr(const char* name) {
+    const NameProcEntry* entry = FindProcEntry(kDeviceProcTbl, name);
+    return entry ? entry->proc : nullptr;
+}

+PFN_vkVoidFunction GetSpecificInstanceProcAddr(const InstanceVtbl* vtbl,
+                                               const char* name) {
+    const NameOffsetEntry* entry = FindProcEntry(kInstanceOffsetTbl, name);
+    if (!entry)
+        return nullptr;
+    const unsigned char* base = reinterpret_cast<const unsigned char*>(vtbl);
+    return reinterpret_cast<PFN_vkVoidFunction>(
+        const_cast<unsigned char*>(base) + entry->offset);
+}

+PFN_vkVoidFunction GetSpecificDeviceProcAddr(const DeviceVtbl* vtbl,
+                                             const char* name) {
+    const NameOffsetEntry* entry = FindProcEntry(kDeviceOffsetTbl, name);
+    if (!entry)
+        return nullptr;
+    const unsigned char* base = reinterpret_cast<const unsigned char*>(vtbl);
+    return reinterpret_cast<PFN_vkVoidFunction>(
+        const_cast<unsigned char*>(base) + entry->offset);
+}

+bool LoadInstanceVtbl(VkInstance instance,
+                      PFN_vkGetInstanceProcAddr get_proc_addr,
+                      InstanceVtbl& vtbl) {«
+    bool success = true;
+    // clang-format off
+    {{range $f := AllCommands $}}
+      {{if eq (Macro "Vtbl" $f) "Instance"}}
+    vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}} = §
+        reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
+            get_proc_addr(instance, "{{Macro "FunctionName" $f}}"));
+    if (UNLIKELY(!vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}})) {
+        ALOGE("missing instance proc: %s", "{{Macro "FunctionName" $f}}");
+        success = false;
+    }
+      {{end}}
+    {{end}}
+    // clang-format on
+    return success;
+»}

+bool LoadDeviceVtbl(VkDevice device,
+                    PFN_vkGetDeviceProcAddr get_proc_addr,
+                    DeviceVtbl& vtbl) {«
+    bool success = true;
+    // clang-format off
+    {{range $f := AllCommands $}}
+      {{if eq (Macro "Vtbl" $f) "Device"}}
+    vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}} = §
+        reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
+            get_proc_addr(device, "{{Macro "FunctionName" $f}}"));
+    if (UNLIKELY(!vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}})) {
+        ALOGE("missing device proc: %s", "{{Macro "FunctionName" $f}}");
+        success = false;
+    }
+      {{end}}
+    {{end}}
+    // clang-format on
+    return success;
+»}

+} // namespace vulkan

+{{end}}
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
new file mode 100644
index 0000000..a99e90a
--- /dev/null
+++ b/vulkan/libvulkan/loader.cpp
@@ -0,0 +1,532 @@
+// module header
+#include "loader.h"
+// standard C headers
+#include <inttypes.h>
+#include <malloc.h>
+#include <pthread.h>
+#include <string.h>
+// standard C++ headers
+#include <algorithm>
+#include <mutex>
+// platform/library headers
+#include <hardware/hwvulkan.h>
+#include <log/log.h>
+
+using namespace vulkan;
+
+static const uint32_t kMaxPhysicalDevices = 4;
+
+struct VkInstance_T {
+    VkInstance_T(const VkAllocCallbacks* alloc_callbacks)
+        : vtbl(&vtbl_storage), alloc(alloc_callbacks), num_physical_devices(0) {
+        memset(&vtbl_storage, 0, sizeof(vtbl_storage));
+        memset(physical_devices, 0, sizeof(physical_devices));
+        memset(&drv.vtbl, 0, sizeof(drv.vtbl));
+        drv.GetDeviceProcAddr = nullptr;
+        drv.num_physical_devices = 0;
+    }
+
+    InstanceVtbl* vtbl;
+    InstanceVtbl vtbl_storage;
+
+    const VkAllocCallbacks* alloc;
+    uint32_t num_physical_devices;
+    VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
+
+    struct Driver {
+        // Pointers to driver entry points. Used explicitly by the loader; not
+        // set as the dispatch table for any objects.
+        InstanceVtbl vtbl;
+
+        // Pointer to the driver's get_device_proc_addr, must be valid for any
+        // of the driver's physical devices. Not part of the InstanceVtbl since
+        // it's not an Instance/PhysicalDevice function.
+        PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+
+        // Number of physical devices owned by this driver.
+        uint32_t num_physical_devices;
+    } drv;  // may eventually be an array
+};
+
+// -----------------------------------------------------------------------------
+
+namespace {
+
+typedef VkInstance_T Instance;
+
+struct Device {
+    Device(const VkAllocCallbacks* alloc_callbacks) : alloc(alloc_callbacks) {
+        memset(&vtbl_storage, 0, sizeof(vtbl_storage));
+        vtbl_storage.device = this;
+    }
+    DeviceVtbl vtbl_storage;
+    const VkAllocCallbacks* alloc;
+};
+
+// -----------------------------------------------------------------------------
+// Utility Code
+
+inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
+    return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
+}
+
+inline const DeviceVtbl* GetVtbl(VkDevice device) {
+    return *reinterpret_cast<DeviceVtbl**>(device);
+}
+
+void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocType) {
+    return memalign(alignment, size);
+}
+
+void DefaultFree(void*, void* pMem) {
+    free(pMem);
+}
+
+const VkAllocCallbacks kDefaultAllocCallbacks = {
+    .pUserData = nullptr,
+    .pfnAlloc = DefaultAlloc,
+    .pfnFree = DefaultFree,
+};
+
+hwvulkan_device_t* g_hwdevice;
+bool EnsureInitialized() {
+    static std::once_flag once_flag;
+    static const hwvulkan_module_t* module;
+
+    std::call_once(once_flag, []() {
+        int result;
+        result = hw_get_module("vulkan",
+                               reinterpret_cast<const hw_module_t**>(&module));
+        if (result != 0) {
+            ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
+                  result);
+            return;
+        }
+        result = module->common.methods->open(
+            &module->common, HWVULKAN_DEVICE_0,
+            reinterpret_cast<hw_device_t**>(&g_hwdevice));
+        if (result != 0) {
+            ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
+                  result);
+            module = nullptr;
+            return;
+        }
+    });
+
+    return module != nullptr && g_hwdevice != nullptr;
+}
+
+void DestroyDevice(Device* device) {
+    const VkAllocCallbacks* alloc = device->alloc;
+    device->~Device();
+    alloc->pfnFree(alloc->pUserData, device);
+}
+
+// -----------------------------------------------------------------------------
+// "Bottom" functions. These are called at the end of the instance dispatch
+// chain.
+
+VkResult DestroyInstanceBottom(VkInstance instance) {
+    // These checks allow us to call DestroyInstanceBottom from any error path
+    // in CreateInstanceBottom, before the driver instance is fully initialized.
+    if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
+        instance->drv.vtbl.DestroyInstance) {
+        instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance);
+    }
+    const VkAllocCallbacks* alloc = instance->alloc;
+    instance->~VkInstance_T();
+    alloc->pfnFree(alloc->pUserData, instance);
+    return VK_SUCCESS;
+}
+
+VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
+                              VkInstance* instance_ptr) {
+    Instance* instance = *instance_ptr;
+    VkResult result;
+
+    result =
+        g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
+    if (result != VK_SUCCESS) {
+        DestroyInstanceBottom(instance);
+        return result;
+    }
+
+    if (!LoadInstanceVtbl(instance->drv.vtbl.instance,
+                          g_hwdevice->GetInstanceProcAddr,
+                          instance->drv.vtbl)) {
+        DestroyInstanceBottom(instance);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
+    // queryable from the Instance, and that the resulting function work for any
+    // VkDevice created from the instance.
+    instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+        g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
+                                        "vkGetDeviceProcAddr"));
+    if (!instance->drv.GetDeviceProcAddr) {
+        ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
+        DestroyInstanceBottom(instance);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    hwvulkan_dispatch_t* dispatch =
+        reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
+    if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
+        // Skip setting dispatch->vtbl on the driver instance handle, since we
+        // never intentionally call through it; we go through Instance::drv.vtbl
+        // instead.
+    } else {
+        ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
+              dispatch->magic);
+        DestroyInstanceBottom(instance);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    uint32_t num_physical_devices = 0;
+    result = instance->drv.vtbl.EnumeratePhysicalDevices(
+        instance->drv.vtbl.instance, &num_physical_devices, nullptr);
+    if (result != VK_SUCCESS) {
+        DestroyInstanceBottom(instance);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
+    result = instance->drv.vtbl.EnumeratePhysicalDevices(
+        instance->drv.vtbl.instance, &num_physical_devices,
+        instance->physical_devices);
+    if (result != VK_SUCCESS) {
+        DestroyInstanceBottom(instance);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    for (uint32_t i = 0; i < num_physical_devices; i++) {
+        dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
+            instance->physical_devices[i]);
+        if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
+            ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
+                  dispatch->magic);
+            DestroyInstanceBottom(instance);
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+        dispatch->vtbl = instance->vtbl;
+    }
+    instance->drv.num_physical_devices = num_physical_devices;
+
+    instance->num_physical_devices = instance->drv.num_physical_devices;
+    return VK_SUCCESS;
+}
+
+VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
+                                        uint32_t* pdev_count,
+                                        VkPhysicalDevice* pdevs) {
+    uint32_t count = instance->num_physical_devices;
+    if (pdevs) {
+        count = std::min(count, *pdev_count);
+        std::copy(instance->physical_devices,
+                  instance->physical_devices + count, pdevs);
+    }
+    *pdev_count = count;
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
+                                         VkPhysicalDeviceFeatures* features) {
+    return GetVtbl(pdev)
+        ->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
+}
+
+VkResult GetPhysicalDeviceFormatPropertiesBottom(
+    VkPhysicalDevice pdev,
+    VkFormat format,
+    VkFormatProperties* properties) {
+    return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
+        pdev, format, properties);
+}
+
+VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
+    VkPhysicalDevice pdev,
+    VkFormat format,
+    VkImageType type,
+    VkImageTiling tiling,
+    VkImageUsageFlags usage,
+    VkImageFormatProperties* properties) {
+    return GetVtbl(pdev)
+        ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
+            pdev, format, type, tiling, usage, properties);
+}
+
+VkResult GetPhysicalDeviceLimitsBottom(VkPhysicalDevice pdev,
+                                       VkPhysicalDeviceLimits* limits) {
+    return GetVtbl(pdev)
+        ->instance->drv.vtbl.GetPhysicalDeviceLimits(pdev, limits);
+}
+
+VkResult GetPhysicalDevicePropertiesBottom(
+    VkPhysicalDevice pdev,
+    VkPhysicalDeviceProperties* properties) {
+    return GetVtbl(pdev)
+        ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
+}
+
+VkResult GetPhysicalDeviceQueueCountBottom(VkPhysicalDevice pdev,
+                                           uint32_t* count) {
+    return GetVtbl(pdev)
+        ->instance->drv.vtbl.GetPhysicalDeviceQueueCount(pdev, count);
+}
+
+VkResult GetPhysicalDeviceQueuePropertiesBottom(
+    VkPhysicalDevice pdev,
+    uint32_t count,
+    VkPhysicalDeviceQueueProperties* properties) {
+    return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueProperties(
+        pdev, count, properties);
+}
+
+VkResult GetPhysicalDeviceMemoryPropertiesBottom(
+    VkPhysicalDevice pdev,
+    VkPhysicalDeviceMemoryProperties* properties) {
+    return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
+        pdev, properties);
+}
+
+VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
+                            const VkDeviceCreateInfo* create_info,
+                            VkDevice* out_device) {
+    const Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
+    VkResult result;
+
+    void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
+                                         sizeof(Device), alignof(Device),
+                                         VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+    if (!mem)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    Device* device = new (mem) Device(instance.alloc);
+
+    VkDevice drv_device;
+    result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
+    if (result != VK_SUCCESS) {
+        DestroyDevice(device);
+        return result;
+    }
+
+    if (!LoadDeviceVtbl(drv_device, instance.drv.GetDeviceProcAddr,
+                        device->vtbl_storage)) {
+        if (device->vtbl_storage.DestroyDevice)
+            device->vtbl_storage.DestroyDevice(drv_device);
+        DestroyDevice(device);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    hwvulkan_dispatch_t* dispatch =
+        reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
+    if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
+        ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
+        device->vtbl_storage.DestroyDevice(drv_device);
+        DestroyDevice(device);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    dispatch->vtbl = &device->vtbl_storage;
+
+    // TODO: insert device layer entry points into device->vtbl_storage here?
+
+    *out_device = drv_device;
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceExtensionPropertiesBottom(
+    VkPhysicalDevice pdev,
+    const char* layer_name,
+    uint32_t* properties_count,
+    VkExtensionProperties* properties) {
+    // TODO: what are we supposed to do with layer_name here?
+    return GetVtbl(pdev)
+        ->instance->drv.vtbl.GetPhysicalDeviceExtensionProperties(
+            pdev, layer_name, properties_count, properties);
+}
+
+VkResult GetPhysicalDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
+                                                uint32_t* properties_count,
+                                                VkLayerProperties* properties) {
+    return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceLayerProperties(
+        pdev, properties_count, properties);
+}
+
+VkResult GetPhysicalDeviceSparseImageFormatPropertiesBottom(
+    VkPhysicalDevice pdev,
+    VkFormat format,
+    VkImageType type,
+    uint32_t samples,
+    VkImageUsageFlags usage,
+    VkImageTiling tiling,
+    uint32_t* properties_count,
+    VkSparseImageFormatProperties* properties) {
+    return GetVtbl(pdev)
+        ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
+            pdev, format, type, samples, usage, tiling, properties_count,
+            properties);
+}
+
+PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
+
+const InstanceVtbl kBottomInstanceFunctions = {
+    // clang-format off
+    .instance = nullptr,
+    .CreateInstance = CreateInstanceBottom,
+    .DestroyInstance = DestroyInstanceBottom,
+    .GetInstanceProcAddr = GetInstanceProcAddrBottom,
+    .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
+    .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
+    .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
+    .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
+    .GetPhysicalDeviceLimits = GetPhysicalDeviceLimitsBottom,
+    .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
+    .GetPhysicalDeviceQueueCount = GetPhysicalDeviceQueueCountBottom,
+    .GetPhysicalDeviceQueueProperties = GetPhysicalDeviceQueuePropertiesBottom,
+    .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
+    .CreateDevice = CreateDeviceBottom,
+    .GetPhysicalDeviceExtensionProperties = GetPhysicalDeviceExtensionPropertiesBottom,
+    .GetPhysicalDeviceLayerProperties = GetPhysicalDeviceLayerPropertiesBottom,
+    .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
+    // clang-format on
+};
+
+PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
+    // The bottom GetInstanceProcAddr is only called by the innermost layer,
+    // when there is one, when it initializes its own dispatch table.
+    return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
+}
+
+}  // namespace
+
+// -----------------------------------------------------------------------------
+// Global functions. These are called directly from the loader entry points,
+// without going through a dispatch table.
+
+namespace vulkan {
+
+VkResult GetGlobalExtensionProperties(const char* /*layer_name*/,
+                                      uint32_t* count,
+                                      VkExtensionProperties* /*properties*/) {
+    if (!count)
+        return VK_ERROR_INVALID_POINTER;
+    if (!EnsureInitialized())
+        return VK_ERROR_UNAVAILABLE;
+
+    // TODO: not yet implemented
+    ALOGW("vkGetGlobalExtensionProperties not implemented");
+
+    *count = 0;
+    return VK_SUCCESS;
+}
+
+VkResult GetGlobalLayerProperties(uint32_t* count,
+                                  VkLayerProperties* /*properties*/) {
+    if (!count)
+        return VK_ERROR_INVALID_POINTER;
+    if (!EnsureInitialized())
+        return VK_ERROR_UNAVAILABLE;
+
+    // TODO: not yet implemented
+    ALOGW("vkGetGlobalLayerProperties not implemented");
+
+    *count = 0;
+    return VK_SUCCESS;
+}
+
+VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+                        VkInstance* out_instance) {
+    VkResult result;
+
+    if (!EnsureInitialized())
+        return VK_ERROR_UNAVAILABLE;
+
+    VkInstanceCreateInfo local_create_info = *create_info;
+    if (!local_create_info.pAllocCb)
+        local_create_info.pAllocCb = &kDefaultAllocCallbacks;
+    create_info = &local_create_info;
+
+    void* instance_mem = create_info->pAllocCb->pfnAlloc(
+        create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
+        VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+    if (!instance_mem)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
+
+    instance->vtbl_storage = kBottomInstanceFunctions;
+    instance->vtbl_storage.instance = instance;
+
+    // TODO: Insert enabled layers into instance->dispatch_vtbl here.
+
+    // TODO: We'll want to call CreateInstance through the dispatch table
+    // instead of calling the loader's terminator
+    *out_instance = instance;
+    result = CreateInstanceBottom(create_info, out_instance);
+    if (result <= 0) {
+        // For every layer, including the loader top and bottom layers:
+        // - If a call to the next CreateInstance fails, the layer must clean
+        //   up anything it has successfully done so far, and propagate the
+        //   error upwards.
+        // - If a layer successfully calls the next layer's CreateInstance, and
+        //   afterwards must fail for some reason, it must call the next layer's
+        //   DestroyInstance before returning.
+        // - The layer must not call the next layer's DestroyInstance if that
+        //   layer's CreateInstance wasn't called, or returned failure.
+
+        // On failure, CreateInstanceBottom frees the instance struct, so it's
+        // already gone at this point. Nothing to do.
+    }
+
+    return result;
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
+    if (!instance)
+        return GetGlobalInstanceProcAddr(name);
+    // For special-case functions we always return the loader entry
+    if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
+        strcmp(name, "vkGetDeviceProcAddr") == 0) {
+        return GetGlobalInstanceProcAddr(name);
+    }
+    return GetSpecificInstanceProcAddr(instance->vtbl, name);
+}
+
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
+    if (!device)
+        return GetGlobalDeviceProcAddr(name);
+    // For special-case functions we always return the loader entry
+    if (strcmp(name, "vkGetDeviceQueue") == 0 ||
+        strcmp(name, "vkDestroyDevice") == 0) {
+        return GetGlobalDeviceProcAddr(name);
+    }
+    return GetSpecificDeviceProcAddr(GetVtbl(device), name);
+}
+
+VkResult GetDeviceQueue(VkDevice drv_device,
+                        uint32_t family,
+                        uint32_t index,
+                        VkQueue* out_queue) {
+    VkResult result;
+    VkQueue queue;
+    const DeviceVtbl* vtbl = GetVtbl(drv_device);
+    result = vtbl->GetDeviceQueue(drv_device, family, index, &queue);
+    if (result != VK_SUCCESS)
+        return result;
+    hwvulkan_dispatch_t* dispatch =
+        reinterpret_cast<hwvulkan_dispatch_t*>(queue);
+    if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != &vtbl) {
+        ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    dispatch->vtbl = vtbl;
+    *out_queue = queue;
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDevice(VkDevice drv_device) {
+    const DeviceVtbl* vtbl = GetVtbl(drv_device);
+    Device* device = static_cast<Device*>(vtbl->device);
+    vtbl->DestroyDevice(drv_device);
+    DestroyDevice(device);
+    return VK_SUCCESS;
+}
+
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
new file mode 100644
index 0000000..1f6a1d4
--- /dev/null
+++ b/vulkan/libvulkan/loader.h
@@ -0,0 +1,211 @@
+#ifndef LIBVULKAN_LOADER_H
+#define LIBVULKAN_LOADER_H 1
+
+#define VK_PROTOTYPES
+#include <vulkan/vulkan.h>
+
+namespace vulkan {
+
+struct InstanceVtbl {
+    // clang-format off
+    VkInstance instance;
+
+    PFN_vkCreateInstance CreateInstance;
+    PFN_vkDestroyInstance DestroyInstance;
+    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+    PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+
+    PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+    PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
+    PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
+    PFN_vkGetPhysicalDeviceLimits GetPhysicalDeviceLimits;
+    PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
+    PFN_vkGetPhysicalDeviceQueueCount GetPhysicalDeviceQueueCount;
+    PFN_vkGetPhysicalDeviceQueueProperties GetPhysicalDeviceQueueProperties;
+    PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
+    PFN_vkCreateDevice CreateDevice;
+    PFN_vkGetPhysicalDeviceExtensionProperties GetPhysicalDeviceExtensionProperties;
+    PFN_vkGetPhysicalDeviceLayerProperties GetPhysicalDeviceLayerProperties;
+    PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+    // clang-format on
+};
+
+struct DeviceVtbl {
+    void* device;
+
+    PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+    PFN_vkDestroyDevice DestroyDevice;
+    PFN_vkGetDeviceQueue GetDeviceQueue;
+    PFN_vkDeviceWaitIdle DeviceWaitIdle;
+    PFN_vkAllocMemory AllocMemory;
+    PFN_vkFreeMemory FreeMemory;
+    PFN_vkMapMemory MapMemory;
+    PFN_vkUnmapMemory UnmapMemory;
+    PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges;
+    PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges;
+    PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment;
+    PFN_vkBindBufferMemory BindBufferMemory;
+    PFN_vkBindImageMemory BindImageMemory;
+    PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
+    PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
+    PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements;
+    PFN_vkCreateFence CreateFence;
+    PFN_vkDestroyFence DestroyFence;
+    PFN_vkResetFences ResetFences;
+    PFN_vkGetFenceStatus GetFenceStatus;
+    PFN_vkWaitForFences WaitForFences;
+    PFN_vkCreateSemaphore CreateSemaphore;
+    PFN_vkDestroySemaphore DestroySemaphore;
+    PFN_vkCreateEvent CreateEvent;
+    PFN_vkDestroyEvent DestroyEvent;
+    PFN_vkGetEventStatus GetEventStatus;
+    PFN_vkSetEvent SetEvent;
+    PFN_vkResetEvent ResetEvent;
+    PFN_vkCreateQueryPool CreateQueryPool;
+    PFN_vkDestroyQueryPool DestroyQueryPool;
+    PFN_vkGetQueryPoolResults GetQueryPoolResults;
+    PFN_vkCreateBuffer CreateBuffer;
+    PFN_vkDestroyBuffer DestroyBuffer;
+    PFN_vkCreateBufferView CreateBufferView;
+    PFN_vkDestroyBufferView DestroyBufferView;
+    PFN_vkCreateImage CreateImage;
+    PFN_vkDestroyImage DestroyImage;
+    PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
+    PFN_vkCreateImageView CreateImageView;
+    PFN_vkDestroyImageView DestroyImageView;
+    PFN_vkCreateAttachmentView CreateAttachmentView;
+    PFN_vkDestroyAttachmentView DestroyAttachmentView;
+    PFN_vkCreateShaderModule CreateShaderModule;
+    PFN_vkDestroyShaderModule DestroyShaderModule;
+    PFN_vkCreateShader CreateShader;
+    PFN_vkDestroyShader DestroyShader;
+    PFN_vkCreatePipelineCache CreatePipelineCache;
+    PFN_vkDestroyPipelineCache DestroyPipelineCache;
+    PFN_vkGetPipelineCacheSize GetPipelineCacheSize;
+    PFN_vkGetPipelineCacheData GetPipelineCacheData;
+    PFN_vkMergePipelineCaches MergePipelineCaches;
+    PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines;
+    PFN_vkCreateComputePipelines CreateComputePipelines;
+    PFN_vkDestroyPipeline DestroyPipeline;
+    PFN_vkCreatePipelineLayout CreatePipelineLayout;
+    PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
+    PFN_vkCreateSampler CreateSampler;
+    PFN_vkDestroySampler DestroySampler;
+    PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
+    PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
+    PFN_vkCreateDescriptorPool CreateDescriptorPool;
+    PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
+    PFN_vkResetDescriptorPool ResetDescriptorPool;
+    PFN_vkAllocDescriptorSets AllocDescriptorSets;
+    PFN_vkFreeDescriptorSets FreeDescriptorSets;
+    PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
+    PFN_vkCreateDynamicViewportState CreateDynamicViewportState;
+    PFN_vkDestroyDynamicViewportState DestroyDynamicViewportState;
+    PFN_vkCreateDynamicRasterState CreateDynamicRasterState;
+    PFN_vkDestroyDynamicRasterState DestroyDynamicRasterState;
+    PFN_vkCreateDynamicColorBlendState CreateDynamicColorBlendState;
+    PFN_vkDestroyDynamicColorBlendState DestroyDynamicColorBlendState;
+    PFN_vkCreateDynamicDepthStencilState CreateDynamicDepthStencilState;
+    PFN_vkDestroyDynamicDepthStencilState DestroyDynamicDepthStencilState;
+    PFN_vkCreateFramebuffer CreateFramebuffer;
+    PFN_vkDestroyFramebuffer DestroyFramebuffer;
+    PFN_vkCreateRenderPass CreateRenderPass;
+    PFN_vkDestroyRenderPass DestroyRenderPass;
+    PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
+    PFN_vkCreateCommandPool CreateCommandPool;
+    PFN_vkDestroyCommandPool DestroyCommandPool;
+    PFN_vkResetCommandPool ResetCommandPool;
+    PFN_vkCreateCommandBuffer CreateCommandBuffer;
+    PFN_vkDestroyCommandBuffer DestroyCommandBuffer;
+
+    PFN_vkQueueSubmit QueueSubmit;
+    PFN_vkQueueWaitIdle QueueWaitIdle;
+    PFN_vkQueueBindSparseBufferMemory QueueBindSparseBufferMemory;
+    PFN_vkQueueBindSparseImageOpaqueMemory QueueBindSparseImageOpaqueMemory;
+    PFN_vkQueueBindSparseImageMemory QueueBindSparseImageMemory;
+    PFN_vkQueueSignalSemaphore QueueSignalSemaphore;
+    PFN_vkQueueWaitSemaphore QueueWaitSemaphore;
+
+    PFN_vkBeginCommandBuffer BeginCommandBuffer;
+    PFN_vkEndCommandBuffer EndCommandBuffer;
+    PFN_vkResetCommandBuffer ResetCommandBuffer;
+    PFN_vkCmdBindPipeline CmdBindPipeline;
+    PFN_vkCmdBindDynamicViewportState CmdBindDynamicViewportState;
+    PFN_vkCmdBindDynamicRasterState CmdBindDynamicRasterState;
+    PFN_vkCmdBindDynamicColorBlendState CmdBindDynamicColorBlendState;
+    PFN_vkCmdBindDynamicDepthStencilState CmdBindDynamicDepthStencilState;
+    PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+    PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+    PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+    PFN_vkCmdDraw CmdDraw;
+    PFN_vkCmdDrawIndexed CmdDrawIndexed;
+    PFN_vkCmdDrawIndirect CmdDrawIndirect;
+    PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect;
+    PFN_vkCmdDispatch CmdDispatch;
+    PFN_vkCmdDispatchIndirect CmdDispatchIndirect;
+    PFN_vkCmdCopyBuffer CmdCopyBuffer;
+    PFN_vkCmdCopyImage CmdCopyImage;
+    PFN_vkCmdBlitImage CmdBlitImage;
+    PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
+    PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer;
+    PFN_vkCmdUpdateBuffer CmdUpdateBuffer;
+    PFN_vkCmdFillBuffer CmdFillBuffer;
+    PFN_vkCmdClearColorImage CmdClearColorImage;
+    PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage;
+    PFN_vkCmdClearColorAttachment CmdClearColorAttachment;
+    PFN_vkCmdClearDepthStencilAttachment CmdClearDepthStencilAttachment;
+    PFN_vkCmdResolveImage CmdResolveImage;
+    PFN_vkCmdSetEvent CmdSetEvent;
+    PFN_vkCmdResetEvent CmdResetEvent;
+    PFN_vkCmdWaitEvents CmdWaitEvents;
+    PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
+    PFN_vkCmdBeginQuery CmdBeginQuery;
+    PFN_vkCmdEndQuery CmdEndQuery;
+    PFN_vkCmdResetQueryPool CmdResetQueryPool;
+    PFN_vkCmdWriteTimestamp CmdWriteTimestamp;
+    PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults;
+    PFN_vkCmdPushConstants CmdPushConstants;
+    PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+    PFN_vkCmdNextSubpass CmdNextSubpass;
+    PFN_vkCmdEndRenderPass CmdEndRenderPass;
+    PFN_vkCmdExecuteCommands CmdExecuteCommands;
+};
+
+// -----------------------------------------------------------------------------
+// loader.cpp
+
+VkResult GetGlobalExtensionProperties(const char* layer_name,
+                                      uint32_t* count,
+                                      VkExtensionProperties* properties);
+VkResult GetGlobalLayerProperties(uint32_t* count,
+                                  VkLayerProperties* properties);
+VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+                        VkInstance* instance);
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name);
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice drv_device, const char* name);
+VkResult GetDeviceQueue(VkDevice drv_device,
+                        uint32_t family,
+                        uint32_t index,
+                        VkQueue* out_queue);
+VkResult DestroyDevice(VkDevice drv_device);
+
+// -----------------------------------------------------------------------------
+// get_proc_addr.cpp
+
+PFN_vkVoidFunction GetGlobalInstanceProcAddr(const char* name);
+PFN_vkVoidFunction GetGlobalDeviceProcAddr(const char* name);
+PFN_vkVoidFunction GetSpecificInstanceProcAddr(const InstanceVtbl* vtbl,
+                                               const char* name);
+PFN_vkVoidFunction GetSpecificDeviceProcAddr(const DeviceVtbl* vtbl,
+                                             const char* name);
+
+bool LoadInstanceVtbl(VkInstance instance,
+                      PFN_vkGetInstanceProcAddr get_proc_addr,
+                      InstanceVtbl& vtbl);
+bool LoadDeviceVtbl(VkDevice device,
+                    PFN_vkGetDeviceProcAddr get_proc_addr,
+                    DeviceVtbl& vtbl);
+
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_LOADER_H
diff --git a/vulkan/nulldrv/Android.mk b/vulkan/nulldrv/Android.mk
new file mode 100644
index 0000000..a267a79
--- /dev/null
+++ b/vulkan/nulldrv/Android.mk
@@ -0,0 +1,26 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
+LOCAL_CFLAGS += -DLOG_TAG=\"vk_nulldrv\"
+LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef
+LOCAL_CPPFLAGS := -std=c++1y \
+	-Wno-c++98-compat-pedantic \
+	-Wno-c99-extensions
+
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include
+
+LOCAL_SRC_FILES := \
+	null_driver.cpp \
+	null_driver_gen.cpp
+
+LOCAL_SHARED_LIBRARIES := liblog
+
+LOCAL_MODULE := vulkan.$(TARGET_BOARD_PLATFORM)
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
new file mode 100644
index 0000000..a68cdd9
--- /dev/null
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -0,0 +1,734 @@
+#include <hardware/hwvulkan.h>
+
+#include <string.h>
+#include <algorithm>
+
+#include <utils/Errors.h>
+
+#include "null_driver.h"
+
+using namespace null_driver;
+
+struct VkPhysicalDevice_T {
+    hwvulkan_dispatch_t dispatch;
+};
+
+struct VkInstance_T {
+    hwvulkan_dispatch_t dispatch;
+    const VkAllocCallbacks* alloc;
+    VkPhysicalDevice_T physical_device;
+};
+
+struct VkQueue_T {
+    hwvulkan_dispatch_t dispatch;
+};
+
+struct VkCmdBuffer_T {
+    hwvulkan_dispatch_t dispatch;
+};
+
+struct VkDevice_T {
+    hwvulkan_dispatch_t dispatch;
+    VkInstance_T* instance;
+    VkQueue_T queue;
+};
+
+// -----------------------------------------------------------------------------
+// Declare HAL_MODULE_INFO_SYM early so it can be referenced by nulldrv_device
+// later.
+
+namespace {
+int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
+hw_module_methods_t nulldrv_module_methods = {.open = OpenDevice};
+}  // namespace
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
+__attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
+    .common =
+        {
+         .tag = HARDWARE_MODULE_TAG,
+         .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
+         .hal_api_version = HARDWARE_HAL_API_VERSION,
+         .id = HWVULKAN_HARDWARE_MODULE_ID,
+         .name = "Null Vulkan Driver",
+         .author = "The Android Open Source Project",
+         .methods = &nulldrv_module_methods,
+        },
+};
+#pragma clang diagnostic pop
+
+// -----------------------------------------------------------------------------
+
+namespace {
+
+VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+                        VkInstance* out_instance) {
+    VkInstance_T* instance =
+        static_cast<VkInstance_T*>(create_info->pAllocCb->pfnAlloc(
+            create_info->pAllocCb->pUserData, sizeof(VkInstance_T),
+            alignof(VkInstance_T), VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
+    if (!instance)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    instance->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    instance->alloc = create_info->pAllocCb;
+    instance->physical_device.dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+
+    *out_instance = instance;
+    return VK_SUCCESS;
+}
+
+int CloseDevice(struct hw_device_t* /*device*/) {
+    // nothing to do - opening a device doesn't allocate any resources
+    return 0;
+}
+
+hwvulkan_device_t nulldrv_device = {
+    .common =
+        {
+         .tag = HARDWARE_DEVICE_TAG,
+         .version = HWVULKAN_DEVICE_API_VERSION_0_1,
+         .module = &HAL_MODULE_INFO_SYM.common,
+         .close = CloseDevice,
+        },
+    .GetGlobalExtensionProperties = GetGlobalExtensionProperties,
+    .CreateInstance = CreateInstance,
+    .GetInstanceProcAddr = GetInstanceProcAddr};
+
+int OpenDevice(const hw_module_t* /*module*/,
+               const char* id,
+               hw_device_t** device) {
+    if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
+        *device = &nulldrv_device.common;
+        return 0;
+    }
+    return -ENOENT;
+}
+
+VkInstance_T* GetInstanceFromPhysicalDevice(
+    VkPhysicalDevice_T* physical_device) {
+    return reinterpret_cast<VkInstance_T*>(
+        reinterpret_cast<uintptr_t>(physical_device) -
+        offsetof(VkInstance_T, physical_device));
+}
+
+}  // namespace
+
+namespace null_driver {
+
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance, const char* name) {
+    PFN_vkVoidFunction proc = LookupInstanceProcAddr(name);
+    if (!proc && strcmp(name, "vkGetDeviceProcAddr") == 0)
+        proc = reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
+    return proc;
+}
+
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice, const char* name) {
+    return LookupDeviceProcAddr(name);
+}
+
+VkResult DestroyInstance(VkInstance instance) {
+    instance->alloc->pfnFree(instance->alloc->pUserData, instance);
+    return VK_SUCCESS;
+}
+
+VkResult EnumeratePhysicalDevices(VkInstance instance,
+                                  uint32_t* physical_device_count,
+                                  VkPhysicalDevice* physical_devices) {
+    if (physical_devices && *physical_device_count >= 1)
+        physical_devices[0] = &instance->physical_device;
+    *physical_device_count = 1;
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceProperties(VkPhysicalDevice,
+                                     VkPhysicalDeviceProperties* properties) {
+    properties->apiVersion = VK_API_VERSION;
+    properties->driverVersion = VK_MAKE_VERSION(0, 0, 1);
+    properties->vendorId = 0xC0DE;
+    properties->deviceId = 0xCAFE;
+    properties->deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
+    strcpy(properties->deviceName, "Android Vulkan Null Driver");
+    memset(properties->pipelineCacheUUID, 0,
+           sizeof(properties->pipelineCacheUUID));
+    return VK_SUCCESS;
+}
+
+VkResult GetGlobalExtensionProperties(const char*,
+                                      uint32_t* count,
+                                      VkExtensionProperties*) {
+    *count = 0;
+    return VK_SUCCESS;
+}
+
+VkResult CreateDevice(VkPhysicalDevice physical_device,
+                      const VkDeviceCreateInfo*,
+                      VkDevice* out_device) {
+    VkInstance_T* instance = GetInstanceFromPhysicalDevice(physical_device);
+    VkDevice_T* device = static_cast<VkDevice_T*>(instance->alloc->pfnAlloc(
+        instance->alloc->pUserData, sizeof(VkDevice_T), alignof(VkDevice_T),
+        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
+    if (!device)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    device->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    device->instance = instance;
+    device->queue.dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+
+    *out_device = device;
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDevice(VkDevice device) {
+    if (!device)
+        return VK_SUCCESS;
+    const VkAllocCallbacks* alloc = device->instance->alloc;
+    alloc->pfnFree(alloc->pUserData, device);
+    return VK_SUCCESS;
+}
+
+VkResult GetDeviceQueue(VkDevice device, uint32_t, uint32_t, VkQueue* queue) {
+    *queue = &device->queue;
+    return VK_SUCCESS;
+}
+
+// -----------------------------------------------------------------------------
+// No-op entrypoints
+
+// clang-format off
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
+VkResult GetPhysicalDeviceQueueCount(VkPhysicalDevice physicalDevice, uint32_t* pCount) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceQueueProperties(VkPhysicalDevice physicalDevice, uint32_t count, VkPhysicalDeviceQueueProperties* pQueueProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageFormatProperties* pImageFormatProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceLimits(VkPhysicalDevice physicalDevice, VkPhysicalDeviceLimits* pLimits) {
+    return VK_SUCCESS;
+}
+
+VkResult GetGlobalLayerProperties(uint32_t* pCount, VkLayerProperties* pProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pCount, VkLayerProperties* pProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueSubmit(VkQueue queue, uint32_t cmdBufferCount, const VkCmdBuffer* pCmdBuffers, VkFence fence) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueWaitIdle(VkQueue queue) {
+    return VK_SUCCESS;
+}
+
+VkResult DeviceWaitIdle(VkDevice device) {
+    return VK_SUCCESS;
+}
+
+VkResult AllocMemory(VkDevice device, const VkMemoryAllocInfo* pAllocInfo, VkDeviceMemory* pMem) {
+    return VK_SUCCESS;
+}
+
+VkResult FreeMemory(VkDevice device, VkDeviceMemory mem) {
+    return VK_SUCCESS;
+}
+
+VkResult MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
+    return VK_SUCCESS;
+}
+
+VkResult UnmapMemory(VkDevice device, VkDeviceMemory mem) {
+    return VK_SUCCESS;
+}
+
+VkResult FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
+    return VK_SUCCESS;
+}
+
+VkResult InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
+    return VK_SUCCESS;
+}
+
+VkResult GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) {
+    return VK_SUCCESS;
+}
+
+VkResult GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) {
+    return VK_SUCCESS;
+}
+
+VkResult BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset) {
+    return VK_SUCCESS;
+}
+
+VkResult GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) {
+    return VK_SUCCESS;
+}
+
+VkResult BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset) {
+    return VK_SUCCESS;
+}
+
+VkResult GetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pNumRequirements, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, uint32_t samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pNumProperties, VkSparseImageFormatProperties* pProperties) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueBindSparseBufferMemory(VkQueue queue, VkBuffer buffer, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueBindSparseImageOpaqueMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueBindSparseImageMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseImageMemoryBindInfo* pBindInfo) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo, VkFence* pFence) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyFence(VkDevice device, VkFence fence) {
+    return VK_SUCCESS;
+}
+
+VkResult ResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
+    return VK_SUCCESS;
+}
+
+VkResult GetFenceStatus(VkDevice device, VkFence fence) {
+    return VK_SUCCESS;
+}
+
+VkResult WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, VkSemaphore* pSemaphore) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroySemaphore(VkDevice device, VkSemaphore semaphore) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueSignalSemaphore(VkQueue queue, VkSemaphore semaphore) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueWaitSemaphore(VkQueue queue, VkSemaphore semaphore) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, VkEvent* pEvent) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyEvent(VkDevice device, VkEvent event) {
+    return VK_SUCCESS;
+}
+
+VkResult GetEventStatus(VkDevice device, VkEvent event) {
+    return VK_SUCCESS;
+}
+
+VkResult SetEvent(VkDevice device, VkEvent event) {
+    return VK_SUCCESS;
+}
+
+VkResult ResetEvent(VkDevice device, VkEvent event) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, VkQueryPool* pQueryPool) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyQueryPool(VkDevice device, VkQueryPool queryPool) {
+    return VK_SUCCESS;
+}
+
+VkResult GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, size_t* pDataSize, void* pData, VkQueryResultFlags flags) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, VkBuffer* pBuffer) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyBuffer(VkDevice device, VkBuffer buffer) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, VkBufferView* pView) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyBufferView(VkDevice device, VkBufferView bufferView) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyImage(VkDevice device, VkImage image) {
+    return VK_SUCCESS;
+}
+
+VkResult GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, VkImageView* pView) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyImageView(VkDevice device, VkImageView imageView) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateAttachmentView(VkDevice device, const VkAttachmentViewCreateInfo* pCreateInfo, VkAttachmentView* pView) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyAttachmentView(VkDevice device, VkAttachmentView attachmentView) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* pShaderModule) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyShaderModule(VkDevice device, VkShaderModule shaderModule) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateShader(VkDevice device, const VkShaderCreateInfo* pCreateInfo, VkShader* pShader) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyShader(VkDevice device, VkShader shader) {
+    return VK_SUCCESS;
+}
+
+VkResult CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, VkPipelineCache* pPipelineCache) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache) {
+    return VK_SUCCESS;
+}
+
+size_t GetPipelineCacheSize(VkDevice device, VkPipelineCache pipelineCache) {
+    return VK_SUCCESS;
+}
+
+VkResult GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, void* pData) {
+    return VK_SUCCESS;
+}
+
+VkResult MergePipelineCaches(VkDevice device, VkPipelineCache destCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkGraphicsPipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkComputePipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyPipeline(VkDevice device, VkPipeline pipeline) {
+    return VK_SUCCESS;
+}
+
+VkResult CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, VkPipelineLayout* pPipelineLayout) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, VkSampler* pSampler) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroySampler(VkDevice device, VkSampler sampler) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayout* pSetLayout) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateDescriptorPool(VkDevice device, VkDescriptorPoolUsage poolUsage, uint32_t maxSets, const VkDescriptorPoolCreateInfo* pCreateInfo, VkDescriptorPool* pDescriptorPool) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool) {
+    return VK_SUCCESS;
+}
+
+VkResult ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool) {
+    return VK_SUCCESS;
+}
+
+VkResult AllocDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorSetUsage setUsage, uint32_t count, const VkDescriptorSetLayout* pSetLayouts, VkDescriptorSet* pDescriptorSets, uint32_t* pCount) {
+    return VK_SUCCESS;
+}
+
+VkResult UpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies) {
+    return VK_SUCCESS;
+}
+
+VkResult FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateDynamicViewportState(VkDevice device, const VkDynamicViewportStateCreateInfo* pCreateInfo, VkDynamicViewportState* pState) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDynamicViewportState(VkDevice device, VkDynamicViewportState dynamicViewportState) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateDynamicRasterState(VkDevice device, const VkDynamicRasterStateCreateInfo* pCreateInfo, VkDynamicRasterState* pState) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDynamicRasterState(VkDevice device, VkDynamicRasterState dynamicRasterState) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateDynamicColorBlendState(VkDevice device, const VkDynamicColorBlendStateCreateInfo* pCreateInfo, VkDynamicColorBlendState* pState) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDynamicColorBlendState(VkDevice device, VkDynamicColorBlendState dynamicColorBlendState) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateDynamicDepthStencilState(VkDevice device, const VkDynamicDepthStencilStateCreateInfo* pCreateInfo, VkDynamicDepthStencilState* pState) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyDynamicDepthStencilState(VkDevice device, VkDynamicDepthStencilState dynamicDepthStencilState) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, VkFramebuffer* pFramebuffer) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, VkRenderPass* pRenderPass) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyRenderPass(VkDevice device, VkRenderPass renderPass) {
+    return VK_SUCCESS;
+}
+
+VkResult GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateCommandPool(VkDevice device, const VkCmdPoolCreateInfo* pCreateInfo, VkCmdPool* pCmdPool) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyCommandPool(VkDevice device, VkCmdPool cmdPool) {
+    return VK_SUCCESS;
+}
+
+VkResult ResetCommandPool(VkDevice device, VkCmdPool cmdPool, VkCmdPoolResetFlags flags) {
+    return VK_SUCCESS;
+}
+
+VkResult CreateCommandBuffer(VkDevice device, const VkCmdBufferCreateInfo* pCreateInfo, VkCmdBuffer* pCmdBuffer) {
+    return VK_SUCCESS;
+}
+
+VkResult DestroyCommandBuffer(VkDevice device, VkCmdBuffer commandBuffer) {
+    return VK_SUCCESS;
+}
+
+VkResult BeginCommandBuffer(VkCmdBuffer cmdBuffer, const VkCmdBufferBeginInfo* pBeginInfo) {
+    return VK_SUCCESS;
+}
+
+VkResult EndCommandBuffer(VkCmdBuffer cmdBuffer) {
+    return VK_SUCCESS;
+}
+
+VkResult ResetCommandBuffer(VkCmdBuffer cmdBuffer, VkCmdBufferResetFlags flags) {
+    return VK_SUCCESS;
+}
+
+void CmdBindPipeline(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
+}
+
+void CmdBindDynamicViewportState(VkCmdBuffer cmdBuffer, VkDynamicViewportState dynamicViewportState) {
+}
+
+void CmdBindDynamicRasterState(VkCmdBuffer cmdBuffer, VkDynamicRasterState dynamicRasterState) {
+}
+
+void CmdBindDynamicColorBlendState(VkCmdBuffer cmdBuffer, VkDynamicColorBlendState dynamicColorBlendState) {
+}
+
+void CmdBindDynamicDepthStencilState(VkCmdBuffer cmdBuffer, VkDynamicDepthStencilState dynamicDepthStencilState) {
+}
+
+void CmdBindDescriptorSets(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
+}
+
+void CmdBindIndexBuffer(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
+}
+
+void CmdBindVertexBuffers(VkCmdBuffer cmdBuffer, uint32_t startBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) {
+}
+
+void CmdDraw(VkCmdBuffer cmdBuffer, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount) {
+}
+
+void CmdDrawIndexed(VkCmdBuffer cmdBuffer, uint32_t firstIndex, uint32_t indexCount, int32_t vertexOffset, uint32_t firstInstance, uint32_t instanceCount) {
+}
+
+void CmdDrawIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+}
+
+void CmdDrawIndexedIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+}
+
+void CmdDispatch(VkCmdBuffer cmdBuffer, uint32_t x, uint32_t y, uint32_t z) {
+}
+
+void CmdDispatchIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset) {
+}
+
+void CmdCopyBuffer(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkBuffer destBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) {
+}
+
+void CmdCopyImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageCopy* pRegions) {
+}
+
+void CmdBlitImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkTexFilter filter) {
+}
+
+void CmdCopyBufferToImage(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+}
+
+void CmdCopyImageToBuffer(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer destBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+}
+
+void CmdUpdateBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize dataSize, const uint32_t* pData) {
+}
+
+void CmdFillBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize fillSize, uint32_t data) {
+}
+
+void CmdClearColorImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+}
+
+void CmdClearDepthStencilImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+}
+
+void CmdClearColorAttachment(VkCmdBuffer cmdBuffer, uint32_t colorAttachment, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rectCount, const VkRect3D* pRects) {
+}
+
+void CmdClearDepthStencilAttachment(VkCmdBuffer cmdBuffer, VkImageAspectFlags imageAspectMask, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rectCount, const VkRect3D* pRects) {
+}
+
+void CmdResolveImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageResolve* pRegions) {
+}
+
+void CmdSetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+}
+
+void CmdResetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+}
+
+void CmdWaitEvents(VkCmdBuffer cmdBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
+}
+
+void CmdPipelineBarrier(VkCmdBuffer cmdBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, VkBool32 byRegion, uint32_t memBarrierCount, const void* const* ppMemBarriers) {
+}
+
+void CmdBeginQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags) {
+}
+
+void CmdEndQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot) {
+}
+
+void CmdResetQueryPool(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount) {
+}
+
+void CmdWriteTimestamp(VkCmdBuffer cmdBuffer, VkTimestampType timestampType, VkBuffer destBuffer, VkDeviceSize destOffset) {
+}
+
+void CmdCopyQueryPoolResults(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize destStride, VkQueryResultFlags flags) {
+}
+
+void CmdPushConstants(VkCmdBuffer cmdBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t start, uint32_t length, const void* values) {
+}
+
+void CmdBeginRenderPass(VkCmdBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkRenderPassContents contents) {
+}
+
+void CmdNextSubpass(VkCmdBuffer cmdBuffer, VkRenderPassContents contents) {
+}
+
+void CmdEndRenderPass(VkCmdBuffer cmdBuffer) {
+}
+
+void CmdExecuteCommands(VkCmdBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCmdBuffer* pCmdBuffers) {
+}
+
+#pragma clang diagnostic pop
+// clang-format on
+
+}  // namespace null_driver
diff --git a/vulkan/nulldrv/null_driver.h b/vulkan/nulldrv/null_driver.h
new file mode 100644
index 0000000..f9208f9
--- /dev/null
+++ b/vulkan/nulldrv/null_driver.h
@@ -0,0 +1,168 @@
+#ifndef NULLDRV_NULL_DRIVER_H
+#define NULLDRV_NULL_DRIVER_H 1
+
+#define VK_PROTOTYPES
+#include <vulkan/vulkan.h>
+
+namespace null_driver {
+
+PFN_vkVoidFunction LookupInstanceProcAddr(const char* name);
+PFN_vkVoidFunction LookupDeviceProcAddr(const char* name);
+
+// clang-format off
+VkResult DestroyInstance(VkInstance instance);
+VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName);
+VkResult GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
+VkResult GetPhysicalDeviceQueueCount(VkPhysicalDevice physicalDevice, uint32_t* pCount);
+VkResult GetPhysicalDeviceQueueProperties(VkPhysicalDevice physicalDevice, uint32_t count, VkPhysicalDeviceQueueProperties* pQueueProperties);
+VkResult GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName);
+VkResult GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
+VkResult GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties);
+VkResult GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageFormatProperties* pImageFormatProperties);
+VkResult GetPhysicalDeviceLimits(VkPhysicalDevice physicalDevice, VkPhysicalDeviceLimits* pLimits);
+VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice);
+VkResult DestroyDevice(VkDevice device);
+VkResult GetGlobalExtensionProperties(const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties);
+VkResult GetGlobalLayerProperties(uint32_t* pCount, VkLayerProperties* pProperties);
+VkResult GetPhysicalDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pCount, VkLayerProperties* pProperties);
+VkResult GetPhysicalDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties);
+VkResult GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VkResult QueueSubmit(VkQueue queue, uint32_t cmdBufferCount, const VkCmdBuffer* pCmdBuffers, VkFence fence);
+VkResult QueueWaitIdle(VkQueue queue);
+VkResult DeviceWaitIdle(VkDevice device);
+VkResult AllocMemory(VkDevice device, const VkMemoryAllocInfo* pAllocInfo, VkDeviceMemory* pMem);
+VkResult FreeMemory(VkDevice device, VkDeviceMemory mem);
+VkResult MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);
+VkResult UnmapMemory(VkDevice device, VkDeviceMemory mem);
+VkResult FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges);
+VkResult InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges);
+VkResult GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes);
+VkResult GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements);
+VkResult BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset);
+VkResult GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
+VkResult BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset);
+VkResult GetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pNumRequirements, VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+VkResult GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, uint32_t samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pNumProperties, VkSparseImageFormatProperties* pProperties);
+VkResult QueueBindSparseBufferMemory(VkQueue queue, VkBuffer buffer, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo);
+VkResult QueueBindSparseImageOpaqueMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo);
+VkResult QueueBindSparseImageMemory(VkQueue queue, VkImage image, uint32_t numBindings, const VkSparseImageMemoryBindInfo* pBindInfo);
+VkResult CreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo, VkFence* pFence);
+VkResult DestroyFence(VkDevice device, VkFence fence);
+VkResult ResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences);
+VkResult GetFenceStatus(VkDevice device, VkFence fence);
+VkResult WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout);
+VkResult CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, VkSemaphore* pSemaphore);
+VkResult DestroySemaphore(VkDevice device, VkSemaphore semaphore);
+VkResult QueueSignalSemaphore(VkQueue queue, VkSemaphore semaphore);
+VkResult QueueWaitSemaphore(VkQueue queue, VkSemaphore semaphore);
+VkResult CreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, VkEvent* pEvent);
+VkResult DestroyEvent(VkDevice device, VkEvent event);
+VkResult GetEventStatus(VkDevice device, VkEvent event);
+VkResult SetEvent(VkDevice device, VkEvent event);
+VkResult ResetEvent(VkDevice device, VkEvent event);
+VkResult CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, VkQueryPool* pQueryPool);
+VkResult DestroyQueryPool(VkDevice device, VkQueryPool queryPool);
+VkResult GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, size_t* pDataSize, void* pData, VkQueryResultFlags flags);
+VkResult CreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, VkBuffer* pBuffer);
+VkResult DestroyBuffer(VkDevice device, VkBuffer buffer);
+VkResult CreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, VkBufferView* pView);
+VkResult DestroyBufferView(VkDevice device, VkBufferView bufferView);
+VkResult CreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage);
+VkResult DestroyImage(VkDevice device, VkImage image);
+VkResult GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
+VkResult CreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, VkImageView* pView);
+VkResult DestroyImageView(VkDevice device, VkImageView imageView);
+VkResult CreateAttachmentView(VkDevice device, const VkAttachmentViewCreateInfo* pCreateInfo, VkAttachmentView* pView);
+VkResult DestroyAttachmentView(VkDevice device, VkAttachmentView attachmentView);
+VkResult CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* pShaderModule);
+VkResult DestroyShaderModule(VkDevice device, VkShaderModule shaderModule);
+VkResult CreateShader(VkDevice device, const VkShaderCreateInfo* pCreateInfo, VkShader* pShader);
+VkResult DestroyShader(VkDevice device, VkShader shader);
+VkResult CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, VkPipelineCache* pPipelineCache);
+VkResult DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache);
+size_t GetPipelineCacheSize(VkDevice device, VkPipelineCache pipelineCache);
+VkResult GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, void* pData);
+VkResult MergePipelineCaches(VkDevice device, VkPipelineCache destCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches);
+VkResult CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkGraphicsPipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines);
+VkResult CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkComputePipelineCreateInfo* pCreateInfos, VkPipeline* pPipelines);
+VkResult DestroyPipeline(VkDevice device, VkPipeline pipeline);
+VkResult CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, VkPipelineLayout* pPipelineLayout);
+VkResult DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout);
+VkResult CreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, VkSampler* pSampler);
+VkResult DestroySampler(VkDevice device, VkSampler sampler);
+VkResult CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayout* pSetLayout);
+VkResult DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout);
+VkResult CreateDescriptorPool(VkDevice device, VkDescriptorPoolUsage poolUsage, uint32_t maxSets, const VkDescriptorPoolCreateInfo* pCreateInfo, VkDescriptorPool* pDescriptorPool);
+VkResult DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool);
+VkResult ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool);
+VkResult AllocDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorSetUsage setUsage, uint32_t count, const VkDescriptorSetLayout* pSetLayouts, VkDescriptorSet* pDescriptorSets, uint32_t* pCount);
+VkResult FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets);
+VkResult UpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies);
+VkResult CreateDynamicViewportState(VkDevice device, const VkDynamicViewportStateCreateInfo* pCreateInfo, VkDynamicViewportState* pState);
+VkResult DestroyDynamicViewportState(VkDevice device, VkDynamicViewportState dynamicViewportState);
+VkResult CreateDynamicRasterState(VkDevice device, const VkDynamicRasterStateCreateInfo* pCreateInfo, VkDynamicRasterState* pState);
+VkResult DestroyDynamicRasterState(VkDevice device, VkDynamicRasterState dynamicRasterState);
+VkResult CreateDynamicColorBlendState(VkDevice device, const VkDynamicColorBlendStateCreateInfo* pCreateInfo, VkDynamicColorBlendState* pState);
+VkResult DestroyDynamicColorBlendState(VkDevice device, VkDynamicColorBlendState dynamicColorBlendState);
+VkResult CreateDynamicDepthStencilState(VkDevice device, const VkDynamicDepthStencilStateCreateInfo* pCreateInfo, VkDynamicDepthStencilState* pState);
+VkResult DestroyDynamicDepthStencilState(VkDevice device, VkDynamicDepthStencilState dynamicDepthStencilState);
+VkResult CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, VkFramebuffer* pFramebuffer);
+VkResult DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer);
+VkResult CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, VkRenderPass* pRenderPass);
+VkResult DestroyRenderPass(VkDevice device, VkRenderPass renderPass);
+VkResult GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+VkResult CreateCommandPool(VkDevice device, const VkCmdPoolCreateInfo* pCreateInfo, VkCmdPool* pCmdPool);
+VkResult DestroyCommandPool(VkDevice device, VkCmdPool cmdPool);
+VkResult ResetCommandPool(VkDevice device, VkCmdPool cmdPool, VkCmdPoolResetFlags flags);
+VkResult CreateCommandBuffer(VkDevice device, const VkCmdBufferCreateInfo* pCreateInfo, VkCmdBuffer* pCmdBuffer);
+VkResult DestroyCommandBuffer(VkDevice device, VkCmdBuffer commandBuffer);
+VkResult BeginCommandBuffer(VkCmdBuffer cmdBuffer, const VkCmdBufferBeginInfo* pBeginInfo);
+VkResult EndCommandBuffer(VkCmdBuffer cmdBuffer);
+VkResult ResetCommandBuffer(VkCmdBuffer cmdBuffer, VkCmdBufferResetFlags flags);
+void CmdBindPipeline(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+void CmdBindDynamicViewportState(VkCmdBuffer cmdBuffer, VkDynamicViewportState dynamicViewportState);
+void CmdBindDynamicRasterState(VkCmdBuffer cmdBuffer, VkDynamicRasterState dynamicRasterState);
+void CmdBindDynamicColorBlendState(VkCmdBuffer cmdBuffer, VkDynamicColorBlendState dynamicColorBlendState);
+void CmdBindDynamicDepthStencilState(VkCmdBuffer cmdBuffer, VkDynamicDepthStencilState dynamicDepthStencilState);
+void CmdBindDescriptorSets(VkCmdBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets);
+void CmdBindIndexBuffer(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
+void CmdBindVertexBuffers(VkCmdBuffer cmdBuffer, uint32_t startBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets);
+void CmdDraw(VkCmdBuffer cmdBuffer, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount);
+void CmdDrawIndexed(VkCmdBuffer cmdBuffer, uint32_t firstIndex, uint32_t indexCount, int32_t vertexOffset, uint32_t firstInstance, uint32_t instanceCount);
+void CmdDrawIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride);
+void CmdDrawIndexedIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride);
+void CmdDispatch(VkCmdBuffer cmdBuffer, uint32_t x, uint32_t y, uint32_t z);
+void CmdDispatchIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset);
+void CmdCopyBuffer(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkBuffer destBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
+void CmdCopyImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
+void CmdBlitImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkTexFilter filter);
+void CmdCopyBufferToImage(VkCmdBuffer cmdBuffer, VkBuffer srcBuffer, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+void CmdCopyImageToBuffer(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer destBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+void CmdUpdateBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize dataSize, const uint32_t* pData);
+void CmdFillBuffer(VkCmdBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize fillSize, uint32_t data);
+void CmdClearColorImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+void CmdClearDepthStencilImage(VkCmdBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+void CmdClearColorAttachment(VkCmdBuffer cmdBuffer, uint32_t colorAttachment, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rectCount, const VkRect3D* pRects);
+void CmdClearDepthStencilAttachment(VkCmdBuffer cmdBuffer, VkImageAspectFlags imageAspectMask, VkImageLayout imageLayout, float depth, uint32_t stencil, uint32_t rectCount, const VkRect3D* pRects);
+void CmdResolveImage(VkCmdBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageResolve* pRegions);
+void CmdSetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+void CmdResetEvent(VkCmdBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+void CmdWaitEvents(VkCmdBuffer cmdBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, uint32_t memBarrierCount, const void* const* ppMemBarriers);
+void CmdPipelineBarrier(VkCmdBuffer cmdBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags destStageMask, VkBool32 byRegion, uint32_t memBarrierCount, const void* const* ppMemBarriers);
+void CmdBeginQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags);
+void CmdEndQuery(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot);
+void CmdResetQueryPool(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount);
+void CmdWriteTimestamp(VkCmdBuffer cmdBuffer, VkTimestampType timestampType, VkBuffer destBuffer, VkDeviceSize destOffset);
+void CmdCopyQueryPoolResults(VkCmdBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize destStride, VkQueryResultFlags flags);
+void CmdPushConstants(VkCmdBuffer cmdBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t start, uint32_t length, const void* values);
+void CmdBeginRenderPass(VkCmdBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkRenderPassContents contents);
+void CmdNextSubpass(VkCmdBuffer cmdBuffer, VkRenderPassContents contents);
+void CmdEndRenderPass(VkCmdBuffer cmdBuffer);
+void CmdExecuteCommands(VkCmdBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCmdBuffer* pCmdBuffers);
+// clang-format on
+
+}  // namespace null_driver
+
+#endif  // NULLDRV_NULL_DRIVER_H
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
new file mode 100644
index 0000000..56ee49a
--- /dev/null
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -0,0 +1,216 @@
+/*
+* Copyright 2015 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+// This file is generated. Do not edit manually!
+// To regenerate: $ apic template ../api/vulkan.api null_driver_gen.cpp.tmpl
+// Requires apic from https://android.googlesource.com/platform/tools/gpu/.
+
+#include <algorithm>
+#include "null_driver.h"
+
+using namespace null_driver;
+
+namespace {
+
+struct NameProcEntry {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};
+
+template <size_t N>
+PFN_vkVoidFunction LookupProcAddr(const NameProcEntry(&table)[N],
+                                  const char* name) {
+    auto entry = std::lower_bound(table, table + N, name,
+                                  [](const NameProcEntry& e, const char* n) {
+                                      return strcmp(e.name, n) < 0;
+                                  });
+    if (entry != (table + N) && strcmp(entry->name, name) == 0)
+        return entry->proc;
+    return nullptr;
+}
+
+const NameProcEntry kInstanceProcTbl[] = {
+    // clang-format off
+    {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice)},
+    {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)},
+    {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices)},
+    {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr)},
+    {"vkGetPhysicalDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceExtensionProperties)},
+    {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFeatures)},
+    {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFormatProperties)},
+    {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceImageFormatProperties)},
+    {"vkGetPhysicalDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceLayerProperties)},
+    {"vkGetPhysicalDeviceLimits", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceLimits)},
+    {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMemoryProperties)},
+    {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties)},
+    {"vkGetPhysicalDeviceQueueCount", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueCount)},
+    {"vkGetPhysicalDeviceQueueProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueProperties)},
+    {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSparseImageFormatProperties)},
+    // clang-format on
+};
+
+const NameProcEntry kDeviceProcTbl[] = {
+    // clang-format off
+    {"vkAllocDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocDescriptorSets)},
+    {"vkAllocMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocMemory)},
+    {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer)},
+    {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory)},
+    {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory)},
+    {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery)},
+    {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass)},
+    {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets)},
+    {"vkCmdBindDynamicColorBlendState", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDynamicColorBlendState)},
+    {"vkCmdBindDynamicDepthStencilState", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDynamicDepthStencilState)},
+    {"vkCmdBindDynamicRasterState", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDynamicRasterState)},
+    {"vkCmdBindDynamicViewportState", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDynamicViewportState)},
+    {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer)},
+    {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline)},
+    {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers)},
+    {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage)},
+    {"vkCmdClearColorAttachment", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorAttachment)},
+    {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage)},
+    {"vkCmdClearDepthStencilAttachment", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilAttachment)},
+    {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage)},
+    {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer)},
+    {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage)},
+    {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage)},
+    {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer)},
+    {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults)},
+    {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch)},
+    {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect)},
+    {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw)},
+    {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed)},
+    {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect)},
+    {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect)},
+    {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery)},
+    {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdEndRenderPass)},
+    {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(CmdExecuteCommands)},
+    {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer)},
+    {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass)},
+    {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier)},
+    {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants)},
+    {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent)},
+    {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool)},
+    {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage)},
+    {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent)},
+    {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer)},
+    {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents)},
+    {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp)},
+    {"vkCreateAttachmentView", reinterpret_cast<PFN_vkVoidFunction>(CreateAttachmentView)},
+    {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer)},
+    {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView)},
+    {"vkCreateCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandBuffer)},
+    {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool)},
+    {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines)},
+    {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool)},
+    {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout)},
+    {"vkCreateDynamicColorBlendState", reinterpret_cast<PFN_vkVoidFunction>(CreateDynamicColorBlendState)},
+    {"vkCreateDynamicDepthStencilState", reinterpret_cast<PFN_vkVoidFunction>(CreateDynamicDepthStencilState)},
+    {"vkCreateDynamicRasterState", reinterpret_cast<PFN_vkVoidFunction>(CreateDynamicRasterState)},
+    {"vkCreateDynamicViewportState", reinterpret_cast<PFN_vkVoidFunction>(CreateDynamicViewportState)},
+    {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent)},
+    {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence)},
+    {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer)},
+    {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines)},
+    {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage)},
+    {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView)},
+    {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache)},
+    {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout)},
+    {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool)},
+    {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass)},
+    {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler)},
+    {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore)},
+    {"vkCreateShader", reinterpret_cast<PFN_vkVoidFunction>(CreateShader)},
+    {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule)},
+    {"vkDestroyAttachmentView", reinterpret_cast<PFN_vkVoidFunction>(DestroyAttachmentView)},
+    {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer)},
+    {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView)},
+    {"vkDestroyCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandBuffer)},
+    {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool)},
+    {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool)},
+    {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout)},
+    {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)},
+    {"vkDestroyDynamicColorBlendState", reinterpret_cast<PFN_vkVoidFunction>(DestroyDynamicColorBlendState)},
+    {"vkDestroyDynamicDepthStencilState", reinterpret_cast<PFN_vkVoidFunction>(DestroyDynamicDepthStencilState)},
+    {"vkDestroyDynamicRasterState", reinterpret_cast<PFN_vkVoidFunction>(DestroyDynamicRasterState)},
+    {"vkDestroyDynamicViewportState", reinterpret_cast<PFN_vkVoidFunction>(DestroyDynamicViewportState)},
+    {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent)},
+    {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence)},
+    {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer)},
+    {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage)},
+    {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView)},
+    {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline)},
+    {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache)},
+    {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout)},
+    {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool)},
+    {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass)},
+    {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler)},
+    {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore)},
+    {"vkDestroyShader", reinterpret_cast<PFN_vkVoidFunction>(DestroyShader)},
+    {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule)},
+    {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle)},
+    {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer)},
+    {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges)},
+    {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets)},
+    {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory)},
+    {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements)},
+    {"vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceMemoryCommitment)},
+    {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)},
+    {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)},
+    {"vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(GetEventStatus)},
+    {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus)},
+    {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements)},
+    {"vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageSparseMemoryRequirements)},
+    {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout)},
+    {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData)},
+    {"vkGetPipelineCacheSize", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheSize)},
+    {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults)},
+    {"vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(GetRenderAreaGranularity)},
+    {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges)},
+    {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory)},
+    {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches)},
+    {"vkQueueBindSparseBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparseBufferMemory)},
+    {"vkQueueBindSparseImageMemory", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparseImageMemory)},
+    {"vkQueueBindSparseImageOpaqueMemory", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparseImageOpaqueMemory)},
+    {"vkQueueSignalSemaphore", reinterpret_cast<PFN_vkVoidFunction>(QueueSignalSemaphore)},
+    {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit)},
+    {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle)},
+    {"vkQueueWaitSemaphore", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitSemaphore)},
+    {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer)},
+    {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool)},
+    {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool)},
+    {"vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(ResetEvent)},
+    {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences)},
+    {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent)},
+    {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory)},
+    {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets)},
+    {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences)},
+    // clang-format on
+};
+
+}  // namespace
+
+namespace null_driver {
+
+PFN_vkVoidFunction LookupInstanceProcAddr(const char* name) {
+    return LookupProcAddr(kInstanceProcTbl, name);
+}
+
+PFN_vkVoidFunction LookupDeviceProcAddr(const char* name) {
+    return LookupProcAddr(kDeviceProcTbl, name);
+}
+
+}  // namespace null_driver
diff --git a/vulkan/nulldrv/null_driver_gen.cpp.tmpl b/vulkan/nulldrv/null_driver_gen.cpp.tmpl
new file mode 100644
index 0000000..03a3d96
--- /dev/null
+++ b/vulkan/nulldrv/null_driver_gen.cpp.tmpl
@@ -0,0 +1,97 @@
+{{Include "../api/templates/vulkan_common.tmpl"}}
+{{Global "clang-format" (Strings "clang-format" "-style=file")}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "null_driver_gen.cpp" | Format (Global "clang-format") | Write "null_driver_gen.cpp"}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Entry point
+-------------------------------------------------------------------------------
+*/}}
+{{define "null_driver_gen.cpp"}}
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */

+// This file is generated. Do not edit manually!
+// To regenerate: $ apic template ../api/vulkan.api null_driver_gen.cpp.tmpl
+// Requires apic from https://android.googlesource.com/platform/tools/gpu/.

+#include <algorithm>
+#include "null_driver.h"

+using namespace null_driver;

+namespace {

+struct NameProcEntry {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};

+template <size_t N>
+PFN_vkVoidFunction LookupProcAddr(const NameProcEntry (&table)[N], const char* name) {
+    auto entry = std::lower_bound(
+        table, table + N, name,
+        [](const NameProcEntry& e, const char* n) { return strcmp(e.name, n) < 0; });
+    if (entry != (table + N) && strcmp(entry->name, name) == 0)
+        return entry->proc;
+    return nullptr;
+}

+const NameProcEntry kInstanceProcTbl[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if eq (Macro "Vtbl" $f) "Instance"}}
+      {"{{Macro "FunctionName" $f}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "FunctionNameNoPrefix" $f}})},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+const NameProcEntry kDeviceProcTbl[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if eq (Macro "Vtbl" $f) "Device"}}
+      {"{{Macro "FunctionName" $f}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "FunctionNameNoPrefix" $f}})},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+} // namespace

+namespace null_driver {

+PFN_vkVoidFunction LookupInstanceProcAddr(const char* name) {
+    return LookupProcAddr(kInstanceProcTbl, name);
+}

+PFN_vkVoidFunction LookupDeviceProcAddr(const char* name) {
+    return LookupProcAddr(kDeviceProcTbl, name);
+}

+} // namespace null_driver

+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of a function without the "vk" prefix.
+-------------------------------------------------------------------------------
+*/}}
+{{define "FunctionNameNoPrefix"}}{{AssertType $ "Function"}}{{TrimPrefix "vk" $.Name}}{{end}}
diff --git a/vulkan/tools/Android.mk b/vulkan/tools/Android.mk
new file mode 100644
index 0000000..98ffa0f
--- /dev/null
+++ b/vulkan/tools/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
+LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef -Wno-switch-enum
+LOCAL_CPPFLAGS := -std=c++1y \
+	-Wno-c++98-compat-pedantic \
+	-Wno-c99-extensions
+
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include
+
+LOCAL_SRC_FILES := vkinfo.cpp
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_SHARED_LIBRARIES := libvulkan liblog
+
+LOCAL_MODULE := vkinfo
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
new file mode 100644
index 0000000..6eedc76
--- /dev/null
+++ b/vulkan/tools/vkinfo.cpp
@@ -0,0 +1,139 @@
+#include <stdlib.h>
+#include <vector>
+
+#define VK_PROTOTYPES
+#include <vulkan/vulkan.h>
+
+#define LOG_TAG "vkinfo"
+#include <log/log.h>
+
+namespace {
+
+[[noreturn]] void die(const char* proc, VkResult result) {
+    const char* result_str;
+    switch (result) {
+        // clang-format off
+        case VK_SUCCESS: result_str = "VK_SUCCESS"; break;
+        case VK_UNSUPPORTED: result_str = "VK_UNSUPPORTED"; break;
+        case VK_NOT_READY: result_str = "VK_NOT_READY"; break;
+        case VK_TIMEOUT: result_str = "VK_TIMEOUT"; break;
+        case VK_EVENT_SET: result_str = "VK_EVENT_SET"; break;
+        case VK_EVENT_RESET: result_str = "VK_EVENT_RESET"; break;
+        case VK_INCOMPLETE: result_str = "VK_INCOMPLETE"; break;
+        case VK_ERROR_UNKNOWN: result_str = "VK_ERROR_UNKNOWN"; break;
+        case VK_ERROR_UNAVAILABLE: result_str = "VK_ERROR_UNAVAILABLE"; break;
+        case VK_ERROR_INITIALIZATION_FAILED: result_str = "VK_ERROR_INITIALIZATION_FAILED"; break;
+        case VK_ERROR_OUT_OF_HOST_MEMORY: result_str = "VK_ERROR_OUT_OF_HOST_MEMORY"; break;
+        case VK_ERROR_OUT_OF_DEVICE_MEMORY: result_str = "VK_ERROR_OUT_OF_DEVICE_MEMORY"; break;
+        case VK_ERROR_DEVICE_ALREADY_CREATED: result_str = "VK_ERROR_DEVICE_ALREADY_CREATED"; break;
+        case VK_ERROR_DEVICE_LOST: result_str = "VK_ERROR_DEVICE_LOST"; break;
+        case VK_ERROR_INVALID_POINTER: result_str = "VK_ERROR_INVALID_POINTER"; break;
+        case VK_ERROR_INVALID_VALUE: result_str = "VK_ERROR_INVALID_VALUE"; break;
+        case VK_ERROR_INVALID_HANDLE: result_str = "VK_ERROR_INVALID_HANDLE"; break;
+        case VK_ERROR_INVALID_ORDINAL: result_str = "VK_ERROR_INVALID_ORDINAL"; break;
+        case VK_ERROR_INVALID_MEMORY_SIZE: result_str = "VK_ERROR_INVALID_MEMORY_SIZE"; break;
+        case VK_ERROR_INVALID_EXTENSION: result_str = "VK_ERROR_INVALID_EXTENSION"; break;
+        case VK_ERROR_INVALID_FLAGS: result_str = "VK_ERROR_INVALID_FLAGS"; break;
+        case VK_ERROR_INVALID_ALIGNMENT: result_str = "VK_ERROR_INVALID_ALIGNMENT"; break;
+        case VK_ERROR_INVALID_FORMAT: result_str = "VK_ERROR_INVALID_FORMAT"; break;
+        case VK_ERROR_INVALID_IMAGE: result_str = "VK_ERROR_INVALID_IMAGE"; break;
+        case VK_ERROR_INVALID_DESCRIPTOR_SET_DATA: result_str = "VK_ERROR_INVALID_DESCRIPTOR_SET_DATA"; break;
+        case VK_ERROR_INVALID_QUEUE_TYPE: result_str = "VK_ERROR_INVALID_QUEUE_TYPE"; break;
+        case VK_ERROR_UNSUPPORTED_SHADER_IL_VERSION: result_str = "VK_ERROR_UNSUPPORTED_SHADER_IL_VERSION"; break;
+        case VK_ERROR_BAD_SHADER_CODE: result_str = "VK_ERROR_BAD_SHADER_CODE"; break;
+        case VK_ERROR_BAD_PIPELINE_DATA: result_str = "VK_ERROR_BAD_PIPELINE_DATA"; break;
+        case VK_ERROR_NOT_MAPPABLE: result_str = "VK_ERROR_NOT_MAPPABLE"; break;
+        case VK_ERROR_MEMORY_MAP_FAILED: result_str = "VK_ERROR_MEMORY_MAP_FAILED"; break;
+        case VK_ERROR_MEMORY_UNMAP_FAILED: result_str = "VK_ERROR_MEMORY_UNMAP_FAILED"; break;
+        case VK_ERROR_INCOMPATIBLE_DEVICE: result_str = "VK_ERROR_INCOMPATIBLE_DEVICE"; break;
+        case VK_ERROR_INCOMPATIBLE_DRIVER: result_str = "VK_ERROR_INCOMPATIBLE_DRIVER"; break;
+        case VK_ERROR_INCOMPLETE_COMMAND_BUFFER: result_str = "VK_ERROR_INCOMPLETE_COMMAND_BUFFER"; break;
+        case VK_ERROR_BUILDING_COMMAND_BUFFER: result_str = "VK_ERROR_BUILDING_COMMAND_BUFFER"; break;
+        case VK_ERROR_MEMORY_NOT_BOUND: result_str = "VK_ERROR_MEMORY_NOT_BOUND"; break;
+        case VK_ERROR_INCOMPATIBLE_QUEUE: result_str = "VK_ERROR_INCOMPATIBLE_QUEUE"; break;
+        case VK_ERROR_INVALID_LAYER: result_str = "VK_ERROR_INVALID_LAYER"; break;
+        default: result_str = "<unknown VkResult>"; break;
+            // clang-format on
+    }
+    fprintf(stderr, "%s failed: %s (%d)\n", proc, result_str, result);
+    exit(1);
+}
+
+const char* VkPhysicalDeviceTypeStr(VkPhysicalDeviceType type) {
+    switch (type) {
+        case VK_PHYSICAL_DEVICE_TYPE_OTHER:
+            return "OTHER";
+        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
+            return "INTEGRATED_GPU";
+        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
+            return "DISCRETE_GPU";
+        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
+            return "VIRTUAL_GPU";
+        case VK_PHYSICAL_DEVICE_TYPE_CPU:
+            return "CPU";
+        default:
+            return "<UNKNOWN>";
+    }
+}
+
+void DumpPhysicalDevice(uint32_t idx, VkPhysicalDevice pdev) {
+    VkResult result;
+
+    VkPhysicalDeviceProperties props;
+    result = vkGetPhysicalDeviceProperties(pdev, &props);
+    if (result != VK_SUCCESS)
+        die("vkGetPhysicalDeviceProperties", result);
+    printf("  %u: \"%s\" (%s) %u.%u.%u/%#x [%04x:%04x]\n", idx,
+           props.deviceName, VkPhysicalDeviceTypeStr(props.deviceType),
+           (props.apiVersion >> 22) & 0x3FF, (props.apiVersion >> 12) & 0x3FF,
+           (props.apiVersion >> 0) & 0xFFF, props.driverVersion, props.vendorId,
+           props.deviceId);
+}
+
+}  // namespace
+
+int main(int /*argc*/, char const* /*argv*/ []) {
+    VkResult result;
+
+    VkInstance instance;
+    const VkInstanceCreateInfo create_info = {
+        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+        .pNext = nullptr,
+        .pAppInfo = nullptr,
+        .pAllocCb = nullptr,
+        .layerCount = 0,
+        .ppEnabledLayerNames = nullptr,
+        .extensionCount = 0,
+        .ppEnabledExtensionNames = nullptr,
+    };
+    result = vkCreateInstance(&create_info, &instance);
+    if (result != VK_SUCCESS)
+        die("vkCreateInstance", result);
+
+    uint32_t num_physical_devices;
+    result =
+        vkEnumeratePhysicalDevices(instance, &num_physical_devices, nullptr);
+    if (result != VK_SUCCESS)
+        die("vkEnumeratePhysicalDevices (count)", result);
+    std::vector<VkPhysicalDevice> physical_devices(num_physical_devices,
+                                                   VK_NULL_HANDLE);
+    result = vkEnumeratePhysicalDevices(instance, &num_physical_devices,
+                                        physical_devices.data());
+    if (result != VK_SUCCESS)
+        die("vkEnumeratePhysicalDevices (data)", result);
+    if (num_physical_devices != physical_devices.size()) {
+        fprintf(stderr,
+                "number of physical devices decreased from %zu to %u!\n",
+                physical_devices.size(), num_physical_devices);
+        physical_devices.resize(num_physical_devices);
+    }
+    printf("PhysicalDevices:\n");
+    for (uint32_t i = 0; i < physical_devices.size(); i++)
+        DumpPhysicalDevice(i, physical_devices[i]);
+
+    result = vkDestroyInstance(instance);
+    if (result != VK_SUCCESS)
+        die("vkDestroyInstance", result);
+
+    return 0;
+}