Преглед изворни кода

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.
Hossein Noroozpour пре 4 година
родитељ
комит
6001c54598
2 измењених фајлова са 110 додато и 14 уклоњено
  1. 78 1
      backends/imgui_impl_vulkan.cpp
  2. 32 13
      backends/imgui_impl_vulkan.h

+ 78 - 1
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 @@ void    ImGui_ImplVulkan_DestroyDeviceObjects()
 
 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";

+ 32 - 13
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