Explorar o código

Examples: Vulkan: Moved CreateOrResizeWindowData func to imgui_impl_vulkan.h

omar %!s(int64=7) %!d(string=hai) anos
pai
achega
e0cbfd74d7

+ 197 - 41
examples/imgui_impl_vulkan.cpp

@@ -26,11 +26,12 @@
 // Vulkan data
 static const VkAllocationCallbacks* g_Allocator = NULL;
 static VkPhysicalDevice             g_PhysicalDevice = VK_NULL_HANDLE;
+static VkInstance                   g_Instance = VK_NULL_HANDLE;
 static VkDevice                     g_Device = VK_NULL_HANDLE;
-static VkRenderPass                 g_RenderPass = VK_NULL_HANDLE;
 static VkPipelineCache              g_PipelineCache = VK_NULL_HANDLE;
 static VkDescriptorPool             g_DescriptorPool = VK_NULL_HANDLE;
-static void                         (*g_CheckVkResult)(VkResult err) = NULL;
+static VkRenderPass                 g_RenderPass = VK_NULL_HANDLE;
+static void                         (*g_CheckVkResultFn)(VkResult err) = NULL;
 
 static VkDeviceSize           g_BufferMemoryAlignment = 256;
 static VkPipelineCreateFlags  g_PipelineCreateFlags = 0;
@@ -150,13 +151,13 @@ static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, ui
     for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
         if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i))
             return i;
-    return 0xffffffff; // Unable to find memoryType
+    return 0xFFFFFFFF; // Unable to find memoryType
 }
 
-static void ImGui_ImplVulkan_VkResult(VkResult err)
+static void check_vk_result(VkResult err)
 {
-    if (g_CheckVkResult)
-        g_CheckVkResult(err);
+    if (g_CheckVkResultFn)
+        g_CheckVkResultFn(err);
 }
 
 static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
@@ -174,7 +175,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
     buffer_info.usage = usage;
     buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
     err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &buffer);
-    ImGui_ImplVulkan_VkResult(err);
+    check_vk_result(err);
 
     VkMemoryRequirements req;
     vkGetBufferMemoryRequirements(g_Device, buffer, &req);
@@ -184,10 +185,10 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
     alloc_info.allocationSize = req.size;
     alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
     err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &buffer_memory);
-    ImGui_ImplVulkan_VkResult(err);
+    check_vk_result(err);
 
     err = vkBindBufferMemory(g_Device, buffer, buffer_memory, 0);
-    ImGui_ImplVulkan_VkResult(err);
+    check_vk_result(err);
     p_buffer_size = new_size;
 }
 
@@ -214,9 +215,9 @@ void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData*
         ImDrawVert* vtx_dst;
         ImDrawIdx* idx_dst;
         err = vkMapMemory(g_Device, fd->VertexBufferMemory, 0, vertex_size, 0, (void**)(&vtx_dst));
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         err = vkMapMemory(g_Device, fd->IndexBufferMemory, 0, index_size, 0, (void**)(&idx_dst));
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         for (int n = 0; n < draw_data->CmdListsCount; n++)
         {
             const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -233,7 +234,7 @@ void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData*
         range[1].memory = fd->IndexBufferMemory;
         range[1].size = VK_WHOLE_SIZE;
         err = vkFlushMappedMemoryRanges(g_Device, 2, range);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         vkUnmapMemory(g_Device, fd->VertexBufferMemory);
         vkUnmapMemory(g_Device, fd->IndexBufferMemory);
     }
@@ -339,7 +340,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
         info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
         info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
         err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         VkMemoryRequirements req;
         vkGetImageMemoryRequirements(g_Device, g_FontImage, &req);
         VkMemoryAllocateInfo alloc_info = {};
@@ -347,9 +348,9 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
         alloc_info.allocationSize = req.size;
         alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
         err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     // Create the Image View:
@@ -363,7 +364,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
         info.subresourceRange.levelCount = 1;
         info.subresourceRange.layerCount = 1;
         err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     // Update the Descriptor Set:
@@ -389,7 +390,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
         buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
         buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
         err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         VkMemoryRequirements req;
         vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req);
         g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
@@ -398,23 +399,23 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
         alloc_info.allocationSize = req.size;
         alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
         err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     // Upload to Buffer:
     {
         char* map = NULL;
         err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         memcpy(map, pixels, upload_size);
         VkMappedMemoryRange range[1] = {};
         range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
         range[0].memory = g_UploadBufferMemory;
         range[0].size = upload_size;
         err = vkFlushMappedMemoryRanges(g_Device, 1, range);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         vkUnmapMemory(g_Device, g_UploadBufferMemory);
     }
 
@@ -475,13 +476,13 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
         vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
         err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
         VkShaderModuleCreateInfo frag_info = {};
         frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
         frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
         frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
         err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     if (!g_FontSampler)
@@ -498,7 +499,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         info.maxLod = 1000;
         info.maxAnisotropy = 1.0f;
         err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     if (!g_DescriptorSetLayout)
@@ -514,7 +515,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         info.bindingCount = 1;
         info.pBindings = binding;
         err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     // Create Descriptor Set:
@@ -525,7 +526,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         alloc_info.descriptorSetCount = 1;
         alloc_info.pSetLayouts = &g_DescriptorSetLayout;
         err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     if (!g_PipelineLayout)
@@ -543,7 +544,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         layout_info.pushConstantRangeCount = 1;
         layout_info.pPushConstantRanges = push_constants;
         err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout);
-        ImGui_ImplVulkan_VkResult(err);
+        check_vk_result(err);
     }
 
     VkPipelineShaderStageCreateInfo stage[2] = {};
@@ -641,7 +642,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
     info.layout = g_PipelineLayout;
     info.renderPass = g_RenderPass;
     err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline);
-    ImGui_ImplVulkan_VkResult(err);
+    check_vk_result(err);
 
     vkDestroyShaderModule(g_Device, vert_module, g_Allocator);
     vkDestroyShaderModule(g_Device, frag_module, g_Allocator);
@@ -685,15 +686,19 @@ void    ImGui_ImplVulkan_InvalidateDeviceObjects()
     if (g_Pipeline)             { vkDestroyPipeline(g_Device, g_Pipeline, g_Allocator); g_Pipeline = VK_NULL_HANDLE; }
 }
 
-bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo *init_data)
+bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
 {
-    g_Allocator = init_data->Allocator;
-    g_PhysicalDevice = init_data->PhysicalDevice;
-    g_Device = init_data->Device;
-    g_RenderPass = init_data->RenderPass;
-    g_PipelineCache = init_data->PipelineCache;
-    g_DescriptorPool = init_data->DescriptorPool;
-    g_CheckVkResult = init_data->CheckVkResultFn;
+    IM_ASSERT(info->Instance != NULL);
+    IM_ASSERT(info->PhysicalDevice != NULL);
+    IM_ASSERT(info->Device != NULL);
+
+    g_Allocator = info->Allocator;
+    g_PhysicalDevice = info->PhysicalDevice;
+    g_Device = info->Device;
+    g_RenderPass = render_pass;
+    g_PipelineCache = info->PipelineCache;
+    g_DescriptorPool = info->DescriptorPool;
+    g_CheckVkResultFn = info->CheckVkResultFn;
 
     ImGuiIO& io = ImGui::GetIO();
     ImGui_ImplVulkan_CreateDeviceObjects();
@@ -753,9 +758,7 @@ ImGui_ImplVulkan_WindowData::ImGui_ImplVulkan_WindowData()
     FrameIndex = 0;
 }
 
-
-
-VkSurfaceFormatKHR ImGui_ImplVulkan_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
+VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
 {
     IM_ASSERT(request_formats != NULL);
     IM_ASSERT(request_formats_count > 0);
@@ -799,7 +802,7 @@ VkSurfaceFormatKHR ImGui_ImplVulkan_SelectSurfaceFormat(VkPhysicalDevice physica
     }
 }
 
-VkPresentModeKHR ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
+VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
 {
     IM_ASSERT(request_modes != NULL);
     IM_ASSERT(request_modes_count > 0);
@@ -818,6 +821,159 @@ VkPresentModeKHR ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_de
     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)
+{
+    IM_ASSERT(physical_device != NULL && device != NULL);
+
+    VkResult err;
+    VkSwapchainKHR old_swapchain = wd->Swapchain;
+    err = vkDeviceWaitIdle(device);
+    check_vk_result(err);
+
+    // Destroy old Framebuffer
+    for (uint32_t i = 0; i < wd->BackBufferCount; i++)
+    {
+        if (wd->BackBufferView[i])
+            vkDestroyImageView(device, wd->BackBufferView[i], allocator);
+        if (wd->Framebuffer[i])
+            vkDestroyFramebuffer(device, wd->Framebuffer[i], allocator);
+    }
+    wd->BackBufferCount = 0;
+    if (wd->RenderPass)
+        vkDestroyRenderPass(device, wd->RenderPass, allocator);
+
+    // Create Swapchain
+    {
+        VkSwapchainCreateInfoKHR info = {};
+        info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+        info.surface = wd->Surface;
+        info.imageFormat = wd->SurfaceFormat.format;
+        info.imageColorSpace = wd->SurfaceFormat.colorSpace;
+        info.imageArrayLayers = 1;
+        info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+        info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;           // Assume that graphics family == present family
+        info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+        info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+        info.presentMode = wd->PresentMode;
+        info.clipped = VK_TRUE;
+        info.oldSwapchain = old_swapchain;
+        VkSurfaceCapabilitiesKHR cap;
+        err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
+        check_vk_result(err);
+        if (cap.maxImageCount > 0)
+            info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
+        else
+            info.minImageCount = cap.minImageCount + 2;
+
+        if (cap.currentExtent.width == 0xffffffff)
+        {
+            info.imageExtent.width = wd->Width = w;
+            info.imageExtent.height = wd->Height = h;
+        }
+        else
+        {
+            info.imageExtent.width = wd->Width = cap.currentExtent.width;
+            info.imageExtent.height = wd->Height = cap.currentExtent.height;
+        }
+        err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);
+        check_vk_result(err);
+        err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->BackBufferCount, NULL);
+        check_vk_result(err);
+        err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->BackBufferCount, wd->BackBuffer);
+        check_vk_result(err);
+    }
+    if (old_swapchain)
+        vkDestroySwapchainKHR(device, old_swapchain, allocator);
+
+    // Create the Render Pass
+    {
+        VkAttachmentDescription attachment = {};
+        attachment.format = wd->SurfaceFormat.format;
+        attachment.samples = VK_SAMPLE_COUNT_1_BIT;
+        attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+        attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+        attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+        VkAttachmentReference color_attachment = {};
+        color_attachment.attachment = 0;
+        color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+        VkSubpassDescription subpass = {};
+        subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+        subpass.colorAttachmentCount = 1;
+        subpass.pColorAttachments = &color_attachment;
+        VkRenderPassCreateInfo info = {};
+        info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+        info.attachmentCount = 1;
+        info.pAttachments = &attachment;
+        info.subpassCount = 1;
+        info.pSubpasses = &subpass;
+        err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass);
+        check_vk_result(err);
+    }
+
+    // Create The Image Views
+    {
+        VkImageViewCreateInfo info = {};
+        info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+        info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+        info.format = wd->SurfaceFormat.format;
+        info.components.r = VK_COMPONENT_SWIZZLE_R;
+        info.components.g = VK_COMPONENT_SWIZZLE_G;
+        info.components.b = VK_COMPONENT_SWIZZLE_B;
+        info.components.a = VK_COMPONENT_SWIZZLE_A;
+        VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
+        info.subresourceRange = image_range;
+        for (uint32_t i = 0; i < wd->BackBufferCount; i++)
+        {
+            info.image = wd->BackBuffer[i];
+            err = vkCreateImageView(device, &info, allocator, &wd->BackBufferView[i]);
+            check_vk_result(err);
+        }
+    }
+
+    // Create Framebuffer
+    {
+        VkImageView attachment[1];
+        VkFramebufferCreateInfo info = {};
+        info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+        info.renderPass = wd->RenderPass;
+        info.attachmentCount = 1;
+        info.pAttachments = attachment;
+        info.width = wd->Width;
+        info.height = wd->Height;
+        info.layers = 1;
+        for (uint32_t i = 0; i < wd->BackBufferCount; i++)
+        {
+            attachment[0] = wd->BackBufferView[i];
+            err = vkCreateFramebuffer(device, &info, allocator, &wd->Framebuffer[i]);
+            check_vk_result(err);
+        }
+    }
+}
+
+void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator)
+{
+    for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
+    {
+        ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
+        vkDestroyFence(device, fd->Fence, allocator);
+        vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
+        vkDestroyCommandPool(device, fd->CommandPool, allocator);
+        vkDestroySemaphore(device, fd->PresentCompleteSemaphore, allocator);
+        vkDestroySemaphore(device, fd->RenderCompleteSemaphore, allocator);
+    }
+    for (uint32_t i = 0; i < wd->BackBufferCount; i++)
+    {
+        vkDestroyImageView(device, wd->BackBufferView[i], allocator);
+        vkDestroyFramebuffer(device, wd->Framebuffer[i], allocator);
+    }
+    vkDestroyRenderPass(device, wd->RenderPass, allocator);
+    vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
+    vkDestroySurfaceKHR(instance, wd->Surface, allocator);
+}
+
 //--------------------------------------------------------------------------------------------------------
 // Platform Windows (OPTIONAL/EXPERIMENTAL)
 //--------------------------------------------------------------------------------------------------------
