diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a4cbd4de..0220f23a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,9 @@ Other Changes: - Examples: OpenGL3: Minor tweaks + not calling glBindBuffer more than necessary in the render loop. - Examples: Vulkan: Added missing support for 32-bit indices (#define ImDrawIdx unsigned int). - Examples: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like. +- Examples: Vulkan: Added QueuedFramesCount field in ImGui_ImplVulkan_InitInfo, required during + initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). (#2071) [@nathanvoglsam] + Added ImGui_ImplVulkan_SetQueuedFramesCount() to override QueuedFramesCount while running. - Examples: DirectX9: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). (#2454) - Examples: GLUT: Fixed existing FreeGLUT example to work with regular GLUT. (#2465) [@andrewwillmott] - Examples: GLUT: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h. (#2465) [@andrewwillmott] diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 6e25185f..b04bde38 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -23,7 +23,6 @@ #define IMGUI_VULKAN_DEBUG_REPORT #endif -static uint32_t g_MinImageCount = 2; static VkAllocationCallbacks* g_Allocator = NULL; static VkInstance g_Instance = VK_NULL_HANDLE; static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; @@ -35,7 +34,8 @@ static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_WindowData g_WindowData; -static bool g_ResizeWanted = false; +static int g_MinImageCount = 2; +static bool g_WantSwapChainRebuild = false; static int g_ResizeWidth = 0, g_ResizeHeight = 0; static void check_vk_result(VkResult err) @@ -214,6 +214,7 @@ static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR // Create SwapChain, RenderPass, Framebuffer, etc. ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height, g_MinImageCount); ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator); + IM_ASSERT(wd->BackBufferCount > 0); } static void CleanupVulkan() @@ -314,7 +315,7 @@ static void glfw_error_callback(int error, const char* description) static void glfw_resize_callback(GLFWwindow*, int w, int h) { - g_ResizeWanted = true; + g_WantSwapChainRebuild = true; g_ResizeWidth = w; g_ResizeHeight = h; } @@ -373,8 +374,8 @@ int main(int, char**) init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; init_info.Allocator = g_Allocator; + init_info.QueuedFramesCount = (int)wd->BackBufferCount; init_info.CheckVkResultFn = check_vk_result; - init_info.QueuedFrames = wd->BackBufferCount; ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); // Load Fonts @@ -435,13 +436,13 @@ int main(int, char**) // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); - if (g_ResizeWanted) + if (g_WantSwapChainRebuild) { ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_ResizeWidth, g_ResizeHeight, g_MinImageCount); ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, &g_WindowData, g_Allocator); ImGui_ImplVulkan_SetQueuedFramesCount(g_WindowData.BackBufferCount); g_WindowData.FrameIndex = 0; - g_ResizeWanted = false; + g_WantSwapChainRebuild = false; } // Start the Dear ImGui frame @@ -483,28 +484,6 @@ int main(int, char**) ImGui::Text("Hello from another window!"); if (ImGui::Button("Close Me")) show_another_window = false; - - if (ImGui::Button("Increase")) - { - g_MinImageCount++; - g_ResizeWanted = true; - } - - ImGui::SameLine(); - if (ImGui::Button("Decrease")) - { - if (g_MinImageCount != 2) - { - g_MinImageCount--; - g_ResizeWanted = true; - } - } - - ImGui::SameLine(); - ImGui::Text("Back Buffers: %i", g_MinImageCount); - - ImGui::Text("Frame Index %i", wd->FrameIndex); - ImGui::End(); } diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index b430f5a0..15eb62c2 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -15,8 +15,6 @@ #define IMGUI_VULKAN_DEBUG_REPORT #endif -static uint32_t g_MinImageCount = 2; -static bool g_PendingSwapchainRebuild = false; static VkAllocationCallbacks* g_Allocator = NULL; static VkInstance g_Instance = VK_NULL_HANDLE; static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; @@ -28,6 +26,8 @@ static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_WindowData g_WindowData; +static uint32_t g_MinImageCount = 2; +static bool g_WantSwapChainRebuild = false; static void check_vk_result(VkResult err) { @@ -205,6 +205,7 @@ static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR // Create SwapChain, RenderPass, Framebuffer, etc. ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height, g_MinImageCount); ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator); + IM_ASSERT(wd->BackBufferCount > 0); } static void CleanupVulkan() @@ -298,15 +299,6 @@ static void FramePresent(ImGui_ImplVulkanH_WindowData* wd) check_vk_result(err); } -static void RebuildSwapChain(int width, int height) -{ - ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, width, height, g_MinImageCount); - ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, &g_WindowData, g_Allocator); - ImGui_ImplVulkan_SetQueuedFramesCount(g_WindowData.BackBufferCount); - g_WindowData.FrameIndex = 0; - g_PendingSwapchainRebuild = false; -} - int main(int, char**) { // Setup SDL @@ -365,7 +357,7 @@ int main(int, char**) init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; init_info.Allocator = g_Allocator; - init_info.QueuedFrames = wd->BackBufferCount; + init_info.QueuedFramesCount = wd->BackBufferCount; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info, wd->RenderPass); @@ -434,11 +426,21 @@ int main(int, char**) if (event.type == SDL_QUIT) done = true; if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window)) - RebuildSwapChain((int)event.window.data1, (int)event.window.data2); + { + g_WindowData.Width = (int)event.window.data1; + g_WindowData.Height = (int)event.window.data2; + g_WantSwapChainRebuild = true; + } } - if (g_PendingSwapchainRebuild) - RebuildSwapChain(g_WindowData.Width, g_WindowData.Height); + if (g_WantSwapChainRebuild) + { + ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_WindowData.Width, g_WindowData.Height, g_MinImageCount); + ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, &g_WindowData, g_Allocator); + ImGui_ImplVulkan_SetQueuedFramesCount(g_WindowData.BackBufferCount); + g_WindowData.FrameIndex = 0; + g_WantSwapChainRebuild = false; + } // Start the Dear ImGui frame ImGui_ImplVulkan_NewFrame(); @@ -479,28 +481,6 @@ int main(int, char**) ImGui::Text("Hello from another window!"); if (ImGui::Button("Close Me")) show_another_window = false; - - if (ImGui::Button("Increase")) - { - g_MinImageCount++; - g_PendingSwapchainRebuild = true; - } - - ImGui::SameLine(); - if (ImGui::Button("Decrease")) - { - if (g_MinImageCount != 2) - { - g_MinImageCount--; - g_PendingSwapchainRebuild = true; - } - } - - ImGui::SameLine(); - ImGui::Text("Back Buffers: %i", g_MinImageCount); - - ImGui::Text("Frame Index %i", wd->FrameIndex); - ImGui::End(); } diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index a74323ee..9eff80fd 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -13,6 +13,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-XX-XX: Vulkan: Added QueuedFramesCount field in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). +// 2019-XX-XX: Vulkan: Added ImGui_ImplVulkan_SetQueuedFramesCount() to override QueuedFramesCount while running. // 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like. // 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int). // 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display. @@ -63,9 +65,11 @@ struct FrameDataForRender VkDeviceSize IndexBufferSize; VkBuffer VertexBuffer; VkBuffer IndexBuffer; + + FrameDataForRender() { VertexBufferMemory = IndexBufferMemory = VK_NULL_HANDLE; VertexBufferSize = IndexBufferSize = VK_NULL_HANDLE; VertexBuffer = IndexBuffer = VK_NULL_HANDLE; } }; static int g_FrameIndex = 0; -static ImVector g_FramesDataBuffers = {}; +static ImVector g_FramesDataBuffers; // Font data static VkSampler g_FontSampler = VK_NULL_HANDLE; @@ -240,7 +244,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm VkResult err; FrameDataForRender* fd = &g_FramesDataBuffers[g_FrameIndex]; - g_FrameIndex = (g_FrameIndex + 1) % g_FramesDataBuffers.size(); + g_FrameIndex = (g_FrameIndex + 1) % g_FramesDataBuffers.Size; // Create the Vertex and Index buffers: size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); @@ -739,7 +743,7 @@ void ImGui_ImplVulkan_InvalidateDeviceObjects() void ImGui_ImplVulkan_InvalidateFrameDeviceObjects() { - for (int i = 0; i < g_FramesDataBuffers.size(); i++) + for (int i = 0; i < g_FramesDataBuffers.Size; i++) { FrameDataForRender* fd = &g_FramesDataBuffers[i]; if (fd->VertexBuffer) { vkDestroyBuffer(g_Device, fd->VertexBuffer, g_Allocator); fd->VertexBuffer = VK_NULL_HANDLE; } @@ -747,6 +751,7 @@ void ImGui_ImplVulkan_InvalidateFrameDeviceObjects() if (fd->IndexBuffer) { vkDestroyBuffer(g_Device, fd->IndexBuffer, g_Allocator); fd->IndexBuffer = VK_NULL_HANDLE; } if (fd->IndexBufferMemory) { vkFreeMemory (g_Device, fd->IndexBufferMemory, g_Allocator); fd->IndexBufferMemory = VK_NULL_HANDLE; } } + g_FramesDataBuffers.clear(); } bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass) @@ -759,6 +764,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend IM_ASSERT(info->Device != VK_NULL_HANDLE); IM_ASSERT(info->Queue != VK_NULL_HANDLE); IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE); + IM_ASSERT(info->QueuedFramesCount >= 2); IM_ASSERT(render_pass != VK_NULL_HANDLE); g_Instance = info->Instance; @@ -771,9 +777,10 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend g_DescriptorPool = info->DescriptorPool; g_Allocator = info->Allocator; g_CheckVkResultFn = info->CheckVkResultFn; - g_FramesDataBuffers.resize(info->QueuedFrames); - for (int i = 0; i < g_FramesDataBuffers.size(); i++) - g_FramesDataBuffers[i] = FrameDataForRender(); + + g_FramesDataBuffers.reserve(info->QueuedFramesCount); + for (int i = 0; i < info->QueuedFramesCount; i++) + g_FramesDataBuffers.push_back(FrameDataForRender()); ImGui_ImplVulkan_CreateDeviceObjects(); @@ -790,17 +797,16 @@ void ImGui_ImplVulkan_NewFrame() { } -void ImGui_ImplVulkan_SetQueuedFramesCount(uint32_t count) +void ImGui_ImplVulkan_SetQueuedFramesCount(int count) { - if (count == g_FramesDataBuffers.size()) + if (count == g_FramesDataBuffers.Size) return; ImGui_ImplVulkan_InvalidateFrameDeviceObjects(); - uint32_t old_size = g_FramesDataBuffers.size(); - g_FramesDataBuffers.resize(count); - for (uint32_t i = old_size; i < count; i++) - g_FramesDataBuffers[i] = FrameDataForRender(); g_FrameIndex = 0; + g_FramesDataBuffers.reserve(count); + for (int i = 0; i < count; i++) + g_FramesDataBuffers.push_back(FrameDataForRender()); } @@ -921,7 +927,7 @@ void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_ // Create Command Buffers VkResult err; - for (int i = 0; i < wd->Frames.size(); i++) + for (int i = 0; i < wd->Frames.Size; i++) { ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[i]; { @@ -1035,12 +1041,13 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->BackBufferCount, wd->BackBuffer); check_vk_result(err); - for (uint32_t i = 0; i < wd->Frames.size(); i++) + for (int i = 0; i < wd->Frames.Size; i++) ImGui_ImplVulkanH_DestroyFrameData(g_Instance, device, &wd->Frames[i], allocator); - uint32_t old_size = wd->Frames.size(); - wd->Frames.resize(wd->BackBufferCount); - for (uint32_t i = 0; i < wd->Frames.size(); i++) - wd->Frames[i] = ImGui_ImplVulkanH_FrameData(); + wd->Frames.clear(); + + wd->Frames.reserve((int)wd->BackBufferCount); + for (int i = 0; i < (int)wd->BackBufferCount; i++) + wd->Frames.push_back(ImGui_ImplVulkanH_FrameData()); } if (old_swapchain) vkDestroySwapchainKHR(device, old_swapchain, allocator); @@ -1127,7 +1134,7 @@ void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, I vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals) //vkQueueWaitIdle(g_Queue); - for (int i = 0; i < wd->Frames.size(); i++) + for (int i = 0; i < wd->Frames.Size; i++) { ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[i]; ImGui_ImplVulkanH_DestroyFrameData(instance, device, fd, allocator); @@ -1145,9 +1152,15 @@ void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, I void ImGui_ImplVulkanH_DestroyFrameData(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_FrameData* 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->BackbufferIndex = 0; + fd->Fence = VK_NULL_HANDLE; + fd->CommandBuffer = VK_NULL_HANDLE; + fd->CommandPool = VK_NULL_HANDLE; + fd->ImageAcquiredSemaphore = fd->RenderCompleteSemaphore = VK_NULL_HANDLE; } diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index 9164e6c3..f54caf3d 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -27,7 +27,7 @@ struct ImGui_ImplVulkan_InitInfo VkQueue Queue; VkPipelineCache PipelineCache; VkDescriptorPool DescriptorPool; - int QueuedFrames; + int QueuedFramesCount; const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); }; @@ -36,7 +36,7 @@ struct ImGui_ImplVulkan_InitInfo IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplVulkan_SetQueuedFramesCount(uint32_t count); +IMGUI_IMPL_API void ImGui_ImplVulkan_SetQueuedFramesCount(int queued_frames_count); // To override QueuedFramesCount after initialization IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer); IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateFontUploadObjects();