Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulkan: Fixing secondary viewport resize problems on linux #7513

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 15 additions & 3 deletions backends/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1731,7 +1731,12 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
{
{
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);
check_vk_result(err);
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount);
wd->CanPresent = false;
return;
} else
check_vk_result(err);
fd = &wd->Frames[wd->FrameIndex];
}
for (;;)
Expand Down Expand Up @@ -1858,6 +1863,11 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
ImGui_ImplVulkanH_Window* wd = &vd->Window;
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;

if (!wd->CanPresent) {
wd->CanPresent = true;
return;
}

VkResult err;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also clarify how this is needed?
Our main.cpp example do a similar thing via setting g_SwapChainRebuild = true but it is primarily because the swap chain recreation is deferred to later.
Can you confirm what happens if you attempt the vkQueuePresentKHR() ? for my records. Thanks!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and yeah answers to this are in #3390

uint32_t present_index = wd->FrameIndex;

Expand All @@ -1870,9 +1880,11 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &present_index;
err = vkQueuePresentKHR(v->Queue, &info);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) {
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount);
else
return;
}
else
check_vk_result(err);
Copy link
Owner

@ocornut ocornut May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of returning here and not incrementing both indexes?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also confirm that both paths calling ImGui_ImplVulkanH_CreateOrResizeWindow() are needed?
Sorry for the amount of details requested, but since this is rather subtle and brittle and hard to reproduce, any extra details are useful for our records.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

none of this is needed that's just how I handle it in my own backend.


wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences()
Expand Down
2 changes: 2 additions & 0 deletions backends/imgui_impl_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ struct ImGui_ImplVulkanH_Window
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
bool UseDynamicRendering;
bool ClearEnable;
bool CanPresent;
VkClearValue ClearValue;
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
Expand All @@ -183,6 +184,7 @@ struct ImGui_ImplVulkanH_Window
memset((void*)this, 0, sizeof(*this));
PresentMode = (VkPresentModeKHR)~0; // Ensure we get an error if user doesn't set this.
ClearEnable = true;
CanPresent = true;
}
};

Expand Down