Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 30 additions & 21 deletions backends/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1619,10 +1619,7 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi
err = vkCreateFence(device, &info, allocator, &fd->Fence);
check_vk_result(err);
}
}

for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
{
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
{
VkSemaphoreCreateInfo info = {};
Expand Down Expand Up @@ -1659,12 +1656,15 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
// We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
// Destroy old Framebuffer
for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
}

wd->Frames.clear();
wd->FrameSemaphores.clear();
wd->ImageCount = 0;
wd->FrameIndex = 0;
if (wd->RenderPass)
vkDestroyRenderPass(device, wd->RenderPass, allocator);

Expand Down Expand Up @@ -1716,9 +1716,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
check_vk_result(err);

wd->SemaphoreCount = wd->ImageCount + 1;
wd->Frames.resize(wd->ImageCount);
wd->FrameSemaphores.resize(wd->SemaphoreCount);
wd->FrameSemaphores.resize(wd->ImageCount);
memset(wd->Frames.Data, 0, wd->Frames.size_in_bytes());
memset(wd->FrameSemaphores.Data, 0, wd->FrameSemaphores.size_in_bytes());
for (uint32_t i = 0; i < wd->ImageCount; i++)
Expand Down Expand Up @@ -1904,9 +1903,11 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
//vkQueueWaitIdle(bd->Queue);

for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
}

wd->Frames.clear();
wd->FrameSemaphores.clear();
vkDestroyRenderPass(device, wd->RenderPass, allocator);
Expand Down Expand Up @@ -2059,11 +2060,26 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
vd->SwapChainNeedRebuild = vd->SwapChainSuboptimal = false;
}

ImGui_ImplVulkanH_Frame* fd = nullptr;
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];

for (;;)
{
err = vkWaitForFences(v->Device, 1, &fd->Fence, VK_TRUE, 100);
if (err == VK_SUCCESS)
{
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);
err = vkResetFences(v->Device, 1,&fd->Fence);
check_vk_result(err);
break;
}
if (err == VK_TIMEOUT) continue;
check_vk_result(err);
}

ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->FrameIndex];

{
{
err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->ImageIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR)
{
vd->SwapChainNeedRebuild = true; // Since we are not going to swap this frame anyway, it's ok that recreation happens on next frame.
Expand All @@ -2073,15 +2089,8 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
vd->SwapChainSuboptimal = true;
else
check_vk_result(err);
fd = &wd->Frames[wd->FrameIndex];
}
for (;;)
{
err = vkWaitForFences(v->Device, 1, &fd->Fence, VK_TRUE, 100);
if (err == VK_SUCCESS) break;
if (err == VK_TIMEOUT) continue;
check_vk_result(err);
}

{
err = vkResetCommandPool(v->Device, fd->CommandPool, 0);
check_vk_result(err);
Expand Down Expand Up @@ -2203,9 +2212,9 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
return;

VkResult err;
uint32_t present_index = wd->FrameIndex;
uint32_t present_index = wd->ImageIndex;

ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[present_index];
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
Expand All @@ -2223,7 +2232,7 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)
vd->SwapChainSuboptimal = true;
else
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // Swap frame
}

void ImGui_ImplVulkan_InitMultiViewportSupport()
Expand Down
3 changes: 1 addition & 2 deletions backends/imgui_impl_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ struct ImGui_ImplVulkanH_Window
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)
uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
uint32_t ImageIndex; // Current available swapchain image index (returned by vkAcquireNextImageKHR) used to access RenderCompleteSemaphore
ImVector<ImGui_ImplVulkanH_Frame> Frames;
ImVector<ImGui_ImplVulkanH_FrameSemaphores> FrameSemaphores;

Expand Down
28 changes: 15 additions & 13 deletions examples/example_glfw_vulkan/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,16 +263,7 @@ static void CleanupVulkanWindow()

static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
{
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);

VkResult err;
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
Expand All @@ -281,6 +272,16 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
err = vkResetFences(g_Device, 1, &fd->Fence);
check_vk_result(err);
}

VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->FrameIndex].ImageAcquiredSemaphore;
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->ImageIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);

{
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
check_vk_result(err);
Expand Down Expand Up @@ -308,6 +309,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
// Submit command buffer
vkCmdEndRenderPass(fd->CommandBuffer);
{
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->ImageIndex].RenderCompleteSemaphore;
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
Expand All @@ -330,22 +332,22 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
{
if (g_SwapChainRebuild)
return;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->ImageIndex].RenderCompleteSemaphore;
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &render_complete_semaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &wd->FrameIndex;
info.pImageIndices = &wd->ImageIndex;
VkResult err = vkQueuePresentKHR(g_Queue, &info);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // Swap frame
}

// Main code
Expand Down
28 changes: 15 additions & 13 deletions examples/example_sdl2_vulkan/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,16 +254,7 @@ static void CleanupVulkanWindow()

static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
{
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);

VkResult err;
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
Expand All @@ -272,6 +263,16 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
err = vkResetFences(g_Device, 1, &fd->Fence);
check_vk_result(err);
}

VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->FrameIndex].ImageAcquiredSemaphore;
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->ImageIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);

{
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
check_vk_result(err);
Expand Down Expand Up @@ -299,6 +300,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
// Submit command buffer
vkCmdEndRenderPass(fd->CommandBuffer);
{
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->ImageIndex].RenderCompleteSemaphore;
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
Expand All @@ -321,22 +323,22 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
{
if (g_SwapChainRebuild)
return;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->ImageIndex].RenderCompleteSemaphore;
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &render_complete_semaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &wd->FrameIndex;
info.pImageIndices = &wd->ImageIndex;
VkResult err = vkQueuePresentKHR(g_Queue, &info);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // Swap frame
}

// Main code
Expand Down
29 changes: 16 additions & 13 deletions examples/example_sdl3_vulkan/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,16 +256,7 @@ static void CleanupVulkanWindow()

static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
{
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);

VkResult err;
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
Expand All @@ -274,6 +265,17 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
err = vkResetFences(g_Device, 1, &fd->Fence);
check_vk_result(err);
}

VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->FrameIndex].ImageAcquiredSemaphore;
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->ImageIndex);

if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);

{
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
check_vk_result(err);
Expand Down Expand Up @@ -301,6 +303,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
// Submit command buffer
vkCmdEndRenderPass(fd->CommandBuffer);
{
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->ImageIndex].RenderCompleteSemaphore;
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
Expand All @@ -323,22 +326,22 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
{
if (g_SwapChainRebuild)
return;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->ImageIndex].RenderCompleteSemaphore;
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &render_complete_semaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &wd->FrameIndex;
info.pImageIndices = &wd->ImageIndex;
VkResult err = vkQueuePresentKHR(g_Queue, &info);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // Swap frame
}

// Main code
Expand Down
Loading