Browse Source

Examples: Vulkan: Further refactor.

omar 7 years ago
parent
commit
cab41d954e

+ 46 - 2
examples/imgui_impl_vulkan.cpp

@@ -11,6 +11,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
 //  2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
 //  2018-02-18: Vulkan: Offset projection matrix and clipping rectangle by io.DisplayPos (which will be non-zero for multi-viewport applications).
 //  2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
@@ -720,7 +721,6 @@ void ImGui_ImplVulkan_NewFrame()
 
 void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer)
 {
-    ImGui::Render();
     ImGui_ImplVulkan_RenderDrawData(command_buffer, ImGui::GetDrawData());
     g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
 }
@@ -821,10 +821,53 @@ VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_d
     return VK_PRESENT_MODE_FIFO_KHR; // Always available
 }
 
-void ImGui_ImplVulkanH_CreateOrResizeWindowData(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h)
+void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator)
 {
     IM_ASSERT(physical_device != NULL && device != NULL);
+    (void)allocator;
 
+    // Create Command Buffers
+    VkResult err;
+    for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
+    {
+        ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
+        {
+            VkCommandPoolCreateInfo info = {};
+            info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+            info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+            info.queueFamilyIndex = queue_family;
+            err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool);
+            check_vk_result(err);
+        }
+        {
+            VkCommandBufferAllocateInfo info = {};
+            info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+            info.commandPool = fd->CommandPool;
+            info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+            info.commandBufferCount = 1;
+            err = vkAllocateCommandBuffers(device, &info, &fd->CommandBuffer);
+            check_vk_result(err);
+        }
+        {
+            VkFenceCreateInfo info = {};
+            info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+            info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+            err = vkCreateFence(device, &info, allocator, &fd->Fence);
+            check_vk_result(err);
+        }
+        {
+            VkSemaphoreCreateInfo info = {};
+            info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+            err = vkCreateSemaphore(device, &info, allocator, &fd->PresentCompleteSemaphore);
+            check_vk_result(err);
+            err = vkCreateSemaphore(device, &info, allocator, &fd->RenderCompleteSemaphore);
+            check_vk_result(err);
+        }
+    }
+}
+
+void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h)
+{
     VkResult err;
     VkSwapchainKHR old_swapchain = wd->Swapchain;
     err = vkDeviceWaitIdle(device);
@@ -972,6 +1015,7 @@ void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, I
     vkDestroyRenderPass(device, wd->RenderPass, allocator);
     vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
     vkDestroySurfaceKHR(instance, wd->Surface, allocator);
+    *wd = ImGui_ImplVulkan_WindowData();
 }
 
 //--------------------------------------------------------------------------------------------------------

+ 5 - 4
examples/imgui_impl_vulkan.h

@@ -47,12 +47,12 @@ IMGUI_API bool        ImGui_ImplVulkan_CreateDeviceObjects();
 
 struct ImGui_ImplVulkan_FrameData;
 struct ImGui_ImplVulkan_WindowData;
-struct ImGui_ImplVulkan_WindowDataCreateInfo;
 
+IMGUI_API void                  ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator);
+IMGUI_API void                  ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h);
+IMGUI_API void                  ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator);
 IMGUI_API VkSurfaceFormatKHR    ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
 IMGUI_API VkPresentModeKHR      ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
-IMGUI_API void                  ImGui_ImplVulkanH_CreateOrResizeWindowData(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h);
-IMGUI_API void                  ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator);
 
 struct ImGui_ImplVulkan_FrameData
 {
@@ -68,7 +68,8 @@ struct ImGui_ImplVulkan_FrameData
 
 struct ImGui_ImplVulkan_WindowData
 {
-    int                 Width, Height;
+    int                 Width;
+    int                 Height;
     VkSwapchainKHR      Swapchain;
     VkSurfaceKHR        Surface;
     VkSurfaceFormatKHR  SurfaceFormat;

+ 97 - 140
examples/sdl_vulkan_example/main.cpp

@@ -44,57 +44,53 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags,
 }
 #endif // IMGUI_VULKAN_DEBUG_REPORT
 
-static void CreateVulkanInstance(const char** extensions, uint32_t extensions_count)
+static void SetupVulkan(const char** extensions, uint32_t extensions_count)
 {
     VkResult err;
 
-    VkInstanceCreateInfo create_info = {};
-    create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
-    create_info.enabledExtensionCount = extensions_count;
-    create_info.ppEnabledExtensionNames = extensions;
+    // Create Vulkan Instance
+    {
+        VkInstanceCreateInfo create_info = {};
+        create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+        create_info.enabledExtensionCount = extensions_count;
+        create_info.ppEnabledExtensionNames = extensions;
 
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
-    // Enabling multiple validation layers grouped as LunarG standard validation
-    const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
-    create_info.enabledLayerCount = 1;
-    create_info.ppEnabledLayerNames = layers;
-
-    // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
-    const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
-    memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
-    extensions_ext[extensions_count] = "VK_EXT_debug_report";
-    create_info.enabledExtensionCount = extensions_count + 1;
-    create_info.ppEnabledExtensionNames = extensions_ext;
-
-    // Create Vulkan Instance
-    err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
-    check_vk_result(err);
-    free(extensions_ext);
-
-    // Get the function pointer (required for any extensions)
-    auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
-    IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
-
-    // Setup the debug report callback
-    VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
-    debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
-    debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
-    debug_report_ci.pfnCallback = debug_report;
-    debug_report_ci.pUserData = NULL;
-    err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
-    check_vk_result(err);
+        // Enabling multiple validation layers grouped as LunarG standard validation
+        const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
+        create_info.enabledLayerCount = 1;
+        create_info.ppEnabledLayerNames = layers;
+
+        // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
+        const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
+        memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
+        extensions_ext[extensions_count] = "VK_EXT_debug_report";
+        create_info.enabledExtensionCount = extensions_count + 1;
+        create_info.ppEnabledExtensionNames = extensions_ext;
+
+        // Create Vulkan Instance
+        err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+        check_vk_result(err);
+        free(extensions_ext);
+
+        // Get the function pointer (required for any extensions)
+        auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
+        IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
+
+        // Setup the debug report callback
+        VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
+        debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
+        debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+        debug_report_ci.pfnCallback = debug_report;
+        debug_report_ci.pUserData = NULL;
+        err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
+        check_vk_result(err);
 #else
-    // Create Vulkan Instance without any debug feature
-    err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
-    check_vk_result(err);
+        // Create Vulkan Instance without any debug feature
+        err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+        check_vk_result(err);
 #endif
-}
-
-static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
-{
-    IM_ASSERT(wd->Surface != NULL);
-
-    VkResult err;
+    }
 
     // Select GPU
     {
@@ -129,34 +125,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
         IM_ASSERT(g_QueueFamily != -1);
     }
 
-    // Check for WSI support
-    {
-        VkBool32 res;
-        vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
-        if (res != VK_TRUE)
-        {
-            fprintf(stderr, "Error no WSI support on physical device 0\n");
-            exit(-1);
-        }
-    }
-
-    // Get Surface Format
-    {
-        const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
-        const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
-        wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
-    }
-
-    // Get Present Mode
-    {
-#ifdef IMGUI_UNLIMITED_FRAME_RATE
-        VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
-#else
-        VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
-#endif
-        wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
-    }
-
     // Create Logical Device (with 1 queue)
     {
         int device_extension_count = 1;
@@ -178,44 +146,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
         vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
     }
 
-    // Create Command Buffers
-    for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
-    {
-        ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
-        {
-            VkCommandPoolCreateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-            info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
-            info.queueFamilyIndex = g_QueueFamily;
-            err = vkCreateCommandPool(g_Device, &info, g_Allocator, &fd->CommandPool);
-            check_vk_result(err);
-        }
-        {
-            VkCommandBufferAllocateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-            info.commandPool = fd->CommandPool;
-            info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
-            info.commandBufferCount = 1;
-            err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer);
-            check_vk_result(err);
-        }
-        {
-            VkFenceCreateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
-            info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-            err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence);
-            check_vk_result(err);
-        }
-        {
-            VkSemaphoreCreateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
-            err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->PresentCompleteSemaphore);
-            check_vk_result(err);
-            err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->RenderCompleteSemaphore);
-            check_vk_result(err);
-        }
-    }
-
     // Create Descriptor Pool
     {
         VkDescriptorPoolSize pool_sizes[] =
@@ -243,11 +173,42 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
     }
 }
 
