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

Update vulkan swapchain recreation examples #3390

Closed
wants to merge 12 commits into from
1 change: 1 addition & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ Other Changes:
- Backends: OpenGL3: Added support for glad2 loader. (#3330) [@moritz-h]
- Backends: Allegro 5: Fixed horizontal scrolling direction with mouse wheel / touch pads (it seems
like Allegro 5 reports it differently from GLFW and SDL). (#3394, #2424, #1463) [@nobody-special666]
- Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO]
- Examples: Vulkan: Fixed GLFW+Vulkan and SDL+Vulkan clear color not being set. (#3390) [@RoryO]
Copy link
Owner

Choose a reason for hiding this comment

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

This is duplicate, it's already above in the changelog.

- CI: Emscripten has stopped their support for their fastcomp backend, switching to latest sdk [@Xipiryon]

Expand Down
10 changes: 7 additions & 3 deletions examples/example_glfw_vulkan/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ int main(int, char**)
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));

// Main loop
while (!glfwWindowShouldClose(window))
Expand Down Expand Up @@ -505,7 +506,8 @@ int main(int, char**)
ImGui::Checkbox("Another Window", &show_another_window);

ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::ColorEdit3("clear color", (float*)&clear_color)) // Edit 3 floats representing a color
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));

Copy link
Owner

Choose a reason for hiding this comment

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

Those changes have been removed in the merged commits, favoring a simpler approach of copying in 1 location below (the removed line).

if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
Expand All @@ -530,7 +532,6 @@ int main(int, char**)
ImGui::Render();
ImDrawData* main_draw_data = ImGui::GetDrawData();
const bool main_is_minimized = (main_draw_data->DisplaySize.x <= 0.0f || main_draw_data->DisplaySize.y <= 0.0f);
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
if (!main_is_minimized)
FrameRender(wd, main_draw_data);

Expand All @@ -541,11 +542,14 @@ int main(int, char**)
ImGui::RenderPlatformWindowsDefault();
}

if (g_SwapChainRebuild) // Main viewport resized in the middle of this frame, go on to next frame.
continue;

// Present Main Platform Window
if (!main_is_minimized)
FramePresent(wd);
}

}
// Cleanup
err = vkDeviceWaitIdle(g_Device);
check_vk_result(err);
Expand Down
8 changes: 6 additions & 2 deletions examples/example_sdl_vulkan/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ int main(int, char**)
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));

// Main loop
bool done = false;
Expand Down Expand Up @@ -504,7 +505,8 @@ int main(int, char**)
ImGui::Checkbox("Another Window", &show_another_window);

ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::ColorEdit3("clear color", (float*)&clear_color)) // Edit 3 floats representing a color
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));

if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
Expand All @@ -529,7 +531,6 @@ int main(int, char**)
ImGui::Render();
ImDrawData* main_draw_data = ImGui::GetDrawData();
const bool main_is_minimized = (main_draw_data->DisplaySize.x <= 0.0f || main_draw_data->DisplaySize.y <= 0.0f);
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
if (!main_is_minimized)
FrameRender(wd, main_draw_data);

Expand All @@ -540,6 +541,9 @@ int main(int, char**)
ImGui::RenderPlatformWindowsDefault();
}

if (g_SwapChainRebuild) // Main viewport resized in the middle of this frame, go on to next frame.
continue;

// Present Main Platform Window
if (!main_is_minimized)
FramePresent(wd);
Expand Down
24 changes: 23 additions & 1 deletion examples/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ struct ImGuiViewportDataVulkan
bool WindowOwned;
ImGui_ImplVulkanH_Window Window; // Used by secondary viewports only
ImGui_ImplVulkanH_WindowRenderBuffers RenderBuffers; // Used by all viewports
bool SwapChainOutOfDate; // Flag when viewport swapchain resized in the middle of processing a frame

ImGuiViewportDataVulkan() { WindowOwned = false; memset(&RenderBuffers, 0, sizeof(RenderBuffers)); }
ImGuiViewportDataVulkan() { WindowOwned = false; SwapChainOutOfDate = false; memset(&RenderBuffers, 0, sizeof(RenderBuffers)); }
~ImGuiViewportDataVulkan() { }
};

Expand Down Expand Up @@ -1345,6 +1346,13 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
VkResult err;

if (data->SwapChainOutOfDate)
{
ImVec2 dim = ImGui::GetPlatformIO().Platform_GetWindowSize(viewport);
ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, dim.x, dim.y, v->MinImageCount);
data->SwapChainOutOfDate = false;
}

ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
{
Expand All @@ -1357,6 +1365,11 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
}
{
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR)
{
data->SwapChainOutOfDate = true;
return;
}
check_vk_result(err);
fd = &wd->Frames[wd->FrameIndex];
}
Expand Down Expand Up @@ -1417,6 +1430,9 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
ImGui_ImplVulkanH_Window* wd = &data->Window;
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;

if (data->SwapChainOutOfDate) // Frame data became invalid in the middle of rendering
return;

VkResult err;
uint32_t present_index = wd->FrameIndex;

Expand All @@ -1429,6 +1445,12 @@ 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)
{
data->SwapChainOutOfDate = true;
return;
}

check_vk_result(err);

wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences()
Expand Down