2222
2323// CHANGELOG
2424// (minor and older changes stripped away, please see git history for details)
25+ // 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
26+ // 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
27+ // 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
2528// 2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.
2629// 2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init).
2730// 2020-05-04: Vulkan: Fixed crash if initial frame has no vertices.
4851// 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.
4952// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.
5053
51- #include " imgui.h"
5254#include " imgui_impl_vulkan.h"
5355#include < stdio.h>
5456
@@ -85,6 +87,11 @@ static VkPipeline g_Pipeline = VK_NULL_HANDLE;
8587static uint32_t g_Subpass = 0 ;
8688static VkShaderModule g_ShaderModuleVert;
8789static VkShaderModule g_ShaderModuleFrag;
90+ #ifdef VK_NO_PROTOTYPES
91+ static bool g_FunctionsLoaded = false ;
92+ #else
93+ static bool g_FunctionsLoaded = true ;
94+ #endif
8895
8996// Font data
9097static VkSampler g_FontSampler = VK_NULL_HANDLE;
@@ -107,6 +114,75 @@ void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVul
107114void ImGui_ImplVulkanH_CreateWindowSwapChain (VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
108115void ImGui_ImplVulkanH_CreateWindowCommandBuffers (VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
109116
117+ // Vulkan prototypes for use with custom loaders
118+ // (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
119+ #ifdef VK_NO_PROTOTYPES
120+ #define IMGUI_VULKAN_FUNC_MAP (IMGUI_VULKAN_FUNC_MAP_MACRO ) \
121+ IMGUI_VULKAN_FUNC_MAP_MACRO (vkAllocateCommandBuffers) \
122+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \
123+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateMemory) \
124+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindBufferMemory) \
125+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindImageMemory) \
126+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindDescriptorSets) \
127+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindIndexBuffer) \
128+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindPipeline) \
129+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindVertexBuffers) \
130+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdCopyBufferToImage) \
131+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdDrawIndexed) \
132+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPipelineBarrier) \
133+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPushConstants) \
134+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetScissor) \
135+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetViewport) \
136+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateBuffer) \
137+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateCommandPool) \
138+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateDescriptorSetLayout) \
139+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFence) \
140+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFramebuffer) \
141+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateGraphicsPipelines) \
142+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImage) \
143+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImageView) \
144+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreatePipelineLayout) \
145+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateRenderPass) \
146+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSampler) \
147+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSemaphore) \
148+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateShaderModule) \
149+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSwapchainKHR) \
150+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyBuffer) \
151+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyCommandPool) \
152+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyDescriptorSetLayout) \
153+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFence) \
154+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFramebuffer) \
155+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImage) \
156+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImageView) \
157+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipeline) \
158+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipelineLayout) \
159+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyRenderPass) \
160+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySampler) \
161+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySemaphore) \
162+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyShaderModule) \
163+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySurfaceKHR) \
164+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySwapchainKHR) \
165+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \
166+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \
167+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \
168+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \
169+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \
170+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \
171+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceMemoryProperties) \
172+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
173+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceFormatsKHR) \
174+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \
175+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetSwapchainImagesKHR) \
176+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkMapMemory) \
177+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkUnmapMemory) \
178+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets)
179+
180+ // Define function pointers
181+ #define IMGUI_VULKAN_FUNC_DEF (func ) static PFN_##func func;
182+ IMGUI_VULKAN_FUNC_MAP (IMGUI_VULKAN_FUNC_DEF)
183+ #undef IMGUI_VULKAN_FUNC_DEF
184+ #endif // VK_NO_PROTOTYPES
185+
110186// -----------------------------------------------------------------------------
111187// SHADERS
112188// -----------------------------------------------------------------------------
@@ -268,7 +344,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
268344
269345 err = vkBindBufferMemory (v->Device , buffer, buffer_memory, 0 );
270346 check_vk_result (err);
271- p_buffer_size = new_size ;
347+ p_buffer_size = req. size ;
272348}
273349
274350static void ImGui_ImplVulkan_SetupRenderState (ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
@@ -354,9 +430,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
354430 // Upload vertex/index data into a single contiguous GPU buffer
355431 ImDrawVert* vtx_dst = NULL ;
356432 ImDrawIdx* idx_dst = NULL ;
357- VkResult err = vkMapMemory (v->Device , rb->VertexBufferMemory , 0 , vertex_size , 0 , (void **)(&vtx_dst));
433+ VkResult err = vkMapMemory (v->Device , rb->VertexBufferMemory , 0 , rb-> VertexBufferSize , 0 , (void **)(&vtx_dst));
358434 check_vk_result (err);
359- err = vkMapMemory (v->Device , rb->IndexBufferMemory , 0 , index_size , 0 , (void **)(&idx_dst));
435+ err = vkMapMemory (v->Device , rb->IndexBufferMemory , 0 , rb-> IndexBufferSize , 0 , (void **)(&idx_dst));
360436 check_vk_result (err);
361437 for (int n = 0 ; n < draw_data->CmdListsCount ; n++)
362438 {
@@ -587,7 +663,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
587663 }
588664
589665 // Store our identifier
590- io.Fonts ->TexID = ( ImTextureID)(intptr_t )g_FontImage;
666+ io.Fonts ->SetTexID (( ImTextureID)(intptr_t )g_FontImage) ;
591667
592668 return true ;
593669}
@@ -741,8 +817,8 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
741817 color_attachment[0 ].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
742818 color_attachment[0 ].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
743819 color_attachment[0 ].colorBlendOp = VK_BLEND_OP_ADD;
744- color_attachment[0 ].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
745- color_attachment[0 ].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO ;
820+ color_attachment[0 ].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE ;
821+ color_attachment[0 ].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
746822 color_attachment[0 ].alphaBlendOp = VK_BLEND_OP_ADD;
747823 color_attachment[0 ].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
748824
@@ -886,8 +962,31 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
886962 if (g_Pipeline) { vkDestroyPipeline (v->Device , g_Pipeline, v->Allocator ); g_Pipeline = VK_NULL_HANDLE; }
887963}
888964
965+ bool ImGui_ImplVulkan_LoadFunctions (PFN_vkVoidFunction(*loader_func)(const char * function_name, void * user_data), void* user_data)
966+ {
967+ // Load function pointers
968+ // You can use the default Vulkan loader using:
969+ // ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
970+ // But this would be equivalent to not setting VK_NO_PROTOTYPES.
971+ #ifdef VK_NO_PROTOTYPES
972+ #define IMGUI_VULKAN_FUNC_LOAD (func ) \
973+ func = reinterpret_cast <decltype (func)>(loader_func (#func, user_data)); \
974+ if (func == NULL ) \
975+ return false ;
976+ IMGUI_VULKAN_FUNC_MAP (IMGUI_VULKAN_FUNC_LOAD)
977+ #undef IMGUI_VULKAN_FUNC_LOAD
978+ #else
979+ IM_UNUSED (loader_func);
980+ IM_UNUSED (user_data);
981+ #endif
982+ g_FunctionsLoaded = true ;
983+ return true ;
984+ }
985+
889986bool ImGui_ImplVulkan_Init (ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
890987{
988+ IM_ASSERT (g_FunctionsLoaded && " Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
989+
891990 // Setup backend capabilities flags
892991 ImGuiIO& io = ImGui::GetIO ();
893992 io.BackendRendererName = " imgui_impl_vulkan" ;
@@ -952,6 +1051,7 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
9521051
9531052VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat (VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
9541053{
1054+ IM_ASSERT (g_FunctionsLoaded && " Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
9551055 IM_ASSERT (request_formats != NULL );
9561056 IM_ASSERT (request_formats_count > 0 );
9571057
@@ -996,6 +1096,7 @@ VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physic
9961096
9971097VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode (VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
9981098{
1099+ IM_ASSERT (g_FunctionsLoaded && " Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
9991100 IM_ASSERT (request_modes != NULL );
10001101 IM_ASSERT (request_modes_count > 0 );
10011102
@@ -1246,6 +1347,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
12461347// Create or resize window
12471348void ImGui_ImplVulkanH_CreateOrResizeWindow (VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count)
12481349{
1350+ IM_ASSERT (g_FunctionsLoaded && " Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
12491351 (void )instance;
12501352 ImGui_ImplVulkanH_CreateWindowSwapChain (physical_device, device, wd, allocator, width, height, min_image_count);
12511353 ImGui_ImplVulkanH_CreateWindowCommandBuffers (physical_device, device, wd, queue_family, allocator);
0 commit comments