@@ -826,7 +982,7 @@ VkPresentModeKHR ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_de
 
 struct ImGuiPlatformDataVulkan
 {
-    // store swap chain, render target/frame buffer, etc.
+    ImGui_ImplVulkan_WindowData Wd;
 
     ImGuiPlatformDataVulkan() { }
     ~ImGuiPlatformDataVulkan() { }

+ 14 - 5
examples/imgui_impl_vulkan.h

@@ -15,16 +15,16 @@
 
 struct ImGui_ImplVulkan_InitInfo
 {
-    const VkAllocationCallbacks*    Allocator;
+    VkInstance                      Instance;
     VkPhysicalDevice                PhysicalDevice;
     VkDevice                        Device;
-    VkRenderPass                    RenderPass;
     VkPipelineCache                 PipelineCache;
     VkDescriptorPool                DescriptorPool;
+    const VkAllocationCallbacks*    Allocator;
     void                            (*CheckVkResultFn)(VkResult err);
 };
 
-IMGUI_API bool        ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo *init_data);
+IMGUI_API bool        ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
 IMGUI_API void        ImGui_ImplVulkan_Shutdown();
 IMGUI_API void        ImGui_ImplVulkan_NewFrame();
 IMGUI_API void        ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer);
@@ -42,9 +42,17 @@ IMGUI_API bool        ImGui_ImplVulkan_CreateDeviceObjects();
 // But for the purpose of allowing multi-windows, we need those internally anyway. The code being not trivial are exposing it for the benefit of the example code.
 // If your application/engine already has code to create all that data (swap chain, render pass, frame buffers, etc.) you can ignore all of this.
 //-------------------------------------------------------------------------
+// NB: Those functions do NOT use any of the state used/affected by the regular ImGui_ImplVulkan_XXX functions.
+//-------------------------------------------------------------------------
 
-IMGUI_API VkSurfaceFormatKHR    ImGui_ImplVulkan_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
-IMGUI_API VkPresentModeKHR      ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
+struct ImGui_ImplVulkan_FrameData;
+struct ImGui_ImplVulkan_WindowData;
+struct ImGui_ImplVulkan_WindowDataCreateInfo;
+
+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
 {
@@ -76,3 +84,4 @@ struct ImGui_ImplVulkan_WindowData
 
     IMGUI_API ImGui_ImplVulkan_WindowData();
 };
+

+ 25 - 170
examples/sdl_vulkan_example/main.cpp

@@ -15,17 +15,17 @@
 #define IMGUI_VULKAN_DEBUG_REPORT
 #endif
 
-static VkAllocationCallbacks*   g_Allocator = NULL;
-static VkInstance               g_Instance = VK_NULL_HANDLE;
-static VkPhysicalDevice         g_PhysicalDevice = VK_NULL_HANDLE;
-static VkDevice                 g_Device = VK_NULL_HANDLE;
-static uint32_t                 g_QueueFamily = (uint32_t)-1;
-static VkQueue                  g_Queue = VK_NULL_HANDLE;
-static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
-static VkPipelineCache          g_PipelineCache = VK_NULL_HANDLE;
-static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE;
-
-static ImGui_ImplVulkan_WindowData               g_WindowData;
+static VkAllocationCallbacks*       g_Allocator = NULL;
+static VkInstance                   g_Instance = VK_NULL_HANDLE;
+static VkPhysicalDevice             g_PhysicalDevice = VK_NULL_HANDLE;
+static VkDevice                     g_Device = VK_NULL_HANDLE;
+static uint32_t                     g_QueueFamily = (uint32_t)-1;
+static VkQueue                      g_Queue = VK_NULL_HANDLE;
+static VkDebugReportCallbackEXT     g_DebugReport = VK_NULL_HANDLE;
+static VkPipelineCache              g_PipelineCache = VK_NULL_HANDLE;
+static VkDescriptorPool             g_DescriptorPool = VK_NULL_HANDLE;
+
+static ImGui_ImplVulkan_WindowData  g_WindowData;
 
 static void check_vk_result(VkResult err)
 {
@@ -35,136 +35,6 @@ static void check_vk_result(VkResult err)
         abort();
 }
 
