/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2018 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * 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 Software.
 *
 * THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#pragma once

#include "official/vk_layer.h"
#include "official/vk_layer_dispatch_table.h"

// extensions made core in 1.1
#define VK11 VK_MAKE_VERSION(1, 1, 0)

// extensions that are not core in any version
#define VKXX VK_MAKE_VERSION(99, 99, 0)

#if defined(VK_USE_PLATFORM_WIN32_KHR)

#define HookInitInstance_PlatformSpecific()                       \
  HookInitExtension(VK_KHR_win32_surface, CreateWin32SurfaceKHR); \
  HookInitExtension(VK_KHR_win32_surface, GetPhysicalDeviceWin32PresentationSupportKHR);

#define HookInitDevice_PlatformSpecific()                                             \
  HookInitExtension(VK_NV_win32_keyed_mutex, GetMemoryWin32HandleNV);                 \
  HookInitExtension(VK_KHR_external_memory_win32, GetMemoryWin32HandleKHR);           \
  HookInitExtension(VK_KHR_external_memory_win32, GetMemoryWin32HandlePropertiesKHR); \
  HookInitExtension(VK_KHR_external_semaphore_win32, ImportSemaphoreWin32HandleKHR);  \
  HookInitExtension(VK_KHR_external_semaphore_win32, GetSemaphoreWin32HandleKHR);     \
  HookInitExtension(VK_KHR_external_fence_win32, ImportFenceWin32HandleKHR);          \
  HookInitExtension(VK_KHR_external_fence_win32, GetFenceWin32HandleKHR);

#define HookDefine_PlatformSpecific()                                                            \
  HookDefine4(VkResult, vkCreateWin32SurfaceKHR, VkInstance, instance,                           \
              const VkWin32SurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *,   \
              pAllocator, VkSurfaceKHR *, pSurface);                                             \
  HookDefine2(VkBool32, vkGetPhysicalDeviceWin32PresentationSupportKHR, VkPhysicalDevice,        \
              physicalDevice, uint32_t, queueFamilyIndex);                                       \
  HookDefine4(VkResult, vkGetMemoryWin32HandleNV, VkDevice, device, VkDeviceMemory, memory,      \
              VkExternalMemoryHandleTypeFlagsNV, handleType, HANDLE *, pHandle);                 \
  HookDefine3(VkResult, vkGetMemoryWin32HandleKHR, VkDevice, device,                             \
              const VkMemoryGetWin32HandleInfoKHR *, pGetWin32HandleInfo, HANDLE *, pHandle);    \
  HookDefine4(VkResult, vkGetMemoryWin32HandlePropertiesKHR, VkDevice, device,                   \
              VkExternalMemoryHandleTypeFlagBitsKHR, handleType, HANDLE, handle,                 \
              VkMemoryWin32HandlePropertiesKHR *, pMemoryWin32HandleProperties);                 \
  HookDefine2(VkResult, vkImportSemaphoreWin32HandleKHR, VkDevice, device,                       \
              const VkImportSemaphoreWin32HandleInfoKHR *, pImportSemaphoreWin32HandleInfo);     \
  HookDefine3(VkResult, vkGetSemaphoreWin32HandleKHR, VkDevice, device,                          \
              const VkSemaphoreGetWin32HandleInfoKHR *, pGetWin32HandleInfo, HANDLE *, pHandle); \
  HookDefine2(VkResult, vkImportFenceWin32HandleKHR, VkDevice, device,                           \
              const VkImportFenceWin32HandleInfoKHR *, pImportFenceWin32HandleInfo);             \
  HookDefine3(VkResult, vkGetFenceWin32HandleKHR, VkDevice, device,                              \
              const VkFenceGetWin32HandleInfoKHR *, pGetWin32HandleInfo, HANDLE *, pHandle);

#elif defined(VK_USE_PLATFORM_MACOS_MVK)

#define HookInitInstance_PlatformSpecific() \
  HookInitExtension(VK_MVK_macos_surface, CreateMacOSSurfaceMVK);

#define HookInitDevice_PlatformSpecific()

#define HookDefine_PlatformSpecific()                                                          \
  HookDefine4(VkResult, vkCreateMacOSSurfaceMVK, VkInstance, instance,                         \
              const VkMacOSSurfaceCreateInfoMVK *, pCreateInfo, const VkAllocationCallbacks *, \
              pAllocator, VkSurfaceKHR *, pSurface);

#elif defined(VK_USE_PLATFORM_ANDROID_KHR)

#define HookInitInstance_PlatformSpecific() \
  HookInitExtension(VK_KHR_android_surface, CreateAndroidSurfaceKHR);

#define HookInitDevice_PlatformSpecific()

#define HookDefine_PlatformSpecific()                                                            \
  HookDefine4(VkResult, vkCreateAndroidSurfaceKHR, VkInstance, instance,                         \
              const VkAndroidSurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *, \
              pAllocator, VkSurfaceKHR *, pSurface);

#else

#if defined(VK_USE_PLATFORM_XCB_KHR)

#define HookInitInstance_PlatformSpecific_Xcb()               \
  HookInitExtension(VK_KHR_xcb_surface, CreateXcbSurfaceKHR); \
  HookInitExtension(VK_KHR_xcb_surface, GetPhysicalDeviceXcbPresentationSupportKHR);

#define HookDefine_PlatformSpecific_Xcb()                                                    \
  HookDefine4(VkResult, vkCreateXcbSurfaceKHR, VkInstance, instance,                         \
              const VkXcbSurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *, \
              pAllocator, VkSurfaceKHR *, pSurface);                                         \
  HookDefine4(VkBool32, vkGetPhysicalDeviceXcbPresentationSupportKHR, VkPhysicalDevice,      \
              physicalDevice, uint32_t, queueFamilyIndex, xcb_connection_t *, connection,    \
              xcb_visualid_t, visual_id);

#else

#define HookInitInstance_PlatformSpecific_Xcb()
#define HookDefine_PlatformSpecific_Xcb()

#endif

#if defined(VK_USE_PLATFORM_XLIB_KHR)

#define HookInitInstance_PlatformSpecific_Xlib()                                       \
  HookInitExtension(VK_KHR_xlib_surface, CreateXlibSurfaceKHR);                        \
  HookInitExtension(VK_KHR_xlib_surface, GetPhysicalDeviceXlibPresentationSupportKHR); \
  HookInitExtension(VK_EXT_acquire_xlib_display, AcquireXlibDisplayEXT);               \
  HookInitExtension(VK_EXT_acquire_xlib_display, GetRandROutputDisplayEXT);

#define HookDefine_PlatformSpecific_Xlib()                                                         \
  HookDefine4(VkResult, vkCreateXlibSurfaceKHR, VkInstance, instance,                              \
              const VkXlibSurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *,      \
              pAllocator, VkSurfaceKHR *, pSurface);                                               \
  HookDefine4(VkBool32, vkGetPhysicalDeviceXlibPresentationSupportKHR, VkPhysicalDevice,           \
              physicalDevice, uint32_t, queueFamilyIndex, Display *, dpy, VisualID, visualID);     \
  HookDefine3(VkResult, vkAcquireXlibDisplayEXT, VkPhysicalDevice, physicalDevice, Display *, dpy, \
              VkDisplayKHR, display);                                                              \
  HookDefine4(VkResult, vkGetRandROutputDisplayEXT, VkPhysicalDevice, physicalDevice, Display *,   \
              dpy, RROutput, rrOutput, VkDisplayKHR *, pDisplay);

#else

#define HookInitInstance_PlatformSpecific_Xlib()
#define HookDefine_PlatformSpecific_Xlib()

#endif

#define HookInitInstance_PlatformSpecific() \
  HookInitInstance_PlatformSpecific_Xcb() HookInitInstance_PlatformSpecific_Xlib()
#define HookInitDevice_PlatformSpecific()
#define HookDefine_PlatformSpecific() \
  HookDefine_PlatformSpecific_Xcb() HookDefine_PlatformSpecific_Xlib()

#endif

#define HookInitVulkanInstance()                          \
  HookInit(CreateInstance);                               \
  HookInit(DestroyInstance);                              \
  HookInit(EnumeratePhysicalDevices);                     \
  HookInit(GetPhysicalDeviceFeatures);                    \
  HookInit(GetPhysicalDeviceImageFormatProperties);       \
  HookInit(GetPhysicalDeviceFormatProperties);            \
  HookInit(GetPhysicalDeviceSparseImageFormatProperties); \
  HookInit(GetPhysicalDeviceProperties);                  \
  HookInit(GetPhysicalDeviceQueueFamilyProperties);       \
  HookInit(GetPhysicalDeviceMemoryProperties);

#define HookInitVulkanDevice()                \
  HookInit(CreateDevice);                     \
  HookInit(DestroyDevice);                    \
  HookInit(GetDeviceQueue);                   \
  HookInit(QueueSubmit);                      \
  HookInit(QueueWaitIdle);                    \
  HookInit(DeviceWaitIdle);                   \
  HookInit(AllocateMemory);                   \
  HookInit(FreeMemory);                       \
  HookInit(MapMemory);                        \
  HookInit(UnmapMemory);                      \
  HookInit(FlushMappedMemoryRanges);          \
  HookInit(InvalidateMappedMemoryRanges);     \
  HookInit(GetDeviceMemoryCommitment);        \
  HookInit(BindBufferMemory);                 \
  HookInit(BindImageMemory);                  \
  HookInit(QueueBindSparse);                  \
  HookInit(CreateBuffer);                     \
  HookInit(DestroyBuffer);                    \
  HookInit(CreateBufferView);                 \
  HookInit(DestroyBufferView);                \
  HookInit(CreateImage);                      \
  HookInit(DestroyImage);                     \
  HookInit(GetImageSubresourceLayout);        \
  HookInit(GetBufferMemoryRequirements);      \
  HookInit(GetImageMemoryRequirements);       \
  HookInit(GetImageSparseMemoryRequirements); \
  HookInit(CreateImageView);                  \
  HookInit(DestroyImageView);                 \
  HookInit(CreateShaderModule);               \
  HookInit(DestroyShaderModule);              \
  HookInit(CreateGraphicsPipelines);          \
  HookInit(CreateComputePipelines);           \
  HookInit(DestroyPipeline);                  \
  HookInit(CreatePipelineCache);              \
  HookInit(GetPipelineCacheData);             \
  HookInit(MergePipelineCaches);              \
  HookInit(DestroyPipelineCache);             \
  HookInit(CreatePipelineLayout);             \
  HookInit(DestroyPipelineLayout);            \
  HookInit(CreateSemaphore);                  \
  HookInit(DestroySemaphore);                 \
  HookInit(CreateFence);                      \
  HookInit(GetFenceStatus);                   \
  HookInit(ResetFences);                      \
  HookInit(WaitForFences);                    \
  HookInit(DestroyFence);                     \
  HookInit(CreateEvent);                      \
  HookInit(GetEventStatus);                   \
  HookInit(ResetEvent);                       \
  HookInit(SetEvent);                         \
  HookInit(DestroyEvent);                     \
  HookInit(CreateQueryPool);                  \
  HookInit(GetQueryPoolResults);              \
  HookInit(DestroyQueryPool);                 \
  HookInit(CreateSampler);                    \
  HookInit(DestroySampler);                   \
  HookInit(CreateDescriptorSetLayout);        \
  HookInit(DestroyDescriptorSetLayout);       \
  HookInit(CreateDescriptorPool);             \
  HookInit(ResetDescriptorPool);              \
  HookInit(DestroyDescriptorPool);            \
  HookInit(AllocateDescriptorSets);           \
  HookInit(UpdateDescriptorSets);             \
  HookInit(FreeDescriptorSets);               \
  HookInit(GetRenderAreaGranularity);         \
  HookInit(CreateCommandPool);                \
  HookInit(DestroyCommandPool);               \
  HookInit(ResetCommandPool);                 \
  HookInit(AllocateCommandBuffers);           \
  HookInit(FreeCommandBuffers);               \
  HookInit(BeginCommandBuffer);               \
  HookInit(EndCommandBuffer);                 \
  HookInit(ResetCommandBuffer);               \
  HookInit(CmdBindPipeline);                  \
  HookInit(CmdSetViewport);                   \
  HookInit(CmdSetScissor);                    \
  HookInit(CmdSetLineWidth);                  \
  HookInit(CmdSetDepthBias);                  \
  HookInit(CmdSetBlendConstants);             \
  HookInit(CmdSetDepthBounds);                \
  HookInit(CmdSetStencilCompareMask);         \
  HookInit(CmdSetStencilWriteMask);           \
  HookInit(CmdSetStencilReference);           \
  HookInit(CmdBindDescriptorSets);            \
  HookInit(CmdBindVertexBuffers);             \
  HookInit(CmdBindIndexBuffer);               \
  HookInit(CmdDraw);                          \
  HookInit(CmdDrawIndirect);                  \
  HookInit(CmdDrawIndexed);                   \
  HookInit(CmdDrawIndexedIndirect);           \
  HookInit(CmdDispatch);                      \
  HookInit(CmdDispatchIndirect);              \
  HookInit(CmdCopyBufferToImage);             \
  HookInit(CmdCopyImageToBuffer);             \
  HookInit(CmdCopyBuffer);                    \
  HookInit(CmdCopyImage);                     \
  HookInit(CmdBlitImage);                     \
  HookInit(CmdResolveImage);                  \
  HookInit(CmdUpdateBuffer);                  \
  HookInit(CmdFillBuffer);                    \
  HookInit(CmdPushConstants);                 \
  HookInit(CmdClearColorImage);               \
  HookInit(CmdClearDepthStencilImage);        \
  HookInit(CmdClearAttachments);              \
  HookInit(CmdPipelineBarrier);               \
  HookInit(CmdWriteTimestamp);                \
  HookInit(CmdCopyQueryPoolResults);          \
  HookInit(CmdBeginQuery);                    \
  HookInit(CmdEndQuery);                      \
  HookInit(CmdResetQueryPool);                \
  HookInit(CmdSetEvent);                      \
  HookInit(CmdResetEvent);                    \
  HookInit(CmdWaitEvents);                    \
  HookInit(CreateFramebuffer);                \
  HookInit(DestroyFramebuffer);               \
  HookInit(CreateRenderPass);                 \
  HookInit(DestroyRenderPass);                \
  HookInit(CmdBeginRenderPass);               \
  HookInit(CmdNextSubpass);                   \
  HookInit(CmdExecuteCommands);               \
  HookInit(CmdEndRenderPass);

// We can always build in VK_KHR_display and VK_KHR_display_swapchain support
// because they don't need any libraries or headers.
// They're not really used or  relevant on win32/android but for platform simplicity
// we just include it always, it does no harm to include.

// for simplicity and since the check itself is platform agnostic,
// these aren't protected in platform defines
#define CheckInstanceExts()                            \
  CheckExt(KHR_xlib_surface, VKXX);                    \
  CheckExt(KHR_xcb_surface, VKXX);                     \
  CheckExt(KHR_win32_surface, VKXX);                   \
  CheckExt(KHR_android_surface, VKXX);                 \
  CheckExt(MVK_macos_surface, VKXX);                   \
  CheckExt(KHR_surface, VKXX);                         \
  CheckExt(EXT_debug_report, VKXX);                    \
  CheckExt(KHR_display, VKXX);                         \
  CheckExt(NV_external_memory_capabilities, VKXX);     \
  CheckExt(KHR_get_physical_device_properties2, VK11); \
  CheckExt(EXT_display_surface_counter, VKXX);         \
  CheckExt(EXT_direct_mode_display, VKXX);             \
  CheckExt(EXT_acquire_xlib_display, VKXX);            \
  CheckExt(KHR_external_memory_capabilities, VK11);    \
  CheckExt(KHR_external_semaphore_capabilities, VK11); \
  CheckExt(KHR_external_fence_capabilities, VK11);     \
  CheckExt(EXT_debug_utils, VKXX);                     \
  CheckExt(KHR_device_group_creation, VK11);           \
  CheckExt(protected_memory, VK11);                    \
  CheckExt(KHR_get_surface_capabilities2, VKXX);       \
  CheckExt(KHR_get_display_properties2, VKXX);

#define CheckDeviceExts()                         \
  CheckExt(EXT_debug_marker, VKXX);               \
  CheckExt(KHR_swapchain, VKXX);                  \
  CheckExt(KHR_display_swapchain, VKXX);          \
  CheckExt(NV_external_memory, VKXX);             \
  CheckExt(NV_external_memory_win32, VKXX);       \
  CheckExt(NV_win32_keyed_mutex, VKXX);           \
  CheckExt(KHR_maintenance1, VK11);               \
  CheckExt(KHR_maintenance2, VK11);               \
  CheckExt(KHR_maintenance3, VK11);               \
  CheckExt(EXT_display_control, VKXX);            \
  CheckExt(KHR_external_memory, VK11);            \
  CheckExt(KHR_external_memory_win32, VKXX);      \
  CheckExt(KHR_external_memory_fd, VKXX);         \
  CheckExt(KHR_external_semaphore, VK11);         \
  CheckExt(KHR_external_semaphore_win32, VKXX);   \
  CheckExt(KHR_external_semaphore_fd, VKXX);      \
  CheckExt(KHR_external_fence, VK11);             \
  CheckExt(KHR_external_fence_win32, VKXX);       \
  CheckExt(KHR_external_fence_fd, VKXX);          \
  CheckExt(KHR_get_memory_requirements2, VK11);   \
  CheckExt(AMD_shader_info, VKXX);                \
  CheckExt(KHR_push_descriptor, VKXX);            \
  CheckExt(KHR_descriptor_update_template, VK11); \
  CheckExt(KHR_bind_memory2, VK11);               \
  CheckExt(EXT_conservative_rasterization, VKXX); \
  CheckExt(EXT_global_priority, VKXX);            \
  CheckExt(AMD_buffer_marker, VKXX);              \
  CheckExt(EXT_vertex_attribute_divisor, VKXX);   \
  CheckExt(EXT_sampler_filter_minmax, VKXX);      \
  CheckExt(KHR_sampler_ycbcr_conversion, VK11);   \
  CheckExt(KHR_device_group, VK11);               \
  CheckExt(MVK_moltenvk, VKXX);                   \
  CheckExt(KHR_draw_indirect_count, VKXX);        \
  CheckExt(EXT_validation_cache, VKXX);           \
  CheckExt(KHR_shared_presentable_image, VKXX);   \
  CheckExt(KHR_create_renderpass2, VKXX);         \
  CheckExt(EXT_transform_feedback, VKXX);

#define HookInitVulkanInstanceExts()                                                                 \
  HookInitExtension(KHR_surface, DestroySurfaceKHR);                                                 \
  HookInitExtension(KHR_surface, GetPhysicalDeviceSurfaceSupportKHR);                                \
  HookInitExtension(KHR_surface, GetPhysicalDeviceSurfaceCapabilitiesKHR);                           \
  HookInitExtension(KHR_surface, GetPhysicalDeviceSurfaceFormatsKHR);                                \
  HookInitExtension(KHR_surface, GetPhysicalDeviceSurfacePresentModesKHR);                           \
  HookInitExtension(EXT_debug_report, CreateDebugReportCallbackEXT);                                 \
  HookInitExtension(EXT_debug_report, DestroyDebugReportCallbackEXT);                                \
  HookInitExtension(EXT_debug_report, DebugReportMessageEXT);                                        \
  HookInitExtension(KHR_display, GetPhysicalDeviceDisplayPropertiesKHR);                             \
  HookInitExtension(KHR_display, GetPhysicalDeviceDisplayPlanePropertiesKHR);                        \
  HookInitExtension(KHR_display, GetDisplayPlaneSupportedDisplaysKHR);                               \
  HookInitExtension(KHR_display, GetDisplayModePropertiesKHR);                                       \
  HookInitExtension(KHR_display, CreateDisplayModeKHR);                                              \
  HookInitExtension(KHR_display, GetDisplayPlaneCapabilitiesKHR);                                    \
  HookInitExtension(KHR_display, CreateDisplayPlaneSurfaceKHR);                                      \
  HookInitExtension(NV_external_memory_capabilities,                                                 \
                    GetPhysicalDeviceExternalImageFormatPropertiesNV);                               \
  HookInitPromotedExtension(KHR_get_physical_device_properties2, GetPhysicalDeviceFeatures2, KHR);   \
  HookInitPromotedExtension(KHR_get_physical_device_properties2, GetPhysicalDeviceProperties2, KHR); \
  HookInitPromotedExtension(KHR_get_physical_device_properties2,                                     \
                            GetPhysicalDeviceFormatProperties2, KHR);                                \
  HookInitPromotedExtension(KHR_get_physical_device_properties2,                                     \
                            GetPhysicalDeviceImageFormatProperties2, KHR);                           \
  HookInitPromotedExtension(KHR_get_physical_device_properties2,                                     \
                            GetPhysicalDeviceQueueFamilyProperties2, KHR);                           \
  HookInitPromotedExtension(KHR_get_physical_device_properties2,                                     \
                            GetPhysicalDeviceMemoryProperties2, KHR);                                \
  HookInitPromotedExtension(KHR_get_physical_device_properties2,                                     \
                            GetPhysicalDeviceSparseImageFormatProperties2, KHR);                     \
  HookInitExtension(EXT_direct_mode_display, ReleaseDisplayEXT);                                     \
  HookInitExtension(EXT_display_surface_counter, GetPhysicalDeviceSurfaceCapabilities2EXT);          \
  HookInitPromotedExtension(KHR_external_memory_capabilities,                                        \
                            GetPhysicalDeviceExternalBufferProperties, KHR);                         \
  HookInitPromotedExtension(KHR_external_semaphore_capabilities,                                     \
                            GetPhysicalDeviceExternalSemaphoreProperties, KHR);                      \
  HookInitPromotedExtension(KHR_external_fence_capabilities,                                         \
                            GetPhysicalDeviceExternalFenceProperties, KHR);                          \
  HookInitExtension(EXT_debug_utils, CreateDebugUtilsMessengerEXT);                                  \
  HookInitExtension(EXT_debug_utils, DestroyDebugUtilsMessengerEXT);                                 \
  HookInitExtension(EXT_debug_utils, SubmitDebugUtilsMessageEXT);                                    \
  HookInitPromotedExtension(KHR_device_group_creation, EnumeratePhysicalDeviceGroups, KHR);          \
  /* Not technically accurate - part of KHR_device_group - but these extensions are linked and */    \
  /* should always be present/not present together. Keying from the instance extension ensures */    \
  /* we'll load this function correctly when populating dispatch tables. */                          \
  HookInitExtension(KHR_device_group_creation &&KHR_surface, GetPhysicalDevicePresentRectanglesKHR); \
  HookInitExtension(KHR_get_surface_capabilities2, GetPhysicalDeviceSurfaceFormats2KHR);             \
  HookInitExtension(KHR_get_surface_capabilities2, GetPhysicalDeviceSurfaceCapabilities2KHR);        \
  HookInitExtension(KHR_get_display_properties2, GetPhysicalDeviceDisplayProperties2KHR);            \
  HookInitExtension(KHR_get_display_properties2, GetPhysicalDeviceDisplayPlaneProperties2KHR);       \
  HookInitExtension(KHR_get_display_properties2, GetDisplayModeProperties2KHR);                      \
  HookInitExtension(KHR_get_display_properties2, GetDisplayPlaneCapabilities2KHR);                   \
  HookInitInstance_PlatformSpecific()

#define HookInitVulkanDeviceExts()                                                                 \
  HookInitExtension(EXT_debug_marker, DebugMarkerSetObjectTagEXT);                                 \
  HookInitExtension(EXT_debug_marker, DebugMarkerSetObjectNameEXT);                                \
  HookInitExtension(EXT_debug_marker, CmdDebugMarkerBeginEXT);                                     \
  HookInitExtension(EXT_debug_marker, CmdDebugMarkerEndEXT);                                       \
  HookInitExtension(EXT_debug_marker, CmdDebugMarkerInsertEXT);                                    \
  HookInitExtension(KHR_swapchain, CreateSwapchainKHR);                                            \
  HookInitExtension(KHR_swapchain, DestroySwapchainKHR);                                           \
  HookInitExtension(KHR_swapchain, GetSwapchainImagesKHR);                                         \
  HookInitExtension(KHR_swapchain, AcquireNextImageKHR);                                           \
  HookInitExtension(KHR_swapchain, QueuePresentKHR);                                               \
  HookInitExtension(KHR_display_swapchain, CreateSharedSwapchainsKHR);                             \
  HookInitPromotedExtension(KHR_maintenance1, TrimCommandPool, KHR);                               \
  HookInitExtension(EXT_display_control, DisplayPowerControlEXT);                                  \
  HookInitExtension(EXT_display_control, RegisterDeviceEventEXT);                                  \
  HookInitExtension(EXT_display_control, RegisterDisplayEventEXT);                                 \
  HookInitExtension(EXT_display_control, GetSwapchainCounterEXT);                                  \
  HookInitExtension(KHR_external_memory_fd, GetMemoryFdKHR);                                       \
  HookInitExtension(KHR_external_memory_fd, GetMemoryFdPropertiesKHR);                             \
  HookInitExtension(KHR_external_semaphore_fd, ImportSemaphoreFdKHR);                              \
  HookInitExtension(KHR_external_semaphore_fd, GetSemaphoreFdKHR);                                 \
  HookInitExtension(KHR_external_fence_fd, ImportFenceFdKHR);                                      \
  HookInitExtension(KHR_external_fence_fd, GetFenceFdKHR);                                         \
  HookInitPromotedExtension(KHR_get_memory_requirements2, GetBufferMemoryRequirements2, KHR);      \
  HookInitPromotedExtension(KHR_get_memory_requirements2, GetImageMemoryRequirements2, KHR);       \
  HookInitPromotedExtension(KHR_get_memory_requirements2, GetImageSparseMemoryRequirements2, KHR); \
  HookInitExtension(AMD_shader_info, GetShaderInfoAMD);                                            \
  HookInitExtension(KHR_push_descriptor, CmdPushDescriptorSetKHR);                                 \
  HookInitPromotedExtension(KHR_descriptor_update_template, CreateDescriptorUpdateTemplate, KHR);  \
  HookInitPromotedExtension(KHR_descriptor_update_template, DestroyDescriptorUpdateTemplate, KHR); \
  HookInitPromotedExtension(KHR_descriptor_update_template, UpdateDescriptorSetWithTemplate, KHR); \
  HookInitExtension(KHR_push_descriptor &&KHR_descriptor_update_template,                          \
                    CmdPushDescriptorSetWithTemplateKHR);                                          \
  HookInitPromotedExtension(KHR_bind_memory2, BindBufferMemory2, KHR);                             \
  HookInitPromotedExtension(KHR_bind_memory2, BindImageMemory2, KHR);                              \
  HookInitPromotedExtension(KHR_maintenance3, GetDescriptorSetLayoutSupport, KHR);                 \
  HookInitExtension(AMD_buffer_marker, CmdWriteBufferMarkerAMD);                                   \
  HookInitExtension(EXT_debug_utils, SetDebugUtilsObjectNameEXT);                                  \
  HookInitExtension(EXT_debug_utils, SetDebugUtilsObjectTagEXT);                                   \
  HookInitExtension(EXT_debug_utils, QueueBeginDebugUtilsLabelEXT);                                \
  HookInitExtension(EXT_debug_utils, QueueEndDebugUtilsLabelEXT);                                  \
  HookInitExtension(EXT_debug_utils, QueueInsertDebugUtilsLabelEXT);                               \
  HookInitExtension(EXT_debug_utils, CmdBeginDebugUtilsLabelEXT);                                  \
  HookInitExtension(EXT_debug_utils, CmdEndDebugUtilsLabelEXT);                                    \
  HookInitExtension(EXT_debug_utils, CmdInsertDebugUtilsLabelEXT);                                 \
  HookInitPromotedExtension(KHR_sampler_ycbcr_conversion, CreateSamplerYcbcrConversion, KHR);      \
  HookInitPromotedExtension(KHR_sampler_ycbcr_conversion, DestroySamplerYcbcrConversion, KHR);     \
  HookInitPromotedExtension(KHR_device_group, GetDeviceGroupPeerMemoryFeatures, KHR);              \
  HookInitPromotedExtension(KHR_device_group, CmdSetDeviceMask, KHR);                              \
  HookInitPromotedExtension(KHR_device_group, CmdDispatchBase, KHR);                               \
  HookInitExtension(KHR_device_group &&KHR_surface, GetDeviceGroupPresentCapabilitiesKHR);         \
  HookInitExtension(KHR_device_group &&KHR_surface, GetDeviceGroupSurfacePresentModesKHR);         \
  HookInitExtension(KHR_device_group &&KHR_swapchain, AcquireNextImage2KHR);                       \
  HookInitExtension(protected_memory, GetDeviceQueue2);                                            \
  HookInitExtension(KHR_draw_indirect_count, CmdDrawIndirectCountKHR);                             \
  HookInitExtension(KHR_draw_indirect_count, CmdDrawIndexedIndirectCountKHR);                      \
  HookInitExtension(EXT_validation_cache, CreateValidationCacheEXT);                               \
  HookInitExtension(EXT_validation_cache, DestroyValidationCacheEXT);                              \
  HookInitExtension(EXT_validation_cache, MergeValidationCachesEXT);                               \
  HookInitExtension(EXT_validation_cache, GetValidationCacheDataEXT);                              \
  HookInitExtension(KHR_shared_presentable_image, GetSwapchainStatusKHR);                          \
  HookInitExtension(KHR_create_renderpass2, CreateRenderPass2KHR);                                 \
  HookInitExtension(KHR_create_renderpass2, CmdBeginRenderPass2KHR);                               \
  HookInitExtension(KHR_create_renderpass2, CmdNextSubpass2KHR);                                   \
  HookInitExtension(KHR_create_renderpass2, CmdEndRenderPass2KHR);                                 \
  HookInitExtension(EXT_transform_feedback, CmdBindTransformFeedbackBuffersEXT);                   \
  HookInitExtension(EXT_transform_feedback, CmdBeginTransformFeedbackEXT);                         \
  HookInitExtension(EXT_transform_feedback, CmdEndTransformFeedbackEXT);                           \
  HookInitExtension(EXT_transform_feedback, CmdBeginQueryIndexedEXT);                              \
  HookInitExtension(EXT_transform_feedback, CmdEndQueryIndexedEXT);                                \
  HookInitExtension(EXT_transform_feedback, CmdDrawIndirectByteCountEXT);                          \
  HookInitDevice_PlatformSpecific()

