From 1ecc34a0b1096e61b5585025525392886bfebc34 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 4 Sep 2025 14:24:06 +0200 Subject: [PATCH] Backends: Vulkan: misc amends (e.g. changelog, coding style). (8110, 8111, 8053) # Conflicts: # backends/imgui_impl_vulkan.cpp --- backends/imgui_impl_vulkan.cpp | 56 +++++++++++++++------------------- backends/imgui_impl_vulkan.h | 33 +++++++++----------- docs/CHANGELOG.txt | 2 ++ 3 files changed, 41 insertions(+), 50 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 69e3430e0..23bf7b8ce 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) // 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840) // 2025-07-07: Vulkan: Fixed texture synchronization issue introduced on 2025-06-11. (#8772) // 2025-06-27: Vulkan: Fixed validation errors during texture upload/update by aligning upload size to 'nonCoherentAtomSize'. (#8743, #8744) @@ -906,7 +907,11 @@ static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAlloca } } -static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, uint32_t subpass, const ImGui_ImplVulkan_PipelineRenderingCreateInfo* pipeline_rendering_create_info) +#if !defined(IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING) && !(defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering)) +typedef void VkPipelineRenderingCreateInfoKHR; +#endif + +static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, uint32_t subpass, const VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_CreateShaderModules(device, allocator); @@ -1096,33 +1101,22 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() check_vk_result(err); } - { - bool create_pipeline = false; - const ImGui_ImplVulkan_PipelineRenderingCreateInfo* p_dynamic_rendering = nullptr; - if (v->RenderPass) - { - create_pipeline = true; - } - else - { + // Create pipeline + const VkPipelineRenderingCreateInfoKHR* p_dynamic_rendering_create_info = nullptr; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - if (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR) - { - p_dynamic_rendering = &v->PipelineRenderingCreateInfo; - create_pipeline = true; - } + if (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR) + p_dynamic_rendering_create_info = &v->PipelineRenderingCreateInfo; #endif - } - if (create_pipeline) - { - ImGui_ImplVulkan_MainPipelineCreateInfo mp_info = {}; - mp_info.RenderPass = v->RenderPass; - mp_info.Subpass = v->Subpass; - mp_info.MSAASamples = v->MSAASamples; - mp_info.pDynamicRendering = p_dynamic_rendering; - - ImGui_ImplVulkan_ReCreateMainPipeline(mp_info); - } + if (v->RenderPass || p_dynamic_rendering_create_info != nullptr) + { + ImGui_ImplVulkan_MainPipelineCreateInfo mp_info = {}; + mp_info.RenderPass = v->RenderPass; + mp_info.Subpass = v->Subpass; + mp_info.MSAASamples = v->MSAASamples; +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING + mp_info.pDynamicRendering = p_dynamic_rendering_create_info; +#endif + ImGui_ImplVulkan_CreateMainPipeline(mp_info); } // Create command pool/buffer for texture upload @@ -1148,7 +1142,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() return true; } -void ImGui_ImplVulkan_ReCreateMainPipeline(ImGui_ImplVulkan_MainPipelineCreateInfo const& info) +void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_MainPipelineCreateInfo& info) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; @@ -1161,15 +1155,13 @@ void ImGui_ImplVulkan_ReCreateMainPipeline(ImGui_ImplVulkan_MainPipelineCreateIn v->MSAASamples = info.MSAASamples; v->Subpass = info.Subpass; - ImGui_ImplVulkan_PipelineRenderingCreateInfo * pipeline_rendering_create_info = nullptr; + VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = nullptr; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING if (info.pDynamicRendering) { v->PipelineRenderingCreateInfo = *info.pDynamicRendering; pipeline_rendering_create_info = &v->PipelineRenderingCreateInfo; } -#else - IM_ASSERT(info.pDynamicRendering == nullptr); #endif bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, v->Subpass, pipeline_rendering_create_info); } @@ -1297,14 +1289,14 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) IM_ASSERT(info->MinImageCount >= 2); IM_ASSERT(info->ImageCount >= info->MinImageCount); - ImGui_ImplVulkan_InitInfo * v = &bd->VulkanInitInfo; - *v = *info; + bd->VulkanInitInfo = *info; VkPhysicalDeviceProperties properties; vkGetPhysicalDeviceProperties(info->PhysicalDevice, &properties); bd->NonCoherentAtomSize = properties.limits.nonCoherentAtomSize; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING + ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; if (v->PipelineRenderingCreateInfo.pColorAttachmentFormats != NULL) { // Deep copy buffer to reduce error-rate for end user (#8282) diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index d4f897961..e4503261e 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -65,12 +65,6 @@ // Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture(). #define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE (8) // Minimum per atlas -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING -typedef VkPipelineRenderingCreateInfoKHR ImGui_ImplVulkan_PipelineRenderingCreateInfo; -#else -typedef void ImGui_ImplVulkan_PipelineRenderingCreateInfo; -#endif - // Initialization data, for ImGui_ImplVulkan_Init() // [Please zero-clear before use!] // - About descriptor pool: @@ -104,8 +98,7 @@ struct ImGui_ImplVulkan_InitInfo // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3. bool UseDynamicRendering; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - // (Optional, valid iif .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR) - VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; + VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR #endif // (Optional) Allocation, Debugging @@ -115,21 +108,25 @@ struct ImGui_ImplVulkan_InitInfo }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! -IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info); // The main pipeline will be created if possible (RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType is correct)) -#define IMGUI_IMPL_VULKAN_HAS_MAIN_PIPELINE_RE_CREATION 1 -struct ImGui_ImplVulkan_MainPipelineCreateInfo -{ - VkRenderPass RenderPass = VK_NULL_HANDLE; - uint32_t Subpass = 0; - VkSampleCountFlagBits MSAASamples = {}; - const ImGui_ImplVulkan_PipelineRenderingCreateInfo* pDynamicRendering = nullptr; -}; -IMGUI_IMPL_API void ImGui_ImplVulkan_ReCreateMainPipeline(ImGui_ImplVulkan_MainPipelineCreateInfo const& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext)) +IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info); IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE); IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated) +// (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111) +// The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR)) +// Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering. +struct ImGui_ImplVulkan_MainPipelineCreateInfo +{ + VkRenderPass RenderPass = VK_NULL_HANDLE; + uint32_t Subpass = 0; + VkSampleCountFlagBits MSAASamples = {}; +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING + const VkPipelineRenderingCreateInfoKHR* pDynamicRendering = nullptr; +#endif +}; +IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_MainPipelineCreateInfo& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext)) // (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually. IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index da1fd9b0d..afdcbfc6c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -81,6 +81,8 @@ Other Changes: - Backends: SDL_GPU: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and PresentMode to configure how secondary viewports are created. Currently only used multi-viewport mode. (#8892) [@PTSVU] +- Backends: Vulkan: added ImGui_ImplVulkan_CreateMainPipeline() to recreate pipeline + without reinitializing backend. (#8110, #8111) [@SuperRonan] -----------------------------------------------------------------------