From a9e4528d103d7d8f5cc912450a9bf071994a6044 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Fri, 27 Mar 2020 02:52:31 -0300
Subject: [PATCH] renderer_vulkan/wrapper: Add dispatch table and loaders

---
 src/video_core/renderer_vulkan/wrapper.cpp | 146 +++++++++++++++++++++
 src/video_core/renderer_vulkan/wrapper.h   | 137 +++++++++++++++++++
 2 files changed, 283 insertions(+)

diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp
index 1adf1b8c2..6d7e141e1 100644
--- a/src/video_core/renderer_vulkan/wrapper.cpp
+++ b/src/video_core/renderer_vulkan/wrapper.cpp
@@ -14,6 +14,152 @@
 
 namespace Vulkan::vk {
 
+namespace {
+
+template <typename T>
+bool Proc(T& result, const InstanceDispatch& dld, const char* proc_name,
+          VkInstance instance = nullptr) noexcept {
+    result = reinterpret_cast<T>(dld.vkGetInstanceProcAddr(instance, proc_name));
+    return result != nullptr;
+}
+
+template <typename T>
+void Proc(T& result, const DeviceDispatch& dld, const char* proc_name, VkDevice device) noexcept {
+    result = reinterpret_cast<T>(dld.vkGetDeviceProcAddr(device, proc_name));
+}
+
+void Load(VkDevice device, DeviceDispatch& dld) noexcept {
+#define X(name) Proc(dld.name, dld, #name, device)
+    X(vkAcquireNextImageKHR);
+    X(vkAllocateCommandBuffers);
+    X(vkAllocateDescriptorSets);
+    X(vkAllocateMemory);
+    X(vkBeginCommandBuffer);
+    X(vkBindBufferMemory);
+    X(vkBindImageMemory);
+    X(vkCmdBeginQuery);
+    X(vkCmdBeginRenderPass);
+    X(vkCmdBeginTransformFeedbackEXT);
+    X(vkCmdBindDescriptorSets);
+    X(vkCmdBindIndexBuffer);
+    X(vkCmdBindPipeline);
+    X(vkCmdBindTransformFeedbackBuffersEXT);
+    X(vkCmdBindVertexBuffers);
+    X(vkCmdBlitImage);
+    X(vkCmdClearAttachments);
+    X(vkCmdCopyBuffer);
+    X(vkCmdCopyBufferToImage);
+    X(vkCmdCopyImage);
+    X(vkCmdCopyImageToBuffer);
+    X(vkCmdDispatch);
+    X(vkCmdDraw);
+    X(vkCmdDrawIndexed);
+    X(vkCmdEndQuery);
+    X(vkCmdEndRenderPass);
+    X(vkCmdEndTransformFeedbackEXT);
+    X(vkCmdFillBuffer);
+    X(vkCmdPipelineBarrier);
+    X(vkCmdPushConstants);
+    X(vkCmdSetBlendConstants);
+    X(vkCmdSetCheckpointNV);
+    X(vkCmdSetDepthBias);
+    X(vkCmdSetDepthBounds);
+    X(vkCmdSetScissor);
+    X(vkCmdSetStencilCompareMask);
+    X(vkCmdSetStencilReference);
+    X(vkCmdSetStencilWriteMask);
+    X(vkCmdSetViewport);
+    X(vkCreateBuffer);
+    X(vkCreateBufferView);
+    X(vkCreateCommandPool);
+    X(vkCreateComputePipelines);
+    X(vkCreateDescriptorPool);
+    X(vkCreateDescriptorSetLayout);
+    X(vkCreateDescriptorUpdateTemplateKHR);
+    X(vkCreateFence);
+    X(vkCreateFramebuffer);
+    X(vkCreateGraphicsPipelines);
+    X(vkCreateImage);
+    X(vkCreateImageView);
+    X(vkCreatePipelineLayout);
+    X(vkCreateQueryPool);
+    X(vkCreateRenderPass);
+    X(vkCreateSampler);
+    X(vkCreateSemaphore);
+    X(vkCreateShaderModule);
+    X(vkCreateSwapchainKHR);
+    X(vkDestroyBuffer);
+    X(vkDestroyBufferView);
+    X(vkDestroyCommandPool);
+    X(vkDestroyDescriptorPool);
+    X(vkDestroyDescriptorSetLayout);
+    X(vkDestroyDescriptorUpdateTemplateKHR);
+    X(vkDestroyFence);
+    X(vkDestroyFramebuffer);
+    X(vkDestroyImage);
+    X(vkDestroyImageView);
+    X(vkDestroyPipeline);
+    X(vkDestroyPipelineLayout);
+    X(vkDestroyQueryPool);
+    X(vkDestroyRenderPass);
+    X(vkDestroySampler);
+    X(vkDestroySemaphore);
+    X(vkDestroyShaderModule);
+    X(vkDestroySwapchainKHR);
+    X(vkDeviceWaitIdle);
+    X(vkEndCommandBuffer);
+    X(vkFreeCommandBuffers);
+    X(vkFreeDescriptorSets);
+    X(vkFreeMemory);
+    X(vkGetBufferMemoryRequirements);
+    X(vkGetDeviceQueue);
+    X(vkGetFenceStatus);
+    X(vkGetImageMemoryRequirements);
+    X(vkGetQueryPoolResults);
+    X(vkGetQueueCheckpointDataNV);
+    X(vkMapMemory);
+    X(vkQueueSubmit);
+    X(vkResetFences);
+    X(vkResetQueryPoolEXT);
+    X(vkUnmapMemory);
+    X(vkUpdateDescriptorSetWithTemplateKHR);
+    X(vkUpdateDescriptorSets);
+    X(vkWaitForFences);
+#undef X
+}
+
+} // Anonymous namespace
+
+bool Load(InstanceDispatch& dld) noexcept {
+#define X(name) Proc(dld.name, dld, #name)
+    return X(vkCreateInstance) && X(vkEnumerateInstanceExtensionProperties);
+#undef X
+}
+
+bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
+#define X(name) Proc(dld.name, dld, #name, instance)
+    // These functions may fail to load depending on the enabled extensions.
+    // Don't return a failure on these.
+    X(vkCreateDebugUtilsMessengerEXT);
+    X(vkDestroyDebugUtilsMessengerEXT);
+    X(vkDestroySurfaceKHR);
+    X(vkGetPhysicalDeviceFeatures2KHR);
+    X(vkGetPhysicalDeviceProperties2KHR);
+    X(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
+    X(vkGetPhysicalDeviceSurfaceFormatsKHR);
+    X(vkGetPhysicalDeviceSurfacePresentModesKHR);
+    X(vkGetPhysicalDeviceSurfaceSupportKHR);
+    X(vkGetSwapchainImagesKHR);
+    X(vkQueuePresentKHR);
+
+    return X(vkCreateDevice) && X(vkDestroyDevice) && X(vkDestroyDevice) &&
+           X(vkEnumerateDeviceExtensionProperties) && X(vkEnumeratePhysicalDevices) &&
+           X(vkGetDeviceProcAddr) && X(vkGetPhysicalDeviceFormatProperties) &&
+           X(vkGetPhysicalDeviceMemoryProperties) && X(vkGetPhysicalDeviceProperties) &&
+           X(vkGetPhysicalDeviceQueueFamilyProperties);
+#undef X
+}
+
 const char* Exception::what() const noexcept {
     return ToString(result);
 }
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h
index b13d3882e..f5f868233 100644
--- a/src/video_core/renderer_vulkan/wrapper.h
+++ b/src/video_core/renderer_vulkan/wrapper.h
@@ -113,4 +113,141 @@ inline VkResult Filter(VkResult result) {
     return result;
 }
 
+/// Table holding Vulkan instance function pointers.
+struct InstanceDispatch {
+    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+
+    PFN_vkCreateInstance vkCreateInstance;
+    PFN_vkDestroyInstance vkDestroyInstance;
+    PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
+
+    PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
+    PFN_vkCreateDevice vkCreateDevice;
+    PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
+    PFN_vkDestroyDevice vkDestroyDevice;
+    PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
+    PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
+    PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
+    PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+    PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
+    PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
+    PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
+    PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
+    PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
+    PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
+    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
+    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
+    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
+    PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
+    PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
+    PFN_vkQueuePresentKHR vkQueuePresentKHR;
+};
+
+/// Table holding Vulkan device function pointers.
+struct DeviceDispatch : public InstanceDispatch {
+    PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
+    PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
+    PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets;
+    PFN_vkAllocateMemory vkAllocateMemory;
+    PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
+    PFN_vkBindBufferMemory vkBindBufferMemory;
+    PFN_vkBindImageMemory vkBindImageMemory;
+    PFN_vkCmdBeginQuery vkCmdBeginQuery;
+    PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
+    PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT;
+    PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets;
+    PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;
+    PFN_vkCmdBindPipeline vkCmdBindPipeline;
+    PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT;
+    PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;
+    PFN_vkCmdBlitImage vkCmdBlitImage;
+    PFN_vkCmdClearAttachments vkCmdClearAttachments;
+    PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
+    PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;
+    PFN_vkCmdCopyImage vkCmdCopyImage;
+    PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer;
+    PFN_vkCmdDispatch vkCmdDispatch;
+    PFN_vkCmdDraw vkCmdDraw;
+    PFN_vkCmdDrawIndexed vkCmdDrawIndexed;
+    PFN_vkCmdEndQuery vkCmdEndQuery;
+    PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
+    PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT;
+    PFN_vkCmdFillBuffer vkCmdFillBuffer;
+    PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
+    PFN_vkCmdPushConstants vkCmdPushConstants;
+    PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants;
+    PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV;
+    PFN_vkCmdSetDepthBias vkCmdSetDepthBias;
+    PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds;
+    PFN_vkCmdSetScissor vkCmdSetScissor;
+    PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask;
+    PFN_vkCmdSetStencilReference vkCmdSetStencilReference;
+    PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask;
+    PFN_vkCmdSetViewport vkCmdSetViewport;
+    PFN_vkCreateBuffer vkCreateBuffer;
+    PFN_vkCreateBufferView vkCreateBufferView;
+    PFN_vkCreateCommandPool vkCreateCommandPool;
+    PFN_vkCreateComputePipelines vkCreateComputePipelines;
+    PFN_vkCreateDescriptorPool vkCreateDescriptorPool;
+    PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;
+    PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR;
+    PFN_vkCreateFence vkCreateFence;
+    PFN_vkCreateFramebuffer vkCreateFramebuffer;
+    PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
+    PFN_vkCreateImage vkCreateImage;
+    PFN_vkCreateImageView vkCreateImageView;
+    PFN_vkCreatePipelineLayout vkCreatePipelineLayout;
+    PFN_vkCreateQueryPool vkCreateQueryPool;
+    PFN_vkCreateRenderPass vkCreateRenderPass;
+    PFN_vkCreateSampler vkCreateSampler;
+    PFN_vkCreateSemaphore vkCreateSemaphore;
+    PFN_vkCreateShaderModule vkCreateShaderModule;
+    PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
+    PFN_vkDestroyBuffer vkDestroyBuffer;
+    PFN_vkDestroyBufferView vkDestroyBufferView;
+    PFN_vkDestroyCommandPool vkDestroyCommandPool;
+    PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;
+    PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;
+    PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR;
+    PFN_vkDestroyFence vkDestroyFence;
+    PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
+    PFN_vkDestroyImage vkDestroyImage;
+    PFN_vkDestroyImageView vkDestroyImageView;
+    PFN_vkDestroyPipeline vkDestroyPipeline;
+    PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;
+    PFN_vkDestroyQueryPool vkDestroyQueryPool;
+    PFN_vkDestroyRenderPass vkDestroyRenderPass;
+    PFN_vkDestroySampler vkDestroySampler;
+    PFN_vkDestroySemaphore vkDestroySemaphore;
+    PFN_vkDestroyShaderModule vkDestroyShaderModule;
+    PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
+    PFN_vkDeviceWaitIdle vkDeviceWaitIdle;
+    PFN_vkEndCommandBuffer vkEndCommandBuffer;
+    PFN_vkFreeCommandBuffers vkFreeCommandBuffers;
+    PFN_vkFreeDescriptorSets vkFreeDescriptorSets;
+    PFN_vkFreeMemory vkFreeMemory;
+    PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
+    PFN_vkGetDeviceQueue vkGetDeviceQueue;
+    PFN_vkGetFenceStatus vkGetFenceStatus;
+    PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
+    PFN_vkGetQueryPoolResults vkGetQueryPoolResults;
+    PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV;
+    PFN_vkMapMemory vkMapMemory;
+    PFN_vkQueueSubmit vkQueueSubmit;
+    PFN_vkResetFences vkResetFences;
+    PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT;
+    PFN_vkUnmapMemory vkUnmapMemory;
+    PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR;
+    PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;
+    PFN_vkWaitForFences vkWaitForFences;
+};
+
+/// Loads instance agnostic function pointers.
+/// @return True on success, false on error.
+bool Load(InstanceDispatch&) noexcept;
+
+/// Loads instance function pointers.
+/// @return True on success, false on error.
+bool Load(VkInstance, InstanceDispatch&) noexcept;
+
 } // namespace Vulkan::vk