#define DefineHooks()                                                                                \
  HookDefine3(VkResult, vkEnumeratePhysicalDevices, VkInstance, instance, uint32_t *,                \
              pPhysicalDeviceCount, VkPhysicalDevice *, pPhysicalDevices);                           \
  HookDefine2(void, vkGetPhysicalDeviceFeatures, VkPhysicalDevice, physicalDevice,                   \
              VkPhysicalDeviceFeatures *, pFeatures);                                                \
  HookDefine3(void, vkGetPhysicalDeviceFormatProperties, VkPhysicalDevice, physicalDevice,           \
              VkFormat, format, VkFormatProperties *, pFormatProperties);                            \
  HookDefine7(VkResult, vkGetPhysicalDeviceImageFormatProperties, VkPhysicalDevice, physicalDevice,  \
              VkFormat, format, VkImageType, type, VkImageTiling, tiling, VkImageUsageFlags,         \
              usage, VkImageCreateFlags, flags, VkImageFormatProperties *, pImageFormatProperties);  \
  HookDefine8(void, vkGetPhysicalDeviceSparseImageFormatProperties, VkPhysicalDevice,                \
              physicalDevice, VkFormat, format, VkImageType, type, VkSampleCountFlagBits, samples,   \
              VkImageUsageFlags, usage, VkImageTiling, tiling, uint32_t *, pNumProperties,           \
              VkSparseImageFormatProperties *, pProperties);                                         \
  HookDefine2(void, vkGetPhysicalDeviceProperties, VkPhysicalDevice, physicalDevice,                 \
              VkPhysicalDeviceProperties *, pProperties);                                            \
  HookDefine3(void, vkGetPhysicalDeviceQueueFamilyProperties, VkPhysicalDevice, physicalDevice,      \
              uint32_t *, pCount, VkQueueFamilyProperties *, pQueueFamilyProperties);                \
  HookDefine2(void, vkGetPhysicalDeviceMemoryProperties, VkPhysicalDevice, physicalDevice,           \
              VkPhysicalDeviceMemoryProperties *, pMemoryProperties);                                \
  HookDefine4(VkResult, vkCreateDevice, VkPhysicalDevice, physicalDevice,                            \
              const VkDeviceCreateInfo *, pCreateInfo, const VkAllocationCallbacks *, pAllocator,    \
              VkDevice *, pDevice);                                                                  \
  HookDefine2(void, vkDestroyDevice, VkDevice, device, const VkAllocationCallbacks *, pAllocator);   \
  HookDefine4(void, vkGetDeviceQueue, VkDevice, device, uint32_t, queueFamilyIndex, uint32_t,        \
              queueIndex, VkQueue *, pQueue);                                                        \
  HookDefine4(VkResult, vkQueueSubmit, VkQueue, queue, uint32_t, submitCount,                        \
              const VkSubmitInfo *, pSubmits, VkFence, fence);                                       \
  HookDefine1(VkResult, vkQueueWaitIdle, VkQueue, queue);                                            \
  HookDefine1(VkResult, vkDeviceWaitIdle, VkDevice, device);                                         \
  HookDefine4(VkResult, vkAllocateMemory, VkDevice, device, const VkMemoryAllocateInfo *,            \
              pAllocInfo, const VkAllocationCallbacks *, pAllocator, VkDeviceMemory *, pMemory);     \
  HookDefine3(void, vkFreeMemory, VkDevice, device, VkDeviceMemory, mem,                             \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine6(VkResult, vkMapMemory, VkDevice, device, VkDeviceMemory, mem, VkDeviceSize, offset,    \
              VkDeviceSize, size, VkMemoryMapFlags, flags, void **, ppData);                         \
  HookDefine2(void, vkUnmapMemory, VkDevice, device, VkDeviceMemory, mem);                           \
  HookDefine3(VkResult, vkFlushMappedMemoryRanges, VkDevice, device, uint32_t, memRangeCount,        \
              const VkMappedMemoryRange *, pMemRanges);                                              \
  HookDefine3(VkResult, vkInvalidateMappedMemoryRanges, VkDevice, device, uint32_t, memRangeCount,   \
              const VkMappedMemoryRange *, pMemRanges);                                              \
  HookDefine3(void, vkGetDeviceMemoryCommitment, VkDevice, device, VkDeviceMemory, memory,           \
              VkDeviceSize *, pCommittedMemoryInBytes);                                              \
  HookDefine4(VkResult, vkBindBufferMemory, VkDevice, device, VkBuffer, buffer, VkDeviceMemory,      \
              mem, VkDeviceSize, memOffset);                                                         \
  HookDefine4(VkResult, vkBindImageMemory, VkDevice, device, VkImage, image, VkDeviceMemory, mem,    \
              VkDeviceSize, memOffset);                                                              \
  HookDefine4(VkResult, vkQueueBindSparse, VkQueue, queue, uint32_t, bindInfoCount,                  \
              const VkBindSparseInfo *, pBindInfo, VkFence, fence);                                  \
  HookDefine4(VkResult, vkCreateBuffer, VkDevice, device, const VkBufferCreateInfo *, pCreateInfo,   \
              const VkAllocationCallbacks *, pAllocator, VkBuffer *, pBuffer);                       \
  HookDefine3(void, vkDestroyBuffer, VkDevice, device, VkBuffer, buffer,                             \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateBufferView, VkDevice, device, const VkBufferViewCreateInfo *,        \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkBufferView *, pView);        \
  HookDefine3(void, vkDestroyBufferView, VkDevice, device, VkBufferView, bufferView,                 \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateImage, VkDevice, device, const VkImageCreateInfo *, pCreateInfo,     \
              const VkAllocationCallbacks *, pAllocator, VkImage *, pImage);                         \
  HookDefine3(void, vkDestroyImage, VkDevice, device, VkImage, image,                                \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(void, vkGetImageSubresourceLayout, VkDevice, device, VkImage, image,                   \
              const VkImageSubresource *, pSubresource, VkSubresourceLayout *, pLayout);             \
  HookDefine3(void, vkGetBufferMemoryRequirements, VkDevice, device, VkBuffer, buffer,               \
              VkMemoryRequirements *, pMemoryRequirements);                                          \
  HookDefine3(void, vkGetImageMemoryRequirements, VkDevice, device, VkImage, image,                  \
              VkMemoryRequirements *, pMemoryRequirements);                                          \
  HookDefine4(void, vkGetImageSparseMemoryRequirements, VkDevice, device, VkImage, image,            \
              uint32_t *, pNumRequirements, VkSparseImageMemoryRequirements *,                       \
              pSparseMemoryRequirements);                                                            \
  HookDefine4(VkResult, vkCreateImageView, VkDevice, device, const VkImageViewCreateInfo *,          \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkImageView *, pView);         \
  HookDefine3(void, vkDestroyImageView, VkDevice, device, VkImageView, imageView,                    \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateShaderModule, VkDevice, device, const VkShaderModuleCreateInfo *,    \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkShaderModule *,              \
              pShaderModule);                                                                        \
  HookDefine3(void, vkDestroyShaderModule, VkDevice, device, VkShaderModule, shaderModule,           \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine6(VkResult, vkCreateGraphicsPipelines, VkDevice, device, VkPipelineCache,                \
              pipelineCache, uint32_t, count, const VkGraphicsPipelineCreateInfo *, pCreateInfos,    \
              const VkAllocationCallbacks *, pAllocator, VkPipeline *, pPipelines);                  \
  HookDefine6(VkResult, vkCreateComputePipelines, VkDevice, device, VkPipelineCache,                 \
              pipelineCache, uint32_t, count, const VkComputePipelineCreateInfo *, pCreateInfos,     \
              const VkAllocationCallbacks *, pAllocator, VkPipeline *, pPipelines);                  \
  HookDefine3(void, vkDestroyPipeline, VkDevice, device, VkPipeline, pipeline,                       \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreatePipelineCache, VkDevice, device,                                     \
              const VkPipelineCacheCreateInfo *, pCreateInfo, const VkAllocationCallbacks *,         \
              pAllocator, VkPipelineCache *, pPipelineCache);                                        \
  HookDefine3(void, vkDestroyPipelineCache, VkDevice, device, VkPipelineCache, pipelineCache,        \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkGetPipelineCacheData, VkDevice, device, VkPipelineCache, pipelineCache,    \
              size_t *, pDataSize, void *, pData);                                                   \
  HookDefine4(VkResult, vkMergePipelineCaches, VkDevice, device, VkPipelineCache, pipelineCache,     \
              uint32_t, srcCacheCount, const VkPipelineCache *, pSrcCaches);                         \
  HookDefine4(VkResult, vkCreatePipelineLayout, VkDevice, device,                                    \
              const VkPipelineLayoutCreateInfo *, pCreateInfo, const VkAllocationCallbacks *,        \
              pAllocator, VkPipelineLayout *, pPipelineLayout);                                      \
  HookDefine3(void, vkDestroyPipelineLayout, VkDevice, device, VkPipelineLayout, pipelineLayout,     \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateSemaphore, VkDevice, device, const VkSemaphoreCreateInfo *,          \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkSemaphore *, pSemaphore);    \
  HookDefine3(void, vkDestroySemaphore, VkDevice, device, VkSemaphore, semaphore,                    \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateFence, VkDevice, device, const VkFenceCreateInfo *, pCreateInfo,     \
              const VkAllocationCallbacks *, pAllocator, VkFence *, pFence);                         \
  HookDefine3(void, vkDestroyFence, VkDevice, device, VkFence, fence,                                \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateEvent, VkDevice, device, const VkEventCreateInfo *, pCreateInfo,     \
              const VkAllocationCallbacks *, pAllocator, VkEvent *, pEvent);                         \
  HookDefine3(void, vkDestroyEvent, VkDevice, device, VkEvent, event,                                \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine2(VkResult, vkGetEventStatus, VkDevice, device, VkEvent, event);                         \
  HookDefine2(VkResult, vkSetEvent, VkDevice, device, VkEvent, event);                               \
  HookDefine2(VkResult, vkResetEvent, VkDevice, device, VkEvent, event);                             \
  HookDefine4(VkResult, vkCreateQueryPool, VkDevice, device, const VkQueryPoolCreateInfo *,          \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkQueryPool *, pQueryPool);    \
  HookDefine3(void, vkDestroyQueryPool, VkDevice, device, VkQueryPool, queryPool,                    \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine8(VkResult, vkGetQueryPoolResults, VkDevice, device, VkQueryPool, queryPool, uint32_t,   \
              firstQuery, uint32_t, queryCount, size_t, dataSize, void *, pData, VkDeviceSize,       \
              stride, VkQueryResultFlags, flags);                                                    \
  HookDefine2(VkResult, vkGetFenceStatus, VkDevice, device, VkFence, fence);                         \
  HookDefine3(VkResult, vkResetFences, VkDevice, device, uint32_t, fenceCount, const VkFence *,      \
              pFences);                                                                              \
  HookDefine5(VkResult, vkWaitForFences, VkDevice, device, uint32_t, fenceCount, const VkFence *,    \
              pFences, VkBool32, waitAll, uint64_t, timeout);                                        \
  HookDefine4(VkResult, vkCreateSampler, VkDevice, device, const VkSamplerCreateInfo *,              \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkSampler *, pSampler);        \
  HookDefine3(void, vkDestroySampler, VkDevice, device, VkSampler, sampler,                          \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateDescriptorSetLayout, VkDevice, device,                               \
              const VkDescriptorSetLayoutCreateInfo *, pCreateInfo, const VkAllocationCallbacks *,   \
              pAllocator, VkDescriptorSetLayout *, pSetLayout);                                      \
  HookDefine3(void, vkDestroyDescriptorSetLayout, VkDevice, device, VkDescriptorSetLayout,           \
              descriptorSetLayout, const VkAllocationCallbacks *, pAllocator);                       \
  HookDefine4(VkResult, vkCreateDescriptorPool, VkDevice, device,                                    \
              const VkDescriptorPoolCreateInfo *, pCreateInfo, const VkAllocationCallbacks *,        \
              pAllocator, VkDescriptorPool *, pDescriptorPool);                                      \
  HookDefine3(void, vkDestroyDescriptorPool, VkDevice, device, VkDescriptorPool, descriptorPool,     \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine3(VkResult, vkResetDescriptorPool, VkDevice, device, VkDescriptorPool, descriptorPool,   \
              VkDescriptorPoolResetFlags, flags);                                                    \
  HookDefine3(VkResult, vkAllocateDescriptorSets, VkDevice, device,                                  \
              const VkDescriptorSetAllocateInfo *, pAllocateInfo, VkDescriptorSet *,                 \
              pDescriptorSets);                                                                      \
  HookDefine5(void, vkUpdateDescriptorSets, VkDevice, device, uint32_t, writeCount,                  \
              const VkWriteDescriptorSet *, pDescriptorWrites, uint32_t, copyCount,                  \
              const VkCopyDescriptorSet *, pDescriptorCopies);                                       \
  HookDefine4(VkResult, vkFreeDescriptorSets, VkDevice, device, VkDescriptorPool, descriptorPool,    \
              uint32_t, count, const VkDescriptorSet *, pDescriptorSets);                            \
  HookDefine4(VkResult, vkCreateCommandPool, VkDevice, device, const VkCommandPoolCreateInfo *,      \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkCommandPool *,               \
              pCommandPool);                                                                         \
  HookDefine3(void, vkDestroyCommandPool, VkDevice, device, VkCommandPool, commandPool,              \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine3(VkResult, vkResetCommandPool, VkDevice, device, VkCommandPool, commandPool,            \
              VkCommandPoolResetFlags, flags);                                                       \
  HookDefine3(VkResult, vkAllocateCommandBuffers, VkDevice, device,                                  \
              const VkCommandBufferAllocateInfo *, pCreateInfo, VkCommandBuffer *, pCommandBuffers); \
  HookDefine4(void, vkFreeCommandBuffers, VkDevice, device, VkCommandPool, commandPool, uint32_t,    \
              commandBufferCount, const VkCommandBuffer *, pCommandBuffers);                         \
  HookDefine2(VkResult, vkBeginCommandBuffer, VkCommandBuffer, commandBuffer,                        \
              const VkCommandBufferBeginInfo *, pBeginInfo);                                         \
  HookDefine1(VkResult, vkEndCommandBuffer, VkCommandBuffer, commandBuffer);                         \
  HookDefine2(VkResult, vkResetCommandBuffer, VkCommandBuffer, commandBuffer,                        \
              VkCommandBufferResetFlags, flags);                                                     \
  HookDefine3(void, vkCmdBindPipeline, VkCommandBuffer, commandBuffer, VkPipelineBindPoint,          \
              pipelineBindPoint, VkPipeline, pipeline);                                              \
  HookDefine4(void, vkCmdSetViewport, VkCommandBuffer, commandBuffer, uint32_t, firstViewport,       \
              uint32_t, viewportCount, const VkViewport *, pViewports);                              \
  HookDefine4(void, vkCmdSetScissor, VkCommandBuffer, commandBuffer, uint32_t, firstScissor,         \
              uint32_t, scissorCount, const VkRect2D *, pScissors);                                  \
  HookDefine2(void, vkCmdSetLineWidth, VkCommandBuffer, commandBuffer, float, lineWidth);            \
  HookDefine4(void, vkCmdSetDepthBias, VkCommandBuffer, commandBuffer, float, depthBias, float,      \
              depthBiasClamp, float, slopeScaledDepthBias);                                          \
  HookDefine2(void, vkCmdSetBlendConstants, VkCommandBuffer, commandBuffer, const float *,           \
              blendConst);                                                                           \
  HookDefine3(void, vkCmdSetDepthBounds, VkCommandBuffer, commandBuffer, float, minDepthBounds,      \
              float, maxDepthBounds);                                                                \
  HookDefine3(void, vkCmdSetStencilCompareMask, VkCommandBuffer, commandBuffer,                      \
              VkStencilFaceFlags, faceMask, uint32_t, compareMask);                                  \
  HookDefine3(void, vkCmdSetStencilWriteMask, VkCommandBuffer, commandBuffer, VkStencilFaceFlags,    \
              faceMask, uint32_t, writeMask);                                                        \
  HookDefine3(void, vkCmdSetStencilReference, VkCommandBuffer, commandBuffer, VkStencilFaceFlags,    \
              faceMask, uint32_t, reference);                                                        \
  HookDefine8(void, vkCmdBindDescriptorSets, VkCommandBuffer, commandBuffer, VkPipelineBindPoint,    \
              pipelineBindPoint, VkPipelineLayout, layout, uint32_t, firstSet, uint32_t, setCount,   \
              const VkDescriptorSet *, pDescriptorSets, uint32_t, dynamicOffsetCount,                \
              const uint32_t *, pDynamicOffsets);                                                    \
  HookDefine4(void, vkCmdBindIndexBuffer, VkCommandBuffer, commandBuffer, VkBuffer, buffer,          \
              VkDeviceSize, offset, VkIndexType, indexType);                                         \
  HookDefine5(void, vkCmdBindVertexBuffers, VkCommandBuffer, commandBuffer, uint32_t, firstBinding,  \
              uint32_t, bindingCount, const VkBuffer *, pBuffers, const VkDeviceSize *, pOffsets);   \
  HookDefine5(void, vkCmdDraw, VkCommandBuffer, commandBuffer, uint32_t, vertexCount, uint32_t,      \
              instanceCount, uint32_t, firstVertex, uint32_t, firstInstance);                        \
  HookDefine6(void, vkCmdDrawIndexed, VkCommandBuffer, commandBuffer, uint32_t, indexCount,          \
              uint32_t, instanceCount, uint32_t, firstIndex, int32_t, vertexOffset, uint32_t,        \
              firstInstance);                                                                        \
  HookDefine5(void, vkCmdDrawIndirect, VkCommandBuffer, commandBuffer, VkBuffer, buffer,             \
              VkDeviceSize, offset, uint32_t, count, uint32_t, stride);                              \
  HookDefine5(void, vkCmdDrawIndexedIndirect, VkCommandBuffer, commandBuffer, VkBuffer, buffer,      \
              VkDeviceSize, offset, uint32_t, count, uint32_t, stride);                              \
  HookDefine4(void, vkCmdDispatch, VkCommandBuffer, commandBuffer, uint32_t, x, uint32_t, y,         \
              uint32_t, z);                                                                          \
  HookDefine3(void, vkCmdDispatchIndirect, VkCommandBuffer, commandBuffer, VkBuffer, buffer,         \
              VkDeviceSize, offset);                                                                 \
  HookDefine6(void, vkCmdCopyBufferToImage, VkCommandBuffer, commandBuffer, VkBuffer, srcBuffer,     \
              VkImage, destImage, VkImageLayout, destImageLayout, uint32_t, regionCount,             \
              const VkBufferImageCopy *, pRegions);                                                  \
  HookDefine6(void, vkCmdCopyImageToBuffer, VkCommandBuffer, commandBuffer, VkImage, srcImage,       \
              VkImageLayout, srcImageLayout, VkBuffer, destBuffer, uint32_t, regionCount,            \
              const VkBufferImageCopy *, pRegions);                                                  \
  HookDefine5(void, vkCmdCopyBuffer, VkCommandBuffer, commandBuffer, VkBuffer, srcBuffer,            \
              VkBuffer, destBuffer, uint32_t, regionCount, const VkBufferCopy *, pRegions);          \
  HookDefine7(void, vkCmdCopyImage, VkCommandBuffer, commandBuffer, VkImage, srcImage,               \
              VkImageLayout, srcImageLayout, VkImage, destImage, VkImageLayout, destImageLayout,     \
              uint32_t, regionCount, const VkImageCopy *, pRegions);                                 \
  HookDefine8(void, vkCmdBlitImage, VkCommandBuffer, commandBuffer, VkImage, srcImage,               \
              VkImageLayout, srcImageLayout, VkImage, destImage, VkImageLayout, destImageLayout,     \
              uint32_t, regionCount, const VkImageBlit *, pRegions, VkFilter, filter);               \
  HookDefine7(void, vkCmdResolveImage, VkCommandBuffer, commandBuffer, VkImage, srcImage,            \
              VkImageLayout, srcImageLayout, VkImage, destImage, VkImageLayout, destImageLayout,     \
              uint32_t, regionCount, const VkImageResolve *, pRegions);                              \
  HookDefine5(void, vkCmdUpdateBuffer, VkCommandBuffer, commandBuffer, VkBuffer, destBuffer,         \
              VkDeviceSize, destOffset, VkDeviceSize, dataSize, const uint32_t *, pData);            \
  HookDefine5(void, vkCmdFillBuffer, VkCommandBuffer, commandBuffer, VkBuffer, destBuffer,           \
              VkDeviceSize, destOffset, VkDeviceSize, fillSize, uint32_t, data);                     \
  HookDefine6(void, vkCmdPushConstants, VkCommandBuffer, commandBuffer, VkPipelineLayout, layout,    \
              VkShaderStageFlags, stageFlags, uint32_t, start, uint32_t, length, const void *,       \
              values);                                                                               \
  HookDefine6(void, vkCmdClearColorImage, VkCommandBuffer, commandBuffer, VkImage, image,            \
              VkImageLayout, imageLayout, const VkClearColorValue *, pColor, uint32_t, rangeCount,   \
              const VkImageSubresourceRange *, pRanges);                                             \
  HookDefine6(void, vkCmdClearDepthStencilImage, VkCommandBuffer, commandBuffer, VkImage, image,     \
              VkImageLayout, imageLayout, const VkClearDepthStencilValue *, pDepthStencil,           \
              uint32_t, rangeCount, const VkImageSubresourceRange *, pRanges);                       \
  HookDefine5(void, vkCmdClearAttachments, VkCommandBuffer, commandBuffer, uint32_t,                 \
              attachmentCount, const VkClearAttachment *, pAttachments, uint32_t, rectCount,         \
              const VkClearRect *, pRects);                                                          \
  HookDefine10(void, vkCmdPipelineBarrier, VkCommandBuffer, commandBuffer, VkPipelineStageFlags,     \
               srcStageMask, VkPipelineStageFlags, destStageMask, VkDependencyFlags,                 \
               dependencyFlags, uint32_t, memoryBarrierCount, const VkMemoryBarrier *,               \
               pMemoryBarriers, uint32_t, bufferMemoryBarrierCount, const VkBufferMemoryBarrier *,   \
               pBufferMemoryBarriers, uint32_t, imageMemoryBarrierCount,                             \
               const VkImageMemoryBarrier *, pImageMemoryBarriers);                                  \
  HookDefine4(void, vkCmdWriteTimestamp, VkCommandBuffer, commandBuffer, VkPipelineStageFlagBits,    \
              pipelineStage, VkQueryPool, queryPool, uint32_t, query);                               \
  HookDefine8(void, vkCmdCopyQueryPoolResults, VkCommandBuffer, commandBuffer, VkQueryPool,          \
              queryPool, uint32_t, firstQuery, uint32_t, queryCount, VkBuffer, dstBuffer,            \
              VkDeviceSize, dstOffset, VkDeviceSize, stride, VkQueryResultFlags, flags);             \
  HookDefine4(void, vkCmdBeginQuery, VkCommandBuffer, commandBuffer, VkQueryPool, queryPool,         \
              uint32_t, query, VkQueryControlFlags, flags);                                          \
  HookDefine3(void, vkCmdEndQuery, VkCommandBuffer, commandBuffer, VkQueryPool, queryPool,           \
              uint32_t, query);                                                                      \
  HookDefine4(void, vkCmdResetQueryPool, VkCommandBuffer, commandBuffer, VkQueryPool, queryPool,     \
              uint32_t, firstQuery, uint32_t, queryCount);                                           \
  HookDefine3(void, vkCmdSetEvent, VkCommandBuffer, commandBuffer, VkEvent, event,                   \
              VkPipelineStageFlags, stageMask);                                                      \
  HookDefine3(void, vkCmdResetEvent, VkCommandBuffer, commandBuffer, VkEvent, event,                 \
              VkPipelineStageFlags, stageMask);                                                      \
  HookDefine11(void, vkCmdWaitEvents, VkCommandBuffer, commandBuffer, uint32_t, eventCount,          \
               const VkEvent *, pEvents, VkPipelineStageFlags, srcStageMask, VkPipelineStageFlags,   \
               dstStageMask, uint32_t, memoryBarrierCount, const VkMemoryBarrier *,                  \
               pMemoryBarriers, uint32_t, bufferMemoryBarrierCount, const VkBufferMemoryBarrier *,   \
               pBufferMemoryBarriers, uint32_t, imageMemoryBarrierCount,                             \
               const VkImageMemoryBarrier *, pImageMemoryBarriers);                                  \
  HookDefine4(VkResult, vkCreateFramebuffer, VkDevice, device, const VkFramebufferCreateInfo *,      \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkFramebuffer *,               \
              pFramebuffer);                                                                         \
  HookDefine3(void, vkDestroyFramebuffer, VkDevice, device, VkFramebuffer, framebuffer,              \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkCreateRenderPass, VkDevice, device, const VkRenderPassCreateInfo *,        \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkRenderPass *, pRenderPass);  \
  HookDefine3(void, vkDestroyRenderPass, VkDevice, device, VkRenderPass, renderPass,                 \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine3(void, vkGetRenderAreaGranularity, VkDevice, device, VkRenderPass, renderPass,          \
              VkExtent2D *, pGranularity);                                                           \
  HookDefine3(void, vkCmdBeginRenderPass, VkCommandBuffer, commandBuffer,                            \
              const VkRenderPassBeginInfo *, pRenderPassBegin, VkSubpassContents, contents);         \
  HookDefine2(void, vkCmdNextSubpass, VkCommandBuffer, commandBuffer, VkSubpassContents, contents);  \
  HookDefine3(void, vkCmdExecuteCommands, VkCommandBuffer, commandBuffer, uint32_t,                  \
              commandBufferCount, const VkCommandBuffer *, pCommandBuffers);                         \
  HookDefine1(void, vkCmdEndRenderPass, VkCommandBuffer, commandBuffer);                             \
  HookDefine4(VkResult, vkCreateDebugReportCallbackEXT, VkInstance, instance,                        \
              const VkDebugReportCallbackCreateInfoEXT *, pCreateInfo,                               \
              const VkAllocationCallbacks *, pAllocator, VkDebugReportCallbackEXT *, pCallback);     \
  HookDefine3(void, vkDestroyDebugReportCallbackEXT, VkInstance, instance,                           \
              VkDebugReportCallbackEXT, callback, const VkAllocationCallbacks *, pAllocator);        \
  HookDefine8(void, vkDebugReportMessageEXT, VkInstance, instance, VkDebugReportFlagsEXT, flags,     \
              VkDebugReportObjectTypeEXT, objectType, uint64_t, object, size_t, location, int32_t,   \
              messageCode, const char *, pLayerPrefix, const char *, pMessage);                      \
  HookDefine2(VkResult, vkDebugMarkerSetObjectTagEXT, VkDevice, device,                              \
              VkDebugMarkerObjectTagInfoEXT *, pTagInfo);                                            \
  HookDefine2(VkResult, vkDebugMarkerSetObjectNameEXT, VkDevice, device,                             \
              VkDebugMarkerObjectNameInfoEXT *, pNameInfo);                                          \
  HookDefine2(void, vkCmdDebugMarkerBeginEXT, VkCommandBuffer, commandBuffer,                        \
              VkDebugMarkerMarkerInfoEXT *, pMarkerInfo);                                            \
  HookDefine1(void, vkCmdDebugMarkerEndEXT, VkCommandBuffer, commandBuffer);                         \
  HookDefine2(void, vkCmdDebugMarkerInsertEXT, VkCommandBuffer, commandBuffer,                       \
              VkDebugMarkerMarkerInfoEXT *, pMarkerInfo);                                            \
  HookDefine4(VkResult, vkGetPhysicalDeviceSurfaceSupportKHR, VkPhysicalDevice, physicalDevice,      \
              uint32_t, queueFamilyIndex, VkSurfaceKHR, surface, VkBool32 *, pSupported);            \
  HookDefine3(VkResult, vkGetPhysicalDeviceSurfaceCapabilitiesKHR, VkPhysicalDevice, physicalDevice, \
              VkSurfaceKHR, surface, VkSurfaceCapabilitiesKHR *, pSurfaceProperties);                \
  HookDefine4(VkResult, vkGetPhysicalDeviceSurfaceFormatsKHR, VkPhysicalDevice, physicalDevice,      \
              VkSurfaceKHR, surface, uint32_t *, pSurfaceFormatCount, VkSurfaceFormatKHR *,          \
              pSurfaceFormats);                                                                      \
  HookDefine4(VkResult, vkGetPhysicalDeviceSurfacePresentModesKHR, VkPhysicalDevice,                 \
              physicalDevice, VkSurfaceKHR, surface, uint32_t *, pPresentModeCount,                  \
              VkPresentModeKHR *, pPresentModes);                                                    \
  HookDefine4(VkResult, vkCreateSwapchainKHR, VkDevice, device, const VkSwapchainCreateInfoKHR *,    \
              pCreateInfo, const VkAllocationCallbacks *, pAllocator, VkSwapchainKHR *, pSwapchain); \
  HookDefine3(void, vkDestroySwapchainKHR, VkDevice, device, VkSwapchainKHR, swapchain,              \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine4(VkResult, vkGetSwapchainImagesKHR, VkDevice, device, VkSwapchainKHR, swapchain,        \
              uint32_t *, pCount, VkImage *, pSwapchainImages);                                      \
  HookDefine6(VkResult, vkAcquireNextImageKHR, VkDevice, device, VkSwapchainKHR, swapchain,          \
              uint64_t, timeout, VkSemaphore, semaphore, VkFence, fence, uint32_t *, pImageIndex);   \
  HookDefine2(VkResult, vkQueuePresentKHR, VkQueue, queue, VkPresentInfoKHR *, pPresentInfo);        \
  HookDefine3(void, vkDestroySurfaceKHR, VkInstance, instance, VkSurfaceKHR, surface,                \
              const VkAllocationCallbacks *, pAllocator);                                            \
  HookDefine3(VkResult, vkGetPhysicalDeviceDisplayPropertiesKHR, VkPhysicalDevice, physicalDevice,   \
              uint32_t *, pPropertyCount, VkDisplayPropertiesKHR *, pProperties);                    \
  HookDefine3(VkResult, vkGetPhysicalDeviceDisplayPlanePropertiesKHR, VkPhysicalDevice,              \
              physicalDevice, uint32_t *, pPropertyCount, VkDisplayPlanePropertiesKHR *,             \
              pProperties);                                                                          \
  HookDefine4(VkResult, vkGetDisplayPlaneSupportedDisplaysKHR, VkPhysicalDevice, physicalDevice,     \
              uint32_t, planeIndex, uint32_t *, pDisplayCount, VkDisplayKHR *, pDisplays);           \
  HookDefine4(VkResult, vkGetDisplayModePropertiesKHR, VkPhysicalDevice, physicalDevice,             \
              VkDisplayKHR, display, uint32_t *, pPropertyCount, VkDisplayModePropertiesKHR *,       \
              pProperties);                                                                          \
  HookDefine5(VkResult, vkCreateDisplayModeKHR, VkPhysicalDevice, physicalDevice, VkDisplayKHR,      \
              display, const VkDisplayModeCreateInfoKHR *, pCreateInfo,                              \
              const VkAllocationCallbacks *, pAllocator, VkDisplayModeKHR *, pMode);                 \
  HookDefine4(VkResult, vkGetDisplayPlaneCapabilitiesKHR, VkPhysicalDevice, physicalDevice,          \
              VkDisplayModeKHR, mode, uint32_t, planeIndex, VkDisplayPlaneCapabilitiesKHR *,         \
              pCapabilities);                                                                        \
  HookDefine4(VkResult, vkCreateDisplayPlaneSurfaceKHR, VkInstance, instance,                        \
              const VkDisplaySurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *,     \
              pAllocator, VkSurfaceKHR *, pSurface);                                                 \
  HookDefine5(VkResult, vkCreateSharedSwapchainsKHR, VkDevice, device, uint32_t, swapchainCount,     \
              const VkSwapchainCreateInfoKHR *, pCreateInfos, const VkAllocationCallbacks *,         \
              pAllocator, VkSwapchainKHR *, pSwapchains);                                            \
  HookDefine8(VkResult, vkGetPhysicalDeviceExternalImageFormatPropertiesNV, VkPhysicalDevice,        \
              physicalDevice, VkFormat, format, VkImageType, type, VkImageTiling, tiling,            \
              VkImageUsageFlags, usage, VkImageCreateFlags, flags,                                   \
              VkExternalMemoryHandleTypeFlagsNV, externalHandleType,                                 \
              VkExternalImageFormatPropertiesNV *, pExternalImageFormatProperties);                  \
  HookDefine3(void, vkTrimCommandPool, VkDevice, device, VkCommandPool, commandPool,                 \
              VkCommandPoolTrimFlags, flags);                                                        \
  HookDefine2(void, vkGetPhysicalDeviceFeatures2, VkPhysicalDevice, physicalDevice,                  \
              VkPhysicalDeviceFeatures2 *, pFeatures);                                               \
  HookDefine2(void, vkGetPhysicalDeviceProperties2, VkPhysicalDevice, physicalDevice,                \
              VkPhysicalDeviceProperties2 *, pProperties);                                           \
  HookDefine3(void, vkGetPhysicalDeviceFormatProperties2, VkPhysicalDevice, physicalDevice,          \
              VkFormat, format, VkFormatProperties2 *, pFormatProperties);                           \
  HookDefine3(VkResult, vkGetPhysicalDeviceImageFormatProperties2, VkPhysicalDevice,                 \
              physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *, pImageFormatInfo,            \
              VkImageFormatProperties2 *, pImageFormatProperties);                                   \
  HookDefine3(void, vkGetPhysicalDeviceQueueFamilyProperties2, VkPhysicalDevice, physicalDevice,     \
              uint32_t *, pCount, VkQueueFamilyProperties2 *, pQueueFamilyProperties);               \
  HookDefine2(void, vkGetPhysicalDeviceMemoryProperties2, VkPhysicalDevice, physicalDevice,          \
              VkPhysicalDeviceMemoryProperties2 *, pMemoryProperties);                               \
  HookDefine4(void, vkGetPhysicalDeviceSparseImageFormatProperties2, VkPhysicalDevice,               \
              physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 *, pFormatInfo,           \
              uint32_t *, pPropertyCount, VkSparseImageFormatProperties2 *, pProperties);            \
  HookDefine3(VkResult, vkGetPhysicalDeviceSurfaceCapabilities2EXT, VkPhysicalDevice,                \
              physicalDevice, VkSurfaceKHR, surface, VkSurfaceCapabilities2EXT *,                    \
              pSurfaceCapabilities);                                                                 \
  HookDefine3(VkResult, vkDisplayPowerControlEXT, VkDevice, device, VkDisplayKHR, display,           \
              const VkDisplayPowerInfoEXT *, pDisplayPowerInfo);                                     \
  HookDefine4(VkResult, vkRegisterDeviceEventEXT, VkDevice, device, const VkDeviceEventInfoEXT *,    \
              pDeviceEventInfo, const VkAllocationCallbacks *, pAllocator, VkFence *, pFence);       \
  HookDefine5(VkResult, vkRegisterDisplayEventEXT, VkDevice, device, VkDisplayKHR, display,          \
              const VkDisplayEventInfoEXT *, pDisplayEventInfo, const VkAllocationCallbacks *,       \
              pAllocator, VkFence *, pFence);                                                        \
  HookDefine4(VkResult, vkGetSwapchainCounterEXT, VkDevice, device, VkSwapchainKHR, swapchain,       \
              VkSurfaceCounterFlagBitsEXT, counter, uint64_t *, pCounterValue);                      \
  HookDefine2(VkResult, vkReleaseDisplayEXT, VkPhysicalDevice, physicalDevice, VkDisplayKHR,         \
              display);                                                                              \
  HookDefine3(void, vkGetPhysicalDeviceExternalBufferProperties, VkPhysicalDevice, physicalDevice,   \
              const VkPhysicalDeviceExternalBufferInfo *, pExternalBufferInfo,                       \
              VkExternalBufferProperties *, pExternalBufferProperties);                              \
  HookDefine3(VkResult, vkGetMemoryFdKHR, VkDevice, device, const VkMemoryGetFdInfoKHR *,            \
              pGetFdInfo, int *, pFd);                                                               \
  HookDefine4(VkResult, vkGetMemoryFdPropertiesKHR, VkDevice, device,                                \
              VkExternalMemoryHandleTypeFlagBits, handleType, int, fd, VkMemoryFdPropertiesKHR *,    \
              pMemoryFdProperties);                                                                  \
  HookDefine3(void, vkGetPhysicalDeviceExternalSemaphoreProperties, VkPhysicalDevice,                \
              physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *, pExternalSemaphoreInfo, \
              VkExternalSemaphoreProperties *, pExternalSemaphoreProperties);                        \
  HookDefine2(VkResult, vkImportSemaphoreFdKHR, VkDevice, device,                                    \
              const VkImportSemaphoreFdInfoKHR *, pImportSemaphoreFdInfo);                           \
  HookDefine3(VkResult, vkGetSemaphoreFdKHR, VkDevice, device, const VkSemaphoreGetFdInfoKHR *,      \
              pGetFdInfo, int *, pFd);                                                               \
  HookDefine3(void, vkGetPhysicalDeviceExternalFenceProperties, VkPhysicalDevice, physicalDevice,    \
              const VkPhysicalDeviceExternalFenceInfo *, pExternalFenceInfo,                         \
              VkExternalFenceProperties *, pExternalFenceProperties);                                \
  HookDefine2(VkResult, vkImportFenceFdKHR, VkDevice, device, const VkImportFenceFdInfoKHR *,        \
              pImportFenceFdInfo);                                                                   \
  HookDefine3(VkResult, vkGetFenceFdKHR, VkDevice, device, const VkFenceGetFdInfoKHR *,              \
              pGetFdInfo, int *, pFd);                                                               \
  HookDefine3(void, vkGetImageMemoryRequirements2, VkDevice, device,                                 \
              const VkImageMemoryRequirementsInfo2 *, pInfo, VkMemoryRequirements2 *,                \
              pMemoryRequirements);                                                                  \
  HookDefine3(void, vkGetBufferMemoryRequirements2, VkDevice, device,                                \
              const VkBufferMemoryRequirementsInfo2 *, pInfo, VkMemoryRequirements2 *,               \
              pMemoryRequirements);                                                                  \
  HookDefine4(void, vkGetImageSparseMemoryRequirements2, VkDevice, device,                           \
              const VkImageSparseMemoryRequirementsInfo2 *, pInfo, uint32_t *,                       \
              pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2 *,                     \
              pSparseMemoryRequirements);                                                            \
  HookDefine6(VkResult, vkGetShaderInfoAMD, VkDevice, device, VkPipeline, pipeline,                  \
              VkShaderStageFlagBits, shaderStage, VkShaderInfoTypeAMD, infoType, size_t *,           \
              pInfoSize, void *, pInfo);                                                             \
  HookDefine6(void, vkCmdPushDescriptorSetKHR, VkCommandBuffer, commandBuffer,                       \
              VkPipelineBindPoint, pipelineBindPoint, VkPipelineLayout, layout, uint32_t, set,       \
              uint32_t, descriptorWriteCount, const VkWriteDescriptorSet *, pDescriptorWrites);      \
  HookDefine4(VkResult, vkCreateDescriptorUpdateTemplate, VkDevice, device,                          \
              const VkDescriptorUpdateTemplateCreateInfo *, pCreateInfo,                             \
              const VkAllocationCallbacks *, pAllocator, VkDescriptorUpdateTemplate *,               \
              pDescriptorUpdateTemplate);                                                            \
  HookDefine3(void, vkDestroyDescriptorUpdateTemplate, VkDevice, device, VkDescriptorUpdateTemplate, \
              descriptorUpdateTemplate, const VkAllocationCallbacks *, pAllocator);                  \
  HookDefine4(void, vkUpdateDescriptorSetWithTemplate, VkDevice, device, VkDescriptorSet,            \
              descriptorSet, VkDescriptorUpdateTemplate, descriptorUpdateTemplate, const void *,     \
              pData);                                                                                \
  HookDefine5(void, vkCmdPushDescriptorSetWithTemplateKHR, VkCommandBuffer, commandBuffer,           \
              VkDescriptorUpdateTemplate, descriptorUpdateTemplate, VkPipelineLayout, layout,        \
              uint32_t, set, const void *, pData);                                                   \
  HookDefine3(VkResult, vkBindBufferMemory2, VkDevice, device, uint32_t, bindInfoCount,              \
              const VkBindBufferMemoryInfo *, pBindInfos);                                           \
  HookDefine3(VkResult, vkBindImageMemory2, VkDevice, device, uint32_t, bindInfoCount,               \
              const VkBindImageMemoryInfo *, pBindInfos);                                            \
  HookDefine3(void, vkGetDescriptorSetLayoutSupport, VkDevice, device,                               \
              const VkDescriptorSetLayoutCreateInfo *, pCreateInfo,                                  \
              VkDescriptorSetLayoutSupport *, pSupport);                                             \
  HookDefine5(void, vkCmdWriteBufferMarkerAMD, VkCommandBuffer, commandBuffer,                       \
              VkPipelineStageFlagBits, pipelineStage, VkBuffer, dstBuffer, VkDeviceSize,             \
              dstOffset, uint32_t, marker);                                                          \
  HookDefine2(VkResult, vkSetDebugUtilsObjectNameEXT, VkDevice, device,                              \
              const VkDebugUtilsObjectNameInfoEXT *, pNameInfo);                                     \
  HookDefine2(VkResult, vkSetDebugUtilsObjectTagEXT, VkDevice, device,                               \
              const VkDebugUtilsObjectTagInfoEXT *, pTagInfo);                                       \
  HookDefine2(void, vkQueueBeginDebugUtilsLabelEXT, VkQueue, queue, const VkDebugUtilsLabelEXT *,    \
              pLabelInfo);                                                                           \
  HookDefine1(void, vkQueueEndDebugUtilsLabelEXT, VkQueue, queue);                                   \
  HookDefine2(void, vkQueueInsertDebugUtilsLabelEXT, VkQueue, queue, const VkDebugUtilsLabelEXT *,   \
              pLabelInfo);                                                                           \
  HookDefine2(void, vkCmdBeginDebugUtilsLabelEXT, VkCommandBuffer, commandBuffer,                    \
              const VkDebugUtilsLabelEXT *, pLabelInfo);                                             \
  HookDefine1(void, vkCmdEndDebugUtilsLabelEXT, VkCommandBuffer, commandBuffer);                     \
  HookDefine2(void, vkCmdInsertDebugUtilsLabelEXT, VkCommandBuffer, commandBuffer,                   \
              const VkDebugUtilsLabelEXT *, pLabelInfo);                                             \
  HookDefine4(VkResult, vkCreateDebugUtilsMessengerEXT, VkInstance, instance,                        \
              const VkDebugUtilsMessengerCreateInfoEXT *, pCreateInfo,                               \
              const VkAllocationCallbacks *, pAllocator, VkDebugUtilsMessengerEXT *, pMessenger);    \
  HookDefine3(void, vkDestroyDebugUtilsMessengerEXT, VkInstance, instance,                           \
              VkDebugUtilsMessengerEXT, messenger, const VkAllocationCallbacks *, pAllocator);       \
  HookDefine4(void, vkSubmitDebugUtilsMessageEXT, VkInstance, instance,                              \
              VkDebugUtilsMessageSeverityFlagBitsEXT, messageSeverity,                               \
              VkDebugUtilsMessageTypeFlagsEXT, messageTypes,                                         \
              const VkDebugUtilsMessengerCallbackDataEXT *, pCallbackData);                          \
  HookDefine4(VkResult, vkCreateSamplerYcbcrConversion, VkDevice, device,                            \
              const VkSamplerYcbcrConversionCreateInfo *, pCreateInfo,                               \
              const VkAllocationCallbacks *, pAllocator, VkSamplerYcbcrConversion *,                 \
              pYcbcrConversion);                                                                     \
  HookDefine3(void, vkDestroySamplerYcbcrConversion, VkDevice, device, VkSamplerYcbcrConversion,     \
              ycbcrConversion, const VkAllocationCallbacks *, pAllocator);                           \
  HookDefine3(VkResult, vkEnumeratePhysicalDeviceGroups, VkInstance, instance, uint32_t *,           \
              pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *,                          \
              pPhysicalDeviceGroupProperties);                                                       \
  HookDefine5(void, vkGetDeviceGroupPeerMemoryFeatures, VkDevice, device, uint32_t, heapIndex,       \
              uint32_t, localDeviceIndex, uint32_t, remoteDeviceIndex, VkPeerMemoryFeatureFlags *,   \
              pPeerMemoryFeatures);                                                                  \
  HookDefine2(void, vkCmdSetDeviceMask, VkCommandBuffer, commandBuffer, uint32_t, deviceMask);       \
  HookDefine7(void, vkCmdDispatchBase, VkCommandBuffer, commandBuffer, uint32_t, baseGroupX,         \
              uint32_t, baseGroupY, uint32_t, baseGroupZ, uint32_t, groupCountX, uint32_t,           \
              groupCountY, uint32_t, groupCountZ);                                                   \
  HookDefine2(VkResult, vkGetDeviceGroupPresentCapabilitiesKHR, VkDevice, device,                    \
              VkDeviceGroupPresentCapabilitiesKHR *, pDeviceGroupPresentCapabilities);               \
  HookDefine3(VkResult, vkGetDeviceGroupSurfacePresentModesKHR, VkDevice, device, VkSurfaceKHR,      \
              surface, VkDeviceGroupPresentModeFlagsKHR *, pModes);                                  \
  HookDefine4(VkResult, vkGetPhysicalDevicePresentRectanglesKHR, VkPhysicalDevice, physicalDevice,   \
              VkSurfaceKHR, surface, uint32_t *, pRectCount, VkRect2D *, pRects);                    \
  HookDefine3(VkResult, vkAcquireNextImage2KHR, VkDevice, device,                                    \
              const VkAcquireNextImageInfoKHR *, pAcquireInfo, uint32_t *, pImageIndex);             \
  HookDefine3(void, vkGetDeviceQueue2, VkDevice, device, const VkDeviceQueueInfo2 *, pQueueInfo,     \
              VkQueue *, pQueue);                                                                    \
  HookDefine3(VkResult, vkGetPhysicalDeviceSurfaceCapabilities2KHR, VkPhysicalDevice,                \
              physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, pSurfaceInfo,                 \
              VkSurfaceCapabilities2KHR *, pSurfaceCapabilities);                                    \
  HookDefine4(VkResult, vkGetPhysicalDeviceSurfaceFormats2KHR, VkPhysicalDevice, physicalDevice,     \
              const VkPhysicalDeviceSurfaceInfo2KHR *, pSurfaceInfo, uint32_t *,                     \
              pSurfaceFormatCount, VkSurfaceFormat2KHR *, pSurfaceFormats);                          \
  HookDefine3(VkResult, vkGetPhysicalDeviceDisplayProperties2KHR, VkPhysicalDevice,                  \
              physicalDevice, uint32_t *, pPropertyCount, VkDisplayProperties2KHR *, pProperties);   \
  HookDefine3(VkResult, vkGetPhysicalDeviceDisplayPlaneProperties2KHR, VkPhysicalDevice,             \
              physicalDevice, uint32_t *, pPropertyCount, VkDisplayPlaneProperties2KHR *,            \
              pProperties);                                                                          \
  HookDefine4(VkResult, vkGetDisplayModeProperties2KHR, VkPhysicalDevice, physicalDevice,            \
              VkDisplayKHR, display, uint32_t *, pPropertyCount, VkDisplayModeProperties2KHR *,      \
              pProperties);                                                                          \
  HookDefine3(VkResult, vkGetDisplayPlaneCapabilities2KHR, VkPhysicalDevice, physicalDevice,         \
              const VkDisplayPlaneInfo2KHR *, pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR *,   \
              pCapabilities);                                                                        \
  HookDefine7(void, vkCmdDrawIndirectCountKHR, VkCommandBuffer, commandBuffer, VkBuffer, buffer,     \
              VkDeviceSize, offset, VkBuffer, countBuffer, VkDeviceSize, countBufferOffset,          \
              uint32_t, maxDrawCount, uint32_t, stride);                                             \
  HookDefine7(void, vkCmdDrawIndexedIndirectCountKHR, VkCommandBuffer, commandBuffer, VkBuffer,      \
              buffer, VkDeviceSize, offset, VkBuffer, countBuffer, VkDeviceSize,                     \
              countBufferOffset, uint32_t, maxDrawCount, uint32_t, stride);                          \
  HookDefine4(VkResult, vkCreateValidationCacheEXT, VkDevice, device,                                \
              const VkValidationCacheCreateInfoEXT *, pCreateInfo, const VkAllocationCallbacks *,    \
              pAllocator, VkValidationCacheEXT *, pValidationCache);                                 \
  HookDefine3(void, vkDestroyValidationCacheEXT, VkDevice, device, VkValidationCacheEXT,             \
              validationCache, const VkAllocationCallbacks *, pAllocator);                           \
  HookDefine4(VkResult, vkMergeValidationCachesEXT, VkDevice, device, VkValidationCacheEXT,          \
              dstCache, uint32_t, srcCacheCount, const VkValidationCacheEXT *, pSrcCaches);          \
  HookDefine4(VkResult, vkGetValidationCacheDataEXT, VkDevice, device, VkValidationCacheEXT,         \
              validationCache, size_t *, pDataSize, void *, pData);                                  \
  HookDefine2(VkResult, vkGetSwapchainStatusKHR, VkDevice, device, VkSwapchainKHR, swapchain);       \
  HookDefine4(VkResult, vkCreateRenderPass2KHR, VkDevice, device,                                    \
              const VkRenderPassCreateInfo2KHR *, pCreateInfo, const VkAllocationCallbacks *,        \
              pAllocator, VkRenderPass *, pRenderPass);                                              \
  HookDefine3(void, vkCmdBeginRenderPass2KHR, VkCommandBuffer, commandBuffer,                        \
              const VkRenderPassBeginInfo *, pRenderPassBegin, const VkSubpassBeginInfoKHR *,        \
              pSubpassBeginInfo);                                                                    \
  HookDefine3(void, vkCmdNextSubpass2KHR, VkCommandBuffer, commandBuffer,                            \
              const VkSubpassBeginInfoKHR *, pSubpassBeginInfo, const VkSubpassEndInfoKHR *,         \
              pSubpassEndInfo);                                                                      \
  HookDefine2(void, vkCmdEndRenderPass2KHR, VkCommandBuffer, commandBuffer,                          \
              const VkSubpassEndInfoKHR *, pSubpassEndInfo);                                         \
  HookDefine6(void, vkCmdBindTransformFeedbackBuffersEXT, VkCommandBuffer, commandBuffer,            \
              uint32_t, firstBinding, uint32_t, bindingCount, const VkBuffer *, pBuffers,            \
              const VkDeviceSize *, pOffsets, const VkDeviceSize *, pSizes);                         \
  HookDefine5(void, vkCmdBeginTransformFeedbackEXT, VkCommandBuffer, commandBuffer, uint32_t,        \
              firstBuffer, uint32_t, bufferCount, const VkBuffer *, pCounterBuffers,                 \
              const VkDeviceSize *, pCounterBufferOffsets);                                          \
  HookDefine5(void, vkCmdEndTransformFeedbackEXT, VkCommandBuffer, commandBuffer, uint32_t,          \
              firstBuffer, uint32_t, bufferCount, const VkBuffer *, pCounterBuffers,                 \
              const VkDeviceSize *, pCounterBufferOffsets);                                          \
  HookDefine5(void, vkCmdBeginQueryIndexedEXT, VkCommandBuffer, commandBuffer, VkQueryPool,          \
              queryPool, uint32_t, query, VkQueryControlFlags, flags, uint32_t, index);              \
  HookDefine4(void, vkCmdEndQueryIndexedEXT, VkCommandBuffer, commandBuffer, VkQueryPool,            \
              queryPool, uint32_t, query, uint32_t, index);                                          \
  HookDefine7(void, vkCmdDrawIndirectByteCountEXT, VkCommandBuffer, commandBuffer, uint32_t,         \
              instanceCount, uint32_t, firstInstance, VkBuffer, counterBuffer, VkDeviceSize,         \
              counterBufferOffset, uint32_t, counterOffset, uint32_t, vertexStride);                 \
  HookDefine_PlatformSpecific()

struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable
{
};

struct VkLayerDispatchTableExtended : VkLayerDispatchTable
{
  // for consistency & ease, we declare the CreateDevice pointer here
  // even though it won't actually ever get used and is on the instance dispatch chain
  PFN_vkCreateDevice CreateDevice;
};