-static void cleanup_vulkan()
+static void SetupVulkanWindowData(ImGui_ImplVulkan_WindowData* wd, VkSurfaceKHR surface, int width, int height)
+{
+    wd->Surface = surface;
+
+    // Check for WSI support
+    VkBool32 res;
+    vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
+    if (res != VK_TRUE)
+    {
+        fprintf(stderr, "Error no WSI support on physical device 0\n");
+        exit(-1);
+    }
+
+    // Get Surface Format
+    const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
+    const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+    wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
+
+    // Get Present Mode
+#ifdef IMGUI_UNLIMITED_FRAME_RATE
+    VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+#else
+    VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
+#endif
+    wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
+
+    // Create SwapChain, RenderPass, Framebuffer, etc.
+    ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
+    ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height);
+}
+
+static void CleanupVulkan()
 {
     ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
-    vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
     ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
+    vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
 
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
     // Remove the debug report callback
@@ -259,7 +220,7 @@ static void cleanup_vulkan()
     vkDestroyInstance(g_Instance, g_Allocator);
 }
 
-static void frame_begin(ImGui_ImplVulkan_WindowData* wd)
+static void FrameBegin(ImGui_ImplVulkan_WindowData* wd)
 {
     ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
     VkResult err;
@@ -296,7 +257,7 @@ static void frame_begin(ImGui_ImplVulkan_WindowData* wd)
     }
 }
 
-static void frame_end(ImGui_ImplVulkan_WindowData* wd)
+static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
 {
     ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
     VkResult err;
@@ -322,14 +283,14 @@ static void frame_end(ImGui_ImplVulkan_WindowData* wd)
     }
 }
 
-static void frame_present(ImGui_ImplVulkan_WindowData* wd)
+static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
 {
     VkResult err;
     // If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame
 #ifdef IMGUI_UNLIMITED_FRAME_RATE
     uint32_t PresentIndex = (wd->FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES;
 #else
-    uint32_t PresentIndex = g_FrameIndex;
+    uint32_t PresentIndex = wd->FrameIndex;
 #endif // IMGUI_UNLIMITED_FRAME_RATE
 
     ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex];
@@ -359,34 +320,29 @@ int main(int, char**)
     SDL_Window* window = SDL_CreateWindow("ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_VULKAN|SDL_WINDOW_RESIZABLE);
 
     // Setup Vulkan
-    uint32_t sdl_extensions_count;
-    SDL_Vulkan_GetInstanceExtensions(window, &sdl_extensions_count, NULL);
-    const char** sdl_extensions = new const char*[sdl_extensions_count];
-    SDL_Vulkan_GetInstanceExtensions(window, &sdl_extensions_count, sdl_extensions);
-    CreateVulkanInstance(sdl_extensions, sdl_extensions_count);
-    delete[] sdl_extensions;
+    uint32_t extensions_count = 0;
+    SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, NULL);
+    const char** extensions = new const char*[extensions_count];
+    SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, extensions);
+    SetupVulkan(extensions, extensions_count);
+    delete[] extensions;
 
     // Create Window Surface
-    ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
-    SDL_bool result = SDL_Vulkan_CreateSurface(window, g_Instance, &wd->Surface);
-    if (result == 0) 
+    VkSurfaceKHR surface;
+    if (SDL_Vulkan_CreateSurface(window, g_Instance, &surface) == 0)
     {
         printf("Failed to create Vulkan surface.\n");
         return 1;
     }
 
-    SetupVulkan(wd);
-
     // Create Framebuffers
-    {
-        int w, h;
-        SDL_GetWindowSize(window, &w, &h);
-        ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, wd, g_Allocator, w, h);
-    }
+    int w, h;
+    SDL_GetWindowSize(window, &w, &h);
+    ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
+    SetupVulkanWindowData(wd, surface, w, h);
 
     // Setup ImGui binding
     ImGui::CreateContext();
-
     ImGuiIO& io = ImGui::GetIO(); (void)io;
     io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
     //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls
@@ -399,8 +355,8 @@ int main(int, char**)
     init_info.DescriptorPool = g_DescriptorPool;
     init_info.Allocator = g_Allocator;
     init_info.CheckVkResultFn = check_vk_result;
-    ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
     ImGui_ImplSDL2_Init(window, NULL);
+    ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
 
     // Setup style
     ImGui::StyleColorsDark();
@@ -473,7 +429,7 @@ 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)) 
-                ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2);
+                ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2);
         }
         ImGui_ImplVulkan_NewFrame();
         ImGui_ImplSDL2_NewFrame(window);
@@ -516,10 +472,11 @@ int main(int, char**)
         }
 
         // Rendering
+        ImGui::Render();
         memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
-        frame_begin(wd);
+        FrameBegin(wd);
         ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
-        frame_end(wd);
+        FrameEnd(wd);
 
 		ImGui::RenderAdditionalViewports();
 
@@ -527,9 +484,9 @@ int main(int, char**)
         // When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before.
         // Hence we must render once and increase the FrameIndex without presenting.
         if (swap_chain_has_at_least_one_image)
-            frame_present(wd);
+            FramePresent(wd);
 #else
-        frame_present(wd);
+        FramePresent(wd);
 #endif
         swap_chain_has_at_least_one_image = true;
         wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
@@ -542,7 +499,7 @@ int main(int, char**)
     ImGui_ImplSDL2_Shutdown();
     ImGui::DestroyContext();
     SDL_DestroyWindow(window);
-    cleanup_vulkan();
+    CleanupVulkan();
     SDL_Quit();
 
     return 0;

+ 92 - 132
examples/vulkan_example/main.cpp

@@ -47,57 +47,53 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags,
 }
 #endif // IMGUI_VULKAN_DEBUG_REPORT
 
-static void CreateVulkanInstance(const char** extensions, uint32_t extensions_count)
+static void SetupVulkan(const char** extensions, uint32_t extensions_count)
 {
     VkResult err;
 
-    VkInstanceCreateInfo create_info = {};
-    create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
-    create_info.enabledExtensionCount = extensions_count;
-    create_info.ppEnabledExtensionNames = extensions;
+    // Create Vulkan Instance
+    {
+        VkInstanceCreateInfo create_info = {};
+        create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+        create_info.enabledExtensionCount = extensions_count;
+        create_info.ppEnabledExtensionNames = extensions;
 
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
-    // Enabling multiple validation layers grouped as LunarG standard validation
-    const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
-    create_info.enabledLayerCount = 1;
-    create_info.ppEnabledLayerNames = layers;
-
-    // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
-    const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
-    memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
-    extensions_ext[extensions_count] = "VK_EXT_debug_report";
-    create_info.enabledExtensionCount = extensions_count + 1;
-    create_info.ppEnabledExtensionNames = extensions_ext;
-
-    // Create Vulkan Instance
-    err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
-    check_vk_result(err);
-    free(extensions_ext);
-
-    // Get the function pointer (required for any extensions)
-    auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
-    IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
-
-    // Setup the debug report callback
-    VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
-    debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
-    debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
-    debug_report_ci.pfnCallback = debug_report;
-    debug_report_ci.pUserData = NULL;
-    err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
-    check_vk_result(err);
+        // Enabling multiple validation layers grouped as LunarG standard validation
+        const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
+        create_info.enabledLayerCount = 1;
+        create_info.ppEnabledLayerNames = layers;
+
+        // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
+        const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
+        memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
+        extensions_ext[extensions_count] = "VK_EXT_debug_report";
+        create_info.enabledExtensionCount = extensions_count + 1;
+        create_info.ppEnabledExtensionNames = extensions_ext;
+
+        // Create Vulkan Instance
+        err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+        check_vk_result(err);
+        free(extensions_ext);
+
+        // Get the function pointer (required for any extensions)
+        auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
+        IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
+
+        // Setup the debug report callback
+        VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
+        debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
+        debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+        debug_report_ci.pfnCallback = debug_report;
+        debug_report_ci.pUserData = NULL;
+        err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
+        check_vk_result(err);
 #else
-    // Create Vulkan Instance without any debug feature
-    err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
-    check_vk_result(err);
+        // Create Vulkan Instance without any debug feature
+        err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+        check_vk_result(err);
 #endif
-}
-
-static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
-{
-    IM_ASSERT(wd->Surface != NULL);
-
-    VkResult err;
+    }
 
     // Select GPU
     {
@@ -132,34 +128,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
         IM_ASSERT(g_QueueFamily != -1);
     }
 
-    // Check for WSI support
-    {
-        VkBool32 res;
-        vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
-        if (res != VK_TRUE)
-        {
-            fprintf(stderr, "Error no WSI support on physical device 0\n");
-            exit(-1);
-        }
-    }
-
-    // Get Surface Format
-    {
-        const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
-        const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
-        wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
-    }
-
-    // Get Present Mode
-    {
-#ifdef IMGUI_UNLIMITED_FRAME_RATE
-        VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
-#else
-        VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
-#endif
-        wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
-    }
-
     // Create Logical Device (with 1 queue)
     {
         int device_extension_count = 1;
@@ -181,44 +149,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
         vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
     }
 
-    // Create Command Buffers
-    for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
-    {
-        ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
-        {
-            VkCommandPoolCreateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-            info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
-            info.queueFamilyIndex = g_QueueFamily;
-            err = vkCreateCommandPool(g_Device, &info, g_Allocator, &fd->CommandPool);
-            check_vk_result(err);
-        }
-        {
-            VkCommandBufferAllocateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-            info.commandPool = fd->CommandPool;
-            info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
-            info.commandBufferCount = 1;
-            err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer);
-            check_vk_result(err);
-        }
-        {
-            VkFenceCreateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
-            info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-            err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence);
-            check_vk_result(err);
-        }
-        {
-            VkSemaphoreCreateInfo info = {};
-            info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
-            err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->PresentCompleteSemaphore);
-            check_vk_result(err);
-            err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->RenderCompleteSemaphore);
-            check_vk_result(err);
-        }
-    }
-
     // Create Descriptor Pool
     {
         VkDescriptorPoolSize pool_sizes[] =
@@ -246,11 +176,42 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
     }
 }
 
-static void cleanup_vulkan()
+static void SetupVulkanWindowData(ImGui_ImplVulkan_WindowData* wd, VkSurfaceKHR surface, int width, int height)
+{
+    wd->Surface = surface;
+
+    // Check for WSI support
+    VkBool32 res;
+    vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
+    if (res != VK_TRUE)
+    {
+        fprintf(stderr, "Error no WSI support on physical device 0\n");
+        exit(-1);
+    }
+
+    // Get Surface Format
+    const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
+    const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+    wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
+
+    // Get Present Mode
+#ifdef IMGUI_UNLIMITED_FRAME_RATE
+    VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+#else
+    VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
+#endif
+    wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
+
+    // Create SwapChain, RenderPass, Framebuffer, etc.
+    ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
+    ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height);
+}
+
+static void CleanupVulkan()
 {
     ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
-    vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
     ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
+    vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
 
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
     // Remove the debug report callback
@@ -262,7 +223,7 @@ static void cleanup_vulkan()
     vkDestroyInstance(g_Instance, g_Allocator);
 }
 
