diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index a8962ecd2..52232901e 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -33,6 +33,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().) // 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering. // 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure. // 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) @@ -108,12 +109,13 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi // Vulkan prototypes for use with custom loaders // (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h -#ifdef VK_NO_PROTOTYPES +#if defined(VK_NO_PROTOTYPES) && !defined(VOLK_H_) +#define IMGUI_IMPL_VULKAN_USE_LOADER static bool g_FunctionsLoaded = false; #else static bool g_FunctionsLoaded = true; #endif -#ifdef VK_NO_PROTOTYPES +#ifdef IMGUI_IMPL_VULKAN_USE_LOADER #define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \ @@ -184,7 +186,7 @@ static bool g_FunctionsLoaded = true; #define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func; IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF) #undef IMGUI_VULKAN_FUNC_DEF -#endif // VK_NO_PROTOTYPES +#endif // IMGUI_IMPL_VULKAN_USE_LOADER #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR; @@ -1048,8 +1050,8 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch // Load function pointers // You can use the default Vulkan loader using: // ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); }); - // But this would be equivalent to not setting VK_NO_PROTOTYPES. -#ifdef VK_NO_PROTOTYPES + // But this would be roughly equivalent to not setting VK_NO_PROTOTYPES. +#ifdef IMGUI_IMPL_VULKAN_USE_LOADER #define IMGUI_VULKAN_FUNC_LOAD(func) \ func = reinterpret_cast(loader_func(#func, user_data)); \ if (func == nullptr) \ @@ -1078,7 +1080,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) if (info->UseDynamicRendering) { #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING -#ifndef VK_NO_PROTOTYPES +#ifndef IMGUI_IMPL_VULKAN_USE_LOADER ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(vkGetInstanceProcAddr(info->Instance, "vkCmdBeginRenderingKHR")); ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(vkGetInstanceProcAddr(info->Instance, "vkCmdEndRenderingKHR")); #endif diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index f77fc235b..c174a6ca1 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -42,13 +42,20 @@ // If you have no idea what this is, leave it alone! //#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES -// Vulkan includes +// Convenience support for Volk +// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().) +//#define IMGUI_IMPL_VULKAN_USE_VOLK + #if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES) #define VK_NO_PROTOTYPES #endif #if defined(VK_USE_PLATFORM_WIN32_KHR) && !defined(NOMINMAX) #define NOMINMAX -#include +#endif + +// Vulkan includes +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK +#include #else #include #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6c4102ec9..8b2c372ee 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,8 +66,12 @@ Other changes: mitigitate issues with reading vertex indexing limits with 16-bit indices. (#7496, #5720) - Backends: OpenGL: Detect ES3 contexts on desktop based on version string, to e.g. avoid calling glPolygonMode() on them. (#7447) [@afraidofdark, @ocornut] +- Backends: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define. + (you could always use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + ImGui_ImplVulkan_LoadFunctions() as well). + (#6582, #4854) [@adalsteinnh, @kennyalive, @ocornut] - Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput() as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky] +- Examples: GLFW+Vulkan, SDL+Vulkan: Added optional support for Volk. (#6582, #4854) - Examples: GLFW+WebGPU: Added support for WebGPU-native/Dawn (#7435, #7132) [@eliasdaler, @Zelif] - Examples: GLFW+WebGPU: Renamed example_emscripten_wgpu/ to example_glfw_wgpu/. (#7435, #7132) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index b1c596dd3..b6e53ed8d 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -21,8 +21,12 @@ #define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_VULKAN #include -#include -//#include + +// Volk headers +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK +#define VOLK_IMPLEMENTATION +#include +#endif // [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers. // To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma. @@ -113,6 +117,9 @@ static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() static void SetupVulkan(ImVector instance_extensions) { VkResult err; +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkInitialize(); +#endif // Create Vulkan Instance { @@ -151,17 +158,20 @@ static void SetupVulkan(ImVector instance_extensions) create_info.ppEnabledExtensionNames = instance_extensions.Data; err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); check_vk_result(err); +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkLoadInstance(g_Instance); +#endif // Setup the debug report callback #ifdef APP_USE_VULKAN_DEBUG_REPORT - auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); - IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr); + auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); + IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr); VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; debug_report_ci.pfnCallback = debug_report; debug_report_ci.pUserData = nullptr; - err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); + err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); check_vk_result(err); #endif } @@ -277,8 +287,8 @@ static void CleanupVulkan() #ifdef APP_USE_VULKAN_DEBUG_REPORT // Remove the debug report callback - auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); - vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); + auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); + f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); #endif // APP_USE_VULKAN_DEBUG_REPORT vkDestroyDevice(g_Device, g_Allocator); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 633f8bb8b..df0db4d1e 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -20,8 +20,12 @@ #include // abort #include #include -#include -//#include + +// Volk headers +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK +#define VOLK_IMPLEMENTATION +#include +#endif //#define APP_USE_UNLIMITED_FRAME_RATE #ifdef _DEBUG @@ -101,6 +105,9 @@ static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() static void SetupVulkan(ImVector instance_extensions) { VkResult err; +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkInitialize(); +#endif // Create Vulkan Instance { @@ -139,17 +146,20 @@ static void SetupVulkan(ImVector instance_extensions) create_info.ppEnabledExtensionNames = instance_extensions.Data; err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); check_vk_result(err); +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkLoadInstance(g_Instance); +#endif // Setup the debug report callback #ifdef APP_USE_VULKAN_DEBUG_REPORT - auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); - IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr); + auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); + IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr); VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; debug_report_ci.pfnCallback = debug_report; debug_report_ci.pUserData = nullptr; - err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); + err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); check_vk_result(err); #endif } @@ -265,8 +275,8 @@ static void CleanupVulkan() #ifdef APP_USE_VULKAN_DEBUG_REPORT // Remove the debug report callback - auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); - vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); + auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); + f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); #endif // APP_USE_VULKAN_DEBUG_REPORT vkDestroyDevice(g_Device, g_Allocator);