-static void CreateOrResizeSwapChainAndFrameBuffer(ImGui_ImplVulkan_WindowData* wd, int w, int h)
-{
-    VkResult err;
-    VkSwapchainKHR old_swapchain = wd->Swapchain;
-    err = vkDeviceWaitIdle(g_Device);
-    check_vk_result(err);
-
-    // Destroy old Framebuffer
-    for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-    {
-        if (wd->BackBufferView[i])
-            vkDestroyImageView(g_Device, wd->BackBufferView[i], g_Allocator);
-        if (wd->Framebuffer[i])
-            vkDestroyFramebuffer(g_Device, wd->Framebuffer[i], g_Allocator);
-    }
-    wd->BackBufferCount = 0;
-    if (wd->RenderPass)
-        vkDestroyRenderPass(g_Device, wd->RenderPass, g_Allocator);
-
-    // Create Swapchain
-    {
-        VkSwapchainCreateInfoKHR info = {};
-        info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
-        info.surface = wd->Surface;
-        info.imageFormat = wd->SurfaceFormat.format;
-        info.imageColorSpace = wd->SurfaceFormat.colorSpace;
-        info.imageArrayLayers = 1;
-        info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-        info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;           // Assume that graphics family == present family
-        info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
-        info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-        info.presentMode = wd->PresentMode;
-        info.clipped = VK_TRUE;
-        info.oldSwapchain = old_swapchain;
-        VkSurfaceCapabilitiesKHR cap;
-        err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_PhysicalDevice, wd->Surface, &cap);
-        check_vk_result(err);
-        if (cap.maxImageCount > 0)
-            info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
-        else
-            info.minImageCount = cap.minImageCount + 2;
-
-        if (cap.currentExtent.width == 0xffffffff)
-        {
-            info.imageExtent.width = wd->Width = w;
-            info.imageExtent.height = wd->Height = h;
-        }
-        else
-        {
-            info.imageExtent.width = wd->Width = cap.currentExtent.width;
-            info.imageExtent.height = wd->Height = cap.currentExtent.height;
-        }
-        err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &wd->Swapchain);
-        check_vk_result(err);
-        err = vkGetSwapchainImagesKHR(g_Device, wd->Swapchain, &wd->BackBufferCount, NULL);
-        check_vk_result(err);
-        err = vkGetSwapchainImagesKHR(g_Device, wd->Swapchain, &wd->BackBufferCount, wd->BackBuffer);
-        check_vk_result(err);
-    }
-    if (old_swapchain)
-        vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator);
-
-    // Create the Render Pass
-    {
-        VkAttachmentDescription attachment = {};
-        attachment.format = wd->SurfaceFormat.format;
-        attachment.samples = VK_SAMPLE_COUNT_1_BIT;
-        attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
-        attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
-        attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
-        attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-        attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-        attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-        VkAttachmentReference color_attachment = {};
-        color_attachment.attachment = 0;
-        color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-        VkSubpassDescription subpass = {};
-        subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
-        subpass.colorAttachmentCount = 1;
-        subpass.pColorAttachments = &color_attachment;
-        VkRenderPassCreateInfo info = {};
-        info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
-        info.attachmentCount = 1;
-        info.pAttachments = &attachment;
-        info.subpassCount = 1;
-        info.pSubpasses = &subpass;
-        err = vkCreateRenderPass(g_Device, &info, g_Allocator, &wd->RenderPass);
-        check_vk_result(err);
-    }
-
-    // Create The Image Views
-    {
-        VkImageViewCreateInfo info = {};
-        info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
-        info.viewType = VK_IMAGE_VIEW_TYPE_2D;
-        info.format = wd->SurfaceFormat.format;
-        info.components.r = VK_COMPONENT_SWIZZLE_R;
-        info.components.g = VK_COMPONENT_SWIZZLE_G;
-        info.components.b = VK_COMPONENT_SWIZZLE_B;
-        info.components.a = VK_COMPONENT_SWIZZLE_A;
-        VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
-        info.subresourceRange = image_range;
-        for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-        {
-            info.image = wd->BackBuffer[i];
-            err = vkCreateImageView(g_Device, &info, g_Allocator, &wd->BackBufferView[i]);
-            check_vk_result(err);
-        }
-    }
-
-    // Create Framebuffer
-    {
-        VkImageView attachment[1];
-        VkFramebufferCreateInfo info = {};
-        info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
-        info.renderPass = wd->RenderPass;
-        info.attachmentCount = 1;
-        info.pAttachments = attachment;
-        info.width = wd->Width;
-        info.height = wd->Height;
-        info.layers = 1;
-        for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-        {
-            attachment[0] = wd->BackBufferView[i];
-            err = vkCreateFramebuffer(g_Device, &info, g_Allocator, &wd->Framebuffer[i]);
-            check_vk_result(err);
-        }
-    }
-}
-
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
 static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
 {
@@ -222,6 +92,8 @@ static void CreateVulkanInstance(const char** extensions, uint32_t extensions_co
 
 static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
 {
+    IM_ASSERT(wd->Surface != NULL);
+
     VkResult err;
 
     // Select GPU
@@ -272,7 +144,7 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
     {
         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_ImplVulkan_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
+        wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
     }
 
     // Get Present Mode
@@ -282,7 +154,7 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
 #else
         VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
 #endif
-        wd->PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
+        wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
     }
 
     // Create Logical Device (with 1 queue)
@@ -375,23 +247,7 @@ static void cleanup_vulkan()
 {
     ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
     vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
-    for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
-    {
-        ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
-        vkDestroyFence(g_Device, fd->Fence, g_Allocator);
-        vkFreeCommandBuffers(g_Device, fd->CommandPool, 1, &fd->CommandBuffer);
-        vkDestroyCommandPool(g_Device, fd->CommandPool, g_Allocator);
-        vkDestroySemaphore(g_Device, fd->PresentCompleteSemaphore, g_Allocator);
-        vkDestroySemaphore(g_Device, fd->RenderCompleteSemaphore, g_Allocator);
-    }
-    for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-    {
-        vkDestroyImageView(g_Device, wd->BackBufferView[i], g_Allocator);
-        vkDestroyFramebuffer(g_Device, wd->Framebuffer[i], g_Allocator);
-    }
-    vkDestroyRenderPass(g_Device, wd->RenderPass, g_Allocator);
-    vkDestroySwapchainKHR(g_Device, wd->Swapchain, g_Allocator);
-    vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
+    ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
 
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
     // Remove the debug report callback
@@ -525,26 +381,25 @@ int main(int, char**)
     {
         int w, h;
         SDL_GetWindowSize(window, &w, &h);
-        CreateOrResizeSwapChainAndFrameBuffer(wd, w, h);
+        ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, wd, g_Allocator, w, h);
     }
 
     // Setup ImGui binding
     ImGui::CreateContext();
 
+    ImGuiIO& io = ImGui::GetIO(); (void)io;
+    io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
+    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls
+
     ImGui_ImplVulkan_InitInfo init_info = {};
-    init_info.Allocator = g_Allocator;
+    init_info.Instance = g_Instance;
     init_info.PhysicalDevice = g_PhysicalDevice;
     init_info.Device = g_Device;
-    init_info.RenderPass = wd->RenderPass;
     init_info.PipelineCache = g_PipelineCache;
     init_info.DescriptorPool = g_DescriptorPool;
+    init_info.Allocator = g_Allocator;
     init_info.CheckVkResultFn = check_vk_result;
-
-    ImGuiIO& io = ImGui::GetIO(); (void)io;
-    //io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
-    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls
-
-    ImGui_ImplVulkan_Init(&init_info);
+    ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
     ImGui_ImplSDL2_Init(window, NULL);
 
     // Setup style
@@ -618,7 +473,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)) 
-                CreateOrResizeSwapChainAndFrameBuffer(wd, (int)event.window.data1, (int)event.window.data2);
+                ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2);
         }
         ImGui_ImplVulkan_NewFrame();
         ImGui_ImplSDL2_NewFrame(window);