-static void frame_begin(ImGui_ImplVulkan_WindowData* wd)
+static void FrameBegin(ImGui_ImplVulkan_WindowData* wd)
 {
     ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
     VkResult err;
@@ -299,7 +260,7 @@ static void frame_begin(ImGui_ImplVulkan_WindowData* wd)
     }
 }
 
-static void frame_end(ImGui_ImplVulkan_WindowData* wd)
+static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
 {
     ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
     VkResult err;
@@ -325,14 +286,14 @@ static void frame_end(ImGui_ImplVulkan_WindowData* wd)
     }
 }
 
-static void frame_present(ImGui_ImplVulkan_WindowData* wd)
+static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
 {
     VkResult err;
     // If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame
 #ifdef IMGUI_UNLIMITED_FRAME_RATE
     uint32_t PresentIndex = (wd->FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES;
 #else
-    uint32_t PresentIndex = g_FrameIndex;
+    uint32_t PresentIndex = wd->FrameIndex;
 #endif // IMGUI_UNLIMITED_FRAME_RATE
 
     ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex];
@@ -354,7 +315,7 @@ static void glfw_error_callback(int error, const char* description)
 
 static void glfw_resize_callback(GLFWwindow*, int w, int h)
 {
-    ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, w, h);
+    ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, w, h);
 }
 
 int main(int, char**)
@@ -373,26 +334,24 @@ int main(int, char**)
         printf("GLFW: Vulkan Not Supported\n");
         return 1;
     }
-    uint32_t glfw_extensions_count = 0;
-    const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extensions_count);
-    CreateVulkanInstance(glfw_extensions, glfw_extensions_count);
+    uint32_t extensions_count = 0;
+    const char** extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
+    SetupVulkan(extensions, extensions_count);
 
     // Create Window Surface
-    ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
-    VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &wd->Surface);
+    VkSurfaceKHR surface;
+    VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &surface);
     check_vk_result(err);
 
-    SetupVulkan(wd);
-
     // Create Framebuffers
     int w, h;
     glfwGetFramebufferSize(window, &w, &h);
-    ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, wd, g_Allocator, w, h);
     glfwSetFramebufferSizeCallback(window, glfw_resize_callback);
+    ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
+    SetupVulkanWindowData(wd, surface, w, h);
 
     // Setup ImGui binding
     ImGui::CreateContext();
-
     ImGuiIO& io = ImGui::GetIO(); (void)io;
     io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
     //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls
@@ -405,8 +364,8 @@ int main(int, char**)
     init_info.DescriptorPool = g_DescriptorPool;
     init_info.Allocator = g_Allocator;
     init_info.CheckVkResultFn = check_vk_result;
-    ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
     ImGui_ImplGlfw_InitForVulkan(window, true);
+    ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
 
     // Setup style
     ImGui::StyleColorsDark();
@@ -513,10 +472,11 @@ int main(int, char**)
         }
 
         // Rendering
+        ImGui::Render();
         memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
-        frame_begin(wd);
+        FrameBegin(wd);
         ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
-        frame_end(wd);
+        FrameEnd(wd);
 
 		ImGui::RenderAdditionalViewports();
 
@@ -524,9 +484,9 @@ int main(int, char**)
         // When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before.
         // Hence we must render once and increase the FrameIndex without presenting.
         if (swap_chain_has_at_least_one_image)
-            frame_present(wd);
+            FramePresent(wd);
 #else
-        frame_present(wd);
+        FramePresent(wd);
 #endif
         swap_chain_has_at_least_one_image = true;
         wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
@@ -538,7 +498,7 @@ int main(int, char**)
     ImGui_ImplVulkan_Shutdown();
     ImGui_ImplGlfw_Shutdown();
     ImGui::DestroyContext();
-    cleanup_vulkan();
+    CleanupVulkan();
     glfwTerminate();
 
     return 0;