From 8ec24036d70d653a3eb8615c7dffc933acf483b8 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Apr 2019 00:00:29 +0200 Subject: [PATCH 1/5] Vulkan: Viewports: Removed redundant field. --- examples/imgui_impl_vulkan.cpp | 20 ++++++++++---------- examples/imgui_impl_vulkan.h | 1 - 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index ae5a1737..5956571b 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -783,7 +783,7 @@ void ImGui_ImplVulkan_NewFrame() { } -// Note: this has no effect in the 'master' branch, but multi-viewports needs this to recreate swap-chains. +// FIXME-VIEWPORT: Need to recreate all swap chains? void ImGui_ImplVulkan_SetSwapChainMinImageCount(int min_image_count) { IM_ASSERT(min_image_count >= 2); @@ -1225,8 +1225,8 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; VkResult err; + ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; { - ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; for (;;) { err = vkWaitForFences(v->Device, 1, &fd->Fence, VK_TRUE, 100); @@ -1235,10 +1235,10 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) check_vk_result(err); } { - err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &fd->BackbufferCurrentIndex); + err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex); check_vk_result(err); + fd = &wd->Frames[wd->FrameIndex]; } - IM_ASSERT(wd->FrameIndex == fd->BackbufferCurrentIndex); // FIXME { err = vkResetCommandPool(v->Device, fd->CommandPool, 0); check_vk_result(err); @@ -1255,7 +1255,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) VkRenderPassBeginInfo info = {}; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; info.renderPass = wd->RenderPass; - info.framebuffer = wd->Frames[fd->BackbufferCurrentIndex].Framebuffer; + info.framebuffer = fd->Framebuffer; info.renderArea.extent.width = wd->Width; info.renderArea.extent.height = wd->Height; info.clearValueCount = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? 0 : 1; @@ -1264,7 +1264,6 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) } } - ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer, &fd->RenderBuffers); { @@ -1298,19 +1297,20 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*) ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; VkResult err; - uint32_t PresentIndex = wd->FrameIndex; + uint32_t present_index = wd->FrameIndex; - ImGui_ImplVulkanH_Frame* fd = &wd->Frames[PresentIndex]; + ImGui_ImplVulkanH_Frame* fd = &wd->Frames[present_index]; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; info.pWaitSemaphores = &fd->RenderCompleteSemaphore; info.swapchainCount = 1; info.pSwapchains = &wd->Swapchain; - info.pImageIndices = &fd->BackbufferCurrentIndex; + info.pImageIndices = &present_index; err = vkQueuePresentKHR(v->Queue, &info); check_vk_result(err); - wd->FrameIndex = (wd->FrameIndex + 1) % wd->FramesQueueSize; + + wd->FrameIndex = (wd->FrameIndex + 1) % wd->FramesQueueSize; // This is for the next vkWaitForFences() } void ImGui_ImplVulkan_InitPlatformInterface() diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index 56c237d6..c160b060 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -106,7 +106,6 @@ struct ImGui_ImplVulkanH_Frame VkSemaphore RenderCompleteSemaphore; VkImage Backbuffer; VkImageView BackbufferView; - uint32_t BackbufferCurrentIndex; VkFramebuffer Framebuffer; ImGui_ImplVulkan_FrameRenderBuffers RenderBuffers; }; From 01de69de366bac816328a112dce4ffcff59ddee8 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Apr 2019 00:25:42 +0200 Subject: [PATCH 2/5] Vulkan: Note for unsupported feature with multi-viewports. (#2071) --- examples/imgui_impl_vulkan.cpp | 4 +++- examples/imgui_impl_vulkan.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 5956571b..43d8d4d9 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -783,10 +783,12 @@ void ImGui_ImplVulkan_NewFrame() { } -// FIXME-VIEWPORT: Need to recreate all swap chains? void ImGui_ImplVulkan_SetSwapChainMinImageCount(int min_image_count) { IM_ASSERT(min_image_count >= 2); + if (g_VulkanInitInfo.MinImageCount == min_image_count) + return; + IM_ASSERT(0); // FIXME-VIEWPORT: Need to recreate all swap chains? g_VulkanInitInfo.MinImageCount = min_image_count; } diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index c160b060..1b156fec 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -61,7 +61,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, V IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects(); IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkInstance instance, VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator); -IMGUI_IMPL_API void ImGui_ImplVulkan_SetSwapChainMinImageCount(int frames_queue_size); // To override MinImageCount after initialization +IMGUI_IMPL_API void ImGui_ImplVulkan_SetSwapChainMinImageCount(int min_image_count); // To override MinImageCount after initialization // Called by ImGui_ImplVulkan_Init(), might be useful elsewhere. IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateDeviceObjects(); From 1ba79baab5888ce103be05d2270340841812a534 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Apr 2019 16:33:41 +0200 Subject: [PATCH 3/5] Vulkan, Viewports: Fixed ImGui_ImplVulkan_SetWindowSize() not recreating command-buffers, fence etc. (#2472, #2461, #2071) --- examples/imgui_impl_vulkan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 43d8d4d9..8767cb2f 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -1217,7 +1217,7 @@ static void ImGui_ImplVulkan_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) return; ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; data->Window.ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true; - ImGui_ImplVulkanH_CreateWindowSwapChain(v->Instance, v->PhysicalDevice, v->Device, &data->Window, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount); + ImGui_ImplVulkanH_CreateWindow(v->Instance, v->PhysicalDevice, v->Device, &data->Window, v->QueueFamily, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount); } static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) From 9acb158990ea32cb138801430423a9d0e715354b Mon Sep 17 00:00:00 2001 From: MindSpunk Date: Fri, 5 Apr 2019 15:50:21 +1100 Subject: [PATCH 4/5] Vulkan, Viewports: Fix for resizing viewport windows crashing. (#2472) --- examples/example_glfw_vulkan/main.cpp | 9 +++--- examples/example_sdl_vulkan/main.cpp | 9 +++--- examples/imgui_impl_vulkan.cpp | 41 ++++++++++++++++++++------- examples/imgui_impl_vulkan.h | 11 +++++-- 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 0b3bd955..bf5414aa 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -252,7 +252,8 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd) { VkResult err; - VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore; + VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); check_vk_result(err); @@ -300,7 +301,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd) info.commandBufferCount = 1; info.pCommandBuffers = &fd->CommandBuffer; info.signalSemaphoreCount = 1; - info.pSignalSemaphores = &fd->RenderCompleteSemaphore; + info.pSignalSemaphores = &render_complete_semaphore; err = vkEndCommandBuffer(fd->CommandBuffer); check_vk_result(err); @@ -311,11 +312,11 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd) static void FramePresent(ImGui_ImplVulkanH_Window* wd) { - ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &fd->RenderCompleteSemaphore; + info.pWaitSemaphores = &render_complete_semaphore; info.swapchainCount = 1; info.pSwapchains = &wd->Swapchain; info.pImageIndices = &wd->FrameIndex; diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 37d5ace2..837fc880 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -244,7 +244,8 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd) { VkResult err; - VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore; + VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); check_vk_result(err); @@ -292,7 +293,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd) info.commandBufferCount = 1; info.pCommandBuffers = &fd->CommandBuffer; info.signalSemaphoreCount = 1; - info.pSignalSemaphores = &fd->RenderCompleteSemaphore; + info.pSignalSemaphores = &render_complete_semaphore; err = vkEndCommandBuffer(fd->CommandBuffer); check_vk_result(err); @@ -303,11 +304,11 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd) static void FramePresent(ImGui_ImplVulkanH_Window* wd) { - ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &fd->RenderCompleteSemaphore; + info.pWaitSemaphores = &render_complete_semaphore; info.swapchainCount = 1; info.pSwapchains = &wd->Swapchain; info.pImageIndices = &wd->FrameIndex; diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 8767cb2f..88e7e0dc 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -65,6 +65,7 @@ static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; // Forward Declarations void ImGui_ImplVulkanH_DestroyFrame(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator); +void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_CreateWindowSwapChain(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator); @@ -902,6 +903,7 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkInstance instance, VkPhysica for (uint32_t i = 0; i < wd->FramesQueueSize; i++) { ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i]; + ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i]; { VkCommandPoolCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -929,9 +931,9 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkInstance instance, VkPhysica { VkSemaphoreCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - err = vkCreateSemaphore(device, &info, allocator, &fd->ImageAcquiredSemaphore); + err = vkCreateSemaphore(device, &info, allocator, &fsd->ImageAcquiredSemaphore); check_vk_result(err); - err = vkCreateSemaphore(device, &info, allocator, &fd->RenderCompleteSemaphore); + err = vkCreateSemaphore(device, &info, allocator, &fsd->RenderCompleteSemaphore); check_vk_result(err); } } @@ -960,9 +962,14 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkInstance instance, VkPhysicalDevi // 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->FramesQueueSize; i++) + { ImGui_ImplVulkanH_DestroyFrame(instance, device, &wd->Frames[i], allocator); + ImGui_ImplVulkanH_DestroyFrameSemaphores(instance, device, &wd->FrameSemaphores[i], allocator); + } delete[] wd->Frames; + delete[] wd->FrameSemaphores; wd->Frames = NULL; + wd->FrameSemaphores = NULL; wd->FramesQueueSize = 0; if (wd->RenderPass) vkDestroyRenderPass(device, wd->RenderPass, allocator); @@ -1017,7 +1024,9 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkInstance instance, VkPhysicalDevi IM_ASSERT(wd->Frames == NULL); wd->Frames = new ImGui_ImplVulkanH_Frame[wd->FramesQueueSize]; + wd->FrameSemaphores = new ImGui_ImplVulkanH_FrameSemaphores[wd->FramesQueueSize]; memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->FramesQueueSize); + memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->FramesQueueSize); for (uint32_t i = 0; i < wd->FramesQueueSize; i++) wd->Frames[i].Backbuffer = backbuffers[i]; } @@ -1115,9 +1124,14 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui //vkQueueWaitIdle(g_Queue); for (uint32_t i = 0; i < wd->FramesQueueSize; i++) + { ImGui_ImplVulkanH_DestroyFrame(instance, device, &wd->Frames[i], allocator); + ImGui_ImplVulkanH_DestroyFrameSemaphores(instance, device, &wd->FrameSemaphores[i], allocator); + } delete[] wd->Frames; + delete[] wd->FrameSemaphores; wd->Frames = NULL; + wd->FrameSemaphores = NULL; vkDestroyRenderPass(device, wd->RenderPass, allocator); vkDestroySwapchainKHR(device, wd->Swapchain, allocator); vkDestroySurfaceKHR(instance, wd->Surface, allocator); @@ -1125,18 +1139,23 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui *wd = ImGui_ImplVulkanH_Window(); } +void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator) +{ + (void)instance; + vkDestroySemaphore(device, fsd->ImageAcquiredSemaphore, allocator); + vkDestroySemaphore(device, fsd->RenderCompleteSemaphore, allocator); + fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE; +} + void ImGui_ImplVulkanH_DestroyFrame(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator) { (void)instance; vkDestroyFence(device, fd->Fence, allocator); vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer); vkDestroyCommandPool(device, fd->CommandPool, allocator); - vkDestroySemaphore(device, fd->ImageAcquiredSemaphore, allocator); - vkDestroySemaphore(device, fd->RenderCompleteSemaphore, allocator); fd->Fence = VK_NULL_HANDLE; fd->CommandBuffer = VK_NULL_HANDLE; fd->CommandPool = VK_NULL_HANDLE; - fd->ImageAcquiredSemaphore = fd->RenderCompleteSemaphore = VK_NULL_HANDLE; vkDestroyImageView(device, fd->BackbufferView, allocator); vkDestroyFramebuffer(device, fd->Framebuffer, allocator); @@ -1228,6 +1247,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) VkResult err; ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; + ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex]; { for (;;) { @@ -1237,7 +1257,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) check_vk_result(err); } { - err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex); + err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex); check_vk_result(err); fd = &wd->Frames[wd->FrameIndex]; } @@ -1275,12 +1295,12 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) VkSubmitInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &fd->ImageAcquiredSemaphore; + info.pWaitSemaphores = &fsd->ImageAcquiredSemaphore; info.pWaitDstStageMask = &wait_stage; info.commandBufferCount = 1; info.pCommandBuffers = &fd->CommandBuffer; info.signalSemaphoreCount = 1; - info.pSignalSemaphores = &fd->RenderCompleteSemaphore; + info.pSignalSemaphores = &fsd->RenderCompleteSemaphore; err = vkEndCommandBuffer(fd->CommandBuffer); check_vk_result(err); @@ -1301,11 +1321,11 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*) VkResult err; uint32_t present_index = wd->FrameIndex; - ImGui_ImplVulkanH_Frame* fd = &wd->Frames[present_index]; + ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex]; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &fd->RenderCompleteSemaphore; + info.pWaitSemaphores = &fsd->RenderCompleteSemaphore; info.swapchainCount = 1; info.pSwapchains = &wd->Swapchain; info.pImageIndices = &present_index; @@ -1313,6 +1333,7 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*) check_vk_result(err); wd->FrameIndex = (wd->FrameIndex + 1) % wd->FramesQueueSize; // This is for the next vkWaitForFences() + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->FramesQueueSize; // Now we can use the next set of semaphores } void ImGui_ImplVulkan_InitPlatformInterface() diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index 1b156fec..c632d62c 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -102,14 +102,18 @@ struct ImGui_ImplVulkanH_Frame VkCommandPool CommandPool; VkCommandBuffer CommandBuffer; VkFence Fence; - VkSemaphore ImageAcquiredSemaphore; - VkSemaphore RenderCompleteSemaphore; VkImage Backbuffer; VkImageView BackbufferView; VkFramebuffer Framebuffer; ImGui_ImplVulkan_FrameRenderBuffers RenderBuffers; }; +struct ImGui_ImplVulkanH_FrameSemaphores +{ + VkSemaphore ImageAcquiredSemaphore; + VkSemaphore RenderCompleteSemaphore; +}; + // Helper structure to hold the data needed by one rendering context into one OS window // (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.) struct ImGui_ImplVulkanH_Window @@ -125,7 +129,10 @@ struct ImGui_ImplVulkanH_Window VkClearValue ClearValue; uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount) uint32_t FramesQueueSize; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count) + uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data) ImGui_ImplVulkanH_Frame* Frames; + ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores; + ImGui_ImplVulkanH_Window() { From d61caf57145294fe98445eff3f21e24c71bd58c4 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Apr 2019 18:52:40 +0200 Subject: [PATCH 5/5] Vulkan, Viewports: ImGui_ImplVulkan_RenderDrawData and renderer back-end automatically manage ImGui_ImplVulkanH_WindowRenderBuffers for each viewports so user doesn't have to do it. (#2461, #2348, #2378, #2097) --- examples/imgui_impl_vulkan.cpp | 59 ++++++++++++++++++++++------------ examples/imgui_impl_vulkan.h | 4 --- imgui.cpp | 1 + imgui.h | 3 +- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 1c9e7b51..2dc93b3e 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -65,6 +65,17 @@ struct ImGui_ImplVulkanH_WindowRenderBuffers ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers; }; +// For multi-viewport support +struct ImGuiViewportDataVulkan +{ + bool WindowOwned; + ImGui_ImplVulkanH_Window Window; // Used by secondary viewports only + ImGui_ImplVulkanH_WindowRenderBuffers RenderBuffers; // Used by all viewports + + ImGuiViewportDataVulkan() { WindowOwned = false; memset(&RenderBuffers, 0, sizeof(RenderBuffers)); } + ~ImGuiViewportDataVulkan() { } +}; + // Vulkan data static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = {}; static VkRenderPass g_RenderPass = VK_NULL_HANDLE; @@ -83,14 +94,14 @@ static VkImageView g_FontView = VK_NULL_HANDLE; static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; -// Render buffers -static ImGui_ImplVulkanH_WindowRenderBuffers g_MainWindowRenderBuffers; - // Forward Declarations +bool ImGui_ImplVulkan_CreateDeviceObjects(); +void ImGui_ImplVulkan_DestroyDeviceObjects(); void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator); +void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator); @@ -274,8 +285,10 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; - // Allocate array to store enough vertex/index buffers - ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers; + // Allocate array to store enough vertex/index buffers. Each unique viewport gets its own storage. + ImGuiViewportDataVulkan* viewport_renderer_data = (ImGuiViewportDataVulkan*)draw_data->OwnerViewport->RendererUserData; + IM_ASSERT(viewport_renderer_data != NULL); + ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &viewport_renderer_data->RenderBuffers; if (wrb->FrameRenderBuffers == NULL) { wrb->Index = 0; @@ -777,7 +790,7 @@ void ImGui_ImplVulkan_DestroyFontUploadObjects() void ImGui_ImplVulkan_DestroyDeviceObjects() { ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; - ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator); + ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator); ImGui_ImplVulkan_DestroyFontUploadObjects(); if (g_FontView) { vkDestroyImageView(v->Device, g_FontView, v->Allocator); g_FontView = VK_NULL_HANDLE; } @@ -809,6 +822,10 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend g_RenderPass = render_pass; ImGui_ImplVulkan_CreateDeviceObjects(); + // Our render function expect RendererUserData to be storing the window render buffer we need (for the main viewport we won't use ->Window) + ImGuiViewport* main_viewport = ImGui::GetMainViewport(); + main_viewport->RendererUserData = IM_NEW(ImGuiViewportDataVulkan)(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) ImGui_ImplVulkan_InitPlatformInterface(); @@ -830,11 +847,13 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count) IM_ASSERT(min_image_count >= 2); if (g_VulkanInitInfo.MinImageCount == min_image_count) return; - IM_ASSERT(0); // FIXME-VIEWPORT: Need to recreate all swap chains? + + IM_ASSERT(0); // FIXME-VIEWPORT: Unsupported. Need to recreate all swap chains! ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; VkResult err = vkDeviceWaitIdle(v->Device); check_vk_result(err); - ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator); + + ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator); g_VulkanInitInfo.MinImageCount = min_image_count; } @@ -1211,22 +1230,19 @@ void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVul buffers->Count = 0; } +void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator) +{ + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + for (int n = 0; n < platform_io.Viewports.Size; n++) + if (ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)platform_io.Viewports[n]->RendererUserData) + ImGui_ImplVulkanH_DestroyWindowRenderBuffers(device, &data->RenderBuffers, allocator); +} //-------------------------------------------------------------------------------------------------------- // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT // This is an _advanced_ and _optional_ feature, allowing the back-end to create and handle multiple viewports simultaneously. // If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first.. //-------------------------------------------------------------------------------------------------------- -// FIXME-PLATFORM: Vulkan support unfinished -//-------------------------------------------------------------------------------------------------------- - -struct ImGuiViewportDataVulkan -{ - ImGui_ImplVulkanH_Window Window; - - ImGuiViewportDataVulkan() { } - ~ImGuiViewportDataVulkan() { } -}; static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) { @@ -1263,6 +1279,7 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) // Create SwapChain, RenderPass, Framebuffer, etc. wd->ClearEnable = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? false : true; ImGui_ImplVulkanH_CreateWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount); + data->WindowOwned = true; } static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport) @@ -1271,7 +1288,9 @@ static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport) if (ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)viewport->RendererUserData) { ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; - ImGui_ImplVulkanH_DestroyWindow(v->Instance, v->Device, &data->Window, v->Allocator); + if (data->WindowOwned) + ImGui_ImplVulkanH_DestroyWindow(v->Instance, v->Device, &data->Window, v->Allocator); + ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &data->RenderBuffers, v->Allocator); IM_DELETE(data); } viewport->RendererUserData = NULL; @@ -1380,7 +1399,7 @@ static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*) err = vkQueuePresentKHR(v->Queue, &info); check_vk_result(err); - wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences() + wd->FrameIndex = (wd->FrameIndex + 1) % wd->ImageCount; // This is for the next vkWaitForFences() wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores } diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index eba29c42..9ff70c01 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -49,10 +49,6 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer comm IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects(); IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated) -// Called by ImGui_ImplVulkan_Init(), might be useful elsewhere. -IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateDeviceObjects(); -IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyDeviceObjects(); - //------------------------------------------------------------------------- // Internal / Miscellaneous Vulkan Helpers diff --git a/imgui.cpp b/imgui.cpp index c96b2d8a..51123a68 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4000,6 +4000,7 @@ static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVectorDisplayPos = viewport->Pos; draw_data->DisplaySize = viewport->Size; draw_data->FramebufferScale = ImGui::GetIO().DisplayFramebufferScale; // FIXME-VIEWPORT: This may vary on a per-monitor/viewport basis? + draw_data->OwnerViewport = viewport; for (int n = 0; n < draw_lists->Size; n++) { draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size; diff --git a/imgui.h b/imgui.h index f990e066..fc9d4146 100644 --- a/imgui.h +++ b/imgui.h @@ -2012,11 +2012,12 @@ struct ImDrawData ImVec2 DisplayPos; // Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use) ImVec2 DisplaySize; // Size of the viewport to render (== io.DisplaySize for the main viewport) (DisplayPos + DisplaySize == lower-right of the orthogonal projection matrix to use) ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display. + ImGuiViewport* OwnerViewport; // Viewport carrying the ImDrawData instance, might be of use to the renderer (generally not). // Functions ImDrawData() { Valid = false; Clear(); } ~ImDrawData() { Clear(); } - void Clear() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; DisplayPos = DisplaySize = FramebufferScale = ImVec2(0.f, 0.f); } // The ImDrawList are owned by ImGuiContext! + void Clear() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; DisplayPos = DisplaySize = FramebufferScale = ImVec2(0.f, 0.f); OwnerViewport = NULL; } // The ImDrawList are owned by ImGuiContext! IMGUI_API void DeIndexAllBuffers(); // Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! IMGUI_API void ScaleClipRects(const ImVec2& fb_scale); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. };