diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 85c7e4924..2624f5210 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1321,7 +1321,9 @@ 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); + IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE && info->PipelineInfoForViewports.RenderPass == VK_NULL_HANDLE); + else if (info->PipelineInfoForViewports.RenderPass == NULL) + info->PipelineInfoForViewports.RenderPass = info->PipelineInfoMain.RenderPass; bd->VulkanInitInfo = *info; @@ -1975,10 +1977,11 @@ 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 < v->PipelineRenderingCreateInfo.colorAttachmentCount; n++) - requestSurfaceImageFormats.push_back(v->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]); + 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) @@ -1996,28 +1999,25 @@ 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); + 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); vd->WindowOwned = true; // Create pipeline (shared by all secondary viewports) if (bd->PipelineForViewports == VK_NULL_HANDLE) { - VkPipelineRenderingCreateInfoKHR* p_rendering_info = nullptr; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - VkPipelineRenderingCreateInfoKHR rendering_info = {}; if (wd->UseDynamicRendering) { - rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; - rendering_info.pNext = nullptr; - rendering_info.viewMask = 0; - rendering_info.colorAttachmentCount = 1; - rendering_info.pColorAttachmentFormats = &wd->SurfaceFormat.format; - rendering_info.depthAttachmentFormat = VK_FORMAT_UNDEFINED; - rendering_info.stencilAttachmentFormat = VK_FORMAT_UNDEFINED; - p_rendering_info = &rendering_info; + pipeline_info->PipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats = &wd->SurfaceFormat.format; + } + else + { + IM_ASSERT(pipeline_info->RenderPass != VK_NULL_HANDLE && "Did you set ImGui_ImplVulkan_InitInfo::PipelineInfoForViewports.RenderPass?"); // Since 1.92.4 it is required. } #endif - bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, wd->UseDynamicRendering ? VK_NULL_HANDLE : wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, 0, p_rendering_info); + bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports); } } @@ -2044,7 +2044,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); + 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); } static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) @@ -2057,7 +2057,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); + 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); vd->SwapChainNeedRebuild = vd->SwapChainSuboptimal = false; } diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 0fafbc5ec..44b8b8bae 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -76,6 +76,9 @@ 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 + + // For Secondary viewports only (created/managed by backend) + VkImageUsageFlags SwapChainImageUsage; // 0 defaults to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. Add e.g. VK_IMAGE_USAGE_TRANSFER_SRC_BIT if you need to capture from viewports. }; // Initialization data, for ImGui_ImplVulkan_Init() @@ -102,13 +105,14 @@ 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 //VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead // (Optional) Dynamic Rendering - // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo. + // 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) Allocation, Debugging diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8935c882b..ece3cbdc0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -109,6 +109,14 @@ Docking+Viewports Branch: backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) - Backends: DX10, DX11, DX12: Disabled DXGI's Alt+Enter default behavior on secondary viewports managed by the backend. (#4350) [@PathogenDavid] +- Backends: Vulkan: Added a way to configure secondary viewport pipelinen creation + by setting init_info.PipelineInfoForViewports fields. (#8946, #8110, #8111, #8686) +- Backends: Vulkan: Added a way to configure secondary viewport swapchain VkImageUsageFlags + to e.g. capture rendering. (#8946, #8940) [@olivier-gerard, @ocornut] + Usage example: + `init_info.PipelineInfoForViewports.SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;` +- Backends: Vulkan: pipeline created for secondary viewport automatically match + surface format. (#8686) [@sylmroz] - Backends: Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) [@olivier-gerard] - Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples.