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 +13/−0
- LICENSE +26/−0
- README.md +18/−0
- cbits/DearImGuiCtors.cpp +34/−0
- cbits/DearImGuiWrappers.cpp +3/−0
- cbits/DearImGuiWrappers.h +25/−0
- cbits/dcimgui_impl_vulkan.cpp +202/−0
- cbits/dcimgui_impl_vulkan.h +304/−0
- cbits/imgui_impl_vulkan.cpp +2428/−0
- cbits/imgui_impl_vulkan.h +289/−0
- dear-imgui-impl-vulkan.cabal +60/−0
- src/DearImGui/Impl/Vulkan.hsc +215/−0
- src/DearImGui/Raw/Impl/Vulkan.hsc +388/−0
+ 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, ®ion);++ 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 ()