+ 31 - 181
examples/vulkan_example/main.cpp

@@ -18,17 +18,17 @@
 #define IMGUI_VULKAN_DEBUG_REPORT
 #endif
 
-static VkAllocationCallbacks*   g_Allocator = NULL;
-static VkInstance               g_Instance = VK_NULL_HANDLE;
-static VkPhysicalDevice         g_PhysicalDevice = VK_NULL_HANDLE;
-static VkDevice                 g_Device = VK_NULL_HANDLE;
-static uint32_t                 g_QueueFamily = (uint32_t)-1;
-static VkQueue                  g_Queue = VK_NULL_HANDLE;
-static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
-static VkPipelineCache          g_PipelineCache = VK_NULL_HANDLE;
-static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE;
-
-static ImGui_ImplVulkan_WindowData               g_WindowData;
+static VkAllocationCallbacks*       g_Allocator = NULL;
+static VkInstance                   g_Instance = VK_NULL_HANDLE;
+static VkPhysicalDevice             g_PhysicalDevice = VK_NULL_HANDLE;
+static VkDevice                     g_Device = VK_NULL_HANDLE;
+static uint32_t                     g_QueueFamily = (uint32_t)-1;
+static VkQueue                      g_Queue = VK_NULL_HANDLE;
+static VkDebugReportCallbackEXT     g_DebugReport = VK_NULL_HANDLE;
+static VkPipelineCache              g_PipelineCache = VK_NULL_HANDLE;
+static VkDescriptorPool             g_DescriptorPool = VK_NULL_HANDLE;
+
+static ImGui_ImplVulkan_WindowData  g_WindowData;
 
 static void check_vk_result(VkResult err)
 {
@@ -38,137 +38,6 @@ static void check_vk_result(VkResult err)
         abort();
 }
 
