2020-10-12 17:34:22 +02:00
// dear imgui: Renderer Backend for Vulkan
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
2018-02-05 20:34:11 +01:00
2019-05-29 15:53:36 +02:00
// Implemented features:
2022-01-20 15:53:28 +01:00
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
2023-02-07 12:24:42 +01:00
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
2022-01-20 15:53:28 +01:00
// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
// To build this on 32-bit systems and support texture changes:
// - [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in our .vcxproj files)
// - [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
// - [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
// - [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in our batch files)
2016-11-12 17:49:59 +01:00
2021-06-28 16:52:10 +02:00
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
2021-05-27 13:59:35 +02:00
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
2020-10-14 12:22:53 +02:00
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
2016-03-09 16:39:54 +01:00
2019-01-20 17:56:17 +01:00
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
2018-08-22 16:43:29 +02:00
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
2019-04-03 19:21:06 +02:00
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
2019-04-05 20:27:46 +02:00
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
2020-10-12 17:34:22 +02:00
// You will use those if you want to use this rendering backend in your engine/app.
2019-10-15 16:20:27 +03:00
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
2020-10-12 17:34:22 +02:00
// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
2019-04-03 19:21:06 +02:00
// Read comments in imgui_impl_vulkan.h.
2018-02-16 17:20:18 +01:00
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
2023-07-03 17:48:28 +02:00
// 2023-07-04: Vulkan: Added optional support for VK_KHR_dynamic_rendering. User needs to set init_info->UseDynamicRendering = true and init_info->ColorAttachmentFormat.
2022-12-16 16:48:36 +01:00
// 2023-01-02: Vulkan: Fixed sampler passed to ImGui_ImplVulkan_AddTexture() not being honored + removed a bunch of duplicate code.
2022-10-11 12:22:29 +02:00
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
2022-10-04 12:02:48 +02:00
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symetry. (#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 12:11:11 +02:00
// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
2021-06-28 16:52:10 +02:00
// 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-21 12:29:24 -04:00
// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
2021-02-17 19:29:07 +01:00
// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
2021-01-27 13:23:28 +01:00
// 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
2020-11-07 07:32:48 -08:00
// 2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.
2020-09-08 16:47:06 +02:00
// 2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init).
2020-05-04 11:03:05 +02:00
// 2020-05-04: Vulkan: Fixed crash if initial frame has no vertices.
2019-07-04 18:28:34 -07:00
// 2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices.
2019-07-31 19:50:50 +01:00
// 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 16:29:17 +02:00
// 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
2019-04-30 22:28:29 +02:00
// 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: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
2019-04-04 22:09:12 +02:00
// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
2019-04-01 17:32:14 +02:00
// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
2019-02-16 12:27:46 +01:00
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
2018-11-30 18:18:15 +01:00
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
2018-08-25 21:15:37 +02:00
// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
2020-10-12 17:34:22 +02:00
// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.
2018-06-08 19:37:33 +02:00
// 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: 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-16 17:20:18 +01:00
// 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.
2023-07-13 11:27:52 +02:00
#include "imgui.h"
#ifndef IMGUI_DISABLE
2018-06-08 19:37:33 +02:00
#include "imgui_impl_vulkan.h"
#include <stdio.h>
2016-03-09 16:39:54 +01:00
2022-01-20 15:53:28 +01:00
// Visual Studio warnings
#ifdef _MSC_VER
#pragma warning (disable: 4127) // condition expression is constant
#endif
2019-04-05 17:48:47 +02:00
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
// [Please zero-clear before use!]
struct ImGui_ImplVulkanH_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_ImplVulkanH_WindowRenderBuffers
{
uint32_t Index ;
uint32_t Count ;
ImGui_ImplVulkanH_FrameRenderBuffers * FrameRenderBuffers ;
};
2018-02-20 14:18:02 +01:00
// Vulkan data
2021-06-28 16:52:10 +02:00
struct ImGui_ImplVulkan_Data
{
ImGui_ImplVulkan_InitInfo VulkanInitInfo ;
VkRenderPass RenderPass ;
VkDeviceSize BufferMemoryAlignment ;
VkPipelineCreateFlags PipelineCreateFlags ;
VkDescriptorSetLayout DescriptorSetLayout ;
VkPipelineLayout PipelineLayout ;
VkPipeline Pipeline ;
uint32_t Subpass ;
VkShaderModule ShaderModuleVert ;
VkShaderModule ShaderModuleFrag ;
2016-03-09 16:39:54 +01:00
2021-06-28 16:52:10 +02:00
// Font data
VkSampler FontSampler ;
VkDeviceMemory FontMemory ;
VkImage FontImage ;
VkImageView FontView ;
2022-01-20 15:32:49 +01:00
VkDescriptorSet FontDescriptorSet ;
2021-06-28 16:52:10 +02:00
VkDeviceMemory UploadBufferMemory ;
VkBuffer UploadBuffer ;
2016-03-09 16:39:54 +01:00
2023-02-07 12:24:42 +01:00
// Render buffers for main window
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers ;
ImGui_ImplVulkan_Data ()
{
2022-03-13 13:15:32 +07:00
memset (( void * ) this , 0 , sizeof ( * this ));
2021-06-28 16:52:10 +02:00
BufferMemoryAlignment = 256 ;
}
};
2019-04-03 18:33:13 +02:00
// Forward Declarations
2019-04-05 20:27:46 +02:00
bool ImGui_ImplVulkan_CreateDeviceObjects ();
void ImGui_ImplVulkan_DestroyDeviceObjects ();
2019-04-05 17:54:16 +02:00
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_DestroyFrameRenderBuffers ( VkDevice device , ImGui_ImplVulkanH_FrameRenderBuffers * buffers , const VkAllocationCallbacks * allocator );
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers ( VkDevice device , ImGui_ImplVulkanH_WindowRenderBuffers * buffers , 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 );
void ImGui_ImplVulkanH_CreateWindowCommandBuffers ( VkPhysicalDevice physical_device , VkDevice device , ImGui_ImplVulkanH_Window * wd , uint32_t queue_family , const VkAllocationCallbacks * allocator );
2019-04-03 18:33:13 +02:00
2021-01-27 13:23:28 +01:00
// Vulkan prototypes for use with custom loaders
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
#ifdef VK_NO_PROTOTYPES
2021-06-28 16:52:10 +02:00
static bool g_FunctionsLoaded = false ;
#else
static bool g_FunctionsLoaded = true ;
#endif
#ifdef VK_NO_PROTOTYPES
2021-01-27 13:23:28 +01:00
#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(vkBindBufferMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindImageMemory) \
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(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(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(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(vkFlushMappedMemoryRanges) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \
2022-10-04 12:30:45 +02:00
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeDescriptorSets) \
2021-01-27 13:23:28 +01:00
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceMemoryProperties) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceFormatsKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetSwapchainImagesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkMapMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUnmapMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets)
// Define function pointers
#define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func;
IMGUI_VULKAN_FUNC_MAP ( IMGUI_VULKAN_FUNC_DEF )
#undef IMGUI_VULKAN_FUNC_DEF
#endif // VK_NO_PROTOTYPES
2022-02-19 20:15:58 +01:00
#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering)
2023-07-03 17:48:28 +02:00
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR ;
static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR ;
2022-02-19 20:15:58 +01:00
#endif
2019-04-03 18:33:13 +02:00
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
2018-06-08 19:37:33 +02:00
// glsl_shader.vert, compiled with:
// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
2019-04-03 11:23:54 +02:00
/*
#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);
}
*/
2016-11-13 03:00:36 +01:00
static uint32_t __glsl_shader_vert_spv [] =
2016-04-03 17:32:53 +02:00
{
2016-11-13 03:00:36 +01:00
0x07230203 , 0x00010000 , 0x00080001 , 0x0000002e , 0x00000000 , 0x00020011 , 0x00000001 , 0x0006000b ,
2016-10-18 22:40:58 +02:00
0x00000001 , 0x4c534c47 , 0x6474732e , 0x3035342e , 0x00000000 , 0x0003000e , 0x00000000 , 0x00000001 ,
0x000a000f , 0x00000000 , 0x00000004 , 0x6e69616d , 0x00000000 , 0x0000000b , 0x0000000f , 0x00000015 ,
2016-11-13 03:00:36 +01:00
0x0000001b , 0x0000001c , 0x00030003 , 0x00000002 , 0x000001c2 , 0x00040005 , 0x00000004 , 0x6e69616d ,
2016-10-18 22:40:58 +02:00
0x00000000 , 0x00030005 , 0x00000009 , 0x00000000 , 0x00050006 , 0x00000009 , 0x00000000 , 0x6f6c6f43 ,
0x00000072 , 0x00040006 , 0x00000009 , 0x00000001 , 0x00005655 , 0x00030005 , 0x0000000b , 0x0074754f ,
0x00040005 , 0x0000000f , 0x6c6f4361 , 0x0000726f , 0x00030005 , 0x00000015 , 0x00565561 , 0x00060005 ,
2016-11-13 03:00:36 +01:00
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 , 0x00050048 , 0x00000019 , 0x00000000 , 0x0000000b , 0x00000000 , 0x00030047 ,
0x00000019 , 0x00000002 , 0x00040047 , 0x0000001c , 0x0000001e , 0x00000000 , 0x00050048 , 0x0000001e ,
0x00000000 , 0x00000023 , 0x00000000 , 0x00050048 , 0x0000001e , 0x00000001 , 0x00000023 , 0x00000008 ,
0x00030047 , 0x0000001e , 0x00000002 , 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
2016-03-09 16:39:54 +01:00
};
2018-06-08 19:37:33 +02:00
// glsl_shader.frag, compiled with:
// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
2019-04-03 11:23:54 +02:00
/*
#version 450 core
layout(location = 0) out vec4 fColor;
layout(set=0, binding=0) uniform sampler2D sTexture;
layout(location = 0) in struct { vec4 Color; vec2 UV; } In;
void main()
{
fColor = In.Color * texture(sTexture, In.UV.st);
}
*/
2016-11-13 03:00:36 +01:00
static uint32_t __glsl_shader_frag_spv [] =
2016-04-03 17:32:53 +02:00
{
2016-10-18 22:40:58 +02:00
0x07230203 , 0x00010000 , 0x00080001 , 0x0000001e , 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 , 0x00000016 , 0x78655473 , 0x65727574 ,
0x00000000 , 0x00040047 , 0x00000009 , 0x0000001e , 0x00000000 , 0x00040047 , 0x0000000d , 0x0000001e ,
0x00000000 , 0x00040047 , 0x00000016 , 0x00000022 , 0x00000000 , 0x00040047 , 0x00000016 , 0x00000021 ,
0x00000000 , 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 , 0x0003001b , 0x00000014 , 0x00000013 , 0x00040020 , 0x00000015 , 0x00000000 ,
0x00000014 , 0x0004003b , 0x00000015 , 0x00000016 , 0x00000000 , 0x0004002b , 0x0000000e , 0x00000018 ,
0x00000001 , 0x00040020 , 0x00000019 , 0x00000001 , 0x0000000a , 0x00050036 , 0x00000002 , 0x00000004 ,
0x00000000 , 0x00000003 , 0x000200f8 , 0x00000005 , 0x00050041 , 0x00000010 , 0x00000011 , 0x0000000d ,
0x0000000f , 0x0004003d , 0x00000007 , 0x00000012 , 0x00000011 , 0x0004003d , 0x00000014 , 0x00000017 ,
0x00000016 , 0x00050041 , 0x00000019 , 0x0000001a , 0x0000000d , 0x00000018 , 0x0004003d , 0x0000000a ,
0x0000001b , 0x0000001a , 0x00050057 , 0x00000007 , 0x0000001c , 0x00000017 , 0x0000001b , 0x00050085 ,
0x00000007 , 0x0000001d , 0x00000012 , 0x0000001c , 0x0003003e , 0x00000009 , 0x0000001d , 0x000100fd ,
0x00010038
2016-03-09 16:39:54 +01:00
};
2019-04-03 18:33:13 +02:00
//-----------------------------------------------------------------------------
// FUNCTIONS
//-----------------------------------------------------------------------------
2021-06-30 15:22:15 +02:00
// 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 ()
{
2022-10-11 12:22:29 +02:00
return ImGui :: GetCurrentContext () ? ( ImGui_ImplVulkan_Data * ) ImGui :: GetIO (). BackendRendererUserData : nullptr ;
2021-06-30 15:22:15 +02:00
}
2018-06-08 19:37:33 +02:00
static uint32_t ImGui_ImplVulkan_MemoryType ( VkMemoryPropertyFlags properties , uint32_t type_bits )
2016-03-09 16:39:54 +01:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
2016-03-09 16:39:54 +01:00
VkPhysicalDeviceMemoryProperties prop ;
2019-04-04 22:36:12 +02:00
vkGetPhysicalDeviceMemoryProperties ( v -> PhysicalDevice , & prop );
2016-04-03 17:32:53 +02:00
for ( uint32_t i = 0 ; i < prop . memoryTypeCount ; i ++ )
2020-06-30 15:31:54 +02:00
if (( prop . memoryTypes [ i ]. propertyFlags & properties ) == properties && type_bits & ( 1 << i ))
2016-03-09 16:39:54 +01:00
return i ;
2018-06-08 19:37:33 +02:00
return 0xFFFFFFFF ; // Unable to find memoryType
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
2018-06-08 19:37:33 +02:00
static void check_vk_result ( VkResult err )
2016-03-09 16:39:54 +01:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
if ( ! bd )
return ;
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
2019-04-04 22:36:12 +02:00
if ( v -> CheckVkResultFn )
v -> CheckVkResultFn ( err );
2018-06-08 19:37:33 +02:00
}
static void CreateOrResizeBuffer ( VkBuffer & buffer , VkDeviceMemory & buffer_memory , VkDeviceSize & p_buffer_size , size_t new_size , VkBufferUsageFlagBits usage )
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
2018-06-08 19:37:33 +02:00
VkResult err ;
2018-08-28 18:22:36 +02:00
if ( buffer != VK_NULL_HANDLE )
2019-04-04 22:36:12 +02:00
vkDestroyBuffer ( v -> Device , buffer , v -> Allocator );
2019-04-05 20:27:46 +02:00
if ( buffer_memory != VK_NULL_HANDLE )
2019-04-04 22:36:12 +02:00
vkFreeMemory ( v -> Device , buffer_memory , v -> Allocator );
2018-06-08 19:37:33 +02:00
2021-06-28 16:52:10 +02:00
VkDeviceSize vertex_buffer_size_aligned = (( new_size - 1 ) / bd -> BufferMemoryAlignment + 1 ) * bd -> BufferMemoryAlignment ;
2018-06-08 19:37:33 +02:00
VkBufferCreateInfo buffer_info = {};
buffer_info . sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO ;
buffer_info . size = vertex_buffer_size_aligned ;
buffer_info . usage = usage ;
buffer_info . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
2019-04-04 22:36:12 +02:00
err = vkCreateBuffer ( v -> Device , & buffer_info , v -> Allocator , & buffer );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
VkMemoryRequirements req ;
2019-04-04 22:36:12 +02:00
vkGetBufferMemoryRequirements ( v -> Device , buffer , & req );
2021-06-28 16:52:10 +02:00
bd -> BufferMemoryAlignment = ( bd -> BufferMemoryAlignment > req . alignment ) ? bd -> BufferMemoryAlignment : req . alignment ;
2018-06-08 19:37:33 +02:00
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 );
2019-04-04 22:36:12 +02:00
err = vkAllocateMemory ( v -> Device , & alloc_info , v -> Allocator , & buffer_memory );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2019-04-04 22:36:12 +02:00
err = vkBindBufferMemory ( v -> Device , buffer , buffer_memory , 0 );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2021-03-21 12:29:24 -04:00
p_buffer_size = req . size ;
2016-03-09 16:39:54 +01:00
}
2020-09-08 16:47:06 +02:00
static void ImGui_ImplVulkan_SetupRenderState ( ImDrawData * draw_data , VkPipeline pipeline , VkCommandBuffer command_buffer , ImGui_ImplVulkanH_FrameRenderBuffers * rb , int fb_width , int fb_height )
2019-04-30 22:15:59 +02:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
2022-01-20 15:32:49 +01:00
// Bind pipeline:
2019-04-30 22:15:59 +02:00
{
2020-09-08 16:47:06 +02:00
vkCmdBindPipeline ( command_buffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline );
2019-04-30 22:15:59 +02:00
}
// Bind Vertex And Index Buffer:
2019-07-04 18:28:34 -07:00
if ( draw_data -> TotalVtxCount > 0 )
2019-04-30 22:15:59 +02:00
{
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:
2019-06-06 16:13:30 +02:00
// 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.
2019-04-30 22:15:59 +02:00
{
float scale [ 2 ];
scale [ 0 ] = 2.0f / draw_data -> DisplaySize . x ;
scale [ 1 ] = 2.0f / draw_data -> DisplaySize . y ;
float translate [ 2 ];
translate [ 0 ] = - 1.0f - draw_data -> DisplayPos . x * scale [ 0 ];
translate [ 1 ] = - 1.0f - draw_data -> DisplayPos . y * scale [ 1 ];
2021-06-28 16:52:10 +02:00
vkCmdPushConstants ( command_buffer , bd -> PipelineLayout , VK_SHADER_STAGE_VERTEX_BIT , sizeof ( float ) * 0 , sizeof ( float ) * 2 , scale );
vkCmdPushConstants ( command_buffer , bd -> PipelineLayout , VK_SHADER_STAGE_VERTEX_BIT , sizeof ( float ) * 2 , sizeof ( float ) * 2 , translate );
2019-04-30 22:15:59 +02:00
}
}
2018-06-22 10:02:02 +02:00
// Render function
2020-09-08 16:47:06 +02:00
void ImGui_ImplVulkan_RenderDrawData ( ImDrawData * draw_data , VkCommandBuffer command_buffer , VkPipeline pipeline )
2016-03-09 16:39:54 +01:00
{
2019-02-16 12:33:38 +01:00
// 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 );
int fb_height = ( int )( draw_data -> DisplaySize . y * draw_data -> FramebufferScale . y );
2019-07-04 18:28:34 -07:00
if ( fb_width <= 0 || fb_height <= 0 )
2018-02-16 22:28:52 +01:00
return ;
2016-03-09 16:39:54 +01:00
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
2020-09-08 16:47:06 +02:00
if ( pipeline == VK_NULL_HANDLE )
2021-06-28 16:52:10 +02:00
pipeline = bd -> Pipeline ;
2019-04-05 17:48:47 +02:00
// Allocate array to store enough vertex/index buffers
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkanH_WindowRenderBuffers * wrb = & bd -> MainWindowRenderBuffers ;
2022-10-11 12:22:29 +02:00
if ( wrb -> FrameRenderBuffers == nullptr )
2019-04-05 17:48:47 +02:00
{
wrb -> Index = 0 ;
wrb -> Count = v -> ImageCount ;
2019-04-05 20:27:46 +02:00
wrb -> FrameRenderBuffers = ( ImGui_ImplVulkanH_FrameRenderBuffers * ) IM_ALLOC ( sizeof ( ImGui_ImplVulkanH_FrameRenderBuffers ) * wrb -> Count );
2019-04-05 17:48:47 +02:00
memset ( wrb -> FrameRenderBuffers , 0 , sizeof ( ImGui_ImplVulkanH_FrameRenderBuffers ) * wrb -> Count );
}
IM_ASSERT ( wrb -> Count == v -> ImageCount );
wrb -> Index = ( wrb -> Index + 1 ) % wrb -> Count ;
ImGui_ImplVulkanH_FrameRenderBuffers * rb = & wrb -> FrameRenderBuffers [ wrb -> Index ];
2020-05-04 11:03:05 +02:00
if ( draw_data -> TotalVtxCount > 0 )
2016-03-09 16:39:54 +01:00
{
2020-05-04 11:03:05 +02:00
// Create or resize the vertex/index buffers
size_t vertex_size = draw_data -> TotalVtxCount * sizeof ( ImDrawVert );
size_t index_size = draw_data -> TotalIdxCount * sizeof ( ImDrawIdx );
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
2022-10-11 12:22:29 +02:00
ImDrawVert * vtx_dst = nullptr ;
ImDrawIdx * idx_dst = nullptr ;
2021-03-21 12:29:24 -04:00
VkResult err = vkMapMemory ( v -> Device , rb -> VertexBufferMemory , 0 , rb -> VertexBufferSize , 0 , ( void ** )( & vtx_dst ));
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2021-03-21 12:29:24 -04:00
err = vkMapMemory ( v -> Device , rb -> IndexBufferMemory , 0 , rb -> IndexBufferSize , 0 , ( void ** )( & idx_dst ));
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-04-03 17:32:53 +02:00
for ( int n = 0 ; n < draw_data -> CmdListsCount ; n ++ )
{
2016-03-09 16:39:54 +01:00
const ImDrawList * cmd_list = draw_data -> CmdLists [ n ];
2016-09-03 19:24:57 +02:00
memcpy ( vtx_dst , cmd_list -> VtxBuffer . Data , cmd_list -> VtxBuffer . Size * sizeof ( ImDrawVert ));
memcpy ( idx_dst , cmd_list -> IdxBuffer . Data , cmd_list -> IdxBuffer . Size * sizeof ( ImDrawIdx ));
vtx_dst += cmd_list -> VtxBuffer . Size ;
idx_dst += cmd_list -> IdxBuffer . Size ;
2016-03-09 16:39:54 +01:00
}
VkMappedMemoryRange range [ 2 ] = {};
range [ 0 ]. sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE ;
2019-04-05 17:48:47 +02:00
range [ 0 ]. memory = rb -> VertexBufferMemory ;
2017-02-11 12:08:59 +01:00
range [ 0 ]. size = VK_WHOLE_SIZE ;
2016-03-09 16:39:54 +01:00
range [ 1 ]. sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE ;
2019-04-05 17:48:47 +02:00
range [ 1 ]. memory = rb -> IndexBufferMemory ;
2017-02-11 12:08:59 +01:00
range [ 1 ]. size = VK_WHOLE_SIZE ;
2019-04-04 22:36:12 +02:00
err = vkFlushMappedMemoryRanges ( v -> Device , 2 , range );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2019-04-05 17:48:47 +02:00
vkUnmapMemory ( v -> Device , rb -> VertexBufferMemory );
vkUnmapMemory ( v -> Device , rb -> IndexBufferMemory );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
2019-04-30 22:15:59 +02:00
// Setup desired Vulkan state
2020-09-08 16:47:06 +02:00
ImGui_ImplVulkan_SetupRenderState ( draw_data , pipeline , command_buffer , rb , fb_width , fb_height );
2016-04-03 17:32:53 +02:00
2019-02-16 12:27:46 +01:00
// 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
2019-05-29 15:53:36 +02:00
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0 ;
int global_idx_offset = 0 ;
2016-04-03 17:32:53 +02:00
for ( int n = 0 ; n < draw_data -> CmdListsCount ; n ++ )
{
2016-03-09 16:39:54 +01:00
const ImDrawList * cmd_list = draw_data -> CmdLists [ n ];
2016-09-03 19:24:57 +02:00
for ( int cmd_i = 0 ; cmd_i < cmd_list -> CmdBuffer . Size ; cmd_i ++ )
2016-04-03 17:32:53 +02:00
{
2016-03-09 16:39:54 +01:00
const ImDrawCmd * pcmd = & cmd_list -> CmdBuffer [ cmd_i ];
2022-10-11 12:22:29 +02:00
if ( pcmd -> UserCallback != nullptr )
2016-04-03 17:32:53 +02:00
{
2019-04-30 22:15:59 +02:00
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if ( pcmd -> UserCallback == ImDrawCallback_ResetRenderState )
2020-09-08 16:47:06 +02:00
ImGui_ImplVulkan_SetupRenderState ( draw_data , pipeline , command_buffer , rb , fb_width , fb_height );
2019-04-30 22:15:59 +02:00
else
pcmd -> UserCallback ( cmd_list , pcmd );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
else
{
2019-02-16 12:27:46 +01:00
// Project scissor/clipping rectangles into framebuffer space
2021-08-24 18:03:52 +03:00
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 );
2019-02-16 12:27:46 +01:00
2021-08-24 18:03:52 +03:00
// 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 > fb_width ) { clip_max . x = ( float ) fb_width ; }
if ( clip_max . y > fb_height ) { clip_max . y = ( float ) fb_height ; }
2021-11-30 21:48:29 +01:00
if ( clip_max . x <= clip_min . x || clip_max . y <= clip_min . y )
2021-08-24 18:03:52 +03:00
continue ;
2019-04-04 22:09:12 +02:00
2021-08-24 18:03:52 +03:00
// 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 );
2019-01-20 17:56:17 +01:00
2022-01-20 15:32:49 +01:00
// Bind DescriptorSet with font or user texture
VkDescriptorSet desc_set [ 1 ] = { ( VkDescriptorSet ) pcmd -> TextureId };
2022-01-20 15:53:28 +01:00
if ( sizeof ( ImTextureID ) < sizeof ( ImU64 ))
{
// We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit. Do a flaky check that other textures haven't been used.
IM_ASSERT ( pcmd -> TextureId == ( ImTextureID ) bd -> FontDescriptorSet );
desc_set [ 0 ] = bd -> FontDescriptorSet ;
}
2022-10-11 12:22:29 +02:00
vkCmdBindDescriptorSets ( command_buffer , VK_PIPELINE_BIND_POINT_GRAPHICS , bd -> PipelineLayout , 0 , 1 , desc_set , 0 , nullptr );
2022-01-20 15:32:49 +01:00
2021-08-24 18:03:52 +03:00
// Draw
vkCmdDrawIndexed ( command_buffer , pcmd -> ElemCount , 1 , pcmd -> IdxOffset + global_idx_offset , pcmd -> VtxOffset + global_vtx_offset , 0 );
2016-03-09 16:39:54 +01:00
}
}
2019-05-29 15:53:36 +02:00
global_idx_offset += cmd_list -> IdxBuffer . Size ;
global_vtx_offset += cmd_list -> VtxBuffer . Size ;
2016-03-09 16:39:54 +01:00
}
2021-10-15 12:01:35 +02:00
// 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
2022-09-11 08:35:59 +03:00
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitly set that state.
2021-10-15 12:01:35 +02:00
// 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.
2021-10-15 12:11:11 +02:00
// 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 );
2016-03-09 16:39:54 +01:00
}
2018-06-08 19:37:33 +02:00
bool ImGui_ImplVulkan_CreateFontsTexture ( VkCommandBuffer command_buffer )
2016-03-09 16:39:54 +01:00
{
ImGuiIO & io = ImGui :: GetIO ();
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
2016-03-09 16:39:54 +01:00
unsigned char * pixels ;
int width , height ;
io . Fonts -> GetTexDataAsRGBA32 ( & pixels , & width , & height );
2020-06-30 15:31:54 +02:00
size_t upload_size = width * height * 4 * sizeof ( char );
2016-03-09 16:39:54 +01:00
VkResult err ;
2016-04-03 17:32:53 +02:00
2016-03-09 16:39:54 +01:00
// 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 = width ;
info . extent . height = height ;
info . extent . depth = 1 ;
info . mipLevels = 1 ;
info . arrayLayers = 1 ;
info . samples = VK_SAMPLE_COUNT_1_BIT ;
info . tiling = VK_IMAGE_TILING_OPTIMAL ;
2016-04-03 17:32:53 +02:00
info . usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT ;
2016-03-09 16:39:54 +01:00
info . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
info . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
2021-06-28 16:52:10 +02:00
err = vkCreateImage ( v -> Device , & info , v -> Allocator , & bd -> FontImage );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
VkMemoryRequirements req ;
2021-06-28 16:52:10 +02:00
vkGetImageMemoryRequirements ( v -> Device , bd -> FontImage , & req );
2016-03-09 16:39:54 +01:00
VkMemoryAllocateInfo alloc_info = {};
alloc_info . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
alloc_info . allocationSize = req . size ;
2018-06-08 19:37:33 +02:00
alloc_info . memoryTypeIndex = ImGui_ImplVulkan_MemoryType ( VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT , req . memoryTypeBits );
2021-06-28 16:52:10 +02:00
err = vkAllocateMemory ( v -> Device , & alloc_info , v -> Allocator , & bd -> FontMemory );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2021-06-28 16:52:10 +02:00
err = vkBindImageMemory ( v -> Device , bd -> FontImage , bd -> FontMemory , 0 );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
2016-03-09 16:39:54 +01:00
// Create the Image View:
{
VkImageViewCreateInfo info = {};
info . sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO ;
2021-06-28 16:52:10 +02:00
info . image = bd -> FontImage ;
2016-03-09 16:39:54 +01:00
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 ;
2021-06-28 16:52:10 +02:00
err = vkCreateImageView ( v -> Device , & info , v -> Allocator , & bd -> FontView );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
2022-01-20 15:32:49 +01:00
// Create the Descriptor Set:
bd -> FontDescriptorSet = ( VkDescriptorSet ) ImGui_ImplVulkan_AddTexture ( bd -> FontSampler , bd -> FontView , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
2016-04-03 17:32:53 +02:00
2016-03-09 16:39:54 +01:00
// Create the Upload Buffer:
{
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 ;
2021-06-28 16:52:10 +02:00
err = vkCreateBuffer ( v -> Device , & buffer_info , v -> Allocator , & bd -> UploadBuffer );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
VkMemoryRequirements req ;
2021-06-28 16:52:10 +02:00
vkGetBufferMemoryRequirements ( v -> Device , bd -> UploadBuffer , & req );
bd -> BufferMemoryAlignment = ( bd -> BufferMemoryAlignment > req . alignment ) ? bd -> BufferMemoryAlignment : req . alignment ;
2016-03-09 16:39:54 +01:00
VkMemoryAllocateInfo alloc_info = {};
alloc_info . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
alloc_info . allocationSize = req . size ;
2018-06-08 19:37:33 +02:00
alloc_info . memoryTypeIndex = ImGui_ImplVulkan_MemoryType ( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT , req . memoryTypeBits );
2021-06-28 16:52:10 +02:00
err = vkAllocateMemory ( v -> Device , & alloc_info , v -> Allocator , & bd -> UploadBufferMemory );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2021-06-28 16:52:10 +02:00
err = vkBindBufferMemory ( v -> Device , bd -> UploadBuffer , bd -> UploadBufferMemory , 0 );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
2016-03-09 16:39:54 +01:00
// Upload to Buffer:
{
2022-10-11 12:22:29 +02:00
char * map = nullptr ;
2021-06-28 16:52:10 +02:00
err = vkMapMemory ( v -> Device , bd -> UploadBufferMemory , 0 , upload_size , 0 , ( void ** )( & map ));
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
memcpy ( map , pixels , upload_size );
VkMappedMemoryRange range [ 1 ] = {};
range [ 0 ]. sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE ;
2021-06-28 16:52:10 +02:00
range [ 0 ]. memory = bd -> UploadBufferMemory ;
2016-03-09 16:39:54 +01:00
range [ 0 ]. size = upload_size ;
2019-04-04 22:36:12 +02:00
err = vkFlushMappedMemoryRanges ( v -> Device , 1 , range );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2021-06-28 16:52:10 +02:00
vkUnmapMemory ( v -> Device , bd -> UploadBufferMemory );
2016-03-09 16:39:54 +01:00
}
2018-06-08 19:37:33 +02:00
2016-03-10 12:30:38 +01:00
// Copy to Image:
2016-03-09 16:39:54 +01:00
{
2016-03-10 12:30:38 +01:00
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 = VK_IMAGE_LAYOUT_UNDEFINED ;
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 ;
2021-06-28 16:52:10 +02:00
copy_barrier [ 0 ]. image = bd -> FontImage ;
2016-03-10 12:30:38 +01:00
copy_barrier [ 0 ]. subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
copy_barrier [ 0 ]. subresourceRange . levelCount = 1 ;
copy_barrier [ 0 ]. subresourceRange . layerCount = 1 ;
2022-10-11 12:22:29 +02:00
vkCmdPipelineBarrier ( command_buffer , VK_PIPELINE_STAGE_HOST_BIT , VK_PIPELINE_STAGE_TRANSFER_BIT , 0 , 0 , nullptr , 0 , nullptr , 1 , copy_barrier );
2016-04-03 17:32:53 +02:00
2016-03-09 16:39:54 +01:00
VkBufferImageCopy region = {};
region . imageSubresource . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
region . imageSubresource . layerCount = 1 ;
region . imageExtent . width = width ;
region . imageExtent . height = height ;
2017-03-26 19:38:05 +02:00
region . imageExtent . depth = 1 ;
2021-06-28 16:52:10 +02:00
vkCmdCopyBufferToImage ( command_buffer , bd -> UploadBuffer , bd -> FontImage , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 1 , & region );
2016-04-03 17:32:53 +02:00
2016-03-10 12:30:38 +01:00
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 ;
2021-06-28 16:52:10 +02:00
use_barrier [ 0 ]. image = bd -> FontImage ;
2016-03-10 12:30:38 +01:00
use_barrier [ 0 ]. subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
use_barrier [ 0 ]. subresourceRange . levelCount = 1 ;
use_barrier [ 0 ]. subresourceRange . layerCount = 1 ;
2022-10-11 12:22:29 +02:00
vkCmdPipelineBarrier ( command_buffer , VK_PIPELINE_STAGE_TRANSFER_BIT , VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT , 0 , 0 , nullptr , 0 , nullptr , 1 , use_barrier );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
// Store our identifier
2022-01-20 16:56:29 +01:00
io . Fonts -> SetTexID (( ImTextureID ) bd -> FontDescriptorSet );
2016-03-09 16:39:54 +01:00
return true ;
}
2020-09-08 16:47:06 +02:00
static void ImGui_ImplVulkan_CreateShaderModules ( VkDevice device , const VkAllocationCallbacks * allocator )
{
// Create the shader modules
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
2021-08-24 12:53:54 -07:00
if ( bd -> ShaderModuleVert == VK_NULL_HANDLE )
2020-09-08 16:47:06 +02:00
{
VkShaderModuleCreateInfo vert_info = {};
vert_info . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
vert_info . codeSize = sizeof ( __glsl_shader_vert_spv );
vert_info . pCode = ( uint32_t * ) __glsl_shader_vert_spv ;
2021-06-28 16:52:10 +02:00
VkResult err = vkCreateShaderModule ( device , & vert_info , allocator , & bd -> ShaderModuleVert );
2020-09-08 16:47:06 +02:00
check_vk_result ( err );
}
2021-08-24 12:53:54 -07:00
if ( bd -> ShaderModuleFrag == VK_NULL_HANDLE )
2020-09-08 16:47:06 +02:00
{
VkShaderModuleCreateInfo frag_info = {};
frag_info . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
frag_info . codeSize = sizeof ( __glsl_shader_frag_spv );
frag_info . pCode = ( uint32_t * ) __glsl_shader_frag_spv ;
2021-06-28 16:52:10 +02:00
VkResult err = vkCreateShaderModule ( device , & frag_info , allocator , & bd -> ShaderModuleFrag );
2020-09-08 16:47:06 +02:00
check_vk_result ( err );
}
}
2020-11-07 07:32:48 -08:00
static void ImGui_ImplVulkan_CreatePipeline ( VkDevice device , const VkAllocationCallbacks * allocator , VkPipelineCache pipelineCache , VkRenderPass renderPass , VkSampleCountFlagBits MSAASamples , VkPipeline * pipeline , uint32_t subpass )
2020-09-08 16:47:06 +02:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
2020-09-08 16:47:06 +02:00
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 ;
2021-06-28 16:52:10 +02:00
stage [ 0 ]. module = bd -> ShaderModuleVert ;
2020-09-08 16:47:06 +02:00
stage [ 0 ]. pName = "main" ;
stage [ 1 ]. sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
stage [ 1 ]. stage = VK_SHADER_STAGE_FRAGMENT_BIT ;
2021-06-28 16:52:10 +02:00
stage [ 1 ]. module = bd -> ShaderModuleFrag ;
2020-09-08 16:47:06 +02:00
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 = IM_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 = IM_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 = IM_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 = ( MSAASamples != 0 ) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT ;
VkPipelineColorBlendAttachmentState color_attachment [ 1 ] = {};
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 ;
2021-02-17 19:29:07 +01:00
color_attachment [ 0 ]. srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE ;
color_attachment [ 0 ]. dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
2020-09-08 16:47:06 +02:00
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 = 1 ;
blend_info . pAttachments = color_attachment ;
VkDynamicState dynamic_states [ 2 ] = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamic_state = {};
dynamic_state . sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO ;
dynamic_state . dynamicStateCount = ( uint32_t ) IM_ARRAYSIZE ( dynamic_states );
dynamic_state . pDynamicStates = dynamic_states ;
VkGraphicsPipelineCreateInfo info = {};
info . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
2021-06-28 16:52:10 +02:00
info . flags = bd -> PipelineCreateFlags ;
2020-09-08 16:47:06 +02:00
info . stageCount = 2 ;
info . pStages = stage ;
info . pVertexInputState = & vertex_info ;
info . pInputAssemblyState = & ia_info ;
info . pViewportState = & viewport_info ;
info . pRasterizationState = & raster_info ;
info . pMultisampleState = & ms_info ;
info . pDepthStencilState = & depth_info ;
info . pColorBlendState = & blend_info ;
info . pDynamicState = & dynamic_state ;
2021-06-28 16:52:10 +02:00
info . layout = bd -> PipelineLayout ;
2020-09-08 16:47:06 +02:00
info . renderPass = renderPass ;
2020-11-07 07:32:48 -08:00
info . subpass = subpass ;
2022-02-19 20:15:58 +01:00
2023-07-03 17:48:28 +02:00
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
2022-02-19 20:15:58 +01:00
VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo = {};
pipelineRenderingCreateInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR ;
pipelineRenderingCreateInfo . colorAttachmentCount = 1 ;
pipelineRenderingCreateInfo . pColorAttachmentFormats = & bd -> VulkanInitInfo . ColorAttachmentFormat ;
2023-07-03 17:48:28 +02:00
if ( bd -> VulkanInitInfo . UseDynamicRendering )
{
2022-02-19 20:15:58 +01:00
info . pNext = & pipelineRenderingCreateInfo ;
info . renderPass = VK_NULL_HANDLE ; // Just make sure it's actually nullptr.
}
#endif
2020-09-08 16:47:06 +02:00
VkResult err = vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & info , allocator , pipeline );
check_vk_result ( err );
}
2018-06-08 19:37:33 +02:00
bool ImGui_ImplVulkan_CreateDeviceObjects ()
2016-03-09 16:39:54 +01:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
2016-03-09 16:39:54 +01:00
VkResult err ;
2016-04-03 17:32:53 +02:00
2021-06-28 16:52:10 +02:00
if ( ! bd -> FontSampler )
2016-04-03 17:32:53 +02:00
{
2022-12-16 16:46:14 +01:00
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
2016-03-09 16:39:54 +01:00
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_REPEAT ;
info . addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT ;
info . addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT ;
info . minLod = - 1000 ;
info . maxLod = 1000 ;
2017-05-01 17:07:53 +02:00
info . maxAnisotropy = 1.0f ;
2021-06-28 16:52:10 +02:00
err = vkCreateSampler ( v -> Device , & info , v -> Allocator , & bd -> FontSampler );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
2021-06-28 16:52:10 +02:00
if ( ! bd -> DescriptorSetLayout )
2016-04-03 17:32:53 +02:00
{
2016-03-09 16:39:54 +01:00
VkDescriptorSetLayoutBinding binding [ 1 ] = {};
binding [ 0 ]. descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ;
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 ;
2021-06-28 16:52:10 +02:00
err = vkCreateDescriptorSetLayout ( v -> Device , & info , v -> Allocator , & bd -> DescriptorSetLayout );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
}
2016-04-03 17:32:53 +02:00
2021-06-28 16:52:10 +02:00
if ( ! bd -> PipelineLayout )
2016-04-03 17:32:53 +02:00
{
2018-06-08 19:37:33 +02:00
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
2016-08-20 13:08:34 +02:00
VkPushConstantRange push_constants [ 1 ] = {};
2016-03-09 16:39:54 +01:00
push_constants [ 0 ]. stageFlags = VK_SHADER_STAGE_VERTEX_BIT ;
push_constants [ 0 ]. offset = sizeof ( float ) * 0 ;
2016-08-20 13:08:34 +02:00
push_constants [ 0 ]. size = sizeof ( float ) * 4 ;
2021-06-28 16:52:10 +02:00
VkDescriptorSetLayout set_layout [ 1 ] = { bd -> DescriptorSetLayout };
2016-03-09 16:39:54 +01:00
VkPipelineLayoutCreateInfo layout_info = {};
layout_info . sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO ;
layout_info . setLayoutCount = 1 ;
layout_info . pSetLayouts = set_layout ;
2016-08-20 13:08:34 +02:00
layout_info . pushConstantRangeCount = 1 ;
2016-03-09 16:39:54 +01:00
layout_info . pPushConstantRanges = push_constants ;
2021-06-28 16:52:10 +02:00
err = vkCreatePipelineLayout ( v -> Device , & layout_info , v -> Allocator , & bd -> PipelineLayout );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2016-03-09 16:39:54 +01:00
}
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_CreatePipeline ( v -> Device , v -> Allocator , v -> PipelineCache , bd -> RenderPass , v -> MSAASamples , & bd -> Pipeline , bd -> Subpass );
2016-03-09 16:39:54 +01:00
return true ;
}
2019-04-03 19:21:06 +02:00
void ImGui_ImplVulkan_DestroyFontUploadObjects ()
2016-03-09 16:39:54 +01:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
if ( bd -> UploadBuffer )
2016-04-03 17:32:53 +02:00
{
2021-06-28 16:52:10 +02:00
vkDestroyBuffer ( v -> Device , bd -> UploadBuffer , v -> Allocator );
bd -> UploadBuffer = VK_NULL_HANDLE ;
2016-03-09 16:39:54 +01:00
}
2021-06-28 16:52:10 +02:00
if ( bd -> UploadBufferMemory )
2016-04-03 17:32:53 +02:00
{
2021-06-28 16:52:10 +02:00
vkFreeMemory ( v -> Device , bd -> UploadBufferMemory , v -> Allocator );
bd -> UploadBufferMemory = VK_NULL_HANDLE ;
2016-03-09 16:39:54 +01:00
}
}
2016-04-03 17:32:53 +02:00
2019-04-03 19:21:06 +02:00
void ImGui_ImplVulkan_DestroyDeviceObjects ()
2019-04-03 18:33:13 +02:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
ImGui_ImplVulkanH_DestroyWindowRenderBuffers ( v -> Device , & bd -> MainWindowRenderBuffers , v -> Allocator );
2019-04-04 22:36:12 +02:00
ImGui_ImplVulkan_DestroyFontUploadObjects ();
2019-04-05 17:48:47 +02:00
2021-06-28 16:52:10 +02:00
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 -> FontView ) { vkDestroyImageView ( v -> Device , bd -> FontView , v -> Allocator ); bd -> FontView = VK_NULL_HANDLE ; }
if ( bd -> FontImage ) { vkDestroyImage ( v -> Device , bd -> FontImage , v -> Allocator ); bd -> FontImage = VK_NULL_HANDLE ; }
if ( bd -> FontMemory ) { vkFreeMemory ( v -> Device , bd -> FontMemory , v -> Allocator ); bd -> FontMemory = VK_NULL_HANDLE ; }
if ( bd -> FontSampler ) { vkDestroySampler ( v -> Device , bd -> FontSampler , v -> Allocator ); bd -> FontSampler = VK_NULL_HANDLE ; }
if ( bd -> DescriptorSetLayout ) { vkDestroyDescriptorSetLayout ( v -> Device , bd -> DescriptorSetLayout , v -> Allocator ); bd -> DescriptorSetLayout = 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 ; }
2019-04-03 18:33:13 +02:00
}
2021-01-27 13:23:28 +01:00
bool ImGui_ImplVulkan_LoadFunctions ( 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([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
// But this would be equivalent to not setting VK_NO_PROTOTYPES.
#ifdef VK_NO_PROTOTYPES
#define IMGUI_VULKAN_FUNC_LOAD(func) \
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
2022-10-11 12:22:29 +02:00
if (func == nullptr) \
2021-01-27 13:23:28 +01:00
return false;
IMGUI_VULKAN_FUNC_MAP ( IMGUI_VULKAN_FUNC_LOAD )
#undef IMGUI_VULKAN_FUNC_LOAD
2022-02-19 20:15:58 +01:00
2023-07-03 17:48:28 +02:00
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
// Manually load those two (see #5446)
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast < PFN_vkCmdBeginRenderingKHR > ( loader_func ( "vkCmdBeginRenderingKHR" , user_data ));
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast < PFN_vkCmdEndRenderingKHR > ( loader_func ( "vkCmdEndRenderingKHR" , user_data ));
2022-02-19 20:15:58 +01:00
#endif
2021-01-27 13:23:28 +01:00
#else
IM_UNUSED ( loader_func );
IM_UNUSED ( user_data );
#endif
2022-02-19 20:15:58 +01:00
2021-01-27 13:23:28 +01:00
g_FunctionsLoaded = true ;
return true ;
}
2018-06-08 19:37:33 +02:00
bool ImGui_ImplVulkan_Init ( ImGui_ImplVulkan_InitInfo * info , VkRenderPass render_pass )
2018-02-20 14:09:46 +01:00
{
2021-01-27 13:23:28 +01:00
IM_ASSERT ( g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
2021-01-26 21:04:12 +03:30
2023-07-03 17:48:28 +02:00
if ( info -> UseDynamicRendering )
{
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
2022-02-19 20:15:58 +01:00
#ifndef VK_NO_PROTOTYPES
2023-07-03 17:48:28 +02:00
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast < PFN_vkCmdBeginRenderingKHR > ( vkGetInstanceProcAddr ( info -> Instance , "vkCmdBeginRenderingKHR" ));
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast < PFN_vkCmdEndRenderingKHR > ( vkGetInstanceProcAddr ( info -> Instance , "vkCmdEndRenderingKHR" ));
2022-02-19 20:15:58 +01:00
#endif
2023-07-03 17:48:28 +02:00
IM_ASSERT ( ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR != nullptr );
IM_ASSERT ( ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR != nullptr );
2022-02-19 20:15:58 +01:00
#else
2023-07-03 17:48:28 +02:00
IM_ASSERT ( 0 && "Can't use dynamic rendering when neither VK_VERSION_1_3 or VK_KHR_dynamic_rendering is defined." );
2022-02-19 20:15:58 +01:00
#endif
}
2018-11-30 18:18:15 +01:00
ImGuiIO & io = ImGui :: GetIO ();
2022-10-11 12:22:29 +02:00
IM_ASSERT ( io . BackendRendererUserData == nullptr && "Already initialized a renderer backend!" );
2021-06-28 16:52:10 +02:00
// Setup backend capabilities flags
2021-06-30 15:22:15 +02:00
ImGui_ImplVulkan_Data * bd = IM_NEW ( ImGui_ImplVulkan_Data )();
2021-06-28 16:52:10 +02:00
io . BackendRendererUserData = ( void * ) bd ;
2018-11-30 18:18:15 +01:00
io . BackendRendererName = "imgui_impl_vulkan" ;
2019-05-29 16:29:17 +02:00
io . BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset ; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
2018-11-30 18:18:15 +01:00
2018-08-28 18:22:36 +02:00
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 -> DescriptorPool != VK_NULL_HANDLE );
2019-04-04 23:11:15 +02:00
IM_ASSERT ( info -> MinImageCount >= 2 );
2019-04-05 17:22:24 +02:00
IM_ASSERT ( info -> ImageCount >= info -> MinImageCount );
2023-07-03 17:48:28 +02:00
if ( info -> UseDynamicRendering == false )
2022-02-19 20:15:58 +01:00
IM_ASSERT ( render_pass != VK_NULL_HANDLE );
2018-02-20 14:09:46 +01:00
2021-06-28 16:52:10 +02:00
bd -> VulkanInitInfo = * info ;
bd -> RenderPass = render_pass ;
bd -> Subpass = info -> Subpass ;
2020-11-07 07:32:48 -08:00
2018-06-08 19:37:33 +02:00
ImGui_ImplVulkan_CreateDeviceObjects ();
2016-03-09 16:39:54 +01:00
return true ;
}
2018-06-08 19:37:33 +02:00
void ImGui_ImplVulkan_Shutdown ()
2016-03-09 16:39:54 +01:00
{
2021-06-30 15:22:15 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
2022-10-11 12:22:29 +02:00
IM_ASSERT ( bd != nullptr && "No renderer backend to shutdown, or already shutdown?" );
2021-09-20 18:43:05 +02:00
ImGuiIO & io = ImGui :: GetIO ();
2021-06-30 15:22:15 +02:00
2019-04-03 19:21:06 +02:00
ImGui_ImplVulkan_DestroyDeviceObjects ();
2022-10-11 12:22:29 +02:00
io . BackendRendererName = nullptr ;
io . BackendRendererUserData = nullptr ;
2023-04-17 14:47:15 +02:00
io . BackendFlags &= ~ ImGuiBackendFlags_RendererHasVtxOffset ;
2021-06-30 15:22:15 +02:00
IM_DELETE ( bd );
2016-03-09 16:39:54 +01:00
}
2018-06-08 19:37:33 +02:00
void ImGui_ImplVulkan_NewFrame ()
2016-03-09 16:39:54 +01:00
{
2021-06-29 17:53:41 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
2022-10-11 12:22:29 +02:00
IM_ASSERT ( bd != nullptr && "Did you call ImGui_ImplVulkan_Init()?" );
2021-06-29 17:53:41 +02:00
IM_UNUSED ( bd );
2018-06-08 19:37:33 +02:00
}
2016-03-09 16:39:54 +01:00
2019-04-05 17:48:47 +02:00
void ImGui_ImplVulkan_SetMinImageCount ( uint32_t min_image_count )
2018-09-09 16:04:44 +10:00
{
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
2019-04-04 23:11:15 +02:00
IM_ASSERT ( min_image_count >= 2 );
2021-06-28 16:52:10 +02:00
if ( bd -> VulkanInitInfo . MinImageCount == min_image_count )
2019-04-05 17:48:47 +02:00
return ;
2019-04-04 23:11:15 +02:00
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
2019-04-05 17:48:47 +02:00
VkResult err = vkDeviceWaitIdle ( v -> Device );
check_vk_result ( err );
2021-06-28 16:52:10 +02:00
ImGui_ImplVulkanH_DestroyWindowRenderBuffers ( v -> Device , & bd -> MainWindowRenderBuffers , v -> Allocator );
bd -> VulkanInitInfo . MinImageCount = min_image_count ;
2018-09-09 16:04:44 +10:00
}
2022-01-20 15:32:49 +01:00
// Register a texture
// 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.
2022-01-20 15:53:28 +01:00
VkDescriptorSet ImGui_ImplVulkan_AddTexture ( VkSampler sampler , VkImageView image_view , VkImageLayout image_layout )
2022-01-20 15:32:49 +01:00
{
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
// Create Descriptor Set:
VkDescriptorSet descriptor_set ;
{
VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info . sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO ;
alloc_info . descriptorPool = v -> DescriptorPool ;
alloc_info . descriptorSetCount = 1 ;
alloc_info . pSetLayouts = & bd -> DescriptorSetLayout ;
VkResult err = vkAllocateDescriptorSets ( v -> Device , & alloc_info , & descriptor_set );
check_vk_result ( err );
}
// Update the Descriptor Set:
{
VkDescriptorImageInfo desc_image [ 1 ] = {};
desc_image [ 0 ]. sampler = sampler ;
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_COMBINED_IMAGE_SAMPLER ;
write_desc [ 0 ]. pImageInfo = desc_image ;
2022-10-11 12:22:29 +02:00
vkUpdateDescriptorSets ( v -> Device , 1 , write_desc , 0 , nullptr );
2022-01-20 15:32:49 +01:00
}
2022-01-20 15:53:28 +01:00
return descriptor_set ;
2022-01-20 15:32:49 +01:00
}
2018-08-22 17:59:58 +02:00
2022-10-04 12:02:48 +02:00
void ImGui_ImplVulkan_RemoveTexture ( VkDescriptorSet descriptor_set )
{
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ();
ImGui_ImplVulkan_InitInfo * v = & bd -> VulkanInitInfo ;
vkFreeDescriptorSets ( v -> Device , v -> DescriptorPool , 1 , & descriptor_set );
}
2018-06-08 19:37:33 +02:00
//-------------------------------------------------------------------------
2018-08-22 17:59:58 +02:00
// Internal / Miscellaneous Vulkan Helpers
2019-04-03 18:33:13 +02:00
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
2018-08-22 16:43:29 +02:00
//-------------------------------------------------------------------------
2019-01-20 17:56:17 +01:00
// You probably do NOT need to use or care about those functions.
2018-08-22 17:59:58 +02:00
// 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.
2020-10-12 17:34:22 +02:00
// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,
2018-08-22 17:59:58 +02:00
// but it is too much code to duplicate everywhere so we exceptionally expose them.
2019-04-03 18:33:13 +02:00
//
2019-04-04 22:27:29 +02:00
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
2018-08-22 17:59:58 +02:00
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
2019-04-03 18:33:13 +02:00
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
2018-06-08 19:37:33 +02:00
//-------------------------------------------------------------------------
2016-03-09 16:39:54 +01:00
2018-06-08 19:37:33 +02:00
VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat ( VkPhysicalDevice physical_device , VkSurfaceKHR surface , const VkFormat * request_formats , int request_formats_count , VkColorSpaceKHR request_color_space )
{
2021-01-27 13:23:28 +01:00
IM_ASSERT ( g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
2022-10-11 12:22:29 +02:00
IM_ASSERT ( request_formats != nullptr );
2018-06-08 19:37:33 +02:00
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 ;
2022-10-11 12:22:29 +02:00
vkGetPhysicalDeviceSurfaceFormatsKHR ( physical_device , surface , & avail_count , nullptr );
2018-06-08 19:37:33 +02:00
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 )
2016-03-09 16:39:54 +01:00
{
2018-06-08 19:37:33 +02:00
if ( avail_format [ 0 ]. format == VK_FORMAT_UNDEFINED )
2018-03-20 21:19:23 +01:00
{
2018-06-08 19:37:33 +02:00
VkSurfaceFormatKHR ret ;
ret . format = request_formats [ 0 ];
ret . colorSpace = request_color_space ;
return ret ;
2018-03-20 21:19:23 +01:00
}
else
{
2018-06-08 19:37:33 +02:00
// No point in searching another format
return avail_format [ 0 ];
}
}
else
{
2019-01-20 17:56:17 +01:00
// Request several formats, the first found will be used
2018-06-08 19:37:33 +02:00
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 )
{
2021-01-27 13:23:28 +01:00
IM_ASSERT ( g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
2022-10-11 12:22:29 +02:00
IM_ASSERT ( request_modes != nullptr );
2018-06-08 19:37:33 +02:00
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 ;
2022-10-11 12:22:29 +02:00
vkGetPhysicalDeviceSurfacePresentModesKHR ( physical_device , surface , & avail_count , nullptr );
2018-06-08 19:37:33 +02:00
ImVector < VkPresentModeKHR > avail_modes ;
avail_modes . resize (( int ) avail_count );
vkGetPhysicalDeviceSurfacePresentModesKHR ( physical_device , surface , & avail_count , avail_modes . Data );
2018-08-25 21:15:37 +02:00
//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]);
2018-06-08 19:37:33 +02:00
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
}
2019-04-05 17:54:16 +02:00
void ImGui_ImplVulkanH_CreateWindowCommandBuffers ( VkPhysicalDevice physical_device , VkDevice device , ImGui_ImplVulkanH_Window * wd , uint32_t queue_family , const VkAllocationCallbacks * allocator )
2018-06-08 19:37:33 +02:00
{
2019-04-05 17:54:16 +02:00
IM_ASSERT ( physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE );
2018-10-30 13:15:30 -07:00
( void ) physical_device ;
2018-06-08 19:37:33 +02:00
( void ) allocator ;
// Create Command Buffers
VkResult err ;
2019-04-05 17:22:24 +02:00
for ( uint32_t i = 0 ; i < wd -> ImageCount ; i ++ )
2018-06-08 19:37:33 +02:00
{
2019-04-04 23:28:29 +02:00
ImGui_ImplVulkanH_Frame * fd = & wd -> Frames [ i ];
2019-04-05 15:50:21 +11:00
ImGui_ImplVulkanH_FrameSemaphores * fsd = & wd -> FrameSemaphores [ i ];
2018-06-08 19:37:33 +02:00
{
VkCommandPoolCreateInfo info = {};
info . sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO ;
info . flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT ;
info . queueFamilyIndex = queue_family ;
err = vkCreateCommandPool ( device , & info , allocator , & fd -> CommandPool );
check_vk_result ( err );
}
{
VkCommandBufferAllocateInfo info = {};
info . sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO ;
info . commandPool = fd -> CommandPool ;
info . level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ;
info . commandBufferCount = 1 ;
err = vkAllocateCommandBuffers ( device , & info , & fd -> CommandBuffer );
check_vk_result ( err );
}
{
VkFenceCreateInfo info = {};
info . sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO ;
info . flags = VK_FENCE_CREATE_SIGNALED_BIT ;
err = vkCreateFence ( device , & info , allocator , & fd -> Fence );
check_vk_result ( err );
}
{
VkSemaphoreCreateInfo info = {};
info . sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO ;
2019-04-05 15:50:21 +11:00
err = vkCreateSemaphore ( device , & info , allocator , & fsd -> ImageAcquiredSemaphore );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2019-04-05 15:50:21 +11:00
err = vkCreateSemaphore ( device , & info , allocator , & fsd -> RenderCompleteSemaphore );
2018-06-08 19:37:33 +02:00
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 ;
}
2019-04-04 22:27:29 +02:00
// Also destroy old swap chain and in-flight frames data, if any.
2019-04-05 17:54:16 +02:00
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 )
2018-06-08 19:37:33 +02:00
{
VkResult err ;
VkSwapchainKHR old_swapchain = wd -> Swapchain ;
2021-08-24 12:53:54 -07:00
wd -> Swapchain = VK_NULL_HANDLE ;
2018-06-08 19:37:33 +02:00
err = vkDeviceWaitIdle ( device );
check_vk_result ( err );
2019-04-04 23:28:29 +02:00
// We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
2018-06-08 19:37:33 +02:00
// Destroy old Framebuffer
2019-04-05 17:22:24 +02:00
for ( uint32_t i = 0 ; i < wd -> ImageCount ; i ++ )
2019-04-05 15:50:21 +11:00
{
2019-04-05 17:54:16 +02:00
ImGui_ImplVulkanH_DestroyFrame ( device , & wd -> Frames [ i ], allocator );
ImGui_ImplVulkanH_DestroyFrameSemaphores ( device , & wd -> FrameSemaphores [ i ], allocator );
2019-04-05 15:50:21 +11:00
}
2019-04-05 20:27:46 +02:00
IM_FREE ( wd -> Frames );
IM_FREE ( wd -> FrameSemaphores );
2022-10-11 12:22:29 +02:00
wd -> Frames = nullptr ;
wd -> FrameSemaphores = nullptr ;
2019-04-05 17:22:24 +02:00
wd -> ImageCount = 0 ;
2018-06-08 19:37:33 +02:00
if ( wd -> RenderPass )
vkDestroyRenderPass ( device , wd -> RenderPass , allocator );
2020-09-08 16:47:06 +02:00
if ( wd -> Pipeline )
vkDestroyPipeline ( device , wd -> Pipeline , allocator );
2019-01-20 17:56:17 +01:00
2018-06-08 19:37:33 +02:00
// 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
{
VkSwapchainCreateInfoKHR info = {};
info . sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR ;
info . surface = wd -> Surface ;
2019-04-03 17:23:31 +02:00
info . minImageCount = min_image_count ;
2018-06-08 19:37:33 +02:00
info . imageFormat = wd -> SurfaceFormat . format ;
info . imageColorSpace = wd -> SurfaceFormat . colorSpace ;
info . imageArrayLayers = 1 ;
info . imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ;
info . imageSharingMode = VK_SHARING_MODE_EXCLUSIVE ; // Assume that graphics family == present family
info . preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ;
info . compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR ;
info . presentMode = wd -> PresentMode ;
info . clipped = VK_TRUE ;
info . oldSwapchain = old_swapchain ;
VkSurfaceCapabilitiesKHR cap ;
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR ( physical_device , wd -> Surface , & cap );
check_vk_result ( err );
2018-08-25 21:15:37 +02:00
if ( info . minImageCount < cap . minImageCount )
2019-04-03 17:23:31 +02:00
info . minImageCount = cap . minImageCount ;
else if ( cap . maxImageCount != 0 && info . minImageCount > cap . maxImageCount )
info . minImageCount = cap . maxImageCount ;
2018-06-08 19:37:33 +02:00
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 );
2022-10-11 12:22:29 +02:00
err = vkGetSwapchainImagesKHR ( device , wd -> Swapchain , & wd -> ImageCount , nullptr );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2019-04-03 17:56:18 +02:00
VkImage backbuffers [ 16 ] = {};
2019-04-05 17:22:24 +02:00
IM_ASSERT ( wd -> ImageCount >= min_image_count );
IM_ASSERT ( wd -> ImageCount < IM_ARRAYSIZE ( backbuffers ));
err = vkGetSwapchainImagesKHR ( device , wd -> Swapchain , & wd -> ImageCount , backbuffers );
2018-09-11 22:18:24 +02:00
check_vk_result ( err );
2018-09-09 16:04:44 +10:00
2022-10-11 12:22:29 +02:00
IM_ASSERT ( wd -> Frames == nullptr );
2019-04-05 20:27:46 +02:00
wd -> Frames = ( ImGui_ImplVulkanH_Frame * ) IM_ALLOC ( sizeof ( ImGui_ImplVulkanH_Frame ) * wd -> ImageCount );
wd -> FrameSemaphores = ( ImGui_ImplVulkanH_FrameSemaphores * ) IM_ALLOC ( sizeof ( ImGui_ImplVulkanH_FrameSemaphores ) * wd -> ImageCount );
2019-04-05 17:22:24 +02:00
memset ( wd -> Frames , 0 , sizeof ( wd -> Frames [ 0 ]) * wd -> ImageCount );
memset ( wd -> FrameSemaphores , 0 , sizeof ( wd -> FrameSemaphores [ 0 ]) * wd -> ImageCount );
for ( uint32_t i = 0 ; i < wd -> ImageCount ; i ++ )
2019-04-03 19:21:06 +02:00
wd -> Frames [ i ]. Backbuffer = backbuffers [ i ];
2018-06-08 19:37:33 +02:00
}
if ( old_swapchain )
vkDestroySwapchainKHR ( device , old_swapchain , allocator );
// Create the Render Pass
2023-07-03 17:48:28 +02:00
if ( wd -> UseDynamicRendering == false )
{
2018-06-08 19:37:33 +02:00
VkAttachmentDescription attachment = {};
attachment . format = wd -> SurfaceFormat . format ;
attachment . samples = VK_SAMPLE_COUNT_1_BIT ;
attachment . loadOp = wd -> ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attachment . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attachment . stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attachment . stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attachment . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
attachment . finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ;
VkAttachmentReference color_attachment = {};
color_attachment . attachment = 0 ;
color_attachment . layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
VkSubpassDescription subpass = {};
subpass . pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS ;
subpass . colorAttachmentCount = 1 ;
subpass . pColorAttachments = & color_attachment ;
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 );
2020-09-08 22:39:53 +02:00
// 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:
2021-06-28 16:52:10 +02:00
//ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, bd->Subpass);
2018-06-08 19:37:33 +02:00
}
// 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 ;
2019-04-05 17:22:24 +02:00
for ( uint32_t i = 0 ; i < wd -> ImageCount ; i ++ )
2018-06-08 19:37:33 +02:00
{
2019-04-04 23:28:29 +02:00
ImGui_ImplVulkanH_Frame * fd = & wd -> Frames [ i ];
2019-04-03 19:21:06 +02:00
info . image = fd -> Backbuffer ;
err = vkCreateImageView ( device , & info , allocator , & fd -> BackbufferView );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
2018-03-20 21:19:23 +01:00
}
2018-02-20 14:18:02 +01:00
}
2016-03-09 16:39:54 +01:00
2018-06-08 19:37:33 +02:00
// Create Framebuffer
2023-07-03 17:48:28 +02:00
if ( wd -> UseDynamicRendering == false )
{
2018-06-08 19:37:33 +02:00
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 ;
2019-04-05 17:22:24 +02:00
for ( uint32_t i = 0 ; i < wd -> ImageCount ; i ++ )
2018-06-08 19:37:33 +02:00
{
2019-04-04 23:28:29 +02:00
ImGui_ImplVulkanH_Frame * fd = & wd -> Frames [ i ];
2019-04-03 19:21:06 +02:00
attachment [ 0 ] = fd -> BackbufferView ;
2019-04-03 17:56:18 +02:00
err = vkCreateFramebuffer ( device , & info , allocator , & fd -> Framebuffer );
2018-06-08 19:37:33 +02:00
check_vk_result ( err );
}
}
2016-03-09 16:39:54 +01:00
}
2016-11-12 17:49:59 +01:00
2020-05-25 12:05:11 +02:00
// Create or resize window
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 )
2019-04-03 18:33:13 +02:00
{
2021-01-27 13:23:28 +01:00
IM_ASSERT ( g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!" );
2019-04-05 17:54:16 +02:00
( void ) instance ;
ImGui_ImplVulkanH_CreateWindowSwapChain ( physical_device , device , wd , allocator , width , height , min_image_count );
ImGui_ImplVulkanH_CreateWindowCommandBuffers ( physical_device , device , wd , queue_family , allocator );
2019-04-03 18:33:13 +02:00
}
2019-04-04 23:28:29 +02:00
void ImGui_ImplVulkanH_DestroyWindow ( VkInstance instance , VkDevice device , ImGui_ImplVulkanH_Window * wd , const VkAllocationCallbacks * allocator )
2016-03-09 16:39:54 +01:00
{
2018-06-08 19:37:33 +02:00
vkDeviceWaitIdle ( device ); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
2021-06-28 16:52:10 +02:00
//vkQueueWaitIdle(bd->Queue);
2018-06-08 19:37:33 +02:00
2019-04-05 17:22:24 +02:00
for ( uint32_t i = 0 ; i < wd -> ImageCount ; i ++ )
2019-04-05 15:50:21 +11:00
{
2019-04-05 17:54:16 +02:00
ImGui_ImplVulkanH_DestroyFrame ( device , & wd -> Frames [ i ], allocator );
ImGui_ImplVulkanH_DestroyFrameSemaphores ( device , & wd -> FrameSemaphores [ i ], allocator );
2019-04-05 15:50:21 +11:00
}
2019-04-05 20:27:46 +02:00
IM_FREE ( wd -> Frames );
IM_FREE ( wd -> FrameSemaphores );
2022-10-11 12:22:29 +02:00
wd -> Frames = nullptr ;
wd -> FrameSemaphores = nullptr ;
2020-09-08 22:39:53 +02:00
vkDestroyPipeline ( device , wd -> Pipeline , allocator );
2018-06-08 19:37:33 +02:00
vkDestroyRenderPass ( device , wd -> RenderPass , allocator );
vkDestroySwapchainKHR ( device , wd -> Swapchain , allocator );
vkDestroySurfaceKHR ( instance , wd -> Surface , allocator );
2019-04-04 22:27:29 +02:00
2019-04-04 23:28:29 +02:00
* wd = ImGui_ImplVulkanH_Window ();
2016-03-09 16:39:54 +01:00
}
2018-09-09 16:04:44 +10:00
2019-04-05 17:54:16 +02:00
void ImGui_ImplVulkanH_DestroyFrame ( VkDevice device , ImGui_ImplVulkanH_Frame * fd , const VkAllocationCallbacks * allocator )
2018-09-09 16:04:44 +10:00
{
2018-09-11 22:18:24 +02:00
vkDestroyFence ( device , fd -> Fence , allocator );
vkFreeCommandBuffers ( device , fd -> CommandPool , 1 , & fd -> CommandBuffer );
vkDestroyCommandPool ( device , fd -> CommandPool , allocator );
2019-04-03 15:48:22 +02:00
fd -> Fence = VK_NULL_HANDLE ;
fd -> CommandBuffer = VK_NULL_HANDLE ;
fd -> CommandPool = VK_NULL_HANDLE ;
2019-04-03 17:56:18 +02:00
2019-04-03 19:21:06 +02:00
vkDestroyImageView ( device , fd -> BackbufferView , allocator );
2019-04-03 17:56:18 +02:00
vkDestroyFramebuffer ( device , fd -> Framebuffer , allocator );
2019-04-05 17:48:47 +02:00
}
2019-04-04 22:27:29 +02:00
2019-04-05 17:54:16 +02:00
void ImGui_ImplVulkanH_DestroyFrameSemaphores ( VkDevice device , ImGui_ImplVulkanH_FrameSemaphores * fsd , const VkAllocationCallbacks * allocator )
2019-04-05 17:48:47 +02:00
{
vkDestroySemaphore ( device , fsd -> ImageAcquiredSemaphore , allocator );
vkDestroySemaphore ( device , fsd -> RenderCompleteSemaphore , allocator );
fsd -> ImageAcquiredSemaphore = fsd -> RenderCompleteSemaphore = VK_NULL_HANDLE ;
}
2019-04-05 17:54:16 +02:00
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers ( VkDevice device , ImGui_ImplVulkanH_FrameRenderBuffers * buffers , const VkAllocationCallbacks * allocator )
2019-04-05 17:48:47 +02:00
{
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 ;
}
2019-04-05 17:54:16 +02:00
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers ( VkDevice device , ImGui_ImplVulkanH_WindowRenderBuffers * buffers , const VkAllocationCallbacks * allocator )
2019-04-05 17:48:47 +02:00
{
for ( uint32_t n = 0 ; n < buffers -> Count ; n ++ )
2019-04-05 17:54:16 +02:00
ImGui_ImplVulkanH_DestroyFrameRenderBuffers ( device , & buffers -> FrameRenderBuffers [ n ], allocator );
2019-04-05 20:27:46 +02:00
IM_FREE ( buffers -> FrameRenderBuffers );
2022-10-11 12:22:29 +02:00
buffers -> FrameRenderBuffers = nullptr ;
2019-04-05 17:48:47 +02:00
buffers -> Index = 0 ;
buffers -> Count = 0 ;
2019-04-04 22:27:29 +02:00
}
2023-07-13 11:27:52 +02:00
//-----------------------------------------------------------------------------
#endif // #ifndef IMGUI_DISABLE