Backends: Vulkan: Support for custom function/symbol loader (#3759, #3227)
- It adds an optional feature to support dynamic linkage of Vulkan instead of using default linkage.
- It is now possible to have several potentially working implementation and whenever the Vulkan library was available it can work.
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 4606239..c0c65bc 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -48,10 +48,75 @@
// 2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources.
// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.
-#include "imgui.h"
#include "imgui_impl_vulkan.h"
#include <stdio.h>
+#ifdef IMGUI_IMPL_VULKAN_NO_PROTOTYPES
+#define IMGUI_VULKAN_FUNCTIONS_DEF(func) static PFN_##func func;
+#define IMGUI_VULKAN_FUNCTIONS_MAP(IMGUI_VULKAN_FUNCTIONS_MAP_MACRO) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkAllocateCommandBuffers) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkAllocateDescriptorSets) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkAllocateMemory) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkBindBufferMemory) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkBindImageMemory) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdBindDescriptorSets) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdBindIndexBuffer) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdBindPipeline) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdBindVertexBuffers) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdCopyBufferToImage) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdDrawIndexed) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdPipelineBarrier) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdPushConstants) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdSetScissor) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCmdSetViewport) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateBuffer) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateCommandPool) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateDescriptorSetLayout) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateFence) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateFramebuffer) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateGraphicsPipelines) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateImage) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateImageView) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreatePipelineLayout) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateRenderPass) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateSampler) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateSemaphore) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateShaderModule) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkCreateSwapchainKHR) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyBuffer) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyCommandPool) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyDescriptorSetLayout) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyFence) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyFramebuffer) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyImage) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyImageView) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyPipeline) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyPipelineLayout) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyRenderPass) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroySampler) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroySemaphore) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroyShaderModule) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroySurfaceKHR) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDestroySwapchainKHR) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkDeviceWaitIdle) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkFlushMappedMemoryRanges) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkFreeCommandBuffers) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkFreeMemory) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkGetBufferMemoryRequirements) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkGetImageMemoryRequirements) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkGetPhysicalDeviceMemoryProperties) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkGetPhysicalDeviceSurfaceFormatsKHR) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkGetSwapchainImagesKHR) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkMapMemory) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkUnmapMemory) \
+ IMGUI_VULKAN_FUNCTIONS_MAP_MACRO(vkUpdateDescriptorSets)
+
+IMGUI_VULKAN_FUNCTIONS_MAP(IMGUI_VULKAN_FUNCTIONS_DEF)
+#undef IMGUI_VULKAN_FUNCTIONS_DEF
+#endif
+
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
// [Please zero-clear before use!]
struct ImGui_ImplVulkanH_FrameRenderBuffers
@@ -888,6 +953,18 @@
bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
{
+
+#ifdef IMGUI_IMPL_VULKAN_NO_PROTOTYPES
+ IM_ASSERT(info->GetVulkanProcAddressFn != NULL);
+#define IMGUI_VULKAN_FUNCTIONS_LOAD(func) \
+ func = reinterpret_cast<decltype(func)>(info->GetVulkanProcAddressFn(info->user_data, #func)); \
+ if(NULL == func) { \
+ return false; \
+ }
+ IMGUI_VULKAN_FUNCTIONS_MAP(IMGUI_VULKAN_FUNCTIONS_LOAD)
+#undef IMGUI_VULKAN_FUNCTIONS_LOAD
+#endif
+
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_vulkan";
diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h
index 1e984b3..9915872 100644
--- a/backends/imgui_impl_vulkan.h
+++ b/backends/imgui_impl_vulkan.h
@@ -22,25 +22,44 @@
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
+
+// In order to be able to use a customized Vulkan loader instead of the default one, you can uncomment the
+// underlying definition in here (not in your code) or define it as a compilation flag in your build system.
+// After enabling this, the user has to provide 'GetVulkanProcAddressFn' (and 'user_data' if it was needed) in
+// the 'ImGui_ImplVulkan_InitInfo' so the implementation can resolve function addresses with that.
+// If you have no idea what it is, leave it alone!
+//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
+
+#ifdef IMGUI_IMPL_VULKAN_NO_PROTOTYPES
+#define VK_NO_PROTOTYPES 1
+#endif
#include <vulkan/vulkan.h>
// Initialization data, for ImGui_ImplVulkan_Init()
// [Please zero-clear before use!]
struct ImGui_ImplVulkan_InitInfo
{
- VkInstance Instance;
- VkPhysicalDevice PhysicalDevice;
- VkDevice Device;
- uint32_t QueueFamily;
- VkQueue Queue;
- VkPipelineCache PipelineCache;
- VkDescriptorPool DescriptorPool;
- uint32_t Subpass;
- uint32_t MinImageCount; // >= 2
- uint32_t ImageCount; // >= MinImageCount
- VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
- const VkAllocationCallbacks* Allocator;
- void (*CheckVkResultFn)(VkResult err);
+ VkInstance Instance;
+ VkPhysicalDevice PhysicalDevice;
+ VkDevice Device;
+ uint32_t QueueFamily;
+ VkQueue Queue;
+ VkPipelineCache PipelineCache;
+ VkDescriptorPool DescriptorPool;
+ uint32_t Subpass;
+ uint32_t MinImageCount; // >= 2
+ uint32_t ImageCount; // >= MinImageCount
+ VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
+ const VkAllocationCallbacks* Allocator;
+ void (*CheckVkResultFn)(VkResult err);
+#ifdef IMGUI_IMPL_VULKAN_NO_PROTOTYPES
+ // This function pointer is needed when the default Vulkan loader is disabled(not applicable).
+ // For more information look at comments before '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES'
+ PFN_vkVoidFunction (*GetVulkanProcAddressFn)(void *user_data, const char* pName);
+ // This pointer is going to be fed to the 'GetVulkanProcAddressFn', you can use it for
+ // accessing contex/object that is maybe needed for the function call.
+ void *user_data;
+#endif
};
// Called by user code