-static void CreateOrResizeSwapChainAndFrameBuffer(ImGui_ImplVulkan_WindowData* wd, int w, int h)
-{
-    VkResult err;
-    VkSwapchainKHR old_swapchain = wd->Swapchain;
-    err = vkDeviceWaitIdle(g_Device);
-    check_vk_result(err);
-
-    // Destroy old Framebuffer
-    for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-    {
-        if (wd->BackBufferView[i])
-            vkDestroyImageView(g_Device, wd->BackBufferView[i], g_Allocator);
-        if (wd->Framebuffer[i])
-            vkDestroyFramebuffer(g_Device, wd->Framebuffer[i], g_Allocator);
-    }
-    wd->BackBufferCount = 0;
-    if (wd->RenderPass)
-        vkDestroyRenderPass(g_Device, wd->RenderPass, g_Allocator);
-
-    // Create Swapchain
-    {
-        VkSwapchainCreateInfoKHR info = {};
-        info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
-        info.surface = wd->Surface;
-        info.imageFormat = wd->SurfaceFormat.format;
-        info.imageColorSpace = wd->SurfaceFormat.colorSpace;
-        info.imageArrayLayers = 1;
-        info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-        info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;           // Assume that graphics family == present family
-        info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
-        info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-        info.presentMode = wd->PresentMode;
-        info.clipped = VK_TRUE;
-        info.oldSwapchain = old_swapchain;
-        VkSurfaceCapabilitiesKHR cap;
-        err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_PhysicalDevice, wd->Surface, &cap);
-        check_vk_result(err);
-        if (cap.maxImageCount > 0)
-            info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
-        else
-            info.minImageCount = cap.minImageCount + 2;
-
-        if (cap.currentExtent.width == 0xffffffff)
-        {
-            info.imageExtent.width = wd->Width = w;
-            info.imageExtent.height = wd->Height = h;
-        }
-        else
-        {
-            info.imageExtent.width = wd->Width = cap.currentExtent.width;
-            info.imageExtent.height = wd->Height = cap.currentExtent.height;
-        }
-        err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &wd->Swapchain);
-        check_vk_result(err);
-        err = vkGetSwapchainImagesKHR(g_Device, wd->Swapchain, &wd->BackBufferCount, NULL);
-        check_vk_result(err);
-        IM_ASSERT(wd->BackBufferCount < IM_ARRAYSIZE(wd->BackBuffer));
-        err = vkGetSwapchainImagesKHR(g_Device, wd->Swapchain, &wd->BackBufferCount, wd->BackBuffer);
-        check_vk_result(err);
-    }
-    if (old_swapchain)
-        vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator);
-
-    // Create the Render Pass
-    {
-        VkAttachmentDescription attachment = {};
-        attachment.format = wd->SurfaceFormat.format;
-        attachment.samples = VK_SAMPLE_COUNT_1_BIT;
-        attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
-        attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
-        attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
-        attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-        attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-        attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-        VkAttachmentReference color_attachment = {};
-        color_attachment.attachment = 0;
-        color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-        VkSubpassDescription subpass = {};
-        subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
-        subpass.colorAttachmentCount = 1;
-        subpass.pColorAttachments = &color_attachment;
-        VkRenderPassCreateInfo info = {};
-        info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
-        info.attachmentCount = 1;
-        info.pAttachments = &attachment;
-        info.subpassCount = 1;
-        info.pSubpasses = &subpass;
-        err = vkCreateRenderPass(g_Device, &info, g_Allocator, &wd->RenderPass);
-        check_vk_result(err);
-    }
-
-    // Create The Image Views
-    {
-        VkImageViewCreateInfo info = {};
-        info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
-        info.viewType = VK_IMAGE_VIEW_TYPE_2D;
-        info.format = wd->SurfaceFormat.format;
-        info.components.r = VK_COMPONENT_SWIZZLE_R;
-        info.components.g = VK_COMPONENT_SWIZZLE_G;
-        info.components.b = VK_COMPONENT_SWIZZLE_B;
-        info.components.a = VK_COMPONENT_SWIZZLE_A;
-        VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
-        info.subresourceRange = image_range;
-        for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-        {
-            info.image = wd->BackBuffer[i];
-            err = vkCreateImageView(g_Device, &info, g_Allocator, &wd->BackBufferView[i]);
-            check_vk_result(err);
-        }
-    }
-
-    // Create Framebuffer
-    {
-        VkImageView attachment[1];
-        VkFramebufferCreateInfo info = {};
-        info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
-        info.renderPass = wd->RenderPass;
-        info.attachmentCount = 1;
-        info.pAttachments = attachment;
-        info.width = wd->Width;
-        info.height = wd->Height;
-        info.layers = 1;
-        for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-        {
-            attachment[0] = wd->BackBufferView[i];
-            err = vkCreateFramebuffer(g_Device, &info, g_Allocator, &wd->Framebuffer[i]);
-            check_vk_result(err);
-        }
-    }
-}
-
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
 static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
 {
@@ -226,6 +95,8 @@ static void CreateVulkanInstance(const char** extensions, uint32_t extensions_co
 
 static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
 {
+    IM_ASSERT(wd->Surface != NULL);
+
     VkResult err;
 
     // Select GPU
@@ -276,7 +147,7 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
     {
         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_ImplVulkan_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
+        wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
     }
 
     // Get Present Mode
@@ -286,7 +157,7 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
 #else
         VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
 #endif
-        wd->PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
+        wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
     }
 
     // Create Logical Device (with 1 queue)
@@ -379,23 +250,7 @@ static void cleanup_vulkan()
 {
     ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
     vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
-    for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
-    {
-        ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
-        vkDestroyFence(g_Device, fd->Fence, g_Allocator);
-        vkFreeCommandBuffers(g_Device, fd->CommandPool, 1, &fd->CommandBuffer);
-        vkDestroyCommandPool(g_Device, fd->CommandPool, g_Allocator);
-        vkDestroySemaphore(g_Device, fd->PresentCompleteSemaphore, g_Allocator);
-        vkDestroySemaphore(g_Device, fd->RenderCompleteSemaphore, g_Allocator);
-    }
-    for (uint32_t i = 0; i < wd->BackBufferCount; i++)
-    {
-        vkDestroyImageView(g_Device, wd->BackBufferView[i], g_Allocator);
-        vkDestroyFramebuffer(g_Device, wd->Framebuffer[i], g_Allocator);
-    }
-    vkDestroyRenderPass(g_Device, wd->RenderPass, g_Allocator);
-    vkDestroySwapchainKHR(g_Device, wd->Swapchain, g_Allocator);
-    vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
+    ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
 
 #ifdef IMGUI_VULKAN_DEBUG_REPORT
     // Remove the debug report callback
@@ -499,7 +354,7 @@ static void glfw_error_callback(int error, const char* description)
 
 static void glfw_resize_callback(GLFWwindow*, int w, int h)
 {
-    CreateOrResizeSwapChainAndFrameBuffer(&g_WindowData, w, h);
+    ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, w, h);
 }
 
 int main(int, char**)
@@ -524,38 +379,33 @@ int main(int, char**)
 
     // Create Window Surface
     ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
-    {
-        VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &wd->Surface);
-        check_vk_result(err);
-    }
+    VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &wd->Surface);
+    check_vk_result(err);
 
     SetupVulkan(wd);
 
     // Create Framebuffers
