From ea33a483ba191a29631abd9c91f246eceba5832e Mon Sep 17 00:00:00 2001 From: Ronan Cailleau Date: Tue, 7 Oct 2025 16:05:17 +0200 Subject: [PATCH] Backends: Vulkan: Replaced `InitInfo`'s `PipelineInfo PipelineInfoForViewports` by `SecondaryViewportsInfo SecondaryViewportsInfo` - `PipelineInfoForViewports` was confusing (only one (or two) out of the five (or six) parameters was actually used). - Add `struct ImGui_ImplVulkan_SecondaryViewportsInfo` for viewports specific informations (to be extended and re-used) --- backends/imgui_impl_vulkan.cpp | 39 +++++++++++++++++++--------------- backends/imgui_impl_vulkan.h | 13 +++++++++--- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 9ae9926ab..06f5c4850 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -282,7 +282,6 @@ struct ImGui_ImplVulkan_Data VkDescriptorSetLayout DescriptorSetLayout; VkPipelineLayout PipelineLayout; VkPipeline Pipeline; // pipeline for main render pass (created by app) - VkPipeline PipelineForViewports; // pipeline for secondary viewports (created by backend) VkShaderModule ShaderModuleVert; VkShaderModule ShaderModuleFrag; VkDescriptorPool DescriptorPool; @@ -296,6 +295,12 @@ struct ImGui_ImplVulkan_Data // Render buffers for main window ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers; + // Viewports common data + // Filled during ImGui_ImplVulkan_PrepareViewportsRendering() based on ViewportsFormat and VulkanInitInfo->SecondaryViewportsInfo + ImGui_ImplVulkan_PipelineInfo PipelineInfoForViewports; + VkPipeline PipelineForViewports; // pipeline for secondary viewports (created by backend) + + ImGui_ImplVulkan_Data() { memset((void*)this, 0, sizeof(*this)); @@ -1321,7 +1326,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) else IM_ASSERT(info->DescriptorPoolSize > 0); if (info->UseDynamicRendering) - IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE && info->PipelineInfoForViewports.RenderPass == VK_NULL_HANDLE); + IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE); bd->VulkanInitInfo = *info; @@ -1978,18 +1983,18 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) } // Select Surface Format - ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoForViewports; - ImVector requestSurfaceImageFormats; -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - for (uint32_t n = 0; n < pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount; n++) - requestSurfaceImageFormats.push_back(pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]); -#endif - const VkFormat defaultFormats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; - for (VkFormat format : defaultFormats) - requestSurfaceImageFormats.push_back(format); + ImGui_ImplVulkan_PipelineInfo* pipeline_info = &bd->PipelineInfoForViewports; + const VkFormat requestSurfaceImageFormats[] = { v->SecondaryViewportsInfo.DesiredFormat.format, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; + int requestSurfaceImageFormatsCount = IM_ARRAYSIZE(requestSurfaceImageFormats); + const VkFormat* pRequestSurfaceImageFormats = requestSurfaceImageFormats; + if (pRequestSurfaceImageFormats[0] == VK_FORMAT_UNDEFINED) + { + ++pRequestSurfaceImageFormats; + --requestSurfaceImageFormatsCount; + } - const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormats.Data, (size_t)requestSurfaceImageFormats.Size, requestSurfaceColorSpace); + const VkColorSpaceKHR requestSurfaceColorSpace = v->SecondaryViewportsInfo.DesiredFormat.colorSpace; + wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, pRequestSurfaceImageFormats, requestSurfaceImageFormatsCount, requestSurfaceColorSpace); // Select Present Mode // FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1) @@ -2000,7 +2005,7 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) // Create SwapChain, RenderPass, Framebuffer, etc. wd->ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true; wd->UseDynamicRendering = v->UseDynamicRendering; - ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, pipeline_info->SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, v->SecondaryViewportsInfo.SwapChainImageUsage); vd->WindowOwned = true; // Create pipeline (shared by all secondary viewports) @@ -2018,7 +2023,7 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) pipeline_info->RenderPass = wd->RenderPass; } #endif - bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports); + bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, pipeline_info); } } @@ -2045,7 +2050,7 @@ static void ImGui_ImplVulkan_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) return; ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; vd->Window.ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true; - ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount, v->PipelineInfoForViewports.SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount, v->SecondaryViewportsInfo.SwapChainImageUsage); } static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) @@ -2058,7 +2063,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) if (vd->SwapChainNeedRebuild || vd->SwapChainSuboptimal) { - ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, v->PipelineInfoForViewports.SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, v->SecondaryViewportsInfo.SwapChainImageUsage); vd->SwapChainNeedRebuild = vd->SwapChainSuboptimal = false; } diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index ad89cb9e4..a9f16c43b 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -66,7 +66,7 @@ // 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 -// Specify settings to create pipeline and swapchain +// Specify settings to create pipeline struct ImGui_ImplVulkan_PipelineInfo { // For Main viewport only @@ -78,8 +78,13 @@ struct ImGui_ImplVulkan_PipelineInfo #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR #endif +}; + +struct ImGui_ImplVulkan_SecondaryViewportsInfo +{ + // Ignored if .format == VK_FORMAT_UNDEFINED + VkSurfaceFormatKHR DesiredFormat; - // For Secondary viewports only (created/managed by backend) VkImageUsageFlags SwapChainImageUsage; // Extra flags for vkCreateSwapchainKHR() calls for secondary viewports. We automatically add VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. You can add e.g. VK_IMAGE_USAGE_TRANSFER_SRC_BIT if you need to capture from viewports. }; @@ -107,7 +112,6 @@ struct ImGui_ImplVulkan_InitInfo // Pipeline ImGui_ImplVulkan_PipelineInfo PipelineInfoMain; // Infos for Main Viewport (created by app/user) - ImGui_ImplVulkan_PipelineInfo PipelineInfoForViewports; // Infos for Secondary Viewports (created by backend) //VkRenderPass RenderPass; // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead //uint32_t Subpass; // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead //VkSampleCountFlagBits MSAASamples; // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead @@ -117,6 +121,9 @@ struct ImGui_ImplVulkan_InitInfo // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo and PipelineInfoViewports.PipelineRenderingCreateInfo. bool UseDynamicRendering; + // Optional + ImGui_ImplVulkan_SecondaryViewportsInfo SecondaryViewportsInfo; + // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err);