packages feed

dear-imgui-impl-vulkan (empty) → 1.0.0

raw patch · 13 files changed

+4005/−0 lines, 13 filesdep +basedep +dear-imgui-rawdep +resourcet

Dependencies added: base, dear-imgui-raw, resourcet, vector, vulkan

Files

+ CHANGELOG.md view
@@ -0,0 +1,13 @@+# Changelog for `dear-imgui-impl-vulkan`++All notable changes to this package will be documented in this file.++The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),+and this project adheres to the+[Haskell Package Versioning Policy](https://pvp.haskell.org/).++## 1.0.0 - 2026-10-21++Initial release.++- Generated with dear_bindings `v0.26` from Dear ImGui `v1.93.0-docking`.
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright 2026 IC Rainbow++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1.  Redistributions of source code must retain the above copyright notice, this+    list of conditions and the following disclaimer.++2.  Redistributions in binary form must reproduce the above copyright notice,+    this list of conditions and the following disclaimer in the documentation+    and/or other materials provided with the distribution.++3.  Neither the name of the copyright holder nor the names of its contributors+    may be used to endorse or promote products derived from this software+    without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,18 @@+# dear-imgui-impl-vulkan++Renderer backend for [Dear ImGui] on Vulkan.+Pair it with a platform backend.++```haskell+import Control.Exception (finally)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Trans.Resource (ResourceT)+import DearImGui.Impl.Vulkan qualified as ImplVulkan++withImGuiVulkan :: ImplVulkan.InitArgs -> IO a -> ResourceT IO a+withImGuiVulkan args frames = do+  _descriptorPool <- ImplVulkan.withBackend 0 args+  liftIO (frames `finally` ImplVulkan.shutdown)+```++[Dear ImGui]: https://github.com/ocornut/imgui
+ cbits/DearImGuiCtors.cpp view
@@ -0,0 +1,34 @@+// Generated by dear-bindings-ffi. Do not edit.+#include <new>+#include "imgui_impl_vulkan.h"++extern "C" void ImGui_ImplVulkan_InitInfo_Init_wrap(void* p) {+    using T = ::ImGui_ImplVulkan_InitInfo;+    new (p) T();+}++extern "C" void ImGui_ImplVulkan_InitInfo_Destroy_wrap(void* p) {+    using T = ::ImGui_ImplVulkan_InitInfo;+    static_cast<T*>(p)->~T();+}++extern "C" void ImGui_ImplVulkan_PipelineInfo_Init_wrap(void* p) {+    using T = ::ImGui_ImplVulkan_PipelineInfo;+    new (p) T();+}++extern "C" void ImGui_ImplVulkan_PipelineInfo_Destroy_wrap(void* p) {+    using T = ::ImGui_ImplVulkan_PipelineInfo;+    static_cast<T*>(p)->~T();+}++extern "C" void ImGui_ImplVulkan_RenderState_Init_wrap(void* p) {+    using T = ::ImGui_ImplVulkan_RenderState;+    new (p) T();+}++extern "C" void ImGui_ImplVulkan_RenderState_Destroy_wrap(void* p) {+    using T = ::ImGui_ImplVulkan_RenderState;+    static_cast<T*>(p)->~T();+}+
+ cbits/DearImGuiWrappers.cpp view
@@ -0,0 +1,3 @@+// Generated by dear-bindings-ffi. Do not edit.+#include "DearImGuiWrappers.h"+
+ cbits/DearImGuiWrappers.h view
@@ -0,0 +1,25 @@+// Generated by dear-bindings-ffi. Do not edit.+#ifndef DEAR_IMGUI_WRAPPERS_H+#define DEAR_IMGUI_WRAPPERS_H++#include "dcimgui_impl_vulkan.h"++#ifdef __cplusplus+extern "C" {+#endif++void ImGui_ImplVulkan_InitInfo_Init_wrap(void* p);+void ImGui_ImplVulkan_InitInfo_Destroy_wrap(void* p);++void ImGui_ImplVulkan_PipelineInfo_Init_wrap(void* p);+void ImGui_ImplVulkan_PipelineInfo_Destroy_wrap(void* p);++void ImGui_ImplVulkan_RenderState_Init_wrap(void* p);+void ImGui_ImplVulkan_RenderState_Destroy_wrap(void* p);+++#ifdef __cplusplus+}+#endif++#endif
+ cbits/dcimgui_impl_vulkan.cpp view
@@ -0,0 +1,202 @@+// THIS FILE HAS BEEN AUTO-GENERATED BY THE 'DEAR BINDINGS' GENERATOR.+// **DO NOT EDIT DIRECTLY**+// https://github.com/dearimgui/dear_bindings++#include "imgui.h"+#include "imgui_impl_vulkan.h"++#include <stdio.h>++// Wrap this in a namespace to keep it separate from the C++ API+// This define prevents #defines in the header getting defined again (as they are already in the normal header above),+// and thus generating redefinition warnings+#define DEAR_BINDINGS_INTERNAL_GLUE_CODE+namespace cimgui+{+#include "dcimgui_impl_vulkan.h"+}+#undef DEAR_BINDINGS_INTERNAL_GLUE_CODE++// By-value struct conversions++static inline cimgui::ImVec2 ConvertFromCPP_ImVec2(const ::ImVec2& src)+{+    cimgui::ImVec2 dest;+    dest.x = src.x;+    dest.y = src.y;+    return dest;+}++static inline ::ImVec2 ConvertToCPP_ImVec2(const cimgui::ImVec2& src)+{+    ::ImVec2 dest;+    dest.x = src.x;+    dest.y = src.y;+    return dest;+}++static inline cimgui::ImVec4 ConvertFromCPP_ImVec4(const ::ImVec4& src)+{+    cimgui::ImVec4 dest;+    dest.x = src.x;+    dest.y = src.y;+    dest.z = src.z;+    dest.w = src.w;+    return dest;+}++static inline ::ImVec4 ConvertToCPP_ImVec4(const cimgui::ImVec4& src)+{+    ::ImVec4 dest;+    dest.x = src.x;+    dest.y = src.y;+    dest.z = src.z;+    dest.w = src.w;+    return dest;+}++static inline cimgui::ImTextureRef ConvertFromCPP_ImTextureRef(const ::ImTextureRef& src)+{+    cimgui::ImTextureRef dest;+    dest._TexData = reinterpret_cast<cimgui::ImTextureData*>(src._TexData);+    dest._TexID = src._TexID;+    return dest;+}++static inline ::ImTextureRef ConvertToCPP_ImTextureRef(const cimgui::ImTextureRef& src)+{+    ::ImTextureRef dest;+    dest._TexData = reinterpret_cast<::ImTextureData*>(src._TexData);+    dest._TexID = src._TexID;+    return dest;+}++static inline cimgui::ImColor ConvertFromCPP_ImColor(const ::ImColor& src)+{+    cimgui::ImColor dest;+    dest.Value.x = src.Value.x;+    dest.Value.y = src.Value.y;+    dest.Value.z = src.Value.z;+    dest.Value.w = src.Value.w;+    return dest;+}++static inline ::ImColor ConvertToCPP_ImColor(const cimgui::ImColor& src)+{+    ::ImColor dest;+    dest.Value.x = src.Value.x;+    dest.Value.y = src.Value.y;+    dest.Value.z = src.Value.z;+    dest.Value.w = src.Value.w;+    return dest;+}++// Function stubs++#ifndef IMGUI_DISABLE++CIMGUI_IMPL_API bool cimgui::cImGui_ImplVulkan_Init(cimgui::ImGui_ImplVulkan_InitInfo* info)+{+    return ::ImGui_ImplVulkan_Init(reinterpret_cast<::ImGui_ImplVulkan_InitInfo*>(info));+}++CIMGUI_IMPL_API void cimgui::cImGui_ImplVulkan_Shutdown(void)+{+    ::ImGui_ImplVulkan_Shutdown();+}++CIMGUI_IMPL_API void cimgui::cImGui_ImplVulkan_NewFrame(void)+{+    ::ImGui_ImplVulkan_NewFrame();+}++CIMGUI_IMPL_API void cimgui::cImGui_ImplVulkan_RenderDrawData(cimgui::ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)+{+    ::ImGui_ImplVulkan_RenderDrawData(reinterpret_cast<::ImDrawData*>(draw_data), command_buffer, pipeline);+}++CIMGUI_IMPL_API void cimgui::cImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)+{+    ::ImGui_ImplVulkan_SetMinImageCount(min_image_count);+}++CIMGUI_IMPL_API void cimgui::cImGui_ImplVulkan_CreateMainPipeline(const cimgui::ImGui_ImplVulkan_PipelineInfo* info)+{+    ::ImGui_ImplVulkan_CreateMainPipeline(reinterpret_cast<const ::ImGui_ImplVulkan_PipelineInfo*>(info));+}++CIMGUI_IMPL_API void cimgui::cImGui_ImplVulkan_UpdateTexture(cimgui::ImTextureData* tex)+{+    ::ImGui_ImplVulkan_UpdateTexture(reinterpret_cast<::ImTextureData*>(tex));+}++CIMGUI_IMPL_API VkDescriptorSet cimgui::cImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout)+{+    return ::ImGui_ImplVulkan_AddTexture(image_view, image_layout);+}++CIMGUI_IMPL_API void       cimgui::cImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)+{+    ::ImGui_ImplVulkan_RemoveTexture(descriptor_set);+}++#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS++CIMGUI_IMPL_API VkDescriptorSet cimgui::cImGui_ImplVulkan_AddTextureVkSampler(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)+{+    return ::ImGui_ImplVulkan_AddTexture(sampler, image_view, image_layout);+}++#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS++CIMGUI_IMPL_API bool cimgui::cImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction (*loader_func)(const char* function_name, void* user_data), void* user_data)+{+    return ::ImGui_ImplVulkan_LoadFunctions(api_version, loader_func, user_data);+}++CIMGUI_IMPL_API cimgui::ImGui_ImplVulkan_RenderState* cimgui::cImGui_ImplVulkan_GetRenderState(void)+{+    return reinterpret_cast<::cimgui::ImGui_ImplVulkan_RenderState*>(::ImGui_ImplVulkan_GetRenderState());+}++CIMGUI_IMPL_API void                 cimgui::cImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, cimgui::ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage)+{+    ::ImGui_ImplVulkanH_CreateOrResizeWindow(instance, physical_device, device, reinterpret_cast<::ImGui_ImplVulkanH_Window*>(wd), queue_family, allocator, w, h, min_image_count, image_usage);+}++CIMGUI_IMPL_API void                 cimgui::cImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, cimgui::ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)+{+    ::ImGui_ImplVulkanH_DestroyWindow(instance, device, reinterpret_cast<::ImGui_ImplVulkanH_Window*>(wd), allocator);+}++CIMGUI_IMPL_API VkSurfaceFormatKHR   cimgui::cImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)+{+    return ::ImGui_ImplVulkanH_SelectSurfaceFormat(physical_device, surface, request_formats, request_formats_count, request_color_space);+}++CIMGUI_IMPL_API VkPresentModeKHR     cimgui::cImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)+{+    return ::ImGui_ImplVulkanH_SelectPresentMode(physical_device, surface, request_modes, request_modes_count);+}++CIMGUI_IMPL_API VkPhysicalDevice     cimgui::cImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance)+{+    return ::ImGui_ImplVulkanH_SelectPhysicalDevice(instance);+}++CIMGUI_IMPL_API uint32_t             cimgui::cImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device)+{+    return ::ImGui_ImplVulkanH_SelectQueueFamilyIndex(physical_device);+}++CIMGUI_IMPL_API int                  cimgui::cImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode)+{+    return ::ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(present_mode);+}++CIMGUI_IMPL_API cimgui::ImGui_ImplVulkanH_Window* cimgui::cImGui_ImplVulkanH_GetWindowDataFromViewport(cimgui::ImGuiViewport* viewport)+{+    return reinterpret_cast<::cimgui::ImGui_ImplVulkanH_Window*>(::ImGui_ImplVulkanH_GetWindowDataFromViewport(reinterpret_cast<::ImGuiViewport*>(viewport)));+}++#endif // #ifndef IMGUI_DISABLE
+ cbits/dcimgui_impl_vulkan.h view
@@ -0,0 +1,304 @@+// THIS FILE HAS BEEN AUTO-GENERATED BY THE 'DEAR BINDINGS' GENERATOR.+// **DO NOT EDIT DIRECTLY**+// https://github.com/dearimgui/dear_bindings++// Dear Bindings version as a string+#ifndef DEAR_BINDINGS_VERSION+#define DEAR_BINDINGS_VERSION "0.26"+#endif++// Dear Bindings version as an integer+#ifndef DEAR_BINDINGS_VERSION_NUMBER+#define DEAR_BINDINGS_VERSION_NUMBER 26+#endif++// dear imgui: Renderer Backend for Vulkan+// Auto-generated forward declarations for C header+typedef struct ImVector_VkDynamicState_t ImVector_VkDynamicState;+typedef struct ImGui_ImplVulkan_PipelineInfo_t ImGui_ImplVulkan_PipelineInfo;+typedef struct ImGui_ImplVulkan_InitInfo_t ImGui_ImplVulkan_InitInfo;+typedef struct ImGui_ImplVulkan_RenderState_t ImGui_ImplVulkan_RenderState;+typedef struct ImVector_ImGui_ImplVulkanH_Frame_t ImVector_ImGui_ImplVulkanH_Frame;+typedef struct ImGui_ImplVulkanH_FrameSemaphores_t ImGui_ImplVulkanH_FrameSemaphores;+typedef struct ImVector_ImGui_ImplVulkanH_FrameSemaphores_t ImVector_ImGui_ImplVulkanH_FrameSemaphores;+// ImDrawIdx: vertex index. [Compile-time configurable type]+// - To use 16-bit indices + allow large meshes: backend need to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset (recommended).+// - To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in your imconfig.h file.+#ifndef ImDrawIdx+typedef unsigned short ImDrawIdx;  // Default: 16-bit (for maximum compatibility with renderer backends)+#endif // #ifndef ImDrawIdx+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)++// Implemented features:+//  [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).+//  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplVulkan_GetRenderState().+//  [x] Renderer: Multi-viewport / platform windows. With issues (flickering when creating a new viewport).++// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.+// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/++// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.+// Learn about Dear ImGui:+// - FAQ                  https://dearimgui.com/faq+// - Getting Started      https://dearimgui.com/getting-started+// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).+// - Introduction, links and more at the top of imgui.cpp++// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.+//   You will use those if you want to use this rendering backend in your engine/app.+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by+//   the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.+// Read comments in imgui_impl_vulkan.h.++#pragma once++#ifdef __cplusplus+extern "C"+{+#endif+#ifndef IMGUI_DISABLE+#include "dcimgui.h"+// [Configuration] in order to use a custom Vulkan function loader:+// (1) You'll need to disable default Vulkan function prototypes.+//     We provide a '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' convenience configuration flag.+//     In order to make sure this is visible from the imgui_impl_vulkan.cpp compilation unit:+//     - Add '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' in your imconfig.h file+//     - Or as a compilation flag in your build system+//     - Or uncomment here (not recommended because you'd be modifying imgui sources!)+//     - Do not simply add it in a .cpp file!+// (2) Call ImGui_ImplVulkan_LoadFunctions() before ImGui_ImplVulkan_Init() with your custom function.+// If you have no idea what this is, leave it alone!+//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES++// [Configuration] Convenience support for Volk+// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)+// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header,+//  for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)')+//#define IMGUI_IMPL_VULKAN_USE_VOLK+//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME    <Volk/volk.h>+//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME    <volk.h>       // Default+// Reminder: make those changes in your imconfig.h file, not here!++// Clang/GCC warnings with -Weverything+#if defined(__clang__)+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Wold-style-cast"  // warning: use of old-style cast+#endif // #if defined(__clang__)+#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES)&&!defined(VK_NO_PROTOTYPES)+#define VK_NO_PROTOTYPES+#endif // #if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES)&&!defined(VK_NO_PROTOTYPES)+#if defined(VK_USE_PLATFORM_WIN32_KHR)&&!defined(NOMINMAX)+#define NOMINMAX+#endif // #if defined(VK_USE_PLATFORM_WIN32_KHR)&&!defined(NOMINMAX)+// Vulkan includes+#ifdef IMGUI_IMPL_VULKAN_USE_VOLK+#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME+#include IMGUI_IMPL_VULKAN_VOLK_FILENAME+#else+#include <volk.h>+#endif // #ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME+#else+#include <vulkan/vulkan.h>+#endif // #ifdef IMGUI_IMPL_VULKAN_USE_VOLK+struct ImVector_VkDynamicState_t { int Size; int Capacity; VkDynamicState* Data; };  // Instantiation of ImVector<VkDynamicState>+#if defined(VK_VERSION_1_3)|| defined(VK_KHR_dynamic_rendering)+#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+#endif // #if defined(VK_VERSION_1_3)|| defined(VK_KHR_dynamic_rendering)+// Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().+#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE   (8)      // Minimum per atlas+#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE         (2)      // Minimum for linear + nearest++// Specify settings to create pipeline and swapchain+struct ImGui_ImplVulkan_PipelineInfo_t+{+    // For Main viewport only+    VkRenderPass                     RenderPass;                   // Ignored if using dynamic rendering++    // For Main and Secondary viewports+    uint32_t                         Subpass;                      //+    VkSampleCountFlagBits            MSAASamples /* = {} */;       // 0 defaults to VK_SAMPLE_COUNT_1_BIT+    ImVector_VkDynamicState          ExtraDynamicStates;           // Optional, allows to insert more dynamic states into our VkPipeline+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo;  // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR+#endif // #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    // For Secondary viewports only (created/managed by backend)+    VkImageUsageFlags                SwapChainImageUsage;          // Extra flags for vkCreateSwapchainKHR() calls for secondary viewports. We automatically add VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. You can add e.g. VK_IMAGE_USAGE_TRANSFER_SRC_BIT if you need to capture from viewports.+};++// Initialization data, for ImGui_ImplVulkan_Init()+// [Please zero-clear before use!]+// - About descriptor pool:+//   - A VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,+//     and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.+//   - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.+// - About dynamic rendering:+//   - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.+//   - PipelineRenderingCreateInfo may describe multiple color attachments: we render to the first one and leave the others untouched. This requires the 'independentBlend' device feature.+struct ImGui_ImplVulkan_InitInfo_t+{+    uint32_t                      ApiVersion;                // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)+    VkInstance                    Instance;+    VkPhysicalDevice              PhysicalDevice;+    VkDevice                      Device;+    uint32_t                      QueueFamily;+    VkQueue                       Queue;+    VkDescriptorPool              DescriptorPool;            // See requirements in note above; ignored if using DescriptorPoolSize > 0+    uint32_t                      DescriptorPoolSize;        // Optional: set to create internal ImageView descriptor pool automatically instead of using DescriptorPool.+    uint32_t                      MinImageCount;             // >= 2+    uint32_t                      ImageCount;                // >= MinImageCount+    VkPipelineCache               PipelineCache;             // Optional++    // Pipeline+    ImGui_ImplVulkan_PipelineInfo PipelineInfoMain;          // Infos for Main Viewport (created by app/user)+    ImGui_ImplVulkan_PipelineInfo PipelineInfoForViewports;  // Infos for Secondary Viewports (created by backend)+    //VkRenderPass                  RenderPass;                 // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead+    //uint32_t                      Subpass;                    // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead+    //VkSampleCountFlagBits         MSAASamples;                // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead+    //VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead++    // (Optional) Dynamic Rendering+    // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo and PipelineInfoViewports.PipelineRenderingCreateInfo.+    bool                          UseDynamicRendering;++    // (Optional) Allocation, Debugging+    const VkAllocationCallbacks*  Allocator;+    void (*CheckVkResultFn)(VkResult err);+    VkDeviceSize                  MinAllocationSize;         // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory.++    // (Optional) Customize default vertex/fragment shaders.+    // - if .sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO we use specified structs, otherwise we use defaults.+    // - Shader inputs/outputs need to match ours. Code/data pointed to by the structure needs to survive for whole during of backend usage.+    VkShaderModuleCreateInfo      CustomShaderVertCreateInfo;+    VkShaderModuleCreateInfo      CustomShaderFragCreateInfo;+};++typedef struct ImDrawData_t ImDrawData;+// Follow "Getting Started" link and check examples/ folder to learn about using backends!+CIMGUI_IMPL_API bool cImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info);+CIMGUI_IMPL_API void cImGui_ImplVulkan_Shutdown(void);+CIMGUI_IMPL_API void cImGui_ImplVulkan_NewFrame(void);+CIMGUI_IMPL_API void cImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline /* = VK_NULL_HANDLE */);+CIMGUI_IMPL_API void cImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)++// (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111)+// The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR))+// Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering.+CIMGUI_IMPL_API void cImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info);++// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.+CIMGUI_IMPL_API void cImGui_ImplVulkan_UpdateTexture(ImTextureData* tex);++// Register a texture (VkDescriptorSet for a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE == ImTextureID)+CIMGUI_IMPL_API VkDescriptorSet cImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout);+CIMGUI_IMPL_API void       cImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);++#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS+CIMGUI_IMPL_API VkDescriptorSet cImGui_ImplVulkan_AddTextureVkSampler(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout); // Ignore VkSampler+#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS+// Optional: load Vulkan functions with a custom function loader+// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES+CIMGUI_IMPL_API bool cImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction (*loader_func)(const char* function_name, void* user_data), void* user_data /* = nullptr */);++// [BETA] Selected render state data shared with callbacks.+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.+//      ImGui_ImplVulkan_RenderState* render_state = (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;+// (Please open an issue if you feel you need access to more data)+struct ImGui_ImplVulkan_RenderState_t+{+    VkCommandBuffer  CommandBuffer;+    VkPipeline       Pipeline;+    VkPipelineLayout PipelineLayout;+};+CIMGUI_IMPL_API ImGui_ImplVulkan_RenderState* cImGui_ImplVulkan_GetRenderState(void);++//-------------------------------------------------------------------------+// Internal / Miscellaneous Vulkan Helpers+//-------------------------------------------------------------------------+// Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.+//+// You probably do NOT need to use or care about those functions.+// WE DO NOT PROVIDE STRONG GUARANTEES OF BACKWARD/FORWARD COMPATIBILITY.+// Those functions only exist because:+//   1) they facilitate the readability and maintenance of the multiple main.cpp examples files.+//   2) the multi-viewport / platform window implementation needs them internally.+// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,+// but it is too much code to duplicate everywhere so we exceptionally expose them.+//+// Your engine/app will likely _already_ have code to setup all that stuff (swap chain,+// render pass, frame buffers, etc.). You may read this code if you are curious, but+// it is recommended you use your own custom tailored code to do equivalent work.+//+// The ImGui_ImplVulkanH_XXX functions should NOT interact with any of the state used+// by the regular ImGui_ImplVulkan_XXX functions.+//-------------------------------------------------------------------------++typedef struct ImGui_ImplVulkanH_Frame_t ImGui_ImplVulkanH_Frame;+typedef struct ImGui_ImplVulkanH_Window_t ImGui_ImplVulkanH_Window;++// Helpers+CIMGUI_IMPL_API void                 cImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);+CIMGUI_IMPL_API void                 cImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator);+CIMGUI_IMPL_API VkSurfaceFormatKHR   cImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);+CIMGUI_IMPL_API VkPresentModeKHR     cImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);+CIMGUI_IMPL_API VkPhysicalDevice     cImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance);+CIMGUI_IMPL_API uint32_t             cImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device);+CIMGUI_IMPL_API int                  cImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);+CIMGUI_IMPL_API ImGui_ImplVulkanH_Window* cImGui_ImplVulkanH_GetWindowDataFromViewport(ImGuiViewport* viewport); // Access to Vulkan objects associated with a viewport (e.g to export a screenshot)++// Helper structure to hold the data needed by one rendering frame+// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)+// [Please zero-clear before use!]+struct ImGui_ImplVulkanH_Frame_t+{+    VkCommandPool   CommandPool;+    VkCommandBuffer CommandBuffer;+    VkFence         Fence;+    VkImage         Backbuffer;+    VkImageView     BackbufferView;+    VkFramebuffer   Framebuffer;+};+struct ImVector_ImGui_ImplVulkanH_Frame_t { int Size; int Capacity; ImGui_ImplVulkanH_Frame* Data; };  // Instantiation of ImVector<ImGui_ImplVulkanH_Frame>++struct ImGui_ImplVulkanH_FrameSemaphores_t+{+    VkSemaphore ImageAcquiredSemaphore;+    VkSemaphore RenderCompleteSemaphore;+};+struct ImVector_ImGui_ImplVulkanH_FrameSemaphores_t { int Size; int Capacity; ImGui_ImplVulkanH_FrameSemaphores* Data; };  // Instantiation of ImVector<ImGui_ImplVulkanH_FrameSemaphores>++// Helper structure to hold the data needed by one rendering context into one OS window+// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)+struct ImGui_ImplVulkanH_Window_t+{+    // Input+    bool                             UseDynamicRendering;+    VkSurfaceKHR                     Surface;         // Surface created and destroyed by caller.+    VkSurfaceFormatKHR               SurfaceFormat;+    VkPresentModeKHR                 PresentMode;+    VkAttachmentDescription          AttachmentDesc;  // RenderPass creation: main attachment description.+    VkClearValue                     ClearValue;      // RenderPass creation: clear value when using VK_ATTACHMENT_LOAD_OP_CLEAR.++    // Internal+    int                              Width;           // Generally same as passed to ImGui_ImplVulkanH_CreateOrResizeWindow()+    int                              Height;+    VkSwapchainKHR                   Swapchain;+    VkRenderPass                     RenderPass;+    uint32_t                         FrameIndex;      // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)+    uint32_t                         ImageCount;      // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)+    uint32_t                         SemaphoreCount;  // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR+    uint32_t                         SemaphoreIndex;  // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)+    ImVector_ImGui_ImplVulkanH_Frame Frames;+    ImVector_ImGui_ImplVulkanH_FrameSemaphores FrameSemaphores;+};++#if defined(__clang__)+#pragma clang diagnostic pop+#endif // #if defined(__clang__)+#endif// #ifndef IMGUI_DISABLE+#ifdef __cplusplus+} // End of extern "C" block+#endif
+ cbits/imgui_impl_vulkan.cpp view
@@ -0,0 +1,2428 @@+// dear imgui: Renderer Backend for Vulkan+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)++// Implemented features:+//  [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).+//  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplVulkan_GetRenderState().+//  [x] Renderer: Multi-viewport / platform windows. With issues (flickering when creating a new viewport).++// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.+// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/++// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.+// Learn about Dear ImGui:+// - FAQ                  https://dearimgui.com/faq+// - Getting Started      https://dearimgui.com/getting-started+// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).+// - Introduction, links and more at the top of imgui.cpp++// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.+//   You will use those if you want to use this rendering backend in your engine/app.+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by+//   the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.+// Read comments in imgui_impl_vulkan.h.++// CHANGELOG+// (minor and older changes stripped away, please see git history for details)+//  2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.+//  2026-10-06: Added support for dynamic rendering with multiple color attachments (PipelineRenderingCreateInfo.colorAttachmentCount > 1): we render to the first one and leave the others untouched. (#9574)+//  2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)+//  2026-09-03: Added for support for multiple Vulkan contexts with custom loaders. (#6616)+//  2026-07-15: [Docking] Vulkan: fixed use-after-free when using multi-viewport with dynamic rendering path: deep-copy SurfaceFormat.format into the persistent buffer instead of storing a pointer to the viewport's wd->SurfaceFormat which dangles after the viewport is destroyed. (#9390, #9468)+//  2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)+//  2026-04-22: *BREAKING CHANGE* redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. This change allows us to facilitate changing samplers, in line with other backends.+//              - When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.+//                - Before: ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)+//                - After:  ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)+//                - Kept inline redirection function that ignores the sampler.+//              - When creating your own descriptor pool (instead of letting backend creates its own):+//                - Before: need at least IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER.+//                - After:  need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE.+//                                      + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE       descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.+//  2026-03-11: Vulkan: Added ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[] to allow specifying extra dynamic states to add when creating the VkPipeline. (#9211)+//  2025-09-26: [Helpers] *BREAKING CHANGE*: Vulkan: Helper ImGui_ImplVulkanH_DestroyWindow() does not call vkDestroySurfaceKHR(): as surface is created by caller of ImGui_ImplVulkanH_CreateOrResizeWindow(), it is more consistent that we don't destroy it. (#9163)+//  2026-01-05: [Helpers] *BREAKING CHANGE*: Vulkan: Helper for creating render pass uses ImGui_ImplVulkanH_Window::AttachmentDesc to create render pass. Removed ClearEnabled. (#9152)+//  2025-11-24: [Helpers] Vulkan: Helper for creating a swap-chain (used by examples and multi-viewports) selects VkSwapchainCreateInfoKHR's compositeAlpha based on cap.supportedCompositeAlpha. (#8784)+//  2025-11-13: [Docking] Handle viewport surface creation failure without crashing. (#9068)+//  2025-10-15: Vulkan: Added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to volk.h header. (#9008)+//  2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo.+//  2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users.+//  2025-09-26: [Helpers] *BREAKING CHANGE*: Helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0.+//  2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585)+//  2025-09-22: [Docking] Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940)+//  2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.+//  2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111)+//  2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840)+//  2025-07-07: Vulkan: Fixed texture synchronization issue introduced on 2025-06-11. (#8772)+//  2025-06-27: Vulkan: Fixed validation errors during texture upload/update by aligning upload size to 'nonCoherentAtomSize'. (#8743, #8744)+//  2025-06-11: Vulkan: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplVulkan_CreateFontsTexture() and ImGui_ImplVulkan_DestroyFontsTexture().+//  2025-05-07: Vulkan: Fixed validation errors during window detach in multi-viewport mode. (#8600, #8176)+//  2025-05-07: Vulkan: Load dynamic rendering functions using vkGetDeviceProcAddr() + try both non-KHR and KHR versions. (#8600, #8326, #8365)+//  2025-04-07: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's pColorAttachmentFormats buffer when set, in order to reduce common user-error of specifying a pointer to data that gets out of scope. (#8282)+//  2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().+//  2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)+//  2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642)+//  2025-01-06: [Helpers] Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples.+//  2024-12-11: [Helpers] Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)+//  2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867)+//  2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.+//  2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.+//  2024-10-07: Vulkan: Compiling with '#define ImTextureID=ImU64' is unnecessary now that dear imgui defaults ImTextureID to u64 instead of void*.+//  2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)+//  2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.+//  2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.+//  2024-01-19: [Helpers] Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)+//  2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189).+//  2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238)+//  2024-01-03: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them.+//  2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075)+//  2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts.+//              *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unnecessary as we create and destroy those objects in the backend.+//              ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time.+//              You can call ImGui_ImplVulkan_CreateFontsTexture() again to recreate the font atlas texture.+//              Added ImGui_ImplVulkan_DestroyFontsTexture() but you probably never need to call this.+//  2023-07-04: Vulkan: Added optional support for VK_KHR_dynamic_rendering. User needs to set init_info->UseDynamicRendering = true and init_info->ColorAttachmentFormat.+//  2023-01-02: Vulkan: Fixed sampler passed to ImGui_ImplVulkan_AddTexture() not being honored + removed a bunch of duplicate code.+//  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.+//  2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symmetry. (#914, #5738).+//  2022-01-20: Vulkan: Added support for ImTextureID as VkDescriptorSet. User need to call ImGui_ImplVulkan_AddTexture(). Building for 32-bit targets requires '#define ImTextureID ImU64'. (#914).+//  2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likelihood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.+//  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).+//  2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.+//  2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.+//  2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().+//  2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.+//  2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init).+//  2020-05-04: Vulkan: Fixed crash if initial frame has no vertices.+//  2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices.+//  2019-08-01: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before.+//  2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.+//  2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.+//  2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount().+//  2019-04-04: [Helpers] Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.+//  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.+//  2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.+//  2018-08-25: [Helpers] Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.+//  2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.+//  2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined GLFW+Vulkan example.+//  2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.+//  2018-03-03: [Helpers] 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-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.+//  2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.+//  2017-05-15: Vulkan: Fix scissor offset being negative. Fix new Vulkan validation warnings. Set required depth member for buffer image copy.+//  2016-11-13: Vulkan: Fix validation layer warnings and errors and redeclare gl_PerVertex.+//  2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources.+//  2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.++#include "imgui.h"+#ifndef IMGUI_DISABLE+#include "imgui_impl_vulkan.h"+#include <stdio.h>+#ifndef IM_MAX+#define IM_MAX(A, B)    (((A) >= (B)) ? (A) : (B))+#endif+#undef Status // X11 headers are leaking this.++// Visual Studio warnings+#ifdef _MSC_VER+#pragma warning (disable: 4127) // condition expression is constant+#endif++// Clang/GCC warnings with -Weverything+#if defined(__clang__)+#pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast+#pragma clang diagnostic ignored "-Wsign-conversion"                // warning: implicit conversion changes signedness+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision+#pragma clang diagnostic ignored "-Wcast-function-type"             // warning: cast between incompatible function types (for loader)+#endif++// Forward Declarations+struct ImGui_ImplVulkan_FrameRenderBuffers;+struct ImGui_ImplVulkan_WindowRenderBuffers;+bool ImGui_ImplVulkan_CreateDeviceObjects();+void ImGui_ImplVulkan_DestroyDeviceObjects();+void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);+void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);+void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);+void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);+void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator);+void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);+void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);++// Vulkan prototypes for use with custom loaders+// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h)+#if defined(VK_NO_PROTOTYPES) && !defined(VOLK_H_)+#define IMGUI_IMPL_VULKAN_USE_LOADER+static bool g_FunctionsLoaded = false;+#else+static bool g_FunctionsLoaded = true;+#endif+#ifdef IMGUI_IMPL_VULKAN_USE_LOADER+#define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateMemory) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkAcquireNextImageKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkBeginCommandBuffer) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindBufferMemory) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindImageMemory) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBeginRenderPass) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindDescriptorSets) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindIndexBuffer) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindPipeline) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindVertexBuffers) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdCopyBufferToImage) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdDrawIndexed) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdEndRenderPass) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPipelineBarrier) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPushConstants) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetScissor) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetViewport) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateBuffer) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateCommandPool) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateDescriptorPool) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateDescriptorSetLayout) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFence) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFramebuffer) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateGraphicsPipelines) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImage) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImageView) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreatePipelineLayout) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateRenderPass) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSampler) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSemaphore) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateShaderModule) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSwapchainKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyBuffer) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyCommandPool) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyDescriptorPool) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyDescriptorSetLayout) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFence) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFramebuffer) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImage) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImageView) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipeline) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipelineLayout) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyRenderPass) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySampler) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySemaphore) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyShaderModule) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySurfaceKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySwapchainKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkEnumeratePhysicalDevices) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkEndCommandBuffer) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeDescriptorSets) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetDeviceQueue) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceProperties) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceMemoryProperties) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceQueueFamilyProperties) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceFormatsKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceSupportKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetSwapchainImagesKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkMapMemory) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkQueuePresentKHR) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkQueueSubmit) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkQueueWaitIdle) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkResetCommandPool) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkResetFences) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkUnmapMemory) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets) \+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkWaitForFences)++struct ImGui_ImplVulkan_Functions+{+// Define function pointers+#define IMGUI_VULKAN_FUNC_DEF(func) PFN_##func pfn_##func;+IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)+#undef IMGUI_VULKAN_FUNC_DEF+};++// Globally available function pointers used for initialization of the backend data+static ImGui_ImplVulkan_Functions   ImGuiImplVulkanFuncs;++// Multi Vulkan contexts support: wrap each Vulkan function pointer to properly dispatch it using the current backend data+static ImGui_ImplVulkan_Functions&  ImGui_ImplVulkan_GetFunctions();+#define IMGUI_VULKAN_FUNC_WRAPPER(func) \+    template<typename... Args> \+    auto func(Args&&... args) -> decltype(ImGui_ImplVulkan_GetFunctions().pfn_##func(args...)) \+    { \+        return ImGui_ImplVulkan_GetFunctions().pfn_##func(args...); \+    }+IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_WRAPPER)+#undef IMGUI_VULKAN_FUNC_WRAPPER++#endif // IMGUI_IMPL_VULKAN_USE_LOADER++#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+static PFN_vkCmdBeginRenderingKHR   ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR;+static PFN_vkCmdEndRenderingKHR     ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR;+#endif++// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()+// [Please zero-clear before use!]+struct ImGui_ImplVulkan_FrameRenderBuffers+{+    VkDeviceMemory      VertexBufferMemory;+    VkDeviceMemory      IndexBufferMemory;+    VkDeviceSize        VertexBufferSize;+    VkDeviceSize        IndexBufferSize;+    VkBuffer            VertexBuffer;+    VkBuffer            IndexBuffer;+};++// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers+// [Please zero-clear before use!]+struct ImGui_ImplVulkan_WindowRenderBuffers+{+    uint32_t            Index;+    uint32_t            Count;+    ImVector<ImGui_ImplVulkan_FrameRenderBuffers> FrameRenderBuffers;+};++struct ImGui_ImplVulkan_Texture+{+    VkDeviceMemory              Memory;+    VkImage                     Image;+    VkImageView                 ImageView;+    VkDescriptorSet             DescriptorSet;++    ImGui_ImplVulkan_Texture() { memset((void*)this, 0, sizeof(*this)); }+};++// For multi-viewport support:+// Helper structure we store in the void* RendererUserData field of each ImGuiViewport to easily retrieve our backend data.+struct ImGui_ImplVulkan_ViewportData+{+    ImGui_ImplVulkanH_Window                Window;                 // Used by secondary viewports only+    ImGui_ImplVulkan_WindowRenderBuffers    RenderBuffers;          // Used by all viewports+    bool                                    WindowOwned;+    bool                                    SwapChainNeedRebuild;   // Flag when viewport swapchain resized in the middle of processing a frame+    bool                                    SwapChainSuboptimal;    // Flag when VK_SUBOPTIMAL_KHR was returned.++    ImGui_ImplVulkan_ViewportData() { WindowOwned = SwapChainNeedRebuild = SwapChainSuboptimal = false; memset((void*)&RenderBuffers, 0, sizeof(RenderBuffers)); }+    ~ImGui_ImplVulkan_ViewportData() { }+};++// Vulkan data+struct ImGui_ImplVulkan_Data+{+    ImGui_ImplVulkan_InitInfo   VulkanInitInfo;+    ImGui_ImplVulkan_RenderState* RenderState;          // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.+    VkDeviceSize                BufferMemoryAlignment;+    VkDeviceSize                NonCoherentAtomSize;+    VkPipelineCreateFlags       PipelineCreateFlags;+    VkDescriptorSetLayout       DescriptorSetLayoutTexture;+    VkDescriptorSetLayout       DescriptorSetLayoutSampler;+    VkPipelineLayout            PipelineLayout;+    VkPipeline                  Pipeline;               // pipeline for main render pass (created by app)+    VkPipeline                  PipelineForViewports;   // pipeline for secondary viewports (created by backend)+    VkShaderModule              ShaderModuleVert;+    VkShaderModule              ShaderModuleFrag;+    VkDescriptorPool            DescriptorPool;+    ImVector<VkFormat>          PipelineRenderingCreateInfoColorAttachmentFormats; // Deep copy of format array++    // Texture management+    VkSampler                   SamplerLinear;+    VkSampler                   SamplerNearest;+    VkDescriptorSet             SamplerLinearDS;+    VkDescriptorSet             SamplerNearestDS;+    VkCommandPool               TexCommandPool;+    VkCommandBuffer             TexCommandBuffer;++    // Render buffers for main window+    ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers;++    // Vulkan function pointers loaded for this context+#ifdef IMGUI_IMPL_VULKAN_USE_LOADER+    ImGui_ImplVulkan_Functions  Functions;+#endif++    ImGui_ImplVulkan_Data()+    {+        memset((void*)this, 0, sizeof(*this));+        BufferMemoryAlignment = 256;+        NonCoherentAtomSize = 64;+    }+};++//-----------------------------------------------------------------------------+// SHADERS+//-----------------------------------------------------------------------------++// Forward Declarations+static void ImGui_ImplVulkan_InitMultiViewportSupport();+static void ImGui_ImplVulkan_ShutdownMultiViewportSupport();++// backends/vulkan/glsl_shader.vert, compiled with:+// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert+/*+#version 450 core+layout(location = 0) in vec2 aPos;+layout(location = 1) in vec2 aUV;+layout(location = 2) in vec4 aColor;+layout(push_constant) uniform uPushConstant { vec2 uScale; vec2 uTranslate; } pc;++out gl_PerVertex { vec4 gl_Position; };+layout(location = 0) out struct { vec4 Color; vec2 UV; } Out;++void main()+{+    Out.Color = aColor;+    Out.UV = aUV;+    gl_Position = vec4(aPos * pc.uScale + pc.uTranslate, 0, 1);+}+*/+static uint32_t __glsl_shader_vert_spv[] =+{+    0x07230203,0x00010000,0x0008000b,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,+    0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,+    0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,+    0x0000001b,0x0000001c,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,+    0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c6f43,+    0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074754f,+    0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00060005,+    0x00000019,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000019,0x00000000,+    0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001b,0x00000000,0x00040005,0x0000001c,+    0x736f5061,0x00000000,0x00060005,0x0000001e,0x73755075,0x6e6f4368,0x6e617473,0x00000074,+    0x00050006,0x0000001e,0x00000000,0x61635375,0x0000656c,0x00060006,0x0000001e,0x00000001,+    0x61725475,0x616c736e,0x00006574,0x00030005,0x00000020,0x00006370,0x00040047,0x0000000b,+    0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015,+    0x0000001e,0x00000001,0x00030047,0x00000019,0x00000002,0x00050048,0x00000019,0x00000000,+    0x0000000b,0x00000000,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00030047,0x0000001e,+    0x00000002,0x00050048,0x0000001e,0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,+    0x00000001,0x00000023,0x00000008,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,+    0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040017,+    0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020,+    0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015,+    0x0000000c,0x00000020,0x00000001,0x0004002b,0x0000000c,0x0000000d,0x00000000,0x00040020,+    0x0000000e,0x00000001,0x00000007,0x0004003b,0x0000000e,0x0000000f,0x00000001,0x00040020,+    0x00000011,0x00000003,0x00000007,0x0004002b,0x0000000c,0x00000013,0x00000001,0x00040020,+    0x00000014,0x00000001,0x00000008,0x0004003b,0x00000014,0x00000015,0x00000001,0x00040020,+    0x00000017,0x00000003,0x00000008,0x0003001e,0x00000019,0x00000007,0x00040020,0x0000001a,+    0x00000003,0x00000019,0x0004003b,0x0000001a,0x0000001b,0x00000003,0x0004003b,0x00000014,+    0x0000001c,0x00000001,0x0004001e,0x0000001e,0x00000008,0x00000008,0x00040020,0x0000001f,+    0x00000009,0x0000001e,0x0004003b,0x0000001f,0x00000020,0x00000009,0x00040020,0x00000021,+    0x00000009,0x00000008,0x0004002b,0x00000006,0x00000028,0x00000000,0x0004002b,0x00000006,+    0x00000029,0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,+    0x00000005,0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x00000012,+    0x0000000b,0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x00000016,+    0x00000015,0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x00000018,+    0x00000016,0x0004003d,0x00000008,0x0000001d,0x0000001c,0x00050041,0x00000021,0x00000022,+    0x00000020,0x0000000d,0x0004003d,0x00000008,0x00000023,0x00000022,0x00050085,0x00000008,+    0x00000024,0x0000001d,0x00000023,0x00050041,0x00000021,0x00000025,0x00000020,0x00000013,+    0x0004003d,0x00000008,0x00000026,0x00000025,0x00050081,0x00000008,0x00000027,0x00000024,+    0x00000026,0x00050051,0x00000006,0x0000002a,0x00000027,0x00000000,0x00050051,0x00000006,+    0x0000002b,0x00000027,0x00000001,0x00070050,0x00000007,0x0000002c,0x0000002a,0x0000002b,+    0x00000028,0x00000029,0x00050041,0x00000011,0x0000002d,0x0000001b,0x0000000d,0x0003003e,+    0x0000002d,0x0000002c,0x000100fd,0x00010038+};++// backends/vulkan/glsl_shader.frag, compiled with:+// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag+/*+#version 450 core+layout(location = 0) out vec4 fColor;+layout(set=0, binding=0) uniform texture2D _Texture;+layout(set=1, binding=0) uniform sampler _Sampler;+layout(location = 0) in struct { vec4 Color; vec2 UV; } In;+void main()+{+    fColor = In.Color * texture(sampler2D(_Texture, _Sampler), In.UV.st);+}+*/+static uint32_t __glsl_shader_frag_spv[] =+{+    0x07230203,0x00010000,0x0008000b,0x00000023,0x00000000,0x00020011,0x00000001,0x0006000b,+    0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,+    0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,+    0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,+    0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,+    0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,+    0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000015,0x7865545f,0x65727574,+    0x00000000,0x00050005,0x00000019,0x6d61535f,0x72656c70,0x00000000,0x00040047,0x00000009,+    0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,0x00000000,0x00040047,0x00000015,+    0x00000021,0x00000000,0x00040047,0x00000015,0x00000022,0x00000000,0x00040047,0x00000019,+    0x00000021,0x00000000,0x00040047,0x00000019,0x00000022,0x00000001,0x00020013,0x00000002,+    0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,+    0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007,0x0004003b,0x00000008,+    0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,0x00000002,0x0004001e,0x0000000b,+    0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,0x0000000b,0x0004003b,0x0000000c,+    0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,0x00000001,0x0004002b,0x0000000e,+    0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,0x00000007,0x00090019,0x00000013,+    0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x00040020,+    0x00000014,0x00000000,0x00000013,0x0004003b,0x00000014,0x00000015,0x00000000,0x0002001a,+    0x00000017,0x00040020,0x00000018,0x00000000,0x00000017,0x0004003b,0x00000018,0x00000019,+    0x00000000,0x0003001b,0x0000001b,0x00000013,0x0004002b,0x0000000e,0x0000001d,0x00000001,+    0x00040020,0x0000001e,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,0x00000000,+    0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,0x0000000f,+    0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000013,0x00000016,0x00000015,+    0x0004003d,0x00000017,0x0000001a,0x00000019,0x00050056,0x0000001b,0x0000001c,0x00000016,+    0x0000001a,0x00050041,0x0000001e,0x0000001f,0x0000000d,0x0000001d,0x0004003d,0x0000000a,+    0x00000020,0x0000001f,0x00050057,0x00000007,0x00000021,0x0000001c,0x00000020,0x00050085,+    0x00000007,0x00000022,0x00000012,0x00000021,0x0003003e,0x00000009,0x00000022,0x000100fd,+    0x00010038+};++//-----------------------------------------------------------------------------+// FUNCTIONS+//-----------------------------------------------------------------------------++// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.+// FIXME: multi-context support is not tested and probably dysfunctional in this backend.+static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()+{+    return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;+}++ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState()+{+    return (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;+}++#ifdef IMGUI_IMPL_VULKAN_USE_LOADER+// Get the Vulkan function pointers used by the current backend.+// If no backend is available, return the currently loaded global function pointers (ImGuiImplVulkanFuncs).+static ImGui_ImplVulkan_Functions& ImGui_ImplVulkan_GetFunctions()+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    return bd ? bd->Functions : ImGuiImplVulkanFuncs;+}+#endif++static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkPhysicalDeviceMemoryProperties prop;+    vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop);+    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+}++static void check_vk_result(VkResult err)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    if (!bd)+        return;+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    if (v->CheckVkResultFn)+        v->CheckVkResultFn(err);+}++// Same as IM_MEMALIGN(). 'alignment' must be a power of two.+static inline VkDeviceSize AlignBufferSize(VkDeviceSize size, VkDeviceSize alignment)+{+    return (size + alignment - 1) & ~(alignment - 1);+}++static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& buffer_size, VkDeviceSize new_size, VkBufferUsageFlagBits usage)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkResult err;+    if (buffer != VK_NULL_HANDLE)+        vkDestroyBuffer(v->Device, buffer, v->Allocator);+    if (buffer_memory != VK_NULL_HANDLE)+        vkFreeMemory(v->Device, buffer_memory, v->Allocator);++    VkDeviceSize buffer_size_aligned = AlignBufferSize(IM_MAX(v->MinAllocationSize, new_size), bd->BufferMemoryAlignment);+    VkBufferCreateInfo buffer_info = {};+    buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;+    buffer_info.size = buffer_size_aligned;+    buffer_info.usage = usage;+    buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;+    err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer);+    check_vk_result(err);++    VkMemoryRequirements req;+    vkGetBufferMemoryRequirements(v->Device, buffer, &req);+    bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;+    VkMemoryAllocateInfo alloc_info = {};+    alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;+    alloc_info.allocationSize = req.size;+    alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);+    err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &buffer_memory);+    check_vk_result(err);++    err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0);+    check_vk_result(err);+    buffer_size = buffer_size_aligned;+}++static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkan_FrameRenderBuffers* rb, int fb_width, int fb_height)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();++    // Bind pipeline:+    vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);++    // Bind Vertex And Index Buffer:+    if (draw_data->TotalVtxCount > 0)+    {+        VkBuffer vertex_buffers[1] = { rb->VertexBuffer };+        VkDeviceSize vertex_offset[1] = { 0 };+        vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset);+        vkCmdBindIndexBuffer(command_buffer, rb->IndexBuffer, 0, sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);+    }++    // Setup viewport:+    VkViewport viewport;+    viewport.x = 0;+    viewport.y = 0;+    viewport.width = (float)fb_width;+    viewport.height = (float)fb_height;+    viewport.minDepth = 0.0f;+    viewport.maxDepth = 1.0f;+    vkCmdSetViewport(command_buffer, 0, 1, &viewport);++    // Setup scale and translation:+    // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.+    float constants[4];+    constants[0] = 2.0f / draw_data->DisplaySize.x; // Scale+    constants[1] = 2.0f / draw_data->DisplaySize.y;+    constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate+    constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1];+    vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, (uint32_t)sizeof(float) * 4, constants);++    // Setup sampler+    vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr);+}++// Draw callbacks+static void ImGui_ImplVulkan_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*)     {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.+static void ImGui_ImplVulkan_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*)     { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->RenderState->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); }+static void ImGui_ImplVulkan_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*)    { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->RenderState->PipelineLayout, 1, 1, &bd->SamplerNearestDS, 0, nullptr); }++// If you want to use your own sampler, you can create your own callback, access ImGui_ImplVulkan_RenderState for command-buffer and pipeline layout, e.g.+/*+void ImGui_ImplVulkan_DrawCallback_SetSamplerCustom(const ImDrawList*, const ImDrawCmd* cmd)+{+    ImGui_ImplVulkan_RenderState* render_state = (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;+    vkCmdBindDescriptorSets(render_state->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, render_state->PipelineLayout, 1, 1, (VkDescriptorSet*)cmd->UserCallbackData, 0, nullptr);+}+*/++// Render function+void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)+{+    // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)+    int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);+    int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);+    if (fb_width <= 0 || fb_height <= 0)+        return;++    // Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.+    // (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).+    if (draw_data->Textures != nullptr)+        for (ImTextureData* tex : *draw_data->Textures)+            if (tex->Status != ImTextureStatus_OK)+                ImGui_ImplVulkan_UpdateTexture(tex);++    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    if (pipeline == VK_NULL_HANDLE)+        pipeline = bd->Pipeline;++    // Allocate array to store enough vertex/index buffers. Each unique viewport gets its own storage.+    ImGui_ImplVulkan_ViewportData* viewport_renderer_data = (ImGui_ImplVulkan_ViewportData*)draw_data->OwnerViewport->RendererUserData;+    IM_ASSERT(viewport_renderer_data != nullptr);+    ImGui_ImplVulkan_WindowRenderBuffers* wrb = &viewport_renderer_data->RenderBuffers;+    if (wrb->FrameRenderBuffers.Size == 0)+    {+        wrb->Index = 0;+        wrb->Count = v->ImageCount;+        wrb->FrameRenderBuffers.resize(wrb->Count);+        memset((void*)wrb->FrameRenderBuffers.Data, 0, wrb->FrameRenderBuffers.size_in_bytes());+    }+    IM_ASSERT(wrb->Count == v->ImageCount);+    wrb->Index = (wrb->Index + 1) % wrb->Count;+    ImGui_ImplVulkan_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb->Index];++    if (draw_data->TotalVtxCount > 0)+    {+        // Create or resize the vertex/index buffers+        VkDeviceSize vertex_size = AlignBufferSize(draw_data->TotalVtxCount * sizeof(ImDrawVert), bd->BufferMemoryAlignment);+        VkDeviceSize index_size = AlignBufferSize(draw_data->TotalIdxCount * sizeof(ImDrawIdx), bd->BufferMemoryAlignment);+        if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size)+            CreateOrResizeBuffer(rb->VertexBuffer, rb->VertexBufferMemory, rb->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);+        if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)+            CreateOrResizeBuffer(rb->IndexBuffer, rb->IndexBufferMemory, rb->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);++        // Upload vertex/index data into a single contiguous GPU buffer+        ImDrawVert* vtx_dst = nullptr;+        ImDrawIdx* idx_dst = nullptr;+        VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, vertex_size, 0, (void**)&vtx_dst);+        check_vk_result(err);+        err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, index_size, 0, (void**)&idx_dst);+        check_vk_result(err);+        for (const ImDrawList* draw_list : draw_data->CmdLists)+        {+            memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));+            memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));+            vtx_dst += draw_list->VtxBuffer.Size;+            idx_dst += draw_list->IdxBuffer.Size;+        }+        VkMappedMemoryRange range[2] = {};+        range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;+        range[0].memory = rb->VertexBufferMemory;+        range[0].size = VK_WHOLE_SIZE;+        range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;+        range[1].memory = rb->IndexBufferMemory;+        range[1].size = VK_WHOLE_SIZE;+        err = vkFlushMappedMemoryRanges(v->Device, 2, range);+        check_vk_result(err);+        vkUnmapMemory(v->Device, rb->VertexBufferMemory);+        vkUnmapMemory(v->Device, rb->IndexBufferMemory);+    }++    // Setup render state structure (for callbacks and custom texture bindings)+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();+    ImGui_ImplVulkan_RenderState render_state;+    render_state.CommandBuffer = command_buffer;+    render_state.Pipeline = pipeline;+    render_state.PipelineLayout = bd->PipelineLayout;+    platform_io.Renderer_RenderState = bd->RenderState = &render_state;++    // Setup desired Vulkan state+    ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);++    // Will project scissor/clipping rectangles into framebuffer space+    ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports+    ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)++    // Render command lists+    // (Because we merged all buffers into a single one, we maintain our own offset into them)+    VkDescriptorSet last_image_view = VK_NULL_HANDLE;+    int global_vtx_offset = 0;+    int global_idx_offset = 0;+    for (const ImDrawList* draw_list : draw_data->CmdLists)+    {+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)+        {+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];+            if (pcmd->UserCallback != nullptr)+            {+                // User callback, registered via ImDrawList::AddCallback()+                if (pcmd->UserCallback == ImGui_ImplVulkan_DrawCallback_ResetRenderState)+                {+                    ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);+                    last_image_view = VK_NULL_HANDLE;+                }+                else+                    pcmd->UserCallback(draw_list, pcmd);+            }+            else+            {+                // Project scissor/clipping rectangles into framebuffer space+                ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);+                ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);++                // Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds+                if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }+                if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }+                if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }+                if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }+                if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)+                    continue;++                // Apply scissor/clipping rectangle+                VkRect2D scissor;+                scissor.offset.x = (int32_t)(clip_min.x);+                scissor.offset.y = (int32_t)(clip_min.y);+                scissor.extent.width = (uint32_t)(clip_max.x - clip_min.x);+                scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);+                vkCmdSetScissor(command_buffer, 0, 1, &scissor);++                // Bind DescriptorSets for image view (font or user texture) and samplers+                VkDescriptorSet image_view = (VkDescriptorSet)pcmd->GetTexID();+                if (image_view != last_image_view)+                    vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &image_view, 0, nullptr);+                last_image_view = image_view;++                // Draw+                vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);+            }+        }+        global_idx_offset += draw_list->IdxBuffer.Size;+        global_vtx_offset += draw_list->VtxBuffer.Size;+    }+    platform_io.Renderer_RenderState = bd->RenderState = nullptr;++    // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.+    // Our last values will leak into user/application rendering IF:+    // - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state+    // - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitly set that state.+    // If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.+    // In theory we should aim to backup/restore those values but I am not sure this is possible.+    // We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)+    VkRect2D scissor = { { 0, 0 }, { (uint32_t)fb_width, (uint32_t)fb_height } };+    vkCmdSetScissor(command_buffer, 0, 1, &scissor);+}++static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex)+{+    if (ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData)+    {+        IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);+        ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+        ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+        ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);+        vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator);+        vkDestroyImage(v->Device, backend_tex->Image, v->Allocator);+        vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator);+        IM_DELETE(backend_tex);++        // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)+        tex->SetTexID(ImTextureID_Invalid);+        tex->BackendUserData = nullptr;+    }+    tex->SetStatus(ImTextureStatus_Destroyed);+}++void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)+{+    if (tex->Status == ImTextureStatus_OK)+        return;+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkResult err;++    if (tex->Status == ImTextureStatus_WantCreate)+    {+        // Create and upload new texture to graphics system+        //IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);+        IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);+        IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);+        ImGui_ImplVulkan_Texture* backend_tex = IM_NEW(ImGui_ImplVulkan_Texture)();++        // Create the Image:+        {+            VkImageCreateInfo info = {};+            info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;+            info.imageType = VK_IMAGE_TYPE_2D;+            info.format = VK_FORMAT_R8G8B8A8_UNORM;+            info.extent.width = tex->Width;+            info.extent.height = tex->Height;+            info.extent.depth = 1;+            info.mipLevels = 1;+            info.arrayLayers = 1;+            info.samples = VK_SAMPLE_COUNT_1_BIT;+            info.tiling = VK_IMAGE_TILING_OPTIMAL;+            info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;+            info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;+            info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;+            err = vkCreateImage(v->Device, &info, v->Allocator, &backend_tex->Image);+            check_vk_result(err);+            VkMemoryRequirements req;+            vkGetImageMemoryRequirements(v->Device, backend_tex->Image, &req);+            VkMemoryAllocateInfo alloc_info = {};+            alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;+            alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);+            alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);+            err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &backend_tex->Memory);+            check_vk_result(err);+            err = vkBindImageMemory(v->Device, backend_tex->Image, backend_tex->Memory, 0);+            check_vk_result(err);+        }++        // Create the Image View:+        {+            VkImageViewCreateInfo info = {};+            info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;+            info.image = backend_tex->Image;+            info.viewType = VK_IMAGE_VIEW_TYPE_2D;+            info.format = VK_FORMAT_R8G8B8A8_UNORM;+            info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;+            info.subresourceRange.levelCount = 1;+            info.subresourceRange.layerCount = 1;+            err = vkCreateImageView(v->Device, &info, v->Allocator, &backend_tex->ImageView);+            check_vk_result(err);+        }++        // Create the Descriptor Set+        backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);++        // Store identifiers+        tex->SetTexID((ImTextureID)backend_tex->DescriptorSet);+        tex->BackendUserData = backend_tex;+    }++    if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)+    {+        ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData;++        // Update full texture or selected blocks. We only ever write to textures regions which have never been used before!+        // This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.+        // We could use the smaller rect on _WantCreate but using the full rect allows us to clear the texture.+        const int upload_x = (tex->Status == ImTextureStatus_WantCreate) ? 0 : tex->UpdateRect.x;+        const int upload_y = (tex->Status == ImTextureStatus_WantCreate) ? 0 : tex->UpdateRect.y;+        const int upload_w = (tex->Status == ImTextureStatus_WantCreate) ? tex->Width : tex->UpdateRect.w;+        const int upload_h = (tex->Status == ImTextureStatus_WantCreate) ? tex->Height : tex->UpdateRect.h;++        // Create the Upload Buffer:+        VkDeviceMemory upload_buffer_memory;++        VkBuffer upload_buffer;+        VkDeviceSize upload_pitch = upload_w * tex->BytesPerPixel;+        VkDeviceSize upload_size = AlignBufferSize(upload_h * upload_pitch, bd->NonCoherentAtomSize);+        {+            VkBufferCreateInfo buffer_info = {};+            buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;+            buffer_info.size = upload_size;+            buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;+            buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;+            err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &upload_buffer);+            check_vk_result(err);+            VkMemoryRequirements req;+            vkGetBufferMemoryRequirements(v->Device, upload_buffer, &req);+            bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;+            VkMemoryAllocateInfo alloc_info = {};+            alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;+            alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);+            alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);+            err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &upload_buffer_memory);+            check_vk_result(err);+            err = vkBindBufferMemory(v->Device, upload_buffer, upload_buffer_memory, 0);+            check_vk_result(err);+        }++        // Upload to Buffer:+        {+            char* map = nullptr;+            err = vkMapMemory(v->Device, upload_buffer_memory, 0, upload_size, 0, (void**)(&map));+            check_vk_result(err);+            for (int y = 0; y < upload_h; y++)+                memcpy(map + upload_pitch * y, tex->GetPixelsAt(upload_x, upload_y + y), (size_t)upload_pitch);+            VkMappedMemoryRange range[1] = {};+            range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;+            range[0].memory = upload_buffer_memory;+            range[0].size = upload_size;+            err = vkFlushMappedMemoryRanges(v->Device, 1, range);+            check_vk_result(err);+            vkUnmapMemory(v->Device, upload_buffer_memory);+        }++        // Start command buffer+        {+            err = vkResetCommandPool(v->Device, bd->TexCommandPool, 0);+            check_vk_result(err);+            VkCommandBufferBeginInfo begin_info = {};+            begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;+            begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;+            err = vkBeginCommandBuffer(bd->TexCommandBuffer, &begin_info);+            check_vk_result(err);+        }++        // Copy to Image:+        {+            VkBufferMemoryBarrier upload_barrier[1] = {};+            upload_barrier[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;+            upload_barrier[0].srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;+            upload_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;+            upload_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+            upload_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+            upload_barrier[0].buffer = upload_buffer;+            upload_barrier[0].offset = 0;+            upload_barrier[0].size = upload_size;++            VkImageMemoryBarrier copy_barrier[1] = {};+            copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;+            copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;+            copy_barrier[0].oldLayout = (tex->Status == ImTextureStatus_WantCreate) ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;+            copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;+            copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+            copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+            copy_barrier[0].image = backend_tex->Image;+            copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;+            copy_barrier[0].subresourceRange.levelCount = 1;+            copy_barrier[0].subresourceRange.layerCount = 1;+            vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, upload_barrier, 1, copy_barrier);++            VkBufferImageCopy region = {};+            region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;+            region.imageSubresource.layerCount = 1;+            region.imageExtent.width = upload_w;+            region.imageExtent.height = upload_h;+            region.imageExtent.depth = 1;+            region.imageOffset.x = upload_x;+            region.imageOffset.y = upload_y;+            vkCmdCopyBufferToImage(bd->TexCommandBuffer, upload_buffer, backend_tex->Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);++            VkImageMemoryBarrier use_barrier[1] = {};+            use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;+            use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;+            use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;+            use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;+            use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;+            use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+            use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+            use_barrier[0].image = backend_tex->Image;+            use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;+            use_barrier[0].subresourceRange.levelCount = 1;+            use_barrier[0].subresourceRange.layerCount = 1;+            vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);+        }++        // End command buffer+        {+            VkSubmitInfo end_info = {};+            end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;+            end_info.commandBufferCount = 1;+            end_info.pCommandBuffers = &bd->TexCommandBuffer;+            err = vkEndCommandBuffer(bd->TexCommandBuffer);+            check_vk_result(err);+            err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE);+            check_vk_result(err);+        }++        err = vkQueueWaitIdle(v->Queue); // FIXME-OPT: Suboptimal!+        check_vk_result(err);+        vkDestroyBuffer(v->Device, upload_buffer, v->Allocator);+        vkFreeMemory(v->Device, upload_buffer_memory, v->Allocator);++        tex->SetStatus(ImTextureStatus_OK);+    }++    if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames >= (int)bd->VulkanInitInfo.ImageCount)+        ImGui_ImplVulkan_DestroyTexture(tex);+}++static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    if (bd->ShaderModuleVert == VK_NULL_HANDLE)+    {+        VkShaderModuleCreateInfo default_vert_info = {};+        default_vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;+        default_vert_info.codeSize = sizeof(__glsl_shader_vert_spv);+        default_vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;+        VkShaderModuleCreateInfo* p_vert_info = (v->CustomShaderVertCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderVertCreateInfo : &default_vert_info;+        VkResult err = vkCreateShaderModule(device, p_vert_info, allocator, &bd->ShaderModuleVert);+        check_vk_result(err);+    }+    if (bd->ShaderModuleFrag == VK_NULL_HANDLE)+    {+        VkShaderModuleCreateInfo default_frag_info = {};+        default_frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;+        default_frag_info.codeSize = sizeof(__glsl_shader_frag_spv);+        default_frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;+        VkShaderModuleCreateInfo* p_frag_info = (v->CustomShaderFragCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderFragCreateInfo : &default_frag_info;+        VkResult err = vkCreateShaderModule(device, p_frag_info, allocator, &bd->ShaderModuleFrag);+        check_vk_result(err);+    }+}++#if !defined(IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING) && !(defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering))+typedef void VkPipelineRenderingCreateInfoKHR;+#endif++static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, const ImGui_ImplVulkan_PipelineInfo* info)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_CreateShaderModules(device, allocator);++    VkPipelineShaderStageCreateInfo stage[2] = {};+    stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;+    stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT;+    stage[0].module = bd->ShaderModuleVert;+    stage[0].pName = "main";+    stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;+    stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;+    stage[1].module = bd->ShaderModuleFrag;+    stage[1].pName = "main";++    VkVertexInputBindingDescription binding_desc[1] = {};+    binding_desc[0].stride = sizeof(ImDrawVert);+    binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;++    VkVertexInputAttributeDescription attribute_desc[3] = {};+    attribute_desc[0].location = 0;+    attribute_desc[0].binding = binding_desc[0].binding;+    attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT;+    attribute_desc[0].offset = offsetof(ImDrawVert, pos);+    attribute_desc[1].location = 1;+    attribute_desc[1].binding = binding_desc[0].binding;+    attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT;+    attribute_desc[1].offset = offsetof(ImDrawVert, uv);+    attribute_desc[2].location = 2;+    attribute_desc[2].binding = binding_desc[0].binding;+    attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM;+    attribute_desc[2].offset = offsetof(ImDrawVert, col);++    VkPipelineVertexInputStateCreateInfo vertex_info = {};+    vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;+    vertex_info.vertexBindingDescriptionCount = 1;+    vertex_info.pVertexBindingDescriptions = binding_desc;+    vertex_info.vertexAttributeDescriptionCount = 3;+    vertex_info.pVertexAttributeDescriptions = attribute_desc;++    VkPipelineInputAssemblyStateCreateInfo ia_info = {};+    ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;+    ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;++    VkPipelineViewportStateCreateInfo viewport_info = {};+    viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;+    viewport_info.viewportCount = 1;+    viewport_info.scissorCount = 1;++    VkPipelineRasterizationStateCreateInfo raster_info = {};+    raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;+    raster_info.polygonMode = VK_POLYGON_MODE_FILL;+    raster_info.cullMode = VK_CULL_MODE_NONE;+    raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;+    raster_info.lineWidth = 1.0f;++    VkPipelineMultisampleStateCreateInfo ms_info = {};+    ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;+    ms_info.rasterizationSamples = (info->MSAASamples != 0) ? info->MSAASamples : VK_SAMPLE_COUNT_1_BIT;++    // Blend into the first color attachment. With dynamic rendering, other color attachments of the rendering are left untouched (requires independentBlend feature).+    int color_attachment_count = 1;+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    if (bd->VulkanInitInfo.UseDynamicRendering && info->PipelineRenderingCreateInfo.colorAttachmentCount > 1)+        color_attachment_count = (int)info->PipelineRenderingCreateInfo.colorAttachmentCount;+#endif+    ImVector<VkPipelineColorBlendAttachmentState> color_attachment;+    color_attachment.resize(color_attachment_count, VkPipelineColorBlendAttachmentState()); // colorWriteMask = 0+    color_attachment[0].blendEnable = VK_TRUE;+    color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;+    color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;+    color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD;+    color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;+    color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;+    color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD;+    color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;++    VkPipelineDepthStencilStateCreateInfo depth_info = {};+    depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;++    VkPipelineColorBlendStateCreateInfo blend_info = {};+    blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;+    blend_info.attachmentCount = (uint32_t)color_attachment.Size;+    blend_info.pAttachments = color_attachment.Data;++    ImVector<VkDynamicState> dynamic_states = info->ExtraDynamicStates;+    dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT);+    dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);+    VkPipelineDynamicStateCreateInfo dynamic_state = {};+    dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;+    dynamic_state.dynamicStateCount = dynamic_states.Size;+    dynamic_state.pDynamicStates = dynamic_states.Data;++    VkGraphicsPipelineCreateInfo create_info = {};+    create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;+    create_info.flags = bd->PipelineCreateFlags;+    create_info.stageCount = 2;+    create_info.pStages = stage;+    create_info.pVertexInputState = &vertex_info;+    create_info.pInputAssemblyState = &ia_info;+    create_info.pViewportState = &viewport_info;+    create_info.pRasterizationState = &raster_info;+    create_info.pMultisampleState = &ms_info;+    create_info.pDepthStencilState = &depth_info;+    create_info.pColorBlendState = &blend_info;+    create_info.pDynamicState = &dynamic_state;+    create_info.layout = bd->PipelineLayout;+    create_info.renderPass = info->RenderPass;+    create_info.subpass = info->Subpass;++#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    if (bd->VulkanInitInfo.UseDynamicRendering)+    {+        IM_ASSERT(info->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");+        IM_ASSERT(info->PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr");+        create_info.pNext = &info->PipelineRenderingCreateInfo;+        create_info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.+    }+#endif+    VkPipeline pipeline;+    VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &create_info, allocator, &pipeline);+    check_vk_result(err);+    return pipeline;+}++static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDescriptorSetLayout* p_layout, VkDescriptorType descriptor_type)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;++    VkDescriptorSetLayoutBinding binding[1] = {};+    binding[0].descriptorType = descriptor_type;+    binding[0].descriptorCount = 1;+    binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;+    VkDescriptorSetLayoutCreateInfo info = {};+    info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;+    info.bindingCount = 1;+    info.pBindings = binding;+    VkResult err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, p_layout);+    check_vk_result(err);+}++static VkDescriptorSet ImGui_ImplVulkan_CreateSamplerDS(VkSampler sampler)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;++    VkDescriptorSet descriptor_set;+    VkDescriptorSetAllocateInfo alloc_info = {};+    alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;+    alloc_info.descriptorPool = bd->DescriptorPool ? bd->DescriptorPool : v->DescriptorPool;+    alloc_info.descriptorSetCount = 1;+    alloc_info.pSetLayouts = &bd->DescriptorSetLayoutSampler;+    VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);+    check_vk_result(err);++    VkDescriptorImageInfo desc_image = {};+    desc_image.sampler = sampler;+    VkWriteDescriptorSet sampler_write_desc = {};+    sampler_write_desc.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;+    sampler_write_desc.dstSet = descriptor_set;+    sampler_write_desc.descriptorCount = 1;+    sampler_write_desc.dstBinding = 0;+    sampler_write_desc.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;+    sampler_write_desc.pImageInfo = &desc_image;+    vkUpdateDescriptorSets(v->Device, 1, &sampler_write_desc, 0, nullptr);+    return descriptor_set;+}++bool ImGui_ImplVulkan_CreateDeviceObjects()+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkResult err;++    if (!bd->DescriptorSetLayoutTexture)+        ImGui_ImplVulkan_CreateDescriptorSetLayout(&bd->DescriptorSetLayoutTexture, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);+    if (!bd->DescriptorSetLayoutSampler)+        ImGui_ImplVulkan_CreateDescriptorSetLayout(&bd->DescriptorSetLayoutSampler, VK_DESCRIPTOR_TYPE_SAMPLER);++    if (v->DescriptorPoolSize != 0)+    {+        IM_ASSERT(v->DescriptorPoolSize >= IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE);+        VkDescriptorPoolSize pool_sizes[] =+        {+            { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, v->DescriptorPoolSize },+            { VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },+        };+        VkDescriptorPoolCreateInfo pool_info = {};+        pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;+        pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;+        pool_info.maxSets = v->DescriptorPoolSize + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE;+        pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);+        pool_info.pPoolSizes = pool_sizes;+        err = vkCreateDescriptorPool(v->Device, &pool_info, v->Allocator, &bd->DescriptorPool);+        check_vk_result(err);+    }++    // Create samplers (bilinear sampling is required)+    if (!bd->SamplerLinear || !bd->SamplerNearest)+    {+        VkSamplerCreateInfo info = {};+        info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;+        info.magFilter = VK_FILTER_LINEAR;+        info.minFilter = VK_FILTER_LINEAR;+        info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;+        info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;+        info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;+        info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;+        info.minLod = -1000;+        info.maxLod = 1000;+        info.maxAnisotropy = 1.0f;+        err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->SamplerLinear);+        check_vk_result(err);+        bd->SamplerLinearDS = ImGui_ImplVulkan_CreateSamplerDS(bd->SamplerLinear);++        info.magFilter = VK_FILTER_NEAREST;+        info.minFilter = VK_FILTER_NEAREST;+        info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;+        err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->SamplerNearest);+        check_vk_result(err);+        bd->SamplerNearestDS = ImGui_ImplVulkan_CreateSamplerDS(bd->SamplerNearest);+    }++    if (!bd->PipelineLayout)+    {+        // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix+        VkPushConstantRange push_constants[1] = {};+        push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;+        push_constants[0].offset = sizeof(float) * 0;+        push_constants[0].size = sizeof(float) * 4;+        VkDescriptorSetLayout set_layout[2] = { bd->DescriptorSetLayoutTexture, bd->DescriptorSetLayoutSampler };+        VkPipelineLayoutCreateInfo layout_info = {};+        layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;+        layout_info.setLayoutCount = 2;+        layout_info.pSetLayouts = set_layout;+        layout_info.pushConstantRangeCount = 1;+        layout_info.pPushConstantRanges = push_constants;+        err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &bd->PipelineLayout);+        check_vk_result(err);+    }++    // Create pipeline+    bool create_main_pipeline = (v->PipelineInfoMain.RenderPass != VK_NULL_HANDLE);+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    create_main_pipeline |= (v->UseDynamicRendering && v->PipelineInfoMain.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR);+#endif+    if (create_main_pipeline)+        ImGui_ImplVulkan_CreateMainPipeline(&v->PipelineInfoMain);++    // Create command pool/buffer for texture upload+    if (!bd->TexCommandPool)+    {+        VkCommandPoolCreateInfo info = {};+        info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;+        info.flags = 0;+        info.queueFamilyIndex = v->QueueFamily;+        err = vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->TexCommandPool);+        check_vk_result(err);+    }+    if (!bd->TexCommandBuffer)+    {+        VkCommandBufferAllocateInfo info = {};+        info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;+        info.commandPool = bd->TexCommandPool;+        info.commandBufferCount = 1;+        err = vkAllocateCommandBuffers(v->Device, &info, &bd->TexCommandBuffer);+        check_vk_result(err);+    }++    return true;+}++void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* pipeline_info_in)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    if (bd->Pipeline)+    {+        vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator);+        bd->Pipeline = VK_NULL_HANDLE;+    }+    ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoMain;+    if (pipeline_info != pipeline_info_in)+        *pipeline_info = *pipeline_info_in;++#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = &pipeline_info->PipelineRenderingCreateInfo;+    if (v->UseDynamicRendering && pipeline_rendering_create_info->pColorAttachmentFormats != nullptr)+    {+        // Deep copy buffer to reduce error-rate for end user (#8282)+        ImVector<VkFormat> formats;+        formats.resize((int)pipeline_rendering_create_info->colorAttachmentCount);+        memcpy(formats.Data, pipeline_rendering_create_info->pColorAttachmentFormats, (size_t)formats.size_in_bytes());+        formats.swap(bd->PipelineRenderingCreateInfoColorAttachmentFormats);+        pipeline_rendering_create_info->pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data;+    }+#endif+    bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, pipeline_info);+}++void    ImGui_ImplVulkan_DestroyDeviceObjects()+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator);++    // Destroy all textures+    for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)+        if (tex->RefCount == 1)+            ImGui_ImplVulkan_DestroyTexture(tex);++    if (bd->TexCommandBuffer)     { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; }+    if (bd->TexCommandPool)       { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; }+    if (bd->SamplerLinear)        { vkDestroySampler(v->Device, bd->SamplerLinear, v->Allocator); bd->SamplerLinear = VK_NULL_HANDLE; }+    if (bd->SamplerNearest)       { vkDestroySampler(v->Device, bd->SamplerNearest, v->Allocator); bd->SamplerNearest = VK_NULL_HANDLE; }+    if (bd->ShaderModuleVert)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }+    if (bd->ShaderModuleFrag)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }+    if (bd->DescriptorSetLayoutTexture)  { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayoutTexture, v->Allocator); bd->DescriptorSetLayoutTexture = VK_NULL_HANDLE; }+    if (bd->DescriptorSetLayoutSampler)  { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayoutSampler, v->Allocator); bd->DescriptorSetLayoutSampler = VK_NULL_HANDLE; }+    if (bd->PipelineLayout)       { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }+    if (bd->Pipeline)             { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }+    if (bd->PipelineForViewports) { vkDestroyPipeline(v->Device, bd->PipelineForViewports, v->Allocator); bd->PipelineForViewports = VK_NULL_HANDLE; }+    if (bd->DescriptorPool)       { vkDestroyDescriptorPool(v->Device, bd->DescriptorPool, v->Allocator); bd->DescriptorPool = VK_NULL_HANDLE; }+}++#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)+{+    IM_UNUSED(api_version);++    // Manually load those two (see #5446, #8326, #8365, #8600)+    // - Try loading core (non-KHR) versions first (this will work for Vulkan 1.3+ and the device supports dynamic rendering)+    ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func("vkCmdBeginRendering", user_data));+    ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func("vkCmdEndRendering", user_data));++    // - Fallback to KHR versions if core not available (this will work if KHR extension is available and enabled and also the device supports dynamic rendering)+    if (ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR == nullptr || ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR == nullptr)+    {+        ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func("vkCmdBeginRenderingKHR", user_data));+        ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func("vkCmdEndRenderingKHR", user_data));+    }+}+#endif++// If unspecified by user, assume that ApiVersion == HeaderVersion+ // We don't care about other versions than 1.3 for our checks, so don't need to make this exhaustive (e.g. with all #ifdef VK_VERSION_1_X checks)+static uint32_t ImGui_ImplVulkan_GetDefaultApiVersion()+{+#ifdef VK_HEADER_VERSION_COMPLETE+    return VK_HEADER_VERSION_COMPLETE;+#else+    return VK_API_VERSION_1_0;+#endif+}++bool    ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)+{+    // Load function pointers+    // You can use the default Vulkan loader using:+    //      ImGui_ImplVulkan_LoadFunctions(VK_API_VERSION_1_3, [](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });+    // But this would be roughly equivalent to not setting VK_NO_PROTOTYPES.+    if (api_version == 0)+        api_version = ImGui_ImplVulkan_GetDefaultApiVersion();++#ifdef IMGUI_IMPL_VULKAN_USE_LOADER+#define IMGUI_VULKAN_FUNC_LOAD(func) \+    ImGuiImplVulkanFuncs.pfn_##func = reinterpret_cast<PFN_##func>(loader_func(#func, user_data)); \+    if (ImGuiImplVulkanFuncs.pfn_##func == nullptr)   \+        return false;+    IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD)+#undef IMGUI_VULKAN_FUNC_LOAD++#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    ImGui_ImplVulkan_LoadDynamicRenderingFunctions(api_version, loader_func, user_data);+#endif+#else+    IM_UNUSED(loader_func);+    IM_UNUSED(user_data);+#endif++    g_FunctionsLoaded = true;+    return true;+}++bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)+{+    IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");++    if (info->ApiVersion == 0)+        info->ApiVersion = ImGui_ImplVulkan_GetDefaultApiVersion();++    if (info->UseDynamicRendering)+    {+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+#ifndef IMGUI_IMPL_VULKAN_USE_LOADER+        ImGui_ImplVulkan_LoadDynamicRenderingFunctions(info->ApiVersion, [](const char* function_name, void* user_data) { return vkGetDeviceProcAddr((VkDevice)user_data, function_name); }, (void*)info->Device);+#endif+        IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR != nullptr);+        IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR != nullptr);+#else+        IM_ASSERT(0 && "Can't use dynamic rendering when neither VK_VERSION_1_3 or VK_KHR_dynamic_rendering is defined.");+#endif+    }++    ImGuiIO& io = ImGui::GetIO();+    IMGUI_CHECKVERSION();+    IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");++    // Setup backend capabilities flags+    ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)();+    io.BackendRendererUserData = (void*)bd;+    io.BackendRendererName = "imgui_impl_vulkan";+    io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.+    io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;   // We can honor ImGuiPlatformIO::Textures[] requests during render.+    io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports;  // We can create multi-viewports on the Renderer side (optional)++    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();+    platform_io.DrawCallback_ResetRenderState = ImGui_ImplVulkan_DrawCallback_ResetRenderState;+    platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplVulkan_DrawCallback_SetSamplerLinear;+    platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplVulkan_DrawCallback_SetSamplerNearest;++    // Sanity checks+    IM_ASSERT(info->Instance != VK_NULL_HANDLE);+    IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);+    IM_ASSERT(info->Device != VK_NULL_HANDLE);+    IM_ASSERT(info->Queue != VK_NULL_HANDLE);+    IM_ASSERT(info->MinImageCount >= 2);+    IM_ASSERT(info->ImageCount >= info->MinImageCount);+    if (info->DescriptorPool != VK_NULL_HANDLE) // Either DescriptorPool or DescriptorPoolSize must be set, not both!+        IM_ASSERT(info->DescriptorPoolSize == 0);+    else+        IM_ASSERT(info->DescriptorPoolSize > 0);+    if (info->UseDynamicRendering)+        IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE && info->PipelineInfoForViewports.RenderPass == VK_NULL_HANDLE);++    bd->VulkanInitInfo = *info;+#ifdef IMGUI_IMPL_VULKAN_USE_LOADER+    bd->Functions = ImGuiImplVulkanFuncs;+#endif++    VkPhysicalDeviceProperties properties;+    vkGetPhysicalDeviceProperties(info->PhysicalDevice, &properties);+    bd->NonCoherentAtomSize = properties.limits.nonCoherentAtomSize;++    if (!ImGui_ImplVulkan_CreateDeviceObjects())+        IM_ASSERT(0 && "ImGui_ImplVulkan_CreateDeviceObjects() failed!"); // <- Can't be hit yet.++    // Our render function expect RendererUserData to be storing the window render buffer we need (for the main viewport we won't use ->Window)+    ImGuiViewport* main_viewport = ImGui::GetMainViewport();+    main_viewport->RendererUserData = IM_NEW(ImGui_ImplVulkan_ViewportData)();++    ImGui_ImplVulkan_InitMultiViewportSupport();++    return true;+}++void ImGui_ImplVulkan_Shutdown()+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");+    ImGuiIO& io = ImGui::GetIO();+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();++    // First destroy objects in all viewports+    ImGui_ImplVulkan_DestroyDeviceObjects();++    // Manually delete main viewport render data in-case we haven't initialized for viewports+    ImGuiViewport* main_viewport = ImGui::GetMainViewport();+    if (ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)main_viewport->RendererUserData)+        IM_DELETE(vd);+    main_viewport->RendererUserData = nullptr;++    // Clean up windows+    ImGui_ImplVulkan_ShutdownMultiViewportSupport();++    io.BackendRendererName = nullptr;+    io.BackendRendererUserData = nullptr;+    io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports);+    platform_io.ClearRendererHandlers();+    IM_DELETE(bd);+}++void ImGui_ImplVulkan_NewFrame()+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?");+    IM_UNUSED(bd);+}++void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    IM_ASSERT(min_image_count >= 2);+    if (bd->VulkanInitInfo.MinImageCount == min_image_count)+        return;++    IM_ASSERT(0); // FIXME-VIEWPORT: Unsupported. Need to recreate all swap chains!+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkResult err = vkDeviceWaitIdle(v->Device);+    check_vk_result(err);+    ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(v->Device, v->Allocator);++    bd->VulkanInitInfo.MinImageCount = min_image_count;+}++// Register a texture by creating a descriptor+// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem, please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.+VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkDescriptorPool pool = bd->DescriptorPool ? bd->DescriptorPool : v->DescriptorPool;++    // Create Descriptor Set:+    VkDescriptorSet descriptor_set;+    {+        VkDescriptorSetAllocateInfo alloc_info = {};+        alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;+        alloc_info.descriptorPool = pool;+        alloc_info.descriptorSetCount = 1;+        alloc_info.pSetLayouts = &bd->DescriptorSetLayoutTexture;+        VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);+        check_vk_result(err);+    }++    // Update the Descriptor Set:+    if (descriptor_set != VK_NULL_HANDLE)+    {+        VkDescriptorImageInfo desc_image[1] = {};+        desc_image[0].imageView = image_view;+        desc_image[0].imageLayout = image_layout;+        VkWriteDescriptorSet write_desc[1] = {};+        write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;+        write_desc[0].dstSet = descriptor_set;+        write_desc[0].descriptorCount = 1;+        write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;+        write_desc[0].pImageInfo = desc_image;+        vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, nullptr);+    }+    return descriptor_set;+}++#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS+VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)+{+    IM_UNUSED(sampler);+    return ImGui_ImplVulkan_AddTexture(image_view, image_layout);+}+#endif++void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkDescriptorPool pool = bd->DescriptorPool ? bd->DescriptorPool : v->DescriptorPool;+    vkFreeDescriptorSets(v->Device, pool, 1, &descriptor_set);+}++void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator)+{+    if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; }+    if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; }+    if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; }+    if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; }+    buffers->VertexBufferSize = 0;+    buffers->IndexBufferSize = 0;+}++void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator)+{+    for (uint32_t n = 0; n < buffers->Count; n++)+        ImGui_ImplVulkan_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);+    buffers->FrameRenderBuffers.clear();+    buffers->Index = 0;+    buffers->Count = 0;+}++//-------------------------------------------------------------------------+// Internal / Miscellaneous Vulkan Helpers+// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)+//-------------------------------------------------------------------------+// You probably do NOT need to use or care about those functions.+// Those functions only exist because:+//   1) they facilitate the readability and maintenance of the multiple main.cpp examples files.+//   2) the upcoming multi-viewport feature will need them internally.+// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,+// but it is too much code to duplicate everywhere so we exceptionally expose them.+//+// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).+// You may read this code to learn about Vulkan, but it is recommended you use your own custom tailored code to do equivalent work.+// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)+//-------------------------------------------------------------------------++VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)+{+    IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");+    IM_ASSERT(request_formats != nullptr);+    IM_ASSERT(request_formats_count > 0);++    // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation+    // Assuming that the default behavior is without setting this bit, there is no need for separate Swapchain image and image view format+    // Additionally several new color spaces were introduced with Vulkan Spec v1.0.40,+    // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used.+    uint32_t avail_count;+    vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, nullptr);+    ImVector<VkSurfaceFormatKHR> avail_format;+    avail_format.resize((int)avail_count);+    vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, avail_format.Data);++    // First check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available+    if (avail_count == 1)+    {+        if (avail_format[0].format == VK_FORMAT_UNDEFINED)+        {+            VkSurfaceFormatKHR ret;+            ret.format = request_formats[0];+            ret.colorSpace = request_color_space;+            return ret;+        }+        else+        {+            // No point in searching another format+            return avail_format[0];+        }+    }+    else+    {+        // Request several formats, the first found will be used+        for (int request_i = 0; request_i < request_formats_count; request_i++)+            for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)+                if (avail_format[avail_i].format == request_formats[request_i] && avail_format[avail_i].colorSpace == request_color_space)+                    return avail_format[avail_i];++        // If none of the requested image formats could be found, use the first available+        return avail_format[0];+    }+}++VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)+{+    IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");+    IM_ASSERT(request_modes != nullptr);+    IM_ASSERT(request_modes_count > 0);++    // Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory+    uint32_t avail_count = 0;+    vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, nullptr);+    ImVector<VkPresentModeKHR> avail_modes;+    avail_modes.resize((int)avail_count);+    vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, avail_modes.Data);+    //for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)+    //    printf("[vulkan] avail_modes[%d] = %d\n", avail_i, avail_modes[avail_i]);++    for (int request_i = 0; request_i < request_modes_count; request_i++)+        for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)+            if (request_modes[request_i] == avail_modes[avail_i])+                return request_modes[request_i];++    return VK_PRESENT_MODE_FIFO_KHR; // Always available+}++VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance)+{+    uint32_t gpu_count;+    VkResult err = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);+    check_vk_result(err);+    IM_ASSERT(gpu_count > 0);++    ImVector<VkPhysicalDevice> gpus;+    gpus.resize(gpu_count);+    err = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.Data);+    check_vk_result(err);++    // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers+    // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple+    // dedicated GPUs) is out of scope of this sample.+    for (VkPhysicalDevice& device : gpus)+    {+        VkPhysicalDeviceProperties properties;+        vkGetPhysicalDeviceProperties(device, &properties);+        if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)+            return device;+    }++    // Use first GPU (Integrated) is a Discrete one is not available.+    if (gpu_count > 0)+        return gpus[0];+    return VK_NULL_HANDLE;+}+++uint32_t ImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device)+{+    uint32_t count;+    vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, nullptr);+    ImVector<VkQueueFamilyProperties> queues_properties;+    queues_properties.resize((int)count);+    vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queues_properties.Data);+    for (uint32_t i = 0; i < count; i++)+        if (queues_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)+            return i;+    return (uint32_t)-1;+}++void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator)+{+    IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE);+    IM_UNUSED(physical_device);++    // Create Command Buffers+    VkResult err;+    for (uint32_t i = 0; i < wd->ImageCount; i++)+    {+        ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];+        {+            VkCommandPoolCreateInfo info = {};+            info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;+            info.flags = 0;+            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);+        }+    }++    for (uint32_t i = 0; i < wd->SemaphoreCount; i++)+    {+        ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];+        {+            VkSemaphoreCreateInfo info = {};+            info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;+            err = vkCreateSemaphore(device, &info, allocator, &fsd->ImageAcquiredSemaphore);+            check_vk_result(err);+            err = vkCreateSemaphore(device, &info, allocator, &fsd->RenderCompleteSemaphore);+            check_vk_result(err);+        }+    }+}++int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode)+{+    if (present_mode == VK_PRESENT_MODE_MAILBOX_KHR)+        return 3;+    if (present_mode == VK_PRESENT_MODE_FIFO_KHR || present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR)+        return 2;+    if (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)+        return 1;+    IM_ASSERT(0);+    return 1;+}++// Also destroy old swap chain and in-flight frames data, if any.+void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage)+{+    VkResult err;+    VkSwapchainKHR old_swapchain = wd->Swapchain;+    wd->Swapchain = VK_NULL_HANDLE;+    err = vkDeviceWaitIdle(device);+    check_vk_result(err);++    // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.+    // Destroy old Framebuffer+    for (uint32_t i = 0; i < wd->ImageCount; i++)+        ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);+    for (uint32_t i = 0; i < wd->SemaphoreCount; i++)+        ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);+    wd->Frames.clear();+    wd->FrameSemaphores.clear();+    wd->ImageCount = 0;+    if (wd->RenderPass)+        vkDestroyRenderPass(device, wd->RenderPass, allocator);++    // If min image count was not specified, request different count of images dependent on selected present mode+    if (min_image_count == 0)+        min_image_count = ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(wd->PresentMode);++    // Create Swapchain+    {+        VkSurfaceCapabilitiesKHR cap;+        err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);+        check_vk_result(err);++        VkSwapchainCreateInfoKHR info = {};+        info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;+        info.surface = wd->Surface;+        info.minImageCount = min_image_count;+        info.imageFormat = wd->SurfaceFormat.format;+        info.imageColorSpace = wd->SurfaceFormat.colorSpace;+        info.imageArrayLayers = 1;+        info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | image_usage;+        info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;           // Assume that graphics family == present family+        info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform;+        if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)+            info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;+        else if (cap.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)+            info.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;+        else+            IM_ASSERT(false && "No supported composite alpha mode found!");+        info.presentMode = wd->PresentMode;+        info.clipped = VK_TRUE;+        info.oldSwapchain = old_swapchain;+        if (info.minImageCount < cap.minImageCount)+            info.minImageCount = cap.minImageCount;+        else if (cap.maxImageCount != 0 && info.minImageCount > cap.maxImageCount)+            info.minImageCount = cap.maxImageCount;+        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->ImageCount, nullptr);+        check_vk_result(err);+        VkImage backbuffers[16] = {};+        IM_ASSERT(wd->ImageCount >= min_image_count);+        IM_ASSERT(wd->ImageCount < IM_COUNTOF(backbuffers));+        err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);+        check_vk_result(err);++        wd->SemaphoreCount = wd->ImageCount + 1;+        wd->Frames.resize(wd->ImageCount);+        wd->FrameSemaphores.resize(wd->SemaphoreCount);+        memset(wd->Frames.Data, 0, wd->Frames.size_in_bytes());+        memset(wd->FrameSemaphores.Data, 0, wd->FrameSemaphores.size_in_bytes());+        for (uint32_t i = 0; i < wd->ImageCount; i++)+            wd->Frames[i].Backbuffer = backbuffers[i];+    }+    if (old_swapchain)+        vkDestroySwapchainKHR(device, old_swapchain, allocator);++    // Create the Render Pass+    if (wd->UseDynamicRendering == false)+    {+        VkAttachmentDescription attachment = wd->AttachmentDesc;+        if (attachment.format == VK_FORMAT_UNDEFINED)+            attachment.format = wd->SurfaceFormat.format;+        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;+        VkSubpassDependency dependency = {};+        dependency.srcSubpass = VK_SUBPASS_EXTERNAL;+        dependency.dstSubpass = 0;+        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;+        dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;+        dependency.srcAccessMask = 0;+        dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;+        VkRenderPassCreateInfo info = {};+        info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;+        info.attachmentCount = 1;+        info.pAttachments = &attachment;+        info.subpassCount = 1;+        info.pSubpasses = &subpass;+        info.dependencyCount = 1;+        info.pDependencies = &dependency;+        err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass);+        check_vk_result(err);++        // We do not create a pipeline by default as this is also used by examples' main.cpp,+        // but secondary viewport in multi-viewport mode may want to create one with:+        //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, v->Subpass);+    }++    // 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->ImageCount; i++)+        {+            ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];+            info.image = fd->Backbuffer;+            err = vkCreateImageView(device, &info, allocator, &fd->BackbufferView);+            check_vk_result(err);+        }+    }++    // Create Framebuffer+    if (wd->UseDynamicRendering == false)+    {+        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->ImageCount; i++)+        {+            ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];+            attachment[0] = fd->BackbufferView;+            err = vkCreateFramebuffer(device, &info, allocator, &fd->Framebuffer);+            check_vk_result(err);+        }+    }+}++// Create or resize window+// - 2025/09/26: v1.92.4 added a trailing 'VkImageUsageFlags image_usage' parameter which is usually VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.+void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count, VkImageUsageFlags image_usage)+{+    IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");+    IM_ASSERT(wd->Surface != VK_NULL_HANDLE);+    IM_UNUSED(instance);++    ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count, image_usage);+    ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);++    // FIXME: to submit the command buffer, we need a queue. In the examples folder, the ImGui_ImplVulkanH_CreateOrResizeWindow function is called+    // before the ImGui_ImplVulkan_Init function, so we don't have access to the queue yet. Here we have the queue_family that we can use to grab+    // a queue from the device and submit the command buffer. It would be better to have access to the queue as suggested in the FIXME below.+    VkCommandPool command_pool;+    VkCommandPoolCreateInfo pool_info = {};+    pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;+    pool_info.queueFamilyIndex = queue_family;+    VkResult err = vkCreateCommandPool(device, &pool_info, allocator, &command_pool);+    check_vk_result(err);++    VkFenceCreateInfo fence_info = {};+    fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;+    VkFence fence;+    err = vkCreateFence(device, &fence_info, allocator, &fence);+    check_vk_result(err);++    VkCommandBufferAllocateInfo alloc_info = {};+    alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;+    alloc_info.commandPool = command_pool;+    alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;+    alloc_info.commandBufferCount = 1;+    VkCommandBuffer command_buffer;+    err = vkAllocateCommandBuffers(device, &alloc_info, &command_buffer);+    check_vk_result(err);++    VkCommandBufferBeginInfo begin_info = {};+    begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;+    begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;+    err = vkBeginCommandBuffer(command_buffer, &begin_info);+    check_vk_result(err);++    // Transition the images to the correct layout for rendering+    for (uint32_t i = 0; i < wd->ImageCount; i++)+    {+        VkImageMemoryBarrier barrier = {};+        barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;+        barrier.image = wd->Frames[i].Backbuffer;+        barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;+        barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;+        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;+        barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;+        barrier.subresourceRange.levelCount = 1;+        barrier.subresourceRange.layerCount = 1;+        vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);+    }++    err = vkEndCommandBuffer(command_buffer);+    check_vk_result(err);+    VkSubmitInfo submit_info = {};+    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;+    submit_info.commandBufferCount = 1;+    submit_info.pCommandBuffers = &command_buffer;++    VkQueue queue;+    vkGetDeviceQueue(device, queue_family, 0, &queue);+    err = vkQueueSubmit(queue, 1, &submit_info, fence);+    check_vk_result(err);+    err = vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);+    check_vk_result(err);+    err = vkResetFences(device, 1, &fence);+    check_vk_result(err);++    err = vkResetCommandPool(device, command_pool, 0);+    check_vk_result(err);++    // Destroy command buffer and fence and command pool+    vkFreeCommandBuffers(device, command_pool, 1, &command_buffer);+    vkDestroyCommandPool(device, command_pool, allocator);+    vkDestroyFence(device, fence, allocator);+    command_pool = VK_NULL_HANDLE;+    command_buffer = VK_NULL_HANDLE;+    fence = VK_NULL_HANDLE;+    queue = VK_NULL_HANDLE;+}++void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)+{+    IM_UNUSED(instance);+    vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)+    //vkQueueWaitIdle(bd->Queue);++    for (uint32_t i = 0; i < wd->ImageCount; i++)+        ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);+    for (uint32_t i = 0; i < wd->SemaphoreCount; i++)+        ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);+    wd->Frames.clear();+    wd->FrameSemaphores.clear();+    vkDestroyRenderPass(device, wd->RenderPass, allocator);+    vkDestroySwapchainKHR(device, wd->Swapchain, allocator);+    wd->RenderPass = VK_NULL_HANDLE;+    wd->Swapchain = VK_NULL_HANDLE;+    wd->Width = wd->Height = 0;+    wd->FrameIndex = wd->ImageCount = wd->SemaphoreCount = wd->SemaphoreIndex = 0;+    //vkDestroySurfaceKHR(instance, wd->Surface, allocator); // v1.92.6 (~2026-01-16): because wd->Surface is user provided we don't attempt to destroy it ourself.+}++void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)+{+    vkDestroyFence(device, fd->Fence, allocator);+    vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);+    vkDestroyCommandPool(device, fd->CommandPool, allocator);+    fd->Fence = VK_NULL_HANDLE;+    fd->CommandBuffer = VK_NULL_HANDLE;+    fd->CommandPool = VK_NULL_HANDLE;++    vkDestroyImageView(device, fd->BackbufferView, allocator);+    vkDestroyFramebuffer(device, fd->Framebuffer, allocator);+}++void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator)+{+    vkDestroySemaphore(device, fsd->ImageAcquiredSemaphore, allocator);+    vkDestroySemaphore(device, fsd->RenderCompleteSemaphore, allocator);+    fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE;+}++void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers(VkDevice device, const VkAllocationCallbacks* allocator)+{+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();+    for (int n = 0; n < platform_io.Viewports.Size; n++)+        if (ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)platform_io.Viewports[n]->RendererUserData)+            ImGui_ImplVulkan_DestroyWindowRenderBuffers(device, &vd->RenderBuffers, allocator);+}++ImGui_ImplVulkanH_Window* ImGui_ImplVulkanH_GetWindowDataFromViewport(ImGuiViewport* viewport)+{+    ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)viewport->RendererUserData;+    return vd ? &vd->Window : nullptr;+}++//--------------------------------------------------------------------------------------------------------+// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT+// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.+// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..+//--------------------------------------------------------------------------------------------------------++static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_ViewportData* vd = IM_NEW(ImGui_ImplVulkan_ViewportData)();+    ImGui_ImplVulkanH_Window* wd = &vd->Window;+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;++    // Create surface+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();+    VkResult err = (VkResult)platform_io.Platform_CreateVkSurface(viewport, (ImU64)v->Instance, (const void*)v->Allocator, (ImU64*)&wd->Surface);+    check_vk_result(err);+    +    // Check if surface creation failed+    if (err != VK_SUCCESS || wd->Surface == VK_NULL_HANDLE)+    {+        IM_DELETE(vd);+        return;+    }++    // Check for WSI support+    VkBool32 res;+    vkGetPhysicalDeviceSurfaceSupportKHR(v->PhysicalDevice, v->QueueFamily, wd->Surface, &res);+    if (res != VK_TRUE)+    {+        vkDestroySurfaceKHR(v->Instance, wd->Surface, v->Allocator); // Error: no WSI support on physical device, clean up and return+        IM_DELETE(vd);+        return;+    }+    viewport->RendererUserData = vd;++    // Select Surface Format+    ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoForViewports;+    ImVector<VkFormat> requestSurfaceImageFormats;+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    for (uint32_t n = 0; n < pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount; n++)+        requestSurfaceImageFormats.push_back(pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]);+#endif+    const VkFormat defaultFormats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };+    for (VkFormat format : defaultFormats)+        requestSurfaceImageFormats.push_back(format);++    const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;+    wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormats.Data, requestSurfaceImageFormats.Size, requestSurfaceColorSpace);++    // Select Present Mode+    // FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1)+    VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };+    wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(v->PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));+    //printf("[vulkan] Secondary window selected PresentMode = %d\n", wd->PresentMode);++    // Create SwapChain, RenderPass, Framebuffer, etc.+    wd->UseDynamicRendering = v->UseDynamicRendering;+    wd->AttachmentDesc.loadOp = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR;+    ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, pipeline_info->SwapChainImageUsage);+    vd->WindowOwned = true;++    // Create pipeline (shared by all secondary viewports)+    if (bd->PipelineForViewports == VK_NULL_HANDLE)+    {+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+        if (wd->UseDynamicRendering)+        {+            pipeline_info->PipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;+            pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount = 1;+            bd->PipelineRenderingCreateInfoColorAttachmentFormats.resize(1);+            bd->PipelineRenderingCreateInfoColorAttachmentFormats[0] = wd->SurfaceFormat.format;+            pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data;+        }+        else+        {+            pipeline_info->RenderPass = wd->RenderPass;+        }+#endif+        bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports);+    }+}++static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport)+{+    // The main viewport (owned by the application) will always have RendererUserData == 0 since we didn't create the data for it.+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    if (ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)viewport->RendererUserData)+    {+        ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+        if (vd->WindowOwned)+        {+            ImGui_ImplVulkanH_DestroyWindow(v->Instance, v->Device, &vd->Window, v->Allocator);+            vkDestroySurfaceKHR(v->Instance, vd->Window.Surface, v->Allocator);+        }+        ImGui_ImplVulkan_DestroyWindowRenderBuffers(v->Device, &vd->RenderBuffers, v->Allocator);+        IM_DELETE(vd);+    }+    viewport->RendererUserData = nullptr;+}++static void ImGui_ImplVulkan_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)viewport->RendererUserData;+    if (vd == nullptr) // This is nullptr for the main viewport (which is left to the user/app to handle)+        return;+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    ImGui_ImplVulkanH_Window* wd = &vd->Window;+    wd->AttachmentDesc.loadOp = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR;+    ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, &vd->Window, v->QueueFamily, v->Allocator, (int)size.x, (int)size.y, v->MinImageCount, v->PipelineInfoForViewports.SwapChainImageUsage);+}++static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)viewport->RendererUserData;+    if (vd == nullptr)+        return;+    ImGui_ImplVulkanH_Window* wd = &vd->Window;+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;+    VkResult err;++    if (vd->SwapChainNeedRebuild || vd->SwapChainSuboptimal)+    {+        ImGui_ImplVulkanH_CreateOrResizeWindow(v->Instance, v->PhysicalDevice, v->Device, wd, v->QueueFamily, v->Allocator, (int)viewport->Size.x, (int)viewport->Size.y, v->MinImageCount, v->PipelineInfoForViewports.SwapChainImageUsage);+        vd->SwapChainNeedRebuild = vd->SwapChainSuboptimal = false;+    }++    ImGui_ImplVulkanH_Frame* fd = nullptr;+    ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];+    {+        {+            err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex);+            if (err == VK_ERROR_OUT_OF_DATE_KHR)+            {+                vd->SwapChainNeedRebuild = true; // Since we are not going to swap this frame anyway, it's ok that recreation happens on next frame.+                return;+            }+            if (err == VK_SUBOPTIMAL_KHR)+                vd->SwapChainSuboptimal = true;+            else+                check_vk_result(err);+            fd = &wd->Frames[wd->FrameIndex];+        }+        for (;;)+        {+            err = vkWaitForFences(v->Device, 1, &fd->Fence, VK_TRUE, 100);+            if (err == VK_SUCCESS) break;+            if (err == VK_TIMEOUT) continue;+            check_vk_result(err);+        }+        {+            err = vkResetCommandPool(v->Device, fd->CommandPool, 0);+            check_vk_result(err);+            VkCommandBufferBeginInfo info = {};+            info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;+            info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;+            err = vkBeginCommandBuffer(fd->CommandBuffer, &info);+            check_vk_result(err);+        }+        {+            ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);+            memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));+        }+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+        if (v->UseDynamicRendering)+        {+            // Transition swapchain image to a layout suitable for drawing.+            VkImageMemoryBarrier barrier = {};+            barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;+            barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;+            barrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;+            barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;+            barrier.image = fd->Backbuffer;+            barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;+            barrier.subresourceRange.levelCount = 1;+            barrier.subresourceRange.layerCount = 1;+            vkCmdPipelineBarrier(fd->CommandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_NONE, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);++            VkRenderingAttachmentInfo attachmentInfo = {};+            attachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR;+            attachmentInfo.imageView = fd->BackbufferView;+            attachmentInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;+            attachmentInfo.resolveMode = VK_RESOLVE_MODE_NONE;+            attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;+            attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;+            attachmentInfo.clearValue = wd->ClearValue;++            VkRenderingInfo renderingInfo = {};+            renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR;+            renderingInfo.renderArea.extent.width = wd->Width;+            renderingInfo.renderArea.extent.height = wd->Height;+            renderingInfo.layerCount = 1;+            renderingInfo.viewMask = 0;+            renderingInfo.colorAttachmentCount = 1;+            renderingInfo.pColorAttachments = &attachmentInfo;++            ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR(fd->CommandBuffer, &renderingInfo);+        }+        else+#endif+        {+            VkRenderPassBeginInfo info = {};+            info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;+            info.renderPass = wd->RenderPass;+            info.framebuffer = fd->Framebuffer;+            info.renderArea.extent.width = wd->Width;+            info.renderArea.extent.height = wd->Height;+            info.clearValueCount = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? 0 : 1;+            info.pClearValues = (viewport->Flags & ImGuiViewportFlags_NoRendererClear) ? nullptr : &wd->ClearValue;+            vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);+        }+    }++    ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer, bd->PipelineForViewports);++    {+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+        if (v->UseDynamicRendering)+        {+            ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR(fd->CommandBuffer);++            // Transition image to a layout suitable for presentation+            VkImageMemoryBarrier barrier = {};+            barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;+            barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;+            barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;+            barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;+            barrier.image = fd->Backbuffer;+            barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;+            barrier.subresourceRange.levelCount = 1;+            barrier.subresourceRange.layerCount = 1;+            vkCmdPipelineBarrier(fd->CommandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);+        }+        else+#endif+        {+            vkCmdEndRenderPass(fd->CommandBuffer);+        }+        {+            VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;+            VkSubmitInfo info = {};+            info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;+            info.waitSemaphoreCount = 1;+            info.pWaitSemaphores = &fsd->ImageAcquiredSemaphore;+            info.pWaitDstStageMask = &wait_stage;+            info.commandBufferCount = 1;+            info.pCommandBuffers = &fd->CommandBuffer;+            info.signalSemaphoreCount = 1;+            info.pSignalSemaphores = &fsd->RenderCompleteSemaphore;++            err = vkEndCommandBuffer(fd->CommandBuffer);+            check_vk_result(err);+            err = vkResetFences(v->Device, 1, &fd->Fence);+            check_vk_result(err);+            err = vkQueueSubmit(v->Queue, 1, &info, fd->Fence);+            check_vk_result(err);+        }+    }+}++static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport, void*)+{+    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();+    ImGui_ImplVulkan_ViewportData* vd = (ImGui_ImplVulkan_ViewportData*)viewport->RendererUserData;+    if (vd == nullptr)+        return;+    ImGui_ImplVulkanH_Window* wd = &vd->Window;+    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;++    if (vd->SwapChainNeedRebuild) // Frame data became invalid in the middle of rendering+        return;++    VkResult err;+    uint32_t present_index = wd->FrameIndex;++    ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[wd->SemaphoreIndex];+    VkPresentInfoKHR info = {};+    info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;+    info.waitSemaphoreCount = 1;+    info.pWaitSemaphores = &fsd->RenderCompleteSemaphore;+    info.swapchainCount = 1;+    info.pSwapchains = &wd->Swapchain;+    info.pImageIndices = &present_index;+    err = vkQueuePresentKHR(v->Queue, &info);+    if (err == VK_ERROR_OUT_OF_DATE_KHR)+    {+        vd->SwapChainNeedRebuild = true;+        return;+    }+    if (err == VK_SUBOPTIMAL_KHR)+        vd->SwapChainSuboptimal = true;+    else+        check_vk_result(err);+    wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores+}++void ImGui_ImplVulkan_InitMultiViewportSupport()+{+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();+    if (ImGui::GetIO().BackendFlags & ImGuiBackendFlags_PlatformHasViewports)+        IM_ASSERT(platform_io.Platform_CreateVkSurface != nullptr && "Platform needs to setup the CreateVkSurface handler.");+    platform_io.Renderer_CreateWindow = ImGui_ImplVulkan_CreateWindow;+    platform_io.Renderer_DestroyWindow = ImGui_ImplVulkan_DestroyWindow;+    platform_io.Renderer_SetWindowSize = ImGui_ImplVulkan_SetWindowSize;+    platform_io.Renderer_RenderWindow = ImGui_ImplVulkan_RenderWindow;+    platform_io.Renderer_SwapBuffers = ImGui_ImplVulkan_SwapBuffers;+}++void ImGui_ImplVulkan_ShutdownMultiViewportSupport()+{+    ImGui::DestroyPlatformWindows();+}++//-----------------------------------------------------------------------------++#endif // #ifndef IMGUI_DISABLE
+ cbits/imgui_impl_vulkan.h view
@@ -0,0 +1,289 @@+// dear imgui: Renderer Backend for Vulkan+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)++// Implemented features:+//  [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).+//  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplVulkan_GetRenderState().+//  [x] Renderer: Multi-viewport / platform windows. With issues (flickering when creating a new viewport).++// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.+// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/++// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.+// Learn about Dear ImGui:+// - FAQ                  https://dearimgui.com/faq+// - Getting Started      https://dearimgui.com/getting-started+// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).+// - Introduction, links and more at the top of imgui.cpp++// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.+//   You will use those if you want to use this rendering backend in your engine/app.+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by+//   the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.+// Read comments in imgui_impl_vulkan.h.++#pragma once+#ifndef IMGUI_DISABLE+#include "imgui.h"      // IMGUI_IMPL_API++// [Configuration] in order to use a custom Vulkan function loader:+// (1) You'll need to disable default Vulkan function prototypes.+//     We provide a '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' convenience configuration flag.+//     In order to make sure this is visible from the imgui_impl_vulkan.cpp compilation unit:+//     - Add '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' in your imconfig.h file+//     - Or as a compilation flag in your build system+//     - Or uncomment here (not recommended because you'd be modifying imgui sources!)+//     - Do not simply add it in a .cpp file!+// (2) Call ImGui_ImplVulkan_LoadFunctions() before ImGui_ImplVulkan_Init() with your custom function.+// If you have no idea what this is, leave it alone!+//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES++// [Configuration] Convenience support for Volk+// (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)+// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header,+//  for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)')+//#define IMGUI_IMPL_VULKAN_USE_VOLK+//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME    <Volk/volk.h>+//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME    <volk.h>       // Default+// Reminder: make those changes in your imconfig.h file, not here!++// Clang/GCC warnings with -Weverything+#if defined(__clang__)+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast+#endif++#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)+#define VK_NO_PROTOTYPES+#endif+#if defined(VK_USE_PLATFORM_WIN32_KHR) && !defined(NOMINMAX)+#define NOMINMAX+#endif++// Vulkan includes+#ifdef IMGUI_IMPL_VULKAN_USE_VOLK+#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME+#include IMGUI_IMPL_VULKAN_VOLK_FILENAME+#else+#include <volk.h>+#endif+#else+#include <vulkan/vulkan.h>+#endif+#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering)+#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+#endif++// Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().+#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE   (8)     // Minimum per atlas+#define IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE         (2)     // Minimum for linear + nearest++// Specify settings to create pipeline and swapchain+struct ImGui_ImplVulkan_PipelineInfo+{+    // For Main viewport only+    VkRenderPass                    RenderPass;                     // Ignored if using dynamic rendering++    // For Main and Secondary viewports+    uint32_t                        Subpass;                        //+    VkSampleCountFlagBits           MSAASamples = {};               // 0 defaults to VK_SAMPLE_COUNT_1_BIT+    ImVector<VkDynamicState>        ExtraDynamicStates;             // Optional, allows to insert more dynamic states into our VkPipeline+#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING+    VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo;   // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR+#endif++    // For Secondary viewports only (created/managed by backend)+    VkImageUsageFlags               SwapChainImageUsage;            // Extra flags for vkCreateSwapchainKHR() calls for secondary viewports. We automatically add VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. You can add e.g. VK_IMAGE_USAGE_TRANSFER_SRC_BIT if you need to capture from viewports.+};++// Initialization data, for ImGui_ImplVulkan_Init()+// [Please zero-clear before use!]+// - About descriptor pool:+//   - A VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,+//     and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.+//   - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.+// - About dynamic rendering:+//   - When using dynamic rendering, set UseDynamicRendering=true + fill PipelineInfoMain.PipelineRenderingCreateInfo structure.+//   - PipelineRenderingCreateInfo may describe multiple color attachments: we render to the first one and leave the others untouched. This requires the 'independentBlend' device feature.+struct ImGui_ImplVulkan_InitInfo+{+    uint32_t                        ApiVersion;                 // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)+    VkInstance                      Instance;+    VkPhysicalDevice                PhysicalDevice;+    VkDevice                        Device;+    uint32_t                        QueueFamily;+    VkQueue                         Queue;+    VkDescriptorPool                DescriptorPool;             // See requirements in note above; ignored if using DescriptorPoolSize > 0+    uint32_t                        DescriptorPoolSize;         // Optional: set to create internal ImageView descriptor pool automatically instead of using DescriptorPool.+    uint32_t                        MinImageCount;              // >= 2+    uint32_t                        ImageCount;                 // >= MinImageCount+    VkPipelineCache                 PipelineCache;              // Optional++    // Pipeline+    ImGui_ImplVulkan_PipelineInfo   PipelineInfoMain;           // Infos for Main Viewport (created by app/user)+    ImGui_ImplVulkan_PipelineInfo   PipelineInfoForViewports;   // Infos for Secondary Viewports (created by backend)+    //VkRenderPass                  RenderPass;                 // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead+    //uint32_t                      Subpass;                    // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead+    //VkSampleCountFlagBits         MSAASamples;                // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead+    //VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead++    // (Optional) Dynamic Rendering+    // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo and PipelineInfoViewports.PipelineRenderingCreateInfo.+    bool                            UseDynamicRendering;++    // (Optional) Allocation, Debugging+    const VkAllocationCallbacks*    Allocator;+    void                            (*CheckVkResultFn)(VkResult err);+    VkDeviceSize                    MinAllocationSize;          // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory.++    // (Optional) Customize default vertex/fragment shaders.+    // - if .sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO we use specified structs, otherwise we use defaults.+    // - Shader inputs/outputs need to match ours. Code/data pointed to by the structure needs to survive for whole during of backend usage.+    VkShaderModuleCreateInfo        CustomShaderVertCreateInfo;+    VkShaderModuleCreateInfo        CustomShaderFragCreateInfo;+};++// Follow "Getting Started" link and check examples/ folder to learn about using backends!+IMGUI_IMPL_API bool             ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info);+IMGUI_IMPL_API void             ImGui_ImplVulkan_Shutdown();+IMGUI_IMPL_API void             ImGui_ImplVulkan_NewFrame();+IMGUI_IMPL_API void             ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);+IMGUI_IMPL_API void             ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)++// (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111)+// The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR))+// Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering.+IMGUI_IMPL_API void             ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info);++// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.+IMGUI_IMPL_API void             ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex);++// Register a texture (VkDescriptorSet for a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE == ImTextureID)+IMGUI_IMPL_API VkDescriptorSet  ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout);+IMGUI_IMPL_API void             ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);++#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS+IMGUI_IMPL_API VkDescriptorSet  ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout); // Ignore VkSampler+#endif++// Optional: load Vulkan functions with a custom function loader+// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES+IMGUI_IMPL_API bool             ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);++// [BETA] Selected render state data shared with callbacks.+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.+//      ImGui_ImplVulkan_RenderState* render_state = (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;+// (Please open an issue if you feel you need access to more data)+struct ImGui_ImplVulkan_RenderState+{+    VkCommandBuffer     CommandBuffer;+    VkPipeline          Pipeline;+    VkPipelineLayout    PipelineLayout;+};+IMGUI_IMPL_API ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState();++//-------------------------------------------------------------------------+// Internal / Miscellaneous Vulkan Helpers+//-------------------------------------------------------------------------+// Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.+//+// You probably do NOT need to use or care about those functions.+// WE DO NOT PROVIDE STRONG GUARANTEES OF BACKWARD/FORWARD COMPATIBILITY.+// Those functions only exist because:+//   1) they facilitate the readability and maintenance of the multiple main.cpp examples files.+//   2) the multi-viewport / platform window implementation needs them internally.+// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,+// but it is too much code to duplicate everywhere so we exceptionally expose them.+//+// Your engine/app will likely _already_ have code to setup all that stuff (swap chain,+// render pass, frame buffers, etc.). You may read this code if you are curious, but+// it is recommended you use your own custom tailored code to do equivalent work.+//+// The ImGui_ImplVulkanH_XXX functions should NOT interact with any of the state used+// by the regular ImGui_ImplVulkan_XXX functions.+//-------------------------------------------------------------------------++struct ImGui_ImplVulkanH_Frame;+struct ImGui_ImplVulkanH_Window;++// Helpers+IMGUI_IMPL_API void                 ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage);+IMGUI_IMPL_API void                 ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator);+IMGUI_IMPL_API VkSurfaceFormatKHR   ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);+IMGUI_IMPL_API VkPresentModeKHR     ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);+IMGUI_IMPL_API VkPhysicalDevice     ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance);+IMGUI_IMPL_API uint32_t             ImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device);+IMGUI_IMPL_API int                  ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);+IMGUI_IMPL_API ImGui_ImplVulkanH_Window* ImGui_ImplVulkanH_GetWindowDataFromViewport(ImGuiViewport* viewport); // Access to Vulkan objects associated with a viewport (e.g to export a screenshot)++// Helper structure to hold the data needed by one rendering frame+// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)+// [Please zero-clear before use!]+struct ImGui_ImplVulkanH_Frame+{+    VkCommandPool       CommandPool;+    VkCommandBuffer     CommandBuffer;+    VkFence             Fence;+    VkImage             Backbuffer;+    VkImageView         BackbufferView;+    VkFramebuffer       Framebuffer;+};++struct ImGui_ImplVulkanH_FrameSemaphores+{+    VkSemaphore         ImageAcquiredSemaphore;+    VkSemaphore         RenderCompleteSemaphore;+};++// Helper structure to hold the data needed by one rendering context into one OS window+// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)+struct ImGui_ImplVulkanH_Window+{+    // Input+    bool                    UseDynamicRendering;+    VkSurfaceKHR            Surface;            // Surface created and destroyed by caller.+    VkSurfaceFormatKHR      SurfaceFormat;+    VkPresentModeKHR        PresentMode;+    VkAttachmentDescription AttachmentDesc;     // RenderPass creation: main attachment description.+    VkClearValue            ClearValue;         // RenderPass creation: clear value when using VK_ATTACHMENT_LOAD_OP_CLEAR.++    // Internal+    int                     Width;              // Generally same as passed to ImGui_ImplVulkanH_CreateOrResizeWindow()+    int                     Height;+    VkSwapchainKHR          Swapchain;+    VkRenderPass            RenderPass;+    uint32_t                FrameIndex;         // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)+    uint32_t                ImageCount;         // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)+    uint32_t                SemaphoreCount;     // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR+    uint32_t                SemaphoreIndex;     // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)+    ImVector<ImGui_ImplVulkanH_Frame>           Frames;+    ImVector<ImGui_ImplVulkanH_FrameSemaphores> FrameSemaphores;++    ImGui_ImplVulkanH_Window()+    {+        memset((void*)this, 0, sizeof(*this));++        // Parameters to create SwapChain+        PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;     // Ensure we get an error if user doesn't set this.++        // Parameters to create RenderPass+        AttachmentDesc.format = VK_FORMAT_UNDEFINED;    // Will automatically use wd->SurfaceFormat.format.+        AttachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;+        AttachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;+        AttachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;+        AttachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;+        AttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;+        AttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;+        AttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;+    }+};++#if defined(__clang__)+#pragma clang diagnostic pop+#endif++#endif // #ifndef IMGUI_DISABLE
+ dear-imgui-impl-vulkan.cabal view
@@ -0,0 +1,60 @@+cabal-version: 2.2++-- This file has been generated from package.yaml by hpack version 0.39.6.+--+-- see: https://github.com/sol/hpack++name:           dear-imgui-impl-vulkan+version:        1.0.0+synopsis:       Vulkan backend bindings for dear-imgui-raw.+description:    Generated with dear_bindings from the imgui_impl_vulkan backend that ships with Dear ImGui.+category:       GUI+maintainer:     IC Rainbow <aenor.realm@gmail.com>+license:        BSD-3-Clause+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    cbits/dcimgui_impl_vulkan.h+    cbits/DearImGuiWrappers.h+    cbits/imgui_impl_vulkan.h+extra-doc-files:+    README.md+    CHANGELOG.md++library+  exposed-modules:+      DearImGui.Impl.Vulkan+      DearImGui.Raw.Impl.Vulkan+  other-modules:+      Paths_dear_imgui_impl_vulkan+  autogen-modules:+      Paths_dear_imgui_impl_vulkan+  hs-source-dirs:+      src+  default-extensions:+      BlockArguments+      DataKinds+      DuplicateRecordFields+      LambdaCase+      NoFieldSelectors+      OverloadedRecordDot+      OverloadedStrings+      StrictData+  ghc-options: -Wall -optc-Wno-discarded-qualifiers -optc-Wno-incompatible-pointer-types -optc-Wno-int-conversion+  cxx-options: -std=c++11 -fpermissive+  include-dirs:+      cbits+  cxx-sources:+      cbits/dcimgui_impl_vulkan.cpp+      cbits/DearImGuiWrappers.cpp+      cbits/DearImGuiCtors.cpp+      cbits/imgui_impl_vulkan.cpp+  build-tool-depends:+      hsc2hs:hsc2hs+  build-depends:+      base >=4.16 && <5+    , dear-imgui-raw ==1.0.*+    , resourcet+    , vector+    , vulkan+  default-language: GHC2021
+ src/DearImGui/Impl/Vulkan.hsc view
@@ -0,0 +1,215 @@+{-# LANGUAGE CApiFFI #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PatternSynonyms #-}++{- | Convenience helpers for the standard imgui Vulkan-backend init dance.++The C-side @ImGui_ImplVulkan_InitInfo@ struct is mostly default-zero; this+module @allocaBytes@'s it, zeroes it, pokes only the app-supplied 'InitArgs'+fields (the way a C app does @info.Instance = ...; ...; Init(&info)@) and+calls @ImGui_ImplVulkan_Init@. The descriptor pool layout dear-imgui-vulkan+expects is also boilerplate, so 'mkDescriptorPool' supplies it; 'withBackend'+composes the two for the common one-shot case.++The main pipeline renders either into a classic 'RenderPassTarget' or, with+'DynamicRenderingTarget', straight into a colour attachment of the given format+(@VK_KHR_dynamic_rendering@ / Vulkan 1.3). The backend resolves+@vkCmdBeginRendering@ itself through @vkGetDeviceProcAddr@, so no+@LoadFunctions@ call is needed for either target.++Caller still invokes 'ImplVulkan.shutdown' manually before destroying the+imgui context — shutdown order is context-dependent and can't auto-wire+into the resource region.+-}+module DearImGui.Impl.Vulkan+  ( InitArgs (..)+  , Target (..)+  , init+  , withBackend+  , mkDescriptorPool+  , surfaceFormatPreference+  , ensureDrawableMatchesSwapchain+  , ImplVulkan.addTexture+  , ImplVulkan.newFrame+  , ImplVulkan.removeTexture+  , ImplVulkan.renderDrawData+  , ImplVulkan.setMinImageCount+  , ImplVulkan.shutdown+  , ImplVulkan.updateTexture+  ) where++import Prelude hiding (init)++import Control.Exception (throwIO)+import Control.Monad (unless)+import Control.Monad.IO.Class (MonadIO, liftIO)+import Control.Monad.Trans.Resource (MonadResource, allocate)+import Data.Vector qualified as V+import Data.Word (Word32)+import Foreign.C.Types (CBool (..))+import Foreign.Marshal.Alloc (allocaBytes)+import Foreign.Marshal.Utils (fillBytes, fromBool, toBool)+import Foreign.Ptr (Ptr, castPtr, plusPtr)+import Foreign.Storable (pokeByteOff)+import Vulkan.CStruct (ToCStruct (..))+import Vulkan.Core10+import Vulkan.Core13 (PipelineRenderingCreateInfo (..))+import Vulkan.Exception (VulkanException (..))+import Vulkan.Extensions.VK_KHR_surface (SurfaceFormatKHR (..), pattern COLOR_SPACE_SRGB_NONLINEAR_KHR)+import Vulkan.Zero (zero)++import DearImGui.Impl.Init (InitFailed (..))+import DearImGui.Raw.Impl.Vulkan (ImGui_ImplVulkan_PipelineInfo)+import DearImGui.Raw.Impl.Vulkan qualified as ImplVulkan++#include "dcimgui_impl_vulkan.h"++-- | App-supplied slice of @ImGui_ImplVulkan_InitInfo@; everything else+-- stays default-zero.+data InitArgs = InitArgs+  { apiVersion :: Word32+  , inst :: Instance+  , physicalDevice :: PhysicalDevice+  , device :: Device+  , queueFamily :: Word32+  , queue :: Queue+  , imageCount :: Word32+  -- ^ Used for both min and current image count+  , target :: Target+  , msaaSamples :: SampleCountFlagBits+  -- ^ Rasterization sample count for the main pipeline. Only the main+  -- pipeline honours this — secondary viewports render into a+  -- single-sample render pass the backend creates for itself, so their+  -- pipeline is always kept at 'SAMPLE_COUNT_1_BIT' regardless of this+  -- setting.+  }++-- | Where the backend's main pipeline renders.+data Target+  = RenderPassTarget RenderPass Word32+  -- ^ Render pass and the subpass index the main pipeline renders into+  | DynamicRenderingTarget Format+  -- ^ Colour attachment format handed to @vkCmdBeginRendering@++{- | One-shot @ImGui_ImplVulkan_Init@ for the common case: one queue+family, one 'Target' shared between main and secondary viewports, no+custom shaders.++Must run AFTER 'imGui_CreateContext' and the platform-side+@InitForVulkan@. Throws 'InitFailed' if the C call returns false.+-}+init :: DescriptorPool -> InitArgs -> IO ()+init pool args =+  allocaBytes #{size ImGui_ImplVulkan_InitInfo} \p -> do+    fillBytes p 0 #{size ImGui_ImplVulkan_InitInfo}+    #{poke ImGui_ImplVulkan_InitInfo, ApiVersion}     p args.apiVersion+    #{poke ImGui_ImplVulkan_InitInfo, Instance}       p (instanceHandle args.inst)+    #{poke ImGui_ImplVulkan_InitInfo, PhysicalDevice} p (physicalDeviceHandle args.physicalDevice)+    #{poke ImGui_ImplVulkan_InitInfo, Device}         p (deviceHandle args.device)+    #{poke ImGui_ImplVulkan_InitInfo, QueueFamily}    p args.queueFamily+    #{poke ImGui_ImplVulkan_InitInfo, Queue}          p (queueHandle args.queue)+    #{poke ImGui_ImplVulkan_InitInfo, DescriptorPool} p pool+    #{poke ImGui_ImplVulkan_InitInfo, MinImageCount}  p args.imageCount+    #{poke ImGui_ImplVulkan_InitInfo, ImageCount}     p args.imageCount+    #{poke ImGui_ImplVulkan_InitInfo, UseDynamicRendering} p (fromBool dynamic :: CBool)+    pokePipelineInfo (p `plusPtr` #{offset ImGui_ImplVulkan_InitInfo, PipelineInfoMain}) mainSubpass args.msaaSamples args.target $+      pokePipelineInfo (p `plusPtr` #{offset ImGui_ImplVulkan_InitInfo, PipelineInfoForViewports}) 0 SAMPLE_COUNT_1_BIT args.target do+        ok <- ImplVulkan.init (castPtr p)+        unless (toBool ok) (throwIO (InitFailed "ImGui_ImplVulkan_Init"))+  where+    dynamic = case args.target of+      RenderPassTarget _ _ -> False+      DynamicRenderingTarget _ -> True+    mainSubpass = case args.target of+      RenderPassTarget _ subpass -> subpass+      DynamicRenderingTarget _ -> 0++pokePipelineInfo :: Ptr ImGui_ImplVulkan_PipelineInfo -> Word32 -> SampleCountFlagBits -> Target -> IO a -> IO a+pokePipelineInfo p subpass samples target continue = do+  #{poke ImGui_ImplVulkan_PipelineInfo, SwapChainImageUsage} p IMAGE_USAGE_COLOR_ATTACHMENT_BIT+  #{poke ImGui_ImplVulkan_PipelineInfo, MSAASamples} p samples+  case target of+    RenderPassTarget rp _ -> do+      #{poke ImGui_ImplVulkan_PipelineInfo, RenderPass} p rp+      #{poke ImGui_ImplVulkan_PipelineInfo, Subpass} p subpass+      continue+    DynamicRenderingTarget format ->+      pokeCStruct+        (p `plusPtr` #{offset ImGui_ImplVulkan_PipelineInfo, PipelineRenderingCreateInfo})+        (zero { colorAttachmentFormats = V.singleton format } :: PipelineRenderingCreateInfo)+        continue++{- | 'mkDescriptorPool' + 'init' composed: allocates the standard pool in+the caller's 'ResourceT' scope, then runs the init for the common+single-target setup. Returns the pool in case the caller wants to+do their own 'ImplVulkan.addTexture' bookkeeping against it.+-}+withBackend+  :: (MonadResource m, MonadIO m)+  => Word32+  -- ^ Extra sampled-image sets beyond the font atlas minimum, for+  -- 'ImplVulkan.addTexture' textures; sizes the pool+  -> InitArgs+  -> m DescriptorPool+withBackend extraTextures args = do+  pool <- mkDescriptorPool args.device extraTextures+  liftIO $ init pool args+  pure pool++{- | Allocate the standard descriptor pool dear-imgui-vulkan needs,+mirroring the backend's own layout: sampled-image slots for the font+atlas(es) plus @extraSets@ for any 'ImplVulkan.addTexture' textures the+app binds, and the backend's fixed linear/nearest samplers. Pool is+freed when the caller's 'ResourceT' scope exits — make sure that scope+tears down AFTER 'ImplVulkan.shutdown'.+-}+mkDescriptorPool+  :: (MonadResource m)+  => Device+  -> Word32+  -- ^ Extra sets beyond the font atlas minimum+  -> m DescriptorPool+mkDescriptorPool dev extra = do+  let+    images = #{const IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE} + extra+    samplers = #{const IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE}+    poolCI :: DescriptorPoolCreateInfo '[]+    poolCI = zero+      { flags = DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT+      , maxSets = images + samplers+      , poolSizes = V.fromList+          [ zero { type' = DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount = images }+          , zero { type' = DESCRIPTOR_TYPE_SAMPLER, descriptorCount = samplers }+          ]+      }+  snd <$> withDescriptorPool dev poolCI Nothing allocate++{- | Surface-format predicate for the swapchain imgui renders into: a UNORM+format in the sRGB colorspace. imgui ships sRGB-encoded vertex colors, so an+@*_SRGB@ surface format would re-encode them and wash out the UI. Matches the+formats the backend's own @ImGui_ImplVulkanH_SelectSurfaceFormat@ requests.+-}+surfaceFormatPreference :: SurfaceFormatKHR -> Bool+surfaceFormatPreference sf =+  sf.colorSpace == COLOR_SPACE_SRGB_NONLINEAR_KHR && sf.format `elem` unormFormats+  where+    unormFormats =+      [ FORMAT_B8G8R8A8_UNORM+      , FORMAT_R8G8B8A8_UNORM+      , FORMAT_B8G8R8_UNORM+      , FORMAT_R8G8B8_UNORM+      ]++{- | Throw @ERROR_OUT_OF_DATE_KHR@ when the drawable size no longer matches+the swapchain extent, forcing a swapchain rebuild before imgui renders.+@RenderDrawData@ sets the viewport from imgui's own DisplaySize ×+FramebufferScale — the live framebuffer in physical pixels — so rendering+into a pre-resize swapchain image clips the UI and the compositor then+stretches the result. Some drivers don't reliably surface+SUBOPTIMAL\/OUT_OF_DATE on resize, so the post-present signal alone can't be+relied on.+-}+ensureDrawableMatchesSwapchain :: Extent2D -> Extent2D -> IO ()+ensureDrawableMatchesSwapchain drawable swapchainExtent =+  unless (drawable == swapchainExtent) $+    throwIO (VulkanException ERROR_OUT_OF_DATE_KHR)
+ src/DearImGui/Raw/Impl/Vulkan.hsc view
@@ -0,0 +1,388 @@+{-# LANGUAGE CApiFFI #-}+{-# LANGUAGE PatternSynonyms #-}++-- This file was generated by dear-bindings-ffi. Do not edit by hand.++module DearImGui.Raw.Impl.Vulkan+  ( ImGui_ImplVulkan_InitInfo (..)+  , ImGui_ImplVulkan_PipelineInfo (..)+  , ImGui_ImplVulkan_RenderState (..)+  , VkAllocationCallbacks+  , VkPipelineRenderingCreateInfoKHR (..)+  , VkShaderModuleCreateInfo (..)+  , addTexture+  , createMainPipeline+  , destroyImGui_ImplVulkan_InitInfo+  , destroyImGui_ImplVulkan_PipelineInfo+  , destroyImGui_ImplVulkan_RenderState+  , getRenderState+  , init+  , initImGui_ImplVulkan_InitInfo+  , initImGui_ImplVulkan_PipelineInfo+  , initImGui_ImplVulkan_RenderState+  , loadFunctions+  , newFrame+  , pattern IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE+  , pattern IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE+  , removeTexture+  , renderDrawData+  , setMinImageCount+  , shutdown+  , updateTexture+  , withDefaultImGui_ImplVulkan_InitInfo+  , withDefaultImGui_ImplVulkan_PipelineInfo+  , withDefaultImGui_ImplVulkan_RenderState+  , zeroVkPipelineRenderingCreateInfoKHR+  , zeroVkShaderModuleCreateInfo+  ) where++import Control.Exception (bracket_)+import Data.Word (Word32, Word8)+import DearImGui.Raw.ImDrawData (ImDrawData)+import DearImGui.Raw.ImTextureData (ImTextureData)+import DearImGui.Raw.ImVector (ImVector)+import Foreign.C.String (CString)+import Foreign.C.Types+import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrBytes, withForeignPtr)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Marshal.Utils (copyBytes, fillBytes)+import Foreign.Ptr (FunPtr, Ptr, castPtr, plusPtr)+import Foreign.Storable (Storable (..))+import GHC.Records (HasField (..))+import Prelude hiding (init)+import Vulkan.Core10+import Vulkan.Core10.Handles+import Vulkan.Extensions++#include "dcimgui_impl_vulkan.h"++-- structs (opaque)++data {-# CTYPE "dcimgui_impl_vulkan.h" "ImGui_ImplVulkan_InitInfo" #-} ImGui_ImplVulkan_InitInfo = ImGui_ImplVulkan_InitInfo+  { apiVersion :: Word32+  , instance_ :: Ptr Instance_T+  , physicalDevice :: Ptr PhysicalDevice_T+  , device :: Ptr Device_T+  , queueFamily :: Word32+  , queue :: Ptr Queue_T+  , descriptorPool :: DescriptorPool+  , descriptorPoolSize :: Word32+  , minImageCount :: Word32+  , imageCount :: Word32+  , pipelineCache :: PipelineCache+  , pipelineInfoMain :: ImGui_ImplVulkan_PipelineInfo+  , pipelineInfoForViewports :: ImGui_ImplVulkan_PipelineInfo+  , useDynamicRendering :: CBool+  , allocator :: Ptr VkAllocationCallbacks+  , checkVkResultFn :: FunPtr (Result -> IO ())+  , minAllocationSize :: DeviceSize+  , customShaderVertCreateInfo :: VkShaderModuleCreateInfo+  , customShaderFragCreateInfo :: VkShaderModuleCreateInfo+  }+  deriving (Eq, Show)+instance Storable ImGui_ImplVulkan_InitInfo where+  sizeOf _    = #{size ImGui_ImplVulkan_InitInfo}+  alignment _ = #{alignment ImGui_ImplVulkan_InitInfo}+  peek p = ImGui_ImplVulkan_InitInfo <$> #{peek ImGui_ImplVulkan_InitInfo, ApiVersion} p <*> #{peek ImGui_ImplVulkan_InitInfo, Instance} p <*> #{peek ImGui_ImplVulkan_InitInfo, PhysicalDevice} p <*> #{peek ImGui_ImplVulkan_InitInfo, Device} p <*> #{peek ImGui_ImplVulkan_InitInfo, QueueFamily} p <*> #{peek ImGui_ImplVulkan_InitInfo, Queue} p <*> #{peek ImGui_ImplVulkan_InitInfo, DescriptorPool} p <*> #{peek ImGui_ImplVulkan_InitInfo, DescriptorPoolSize} p <*> #{peek ImGui_ImplVulkan_InitInfo, MinImageCount} p <*> #{peek ImGui_ImplVulkan_InitInfo, ImageCount} p <*> #{peek ImGui_ImplVulkan_InitInfo, PipelineCache} p <*> #{peek ImGui_ImplVulkan_InitInfo, PipelineInfoMain} p <*> #{peek ImGui_ImplVulkan_InitInfo, PipelineInfoForViewports} p <*> #{peek ImGui_ImplVulkan_InitInfo, UseDynamicRendering} p <*> #{peek ImGui_ImplVulkan_InitInfo, Allocator} p <*> #{peek ImGui_ImplVulkan_InitInfo, CheckVkResultFn} p <*> #{peek ImGui_ImplVulkan_InitInfo, MinAllocationSize} p <*> #{peek ImGui_ImplVulkan_InitInfo, CustomShaderVertCreateInfo} p <*> #{peek ImGui_ImplVulkan_InitInfo, CustomShaderFragCreateInfo} p+  poke p v = do+    #{poke ImGui_ImplVulkan_InitInfo, ApiVersion} p v.apiVersion+    #{poke ImGui_ImplVulkan_InitInfo, Instance} p v.instance_+    #{poke ImGui_ImplVulkan_InitInfo, PhysicalDevice} p v.physicalDevice+    #{poke ImGui_ImplVulkan_InitInfo, Device} p v.device+    #{poke ImGui_ImplVulkan_InitInfo, QueueFamily} p v.queueFamily+    #{poke ImGui_ImplVulkan_InitInfo, Queue} p v.queue+    #{poke ImGui_ImplVulkan_InitInfo, DescriptorPool} p v.descriptorPool+    #{poke ImGui_ImplVulkan_InitInfo, DescriptorPoolSize} p v.descriptorPoolSize+    #{poke ImGui_ImplVulkan_InitInfo, MinImageCount} p v.minImageCount+    #{poke ImGui_ImplVulkan_InitInfo, ImageCount} p v.imageCount+    #{poke ImGui_ImplVulkan_InitInfo, PipelineCache} p v.pipelineCache+    #{poke ImGui_ImplVulkan_InitInfo, PipelineInfoMain} p v.pipelineInfoMain+    #{poke ImGui_ImplVulkan_InitInfo, PipelineInfoForViewports} p v.pipelineInfoForViewports+    #{poke ImGui_ImplVulkan_InitInfo, UseDynamicRendering} p v.useDynamicRendering+    #{poke ImGui_ImplVulkan_InitInfo, Allocator} p v.allocator+    #{poke ImGui_ImplVulkan_InitInfo, CheckVkResultFn} p v.checkVkResultFn+    #{poke ImGui_ImplVulkan_InitInfo, MinAllocationSize} p v.minAllocationSize+    #{poke ImGui_ImplVulkan_InitInfo, CustomShaderVertCreateInfo} p v.customShaderVertCreateInfo+    #{poke ImGui_ImplVulkan_InitInfo, CustomShaderFragCreateInfo} p v.customShaderFragCreateInfo++instance HasField "apiVersion" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr Word32) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, ApiVersion}++instance HasField "instance_" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr (Ptr Instance_T)) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, Instance}++instance HasField "physicalDevice" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr (Ptr PhysicalDevice_T)) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, PhysicalDevice}++instance HasField "device" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr (Ptr Device_T)) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, Device}++instance HasField "queueFamily" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr Word32) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, QueueFamily}++instance HasField "queue" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr (Ptr Queue_T)) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, Queue}++instance HasField "descriptorPool" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr DescriptorPool) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, DescriptorPool}++instance HasField "descriptorPoolSize" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr Word32) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, DescriptorPoolSize}++instance HasField "minImageCount" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr Word32) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, MinImageCount}++instance HasField "imageCount" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr Word32) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, ImageCount}++instance HasField "pipelineCache" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr PipelineCache) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, PipelineCache}++instance HasField "pipelineInfoMain" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr ImGui_ImplVulkan_PipelineInfo) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, PipelineInfoMain}++instance HasField "pipelineInfoForViewports" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr ImGui_ImplVulkan_PipelineInfo) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, PipelineInfoForViewports}++instance HasField "useDynamicRendering" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr CBool) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, UseDynamicRendering}++instance HasField "allocator" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr (Ptr VkAllocationCallbacks)) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, Allocator}++instance HasField "checkVkResultFn" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr (FunPtr (Result -> IO ()))) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, CheckVkResultFn}++instance HasField "minAllocationSize" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr DeviceSize) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, MinAllocationSize}++instance HasField "customShaderVertCreateInfo" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr VkShaderModuleCreateInfo) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, CustomShaderVertCreateInfo}++instance HasField "customShaderFragCreateInfo" (Ptr ImGui_ImplVulkan_InitInfo) (Ptr VkShaderModuleCreateInfo) where+  getField = #{ptr ImGui_ImplVulkan_InitInfo, CustomShaderFragCreateInfo}++foreign import capi unsafe "DearImGuiWrappers.h ImGui_ImplVulkan_InitInfo_Init_wrap"+  initImGui_ImplVulkan_InitInfo+    :: Ptr ImGui_ImplVulkan_InitInfo+    -> IO ()++foreign import capi unsafe "DearImGuiWrappers.h ImGui_ImplVulkan_InitInfo_Destroy_wrap"+  destroyImGui_ImplVulkan_InitInfo+    :: Ptr ImGui_ImplVulkan_InitInfo+    -> IO ()++withDefaultImGui_ImplVulkan_InitInfo :: (Ptr ImGui_ImplVulkan_InitInfo -> IO a) -> IO a+withDefaultImGui_ImplVulkan_InitInfo k = alloca $ \p -> bracket_ (initImGui_ImplVulkan_InitInfo p) (destroyImGui_ImplVulkan_InitInfo p) (k p)++data {-# CTYPE "dcimgui_impl_vulkan.h" "ImGui_ImplVulkan_PipelineInfo" #-} ImGui_ImplVulkan_PipelineInfo = ImGui_ImplVulkan_PipelineInfo+  { renderPass :: RenderPass+  , subpass :: Word32+  , mSAASamples :: SampleCountFlagBits+  , extraDynamicStates :: ImVector DynamicState+  , pipelineRenderingCreateInfo :: VkPipelineRenderingCreateInfoKHR+  , swapChainImageUsage :: ImageUsageFlags+  }+  deriving (Eq, Show)+instance Storable ImGui_ImplVulkan_PipelineInfo where+  sizeOf _    = #{size ImGui_ImplVulkan_PipelineInfo}+  alignment _ = #{alignment ImGui_ImplVulkan_PipelineInfo}+  peek p = ImGui_ImplVulkan_PipelineInfo <$> #{peek ImGui_ImplVulkan_PipelineInfo, RenderPass} p <*> #{peek ImGui_ImplVulkan_PipelineInfo, Subpass} p <*> #{peek ImGui_ImplVulkan_PipelineInfo, MSAASamples} p <*> #{peek ImGui_ImplVulkan_PipelineInfo, ExtraDynamicStates} p <*> #{peek ImGui_ImplVulkan_PipelineInfo, PipelineRenderingCreateInfo} p <*> #{peek ImGui_ImplVulkan_PipelineInfo, SwapChainImageUsage} p+  poke p v = do+    #{poke ImGui_ImplVulkan_PipelineInfo, RenderPass} p v.renderPass+    #{poke ImGui_ImplVulkan_PipelineInfo, Subpass} p v.subpass+    #{poke ImGui_ImplVulkan_PipelineInfo, MSAASamples} p v.mSAASamples+    #{poke ImGui_ImplVulkan_PipelineInfo, ExtraDynamicStates} p v.extraDynamicStates+    #{poke ImGui_ImplVulkan_PipelineInfo, PipelineRenderingCreateInfo} p v.pipelineRenderingCreateInfo+    #{poke ImGui_ImplVulkan_PipelineInfo, SwapChainImageUsage} p v.swapChainImageUsage++instance HasField "renderPass" (Ptr ImGui_ImplVulkan_PipelineInfo) (Ptr RenderPass) where+  getField = #{ptr ImGui_ImplVulkan_PipelineInfo, RenderPass}++instance HasField "subpass" (Ptr ImGui_ImplVulkan_PipelineInfo) (Ptr Word32) where+  getField = #{ptr ImGui_ImplVulkan_PipelineInfo, Subpass}++instance HasField "mSAASamples" (Ptr ImGui_ImplVulkan_PipelineInfo) (Ptr SampleCountFlagBits) where+  getField = #{ptr ImGui_ImplVulkan_PipelineInfo, MSAASamples}++instance HasField "extraDynamicStates" (Ptr ImGui_ImplVulkan_PipelineInfo) (Ptr (ImVector DynamicState)) where+  getField = #{ptr ImGui_ImplVulkan_PipelineInfo, ExtraDynamicStates}++instance HasField "pipelineRenderingCreateInfo" (Ptr ImGui_ImplVulkan_PipelineInfo) (Ptr VkPipelineRenderingCreateInfoKHR) where+  getField = #{ptr ImGui_ImplVulkan_PipelineInfo, PipelineRenderingCreateInfo}++instance HasField "swapChainImageUsage" (Ptr ImGui_ImplVulkan_PipelineInfo) (Ptr ImageUsageFlags) where+  getField = #{ptr ImGui_ImplVulkan_PipelineInfo, SwapChainImageUsage}++foreign import capi unsafe "DearImGuiWrappers.h ImGui_ImplVulkan_PipelineInfo_Init_wrap"+  initImGui_ImplVulkan_PipelineInfo+    :: Ptr ImGui_ImplVulkan_PipelineInfo+    -> IO ()++foreign import capi unsafe "DearImGuiWrappers.h ImGui_ImplVulkan_PipelineInfo_Destroy_wrap"+  destroyImGui_ImplVulkan_PipelineInfo+    :: Ptr ImGui_ImplVulkan_PipelineInfo+    -> IO ()++withDefaultImGui_ImplVulkan_PipelineInfo :: (Ptr ImGui_ImplVulkan_PipelineInfo -> IO a) -> IO a+withDefaultImGui_ImplVulkan_PipelineInfo k = alloca $ \p -> bracket_ (initImGui_ImplVulkan_PipelineInfo p) (destroyImGui_ImplVulkan_PipelineInfo p) (k p)++data {-# CTYPE "dcimgui_impl_vulkan.h" "ImGui_ImplVulkan_RenderState" #-} ImGui_ImplVulkan_RenderState = ImGui_ImplVulkan_RenderState+  { commandBuffer :: Ptr CommandBuffer_T+  , pipeline :: Pipeline+  , pipelineLayout :: PipelineLayout+  }+  deriving (Eq, Show)+instance Storable ImGui_ImplVulkan_RenderState where+  sizeOf _    = #{size ImGui_ImplVulkan_RenderState}+  alignment _ = #{alignment ImGui_ImplVulkan_RenderState}+  peek p = ImGui_ImplVulkan_RenderState <$> #{peek ImGui_ImplVulkan_RenderState, CommandBuffer} p <*> #{peek ImGui_ImplVulkan_RenderState, Pipeline} p <*> #{peek ImGui_ImplVulkan_RenderState, PipelineLayout} p+  poke p v = do+    #{poke ImGui_ImplVulkan_RenderState, CommandBuffer} p v.commandBuffer+    #{poke ImGui_ImplVulkan_RenderState, Pipeline} p v.pipeline+    #{poke ImGui_ImplVulkan_RenderState, PipelineLayout} p v.pipelineLayout++instance HasField "commandBuffer" (Ptr ImGui_ImplVulkan_RenderState) (Ptr (Ptr CommandBuffer_T)) where+  getField = #{ptr ImGui_ImplVulkan_RenderState, CommandBuffer}++instance HasField "pipeline" (Ptr ImGui_ImplVulkan_RenderState) (Ptr Pipeline) where+  getField = #{ptr ImGui_ImplVulkan_RenderState, Pipeline}++instance HasField "pipelineLayout" (Ptr ImGui_ImplVulkan_RenderState) (Ptr PipelineLayout) where+  getField = #{ptr ImGui_ImplVulkan_RenderState, PipelineLayout}++foreign import capi unsafe "DearImGuiWrappers.h ImGui_ImplVulkan_RenderState_Init_wrap"+  initImGui_ImplVulkan_RenderState+    :: Ptr ImGui_ImplVulkan_RenderState+    -> IO ()++foreign import capi unsafe "DearImGuiWrappers.h ImGui_ImplVulkan_RenderState_Destroy_wrap"+  destroyImGui_ImplVulkan_RenderState+    :: Ptr ImGui_ImplVulkan_RenderState+    -> IO ()++withDefaultImGui_ImplVulkan_RenderState :: (Ptr ImGui_ImplVulkan_RenderState -> IO a) -> IO a+withDefaultImGui_ImplVulkan_RenderState k = alloca $ \p -> bracket_ (initImGui_ImplVulkan_RenderState p) (destroyImGui_ImplVulkan_RenderState p) (k p)++data VkAllocationCallbacks++-- synthetic external; rendered as a managed byte buffer so whiteboxed parents can embed it by value.+newtype VkPipelineRenderingCreateInfoKHR = VkPipelineRenderingCreateInfoKHR (ForeignPtr Word8)+  deriving (Eq, Show)++instance Storable VkPipelineRenderingCreateInfoKHR where+  sizeOf _    = #{size VkPipelineRenderingCreateInfoKHR}+  alignment _ = #{alignment VkPipelineRenderingCreateInfoKHR}+  peek p = do+    let n = #{size VkPipelineRenderingCreateInfoKHR}+    fp <- mallocForeignPtrBytes n+    withForeignPtr fp $ \dst -> copyBytes dst (castPtr p) n+    pure (VkPipelineRenderingCreateInfoKHR fp)+  poke p (VkPipelineRenderingCreateInfoKHR fp) = do+    let n = #{size VkPipelineRenderingCreateInfoKHR}+    withForeignPtr fp $ \src -> copyBytes (castPtr p) src n++zeroVkPipelineRenderingCreateInfoKHR :: IO VkPipelineRenderingCreateInfoKHR+zeroVkPipelineRenderingCreateInfoKHR = do+  let n = #{size VkPipelineRenderingCreateInfoKHR}+  fp <- mallocForeignPtrBytes n+  withForeignPtr fp $ \p -> fillBytes p 0 n+  pure (VkPipelineRenderingCreateInfoKHR fp)++-- synthetic external; rendered as a managed byte buffer so whiteboxed parents can embed it by value.+newtype VkShaderModuleCreateInfo = VkShaderModuleCreateInfo (ForeignPtr Word8)+  deriving (Eq, Show)++instance Storable VkShaderModuleCreateInfo where+  sizeOf _    = #{size VkShaderModuleCreateInfo}+  alignment _ = #{alignment VkShaderModuleCreateInfo}+  peek p = do+    let n = #{size VkShaderModuleCreateInfo}+    fp <- mallocForeignPtrBytes n+    withForeignPtr fp $ \dst -> copyBytes dst (castPtr p) n+    pure (VkShaderModuleCreateInfo fp)+  poke p (VkShaderModuleCreateInfo fp) = do+    let n = #{size VkShaderModuleCreateInfo}+    withForeignPtr fp $ \src -> copyBytes (castPtr p) src n++zeroVkShaderModuleCreateInfo :: IO VkShaderModuleCreateInfo+zeroVkShaderModuleCreateInfo = do+  let n = #{size VkShaderModuleCreateInfo}+  fp <- mallocForeignPtrBytes n+  withForeignPtr fp $ \p -> fillBytes p 0 n+  pure (VkShaderModuleCreateInfo fp)++-- defines++pattern IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE :: (Eq a, Num a) => a+pattern IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE = #{const IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE}++pattern IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE :: (Eq a, Num a) => a+pattern IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE = #{const IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE}++-- functions++-- C: VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_AddTexture"+  addTexture+    :: ImageView -- ^ image_view+    -> ImageLayout -- ^ image_layout+    -> IO DescriptorSet++-- C: void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_CreateMainPipeline"+  createMainPipeline+    :: (Ptr ImGui_ImplVulkan_PipelineInfo) -- ^ info+    -> IO ()++-- C: ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState()+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_GetRenderState"+  getRenderState :: IO (Ptr ImGui_ImplVulkan_RenderState)++-- C: bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_Init"+  init+    :: (Ptr ImGui_ImplVulkan_InitInfo) -- ^ info+    -> IO CBool++-- C: bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction (*loader_func)(const char* function_name, void* user_data) loader_func, void* user_data)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_LoadFunctions"+  loadFunctions+    :: Word32 -- ^ api_version+    -> (FunPtr (CString -> (Ptr ()) -> IO PFN_vkVoidFunction)) -- ^ loader_func+    -> (Ptr ()) -- ^ user_data+    -> IO CBool++-- C: void ImGui_ImplVulkan_NewFrame()+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_NewFrame"+  newFrame :: IO ()++-- C: void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_RemoveTexture"+  removeTexture+    :: DescriptorSet -- ^ descriptor_set+    -> IO ()++-- C: void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_RenderDrawData"+  renderDrawData+    :: (Ptr ImDrawData) -- ^ draw_data+    -> (Ptr CommandBuffer_T) -- ^ command_buffer+    -> Pipeline -- ^ pipeline+    -> IO ()++-- C: void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_SetMinImageCount"+  setMinImageCount+    :: Word32 -- ^ min_image_count+    -> IO ()++-- C: void ImGui_ImplVulkan_Shutdown()+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_Shutdown"+  shutdown :: IO ()++-- C: void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)+foreign import capi safe "dcimgui_impl_vulkan.h cImGui_ImplVulkan_UpdateTexture"+  updateTexture+    :: (Ptr ImTextureData) -- ^ tex+    -> IO ()