-    {
-        int w, h;
-        glfwGetFramebufferSize(window, &w, &h);
-        CreateOrResizeSwapChainAndFrameBuffer(wd, w, h);
-        glfwSetFramebufferSizeCallback(window, glfw_resize_callback);
-    }
+    int w, h;
+    glfwGetFramebufferSize(window, &w, &h);
+    ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, wd, g_Allocator, w, h);
+    glfwSetFramebufferSizeCallback(window, glfw_resize_callback);
 
     // Setup ImGui binding
     ImGui::CreateContext();
 
+    ImGuiIO& io = ImGui::GetIO(); (void)io;
+    io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
+    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls
+
     ImGui_ImplVulkan_InitInfo init_info = {};
-    init_info.Allocator = g_Allocator;
+    init_info.Instance = g_Instance;
     init_info.PhysicalDevice = g_PhysicalDevice;
     init_info.Device = g_Device;
-    init_info.RenderPass = wd->RenderPass;
     init_info.PipelineCache = g_PipelineCache;
     init_info.DescriptorPool = g_DescriptorPool;
+    init_info.Allocator = g_Allocator;
     init_info.CheckVkResultFn = check_vk_result;
-
-    ImGuiIO& io = ImGui::GetIO(); (void)io;
-    //io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
-    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls
-
-    ImGui_ImplVulkan_Init(&init_info);
+    ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
     ImGui_ImplGlfw_InitForVulkan(window, true);
 
     // Setup style
@@ -683,7 +533,7 @@ int main(int, char**)
     }
 
     // Cleanup
-    VkResult err = vkDeviceWaitIdle(g_Device);
+    err = vkDeviceWaitIdle(g_Device);
     check_vk_result(err);
     ImGui_ImplVulkan_Shutdown();
     ImGui_ImplGlfw_Shutdown();