Skip to content

Commit ec4cd2c

Browse files
committed
Backends: Vulkan: Fixed crash with using no prototypes + *BREAKING* Added ApiVersion to ImGui_ImplVulkan_LoadFunctions(). (ocornut#8326, ocornut#8365, ocornut#8400)
1 parent 98c2f6b commit ec4cd2c

File tree

3 files changed

+30
-19
lines changed

3 files changed

+30
-19
lines changed

backends/imgui_impl_vulkan.cpp

+25-18
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
// CHANGELOG
2828
// (minor and older changes stripped away, please see git history for details)
29+
// 2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
2930
// 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)
3031
// 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642)
3132
// 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.
@@ -1081,22 +1082,34 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
10811082
}
10821083

10831084
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
1084-
static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
1085+
static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
10851086
{
10861087
// Manually load those two (see #5446, #8326, #8365)
1087-
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
1088-
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
1089-
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func(v->ApiVersion < VK_API_VERSION_1_3 ? "vkCmdBeginRenderingKHR" : "vkCmdBeginRendering", user_data));
1090-
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func(v->ApiVersion < VK_API_VERSION_1_3 ? "vkCmdEndRenderingKHR" : "vkCmdEndRendering", user_data));
1088+
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func(api_version < VK_API_VERSION_1_3 ? "vkCmdBeginRenderingKHR" : "vkCmdBeginRendering", user_data));
1089+
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func(api_version < VK_API_VERSION_1_3 ? "vkCmdEndRenderingKHR" : "vkCmdEndRendering", user_data));
10911090
}
10921091
#endif
10931092

1094-
bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
1093+
// If unspecified by user, assume that ApiVersion == HeaderVersion
1094+
// We don't care about other versions than 1.3 for our checks, so don't need to make this exhaustive (e.g. with all #ifdef VK_VERSION_1_X checks)
1095+
static uint32_t ImGui_ImplVulkan_GetDefaultApiVersion()
1096+
{
1097+
#ifdef VK_HEADER_VERSION_COMPLETE
1098+
return VK_HEADER_VERSION_COMPLETE;
1099+
#else
1100+
return VK_API_VERSION_1_0;
1101+
#endif
1102+
}
1103+
1104+
bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
10951105
{
10961106
// Load function pointers
10971107
// You can use the default Vulkan loader using:
1098-
// ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
1108+
// ImGui_ImplVulkan_LoadFunctions(VK_API_VERSION_1_3, [](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
10991109
// But this would be roughly equivalent to not setting VK_NO_PROTOTYPES.
1110+
if (api_version == 0)
1111+
api_version = ImGui_ImplVulkan_GetDefaultApiVersion();
1112+
11001113
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
11011114
#define IMGUI_VULKAN_FUNC_LOAD(func) \
11021115
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
@@ -1106,7 +1119,7 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch
11061119
#undef IMGUI_VULKAN_FUNC_LOAD
11071120

11081121
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
1109-
ImGui_ImplVulkan_LoadDynamicRenderingFunctions(loader_func, user_data);
1122+
ImGui_ImplVulkan_LoadDynamicRenderingFunctions(api_version, loader_func, user_data);
11101123
#endif
11111124
#else
11121125
IM_UNUSED(loader_func);
@@ -1121,11 +1134,14 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
11211134
{
11221135
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
11231136

1137+
if (info->ApiVersion == 0)
1138+
info->ApiVersion = ImGui_ImplVulkan_GetDefaultApiVersion();
1139+
11241140
if (info->UseDynamicRendering)
11251141
{
11261142
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
11271143
#ifndef IMGUI_IMPL_VULKAN_USE_LOADER
1128-
ImGui_ImplVulkan_LoadDynamicRenderingFunctions([](const char* function_name, void* user_data) { return vkGetInstanceProcAddr((VkInstance)user_data, function_name); }, (void*)info->Instance);
1144+
ImGui_ImplVulkan_LoadDynamicRenderingFunctions(info->ApiVersion, [](const char* function_name, void* user_data) { return vkGetInstanceProcAddr((VkInstance)user_data, function_name); }, (void*)info->Instance);
11291145
#endif
11301146
IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR != nullptr);
11311147
IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR != nullptr);
@@ -1158,15 +1174,6 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
11581174
IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);
11591175

11601176
bd->VulkanInitInfo = *info;
1161-
if (bd->VulkanInitInfo.ApiVersion == 0)
1162-
{
1163-
// We don't care about other versions for now, so don't need to make this exhaustive (with #ifdef VK_VERSION_1_X checks)
1164-
#ifdef VK_HEADER_VERSION_COMPLETE
1165-
bd->VulkanInitInfo.ApiVersion = VK_HEADER_VERSION_COMPLETE;
1166-
#else
1167-
bd->VulkanInitInfo.ApiVersion = VK_API_VERSION_1_0;
1168-
#endif
1169-
}
11701177

11711178
ImGui_ImplVulkan_CreateDeviceObjects();
11721179

backends/imgui_impl_vulkan.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet d
124124

125125
// Optional: load Vulkan functions with a custom function loader
126126
// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
127-
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
127+
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
128128

129129
// [BETA] Selected render state data shared with callbacks.
130130
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.

docs/CHANGELOG.txt

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ Breaking changes:
4343

4444
- Renamed ImFontConfig::GlyphExtraSpacing.x option to GlyphExtraAdvanceX. (#242)
4545
- Renamed style.TabMinWidthForCloseButton to style.TabCloseButtonMinWidthUnselected.
46+
- Backends: Vulkan: Added 'uint32_t api_version' argument to ImGui_ImplVulkan_LoadFunctions().
47+
Note that it was also added to ImGui_ImplVulkan_InitInfo but for the later it is optional.
48+
(#8326, #8365, #8400)
49+
4650

4751
Other changes:
4852

0 commit comments

Comments
 (0)