2018-09-13 14:44:08 +00:00
// dear imgui: Renderer for Vulkan
2018-02-21 22:05:17 +00:00
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
2018-02-05 19:34:11 +00:00
2019-05-29 13:53:36 +00:00
// Implemented features:
2019-11-20 10:58:25 +00:00
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
2019-11-27 18:27:44 +00:00
// [x] Platform: Multi-viewport / platform windows. With issues (flickering when creating a new viewport).
2018-02-05 19:34:11 +00:00
// Missing features:
2018-06-11 10:33:51 +00:00
// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914
2016-11-12 16:49:59 +00:00
2016-03-09 15:39:54 +00:00
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
2018-07-04 17:06:28 +00:00
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
2016-03-09 15:39:54 +00:00
// https://github.com/ocornut/imgui
2019-01-20 16:56:17 +00:00
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
2018-08-22 14:43:29 +00: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 17:21:06 +00:00
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
2019-04-05 18:27:46 +00:00
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
2019-04-03 17:21:06 +00:00
// You will use those if you want to use this rendering back-end in your engine/app.
2019-09-17 14:35:50 +00:00
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
2019-04-03 17:21:06 +00:00
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
// Read comments in imgui_impl_vulkan.h.
2018-02-16 16:20:18 +00:00
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
2019-07-31 18:50:50 +00: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 14:29:17 +00:00
// 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
2019-04-30 20:28:29 +00: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 20:09:12 +00:00
// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
2019-04-01 15:32:14 +00:00
// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
2019-02-16 11:27:46 +00:00
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
2018-11-30 17:18:15 +00:00
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
2018-08-25 19:15:37 +00:00
// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
2018-06-22 08:02:02 +00:00
// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other bindings.
2018-06-08 17:37:33 +00: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-02 23:29:17 +00:00
// 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 20:11:22 +00:00
// 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
2018-02-16 21:50:19 +00:00
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
2018-02-16 16:20:18 +00: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.
2018-01-29 13:38:46 +00:00
# include "imgui.h"
2018-02-16 21:50:19 +00:00
# include "imgui_impl_vulkan.h"
2018-03-18 17:44:57 +00:00
# include <stdio.h>
2016-03-09 15:39:54 +00:00
2019-04-05 15:48:47 +00: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 ;
} ;
2019-04-05 16:52:40 +00:00
// For multi-viewport support
struct ImGuiViewportDataVulkan
{
bool WindowOwned ;
ImGui_ImplVulkanH_Window Window ; // Used by secondary viewports only
ImGui_ImplVulkanH_WindowRenderBuffers RenderBuffers ; // Used by all viewports
ImGuiViewportDataVulkan ( ) { WindowOwned = false ; memset ( & RenderBuffers , 0 , sizeof ( RenderBuffers ) ) ; }
~ ImGuiViewportDataVulkan ( ) { }
} ;
2018-02-20 13:18:02 +00:00
// Vulkan data
2019-04-04 20:36:12 +00:00
static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = { } ;
2019-04-04 20:27:29 +00:00
static VkRenderPass g_RenderPass = VK_NULL_HANDLE ;
static VkDeviceSize g_BufferMemoryAlignment = 256 ;
static VkPipelineCreateFlags g_PipelineCreateFlags = 0x00 ;
static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE ;
static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE ;
static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE ;
static VkPipeline g_Pipeline = VK_NULL_HANDLE ;
2018-03-02 15:34:47 +00:00
// Font data
2019-04-04 20:27:29 +00:00
static VkSampler g_FontSampler = VK_NULL_HANDLE ;
static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE ;
static VkImage g_FontImage = VK_NULL_HANDLE ;
static VkImageView g_FontView = VK_NULL_HANDLE ;
static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE ;
static VkBuffer g_UploadBuffer = VK_NULL_HANDLE ;
2016-03-09 15:39:54 +00:00
2019-04-03 16:33:13 +00:00
// Forward Declarations
2019-04-05 16:52:40 +00:00
bool ImGui_ImplVulkan_CreateDeviceObjects ( ) ;
void ImGui_ImplVulkan_DestroyDeviceObjects ( ) ;
2019-04-05 15:54:16 +00: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 ) ;
2019-04-05 16:52:40 +00:00
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers ( VkDevice device , const VkAllocationCallbacks * allocator ) ;
2019-04-05 15:54:16 +00: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 ) ;
void ImGui_ImplVulkanH_CreateWindowCommandBuffers ( VkPhysicalDevice physical_device , VkDevice device , ImGui_ImplVulkanH_Window * wd , uint32_t queue_family , const VkAllocationCallbacks * allocator ) ;
2019-04-03 16:33:13 +00:00
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
2016-03-09 15:39:54 +00:00
2018-03-02 18:23:01 +00:00
// Forward Declarations
static void ImGui_ImplVulkan_InitPlatformInterface ( ) ;
static void ImGui_ImplVulkan_ShutdownPlatformInterface ( ) ;
2018-03-02 15:34:47 +00:00
// glsl_shader.vert, compiled with:
// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
2019-04-03 09:23:54 +00: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 02:00:36 +00:00
static uint32_t __glsl_shader_vert_spv [ ] =
2016-04-03 15:32:53 +00:00
{
2016-11-13 02:00:36 +00:00
0x07230203 , 0x00010000 , 0x00080001 , 0x0000002e , 0x00000000 , 0x00020011 , 0x00000001 , 0x0006000b ,
2016-10-18 20:40:58 +00:00
0x00000001 , 0x4c534c47 , 0x6474732e , 0x3035342e , 0x00000000 , 0x0003000e , 0x00000000 , 0x00000001 ,
0x000a000f , 0x00000000 , 0x00000004 , 0x6e69616d , 0x00000000 , 0x0000000b , 0x0000000f , 0x00000015 ,
2016-11-13 02:00:36 +00:00
0x0000001b , 0x0000001c , 0x00030003 , 0x00000002 , 0x000001c2 , 0x00040005 , 0x00000004 , 0x6e69616d ,
2016-10-18 20:40:58 +00: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 02:00:36 +00: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 15:39:54 +00:00
} ;
2018-03-02 15:34:47 +00:00
// glsl_shader.frag, compiled with:
// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
2019-04-03 09:23:54 +00: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 02:00:36 +00:00
static uint32_t __glsl_shader_frag_spv [ ] =
2016-04-03 15:32:53 +00:00
{
2016-10-18 20:40:58 +00: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 15:39:54 +00:00
} ;
2019-04-03 16:33:13 +00:00
//-----------------------------------------------------------------------------
// FUNCTIONS
//-----------------------------------------------------------------------------
2018-02-16 21:50:19 +00:00
static uint32_t ImGui_ImplVulkan_MemoryType ( VkMemoryPropertyFlags properties , uint32_t type_bits )
2016-03-09 15:39:54 +00:00
{
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2016-03-09 15:39:54 +00:00
VkPhysicalDeviceMemoryProperties prop ;
2019-04-04 20:36:12 +00:00
vkGetPhysicalDeviceMemoryProperties ( v - > PhysicalDevice , & prop ) ;
2016-04-03 15:32:53 +00:00
for ( uint32_t i = 0 ; i < prop . memoryTypeCount ; i + + )
if ( ( prop . memoryTypes [ i ] . propertyFlags & properties ) = = properties & & type_bits & ( 1 < < i ) )
2016-03-09 15:39:54 +00:00
return i ;
2018-03-02 22:59:21 +00:00
return 0xFFFFFFFF ; // Unable to find memoryType
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
2018-03-02 22:59:21 +00:00
static void check_vk_result ( VkResult err )
2016-03-09 15:39:54 +00:00
{
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
if ( v - > CheckVkResultFn )
v - > CheckVkResultFn ( err ) ;
2016-03-09 15:39:54 +00:00
}
2018-03-02 15:34:47 +00:00
static void CreateOrResizeBuffer ( VkBuffer & buffer , VkDeviceMemory & buffer_memory , VkDeviceSize & p_buffer_size , size_t new_size , VkBufferUsageFlagBits usage )
{
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2018-03-02 15:34:47 +00:00
VkResult err ;
2018-08-28 16:22:36 +00:00
if ( buffer ! = VK_NULL_HANDLE )
2019-04-04 20:36:12 +00:00
vkDestroyBuffer ( v - > Device , buffer , v - > Allocator ) ;
2019-04-05 18:27:46 +00:00
if ( buffer_memory ! = VK_NULL_HANDLE )
2019-04-04 20:36:12 +00:00
vkFreeMemory ( v - > Device , buffer_memory , v - > Allocator ) ;
2018-03-02 15:34:47 +00:00
VkDeviceSize vertex_buffer_size_aligned = ( ( new_size - 1 ) / g_BufferMemoryAlignment + 1 ) * g_BufferMemoryAlignment ;
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 20:36:12 +00:00
err = vkCreateBuffer ( v - > Device , & buffer_info , v - > Allocator , & buffer ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2018-03-02 15:34:47 +00:00
VkMemoryRequirements req ;
2019-04-04 20:36:12 +00:00
vkGetBufferMemoryRequirements ( v - > Device , buffer , & req ) ;
2018-03-02 15:34:47 +00:00
g_BufferMemoryAlignment = ( g_BufferMemoryAlignment > req . alignment ) ? g_BufferMemoryAlignment : req . alignment ;
VkMemoryAllocateInfo alloc_info = { } ;
alloc_info . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
alloc_info . allocationSize = req . size ;
alloc_info . memoryTypeIndex = ImGui_ImplVulkan_MemoryType ( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT , req . memoryTypeBits ) ;
2019-04-04 20:36:12 +00:00
err = vkAllocateMemory ( v - > Device , & alloc_info , v - > Allocator , & buffer_memory ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2018-03-02 15:34:47 +00:00
2019-04-04 20:36:12 +00:00
err = vkBindBufferMemory ( v - > Device , buffer , buffer_memory , 0 ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2018-03-02 15:34:47 +00:00
p_buffer_size = new_size ;
}
2019-04-30 20:15:59 +00:00
static void ImGui_ImplVulkan_SetupRenderState ( ImDrawData * draw_data , VkCommandBuffer command_buffer , ImGui_ImplVulkanH_FrameRenderBuffers * rb , int fb_width , int fb_height )
{
// Bind pipeline and descriptor sets:
{
vkCmdBindPipeline ( command_buffer , VK_PIPELINE_BIND_POINT_GRAPHICS , g_Pipeline ) ;
VkDescriptorSet desc_set [ 1 ] = { g_DescriptorSet } ;
vkCmdBindDescriptorSets ( command_buffer , VK_PIPELINE_BIND_POINT_GRAPHICS , g_PipelineLayout , 0 , 1 , desc_set , 0 , NULL ) ;
}
// Bind Vertex And Index Buffer:
{
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 14:16:18 +00: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 20:15:59 +00: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 ] ;
vkCmdPushConstants ( command_buffer , g_PipelineLayout , VK_SHADER_STAGE_VERTEX_BIT , sizeof ( float ) * 0 , sizeof ( float ) * 2 , scale ) ;
vkCmdPushConstants ( command_buffer , g_PipelineLayout , VK_SHADER_STAGE_VERTEX_BIT , sizeof ( float ) * 2 , sizeof ( float ) * 2 , translate ) ;
}
}
2018-06-22 08:02:02 +00:00
// Render function
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
2019-04-05 15:48:47 +00:00
void ImGui_ImplVulkan_RenderDrawData ( ImDrawData * draw_data , VkCommandBuffer command_buffer )
2016-03-09 15:39:54 +00:00
{
2019-02-16 11:33:38 +00: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 ) ;
if ( fb_width < = 0 | | fb_height < = 0 | | draw_data - > TotalVtxCount = = 0 )
2018-02-16 21:28:52 +00:00
return ;
2016-03-09 15:39:54 +00:00
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2019-04-05 15:48:47 +00:00
2019-04-05 16:52:40 +00:00
// Allocate array to store enough vertex/index buffers. Each unique viewport gets its own storage.
ImGuiViewportDataVulkan * viewport_renderer_data = ( ImGuiViewportDataVulkan * ) draw_data - > OwnerViewport - > RendererUserData ;
IM_ASSERT ( viewport_renderer_data ! = NULL ) ;
ImGui_ImplVulkanH_WindowRenderBuffers * wrb = & viewport_renderer_data - > RenderBuffers ;
2019-04-05 15:48:47 +00:00
if ( wrb - > FrameRenderBuffers = = NULL )
{
wrb - > Index = 0 ;
wrb - > Count = v - > ImageCount ;
2019-04-05 18:27:46 +00:00
wrb - > FrameRenderBuffers = ( ImGui_ImplVulkanH_FrameRenderBuffers * ) IM_ALLOC ( sizeof ( ImGui_ImplVulkanH_FrameRenderBuffers ) * wrb - > Count ) ;
2019-04-05 15:48:47 +00: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 ] ;
2019-02-16 11:33:38 +00:00
VkResult err ;
2016-04-03 15:32:53 +00:00
2019-04-05 15:48:47 +00:00
// Create or resize the vertex/index buffers
2018-03-02 15:34:47 +00:00
size_t vertex_size = draw_data - > TotalVtxCount * sizeof ( ImDrawVert ) ;
2016-03-09 15:39:54 +00:00
size_t index_size = draw_data - > TotalIdxCount * sizeof ( ImDrawIdx ) ;
2019-04-05 15:48:47 +00:00
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 ) ;
2016-04-03 15:32:53 +00:00
2019-03-29 15:17:04 +00:00
// Upload vertex/index data into a single contiguous GPU buffer
2016-03-09 15:39:54 +00:00
{
2018-08-22 14:43:29 +00:00
ImDrawVert * vtx_dst = NULL ;
ImDrawIdx * idx_dst = NULL ;
2019-04-05 15:48:47 +00:00
err = vkMapMemory ( v - > Device , rb - > VertexBufferMemory , 0 , vertex_size , 0 , ( void * * ) ( & vtx_dst ) ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2019-04-05 15:48:47 +00:00
err = vkMapMemory ( v - > Device , rb - > IndexBufferMemory , 0 , index_size , 0 , ( void * * ) ( & idx_dst ) ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-04-03 15:32:53 +00:00
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
2016-03-09 15:39:54 +00:00
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
2016-09-03 17:24:57 +00: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 15:39:54 +00:00
}
VkMappedMemoryRange range [ 2 ] = { } ;
range [ 0 ] . sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE ;
2019-04-05 15:48:47 +00:00
range [ 0 ] . memory = rb - > VertexBufferMemory ;
2017-02-11 11:08:59 +00:00
range [ 0 ] . size = VK_WHOLE_SIZE ;
2016-03-09 15:39:54 +00:00
range [ 1 ] . sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE ;
2019-04-05 15:48:47 +00:00
range [ 1 ] . memory = rb - > IndexBufferMemory ;
2017-02-11 11:08:59 +00:00
range [ 1 ] . size = VK_WHOLE_SIZE ;
2019-04-04 20:36:12 +00:00
err = vkFlushMappedMemoryRanges ( v - > Device , 2 , range ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2019-04-05 15:48:47 +00:00
vkUnmapMemory ( v - > Device , rb - > VertexBufferMemory ) ;
vkUnmapMemory ( v - > Device , rb - > IndexBufferMemory ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
2019-04-30 20:15:59 +00:00
// Setup desired Vulkan state
ImGui_ImplVulkan_SetupRenderState ( draw_data , command_buffer , rb , fb_width , fb_height ) ;
2016-04-03 15:32:53 +00:00
2019-02-16 11:27:46 +00: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 13:53:36 +00: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 15:32:53 +00:00
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
2016-03-09 15:39:54 +00:00
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
2016-09-03 17:24:57 +00:00
for ( int cmd_i = 0 ; cmd_i < cmd_list - > CmdBuffer . Size ; cmd_i + + )
2016-04-03 15:32:53 +00:00
{
2016-03-09 15:39:54 +00:00
const ImDrawCmd * pcmd = & cmd_list - > CmdBuffer [ cmd_i ] ;
2019-04-30 20:15:59 +00:00
if ( pcmd - > UserCallback ! = NULL )
2016-04-03 15:32:53 +00:00
{
2019-04-30 20:15:59 +00: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 )
ImGui_ImplVulkan_SetupRenderState ( draw_data , command_buffer , rb , fb_width , fb_height ) ;
else
pcmd - > UserCallback ( cmd_list , pcmd ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
else
{
2019-02-16 11:27:46 +00:00
// Project scissor/clipping rectangles into framebuffer space
ImVec4 clip_rect ;
clip_rect . x = ( pcmd - > ClipRect . x - clip_off . x ) * clip_scale . x ;
clip_rect . y = ( pcmd - > ClipRect . y - clip_off . y ) * clip_scale . y ;
clip_rect . z = ( pcmd - > ClipRect . z - clip_off . x ) * clip_scale . x ;
clip_rect . w = ( pcmd - > ClipRect . w - clip_off . y ) * clip_scale . y ;
2019-02-16 11:33:38 +00:00
if ( clip_rect . x < fb_width & & clip_rect . y < fb_height & & clip_rect . z > = 0.0f & & clip_rect . w > = 0.0f )
{
2019-04-04 20:09:12 +00:00
// Negative offsets are illegal for vkCmdSetScissor
if ( clip_rect . x < 0.0f )
clip_rect . x = 0.0f ;
if ( clip_rect . y < 0.0f )
clip_rect . y = 0.0f ;
2019-02-16 11:33:38 +00:00
// Apply scissor/clipping rectangle
VkRect2D scissor ;
scissor . offset . x = ( int32_t ) ( clip_rect . x ) ;
scissor . offset . y = ( int32_t ) ( clip_rect . y ) ;
scissor . extent . width = ( uint32_t ) ( clip_rect . z - clip_rect . x ) ;
scissor . extent . height = ( uint32_t ) ( clip_rect . w - clip_rect . y ) ;
vkCmdSetScissor ( command_buffer , 0 , 1 , & scissor ) ;
2019-01-20 16:56:17 +00:00
2019-02-16 11:33:38 +00:00
// Draw
2019-05-29 13:53:36 +00:00
vkCmdDrawIndexed ( command_buffer , pcmd - > ElemCount , 1 , pcmd - > IdxOffset + global_idx_offset , pcmd - > VtxOffset + global_vtx_offset , 0 ) ;
2019-02-16 11:33:38 +00:00
}
2016-03-09 15:39:54 +00:00
}
}
2019-05-29 13:53:36 +00:00
global_idx_offset + = cmd_list - > IdxBuffer . Size ;
global_vtx_offset + = cmd_list - > VtxBuffer . Size ;
2016-03-09 15:39:54 +00:00
}
}
2018-02-16 21:50:19 +00:00
bool ImGui_ImplVulkan_CreateFontsTexture ( VkCommandBuffer command_buffer )
2016-03-09 15:39:54 +00:00
{
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2016-03-09 15:39:54 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
unsigned char * pixels ;
int width , height ;
io . Fonts - > GetTexDataAsRGBA32 ( & pixels , & width , & height ) ;
size_t upload_size = width * height * 4 * sizeof ( char ) ;
VkResult err ;
2016-04-03 15:32:53 +00:00
2016-03-09 15:39:54 +00: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 15:32:53 +00:00
info . usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT ;
2016-03-09 15:39:54 +00:00
info . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
info . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
2019-04-04 20:36:12 +00:00
err = vkCreateImage ( v - > Device , & info , v - > Allocator , & g_FontImage ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
VkMemoryRequirements req ;
2019-04-04 20:36:12 +00:00
vkGetImageMemoryRequirements ( v - > Device , g_FontImage , & req ) ;
2016-03-09 15:39:54 +00:00
VkMemoryAllocateInfo alloc_info = { } ;
alloc_info . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
alloc_info . allocationSize = req . size ;
2018-02-16 21:50:19 +00:00
alloc_info . memoryTypeIndex = ImGui_ImplVulkan_MemoryType ( VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT , req . memoryTypeBits ) ;
2019-04-04 20:36:12 +00:00
err = vkAllocateMemory ( v - > Device , & alloc_info , v - > Allocator , & g_FontMemory ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2019-04-04 20:36:12 +00:00
err = vkBindImageMemory ( v - > Device , g_FontImage , g_FontMemory , 0 ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
2016-03-09 15:39:54 +00:00
// Create the Image View:
{
VkImageViewCreateInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO ;
info . image = g_FontImage ;
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 ;
2019-04-04 20:36:12 +00:00
err = vkCreateImageView ( v - > Device , & info , v - > Allocator , & g_FontView ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
2016-03-09 15:39:54 +00:00
// Update the Descriptor Set:
{
VkDescriptorImageInfo desc_image [ 1 ] = { } ;
desc_image [ 0 ] . sampler = g_FontSampler ;
desc_image [ 0 ] . imageView = g_FontView ;
desc_image [ 0 ] . imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
VkWriteDescriptorSet write_desc [ 1 ] = { } ;
write_desc [ 0 ] . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET ;
write_desc [ 0 ] . dstSet = g_DescriptorSet ;
write_desc [ 0 ] . descriptorCount = 1 ;
write_desc [ 0 ] . descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ;
write_desc [ 0 ] . pImageInfo = desc_image ;
2019-04-04 20:36:12 +00:00
vkUpdateDescriptorSets ( v - > Device , 1 , write_desc , 0 , NULL ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
2016-03-09 15:39:54 +00: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 ;
2019-04-04 20:36:12 +00:00
err = vkCreateBuffer ( v - > Device , & buffer_info , v - > Allocator , & g_UploadBuffer ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
VkMemoryRequirements req ;
2019-04-04 20:36:12 +00:00
vkGetBufferMemoryRequirements ( v - > Device , g_UploadBuffer , & req ) ;
2016-03-09 15:39:54 +00:00
g_BufferMemoryAlignment = ( g_BufferMemoryAlignment > req . alignment ) ? g_BufferMemoryAlignment : req . alignment ;
VkMemoryAllocateInfo alloc_info = { } ;
alloc_info . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
alloc_info . allocationSize = req . size ;
2018-02-16 21:50:19 +00:00
alloc_info . memoryTypeIndex = ImGui_ImplVulkan_MemoryType ( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT , req . memoryTypeBits ) ;
2019-04-04 20:36:12 +00:00
err = vkAllocateMemory ( v - > Device , & alloc_info , v - > Allocator , & g_UploadBufferMemory ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2019-04-04 20:36:12 +00:00
err = vkBindBufferMemory ( v - > Device , g_UploadBuffer , g_UploadBufferMemory , 0 ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
2016-03-09 15:39:54 +00:00
// Upload to Buffer:
{
2016-04-03 15:32:53 +00:00
char * map = NULL ;
2019-04-04 20:36:12 +00:00
err = vkMapMemory ( v - > Device , g_UploadBufferMemory , 0 , upload_size , 0 , ( void * * ) ( & map ) ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
memcpy ( map , pixels , upload_size ) ;
VkMappedMemoryRange range [ 1 ] = { } ;
range [ 0 ] . sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE ;
range [ 0 ] . memory = g_UploadBufferMemory ;
range [ 0 ] . size = upload_size ;
2019-04-04 20:36:12 +00:00
err = vkFlushMappedMemoryRanges ( v - > Device , 1 , range ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2019-04-04 20:36:12 +00:00
vkUnmapMemory ( v - > Device , g_UploadBufferMemory ) ;
2016-03-09 15:39:54 +00:00
}
2018-02-18 20:15:51 +00:00
2016-03-10 11:30:38 +00:00
// Copy to Image:
2016-03-09 15:39:54 +00:00
{
2016-03-10 11:30:38 +00: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 ;
copy_barrier [ 0 ] . image = g_FontImage ;
copy_barrier [ 0 ] . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
copy_barrier [ 0 ] . subresourceRange . levelCount = 1 ;
copy_barrier [ 0 ] . subresourceRange . layerCount = 1 ;
2016-04-03 15:32:53 +00:00
vkCmdPipelineBarrier ( command_buffer , VK_PIPELINE_STAGE_HOST_BIT , VK_PIPELINE_STAGE_TRANSFER_BIT , 0 , 0 , NULL , 0 , NULL , 1 , copy_barrier ) ;
2016-03-09 15:39:54 +00: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 17:38:05 +00:00
region . imageExtent . depth = 1 ;
2016-04-03 15:32:53 +00:00
vkCmdCopyBufferToImage ( command_buffer , g_UploadBuffer , g_FontImage , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 1 , & region ) ;
2016-03-10 11:30:38 +00: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 ;
use_barrier [ 0 ] . image = g_FontImage ;
use_barrier [ 0 ] . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
use_barrier [ 0 ] . subresourceRange . levelCount = 1 ;
use_barrier [ 0 ] . subresourceRange . layerCount = 1 ;
2016-04-03 15:32:53 +00:00
vkCmdPipelineBarrier ( command_buffer , VK_PIPELINE_STAGE_TRANSFER_BIT , VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT , 0 , 0 , NULL , 0 , NULL , 1 , use_barrier ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
// Store our identifier
2018-08-09 15:49:48 +00:00
io . Fonts - > TexID = ( ImTextureID ) ( intptr_t ) g_FontImage ;
2016-03-09 15:39:54 +00:00
return true ;
}
2018-02-16 21:50:19 +00:00
bool ImGui_ImplVulkan_CreateDeviceObjects ( )
2016-03-09 15:39:54 +00:00
{
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2016-03-09 15:39:54 +00:00
VkResult err ;
VkShaderModule vert_module ;
VkShaderModule frag_module ;
// Create The Shader Modules:
{
VkShaderModuleCreateInfo vert_info = { } ;
vert_info . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
2016-10-18 20:40:58 +00:00
vert_info . codeSize = sizeof ( __glsl_shader_vert_spv ) ;
2016-03-09 15:39:54 +00:00
vert_info . pCode = ( uint32_t * ) __glsl_shader_vert_spv ;
2019-04-04 20:36:12 +00:00
err = vkCreateShaderModule ( v - > Device , & vert_info , v - > Allocator , & vert_module ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
VkShaderModuleCreateInfo frag_info = { } ;
frag_info . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
2016-10-18 20:40:58 +00:00
frag_info . codeSize = sizeof ( __glsl_shader_frag_spv ) ;
2016-03-09 15:39:54 +00:00
frag_info . pCode = ( uint32_t * ) __glsl_shader_frag_spv ;
2019-04-04 20:36:12 +00:00
err = vkCreateShaderModule ( v - > Device , & frag_info , v - > Allocator , & frag_module ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
if ( ! g_FontSampler )
{
2016-03-09 15:39:54 +00: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 15:07:53 +00:00
info . maxAnisotropy = 1.0f ;
2019-04-04 20:36:12 +00:00
err = vkCreateSampler ( v - > Device , & info , v - > Allocator , & g_FontSampler ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
if ( ! g_DescriptorSetLayout )
{
2016-03-09 15:39:54 +00:00
VkSampler sampler [ 1 ] = { g_FontSampler } ;
VkDescriptorSetLayoutBinding binding [ 1 ] = { } ;
binding [ 0 ] . descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ;
binding [ 0 ] . descriptorCount = 1 ;
binding [ 0 ] . stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT ;
binding [ 0 ] . pImmutableSamplers = sampler ;
VkDescriptorSetLayoutCreateInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO ;
info . bindingCount = 1 ;
info . pBindings = binding ;
2019-04-04 20:36:12 +00:00
err = vkCreateDescriptorSetLayout ( v - > Device , & info , v - > Allocator , & g_DescriptorSetLayout ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
2016-03-10 11:30:38 +00:00
// Create Descriptor Set:
2016-03-09 15:39:54 +00:00
{
VkDescriptorSetAllocateInfo alloc_info = { } ;
alloc_info . sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO ;
2019-04-04 20:36:12 +00:00
alloc_info . descriptorPool = v - > DescriptorPool ;
2016-03-09 15:39:54 +00:00
alloc_info . descriptorSetCount = 1 ;
alloc_info . pSetLayouts = & g_DescriptorSetLayout ;
2019-04-04 20:36:12 +00:00
err = vkAllocateDescriptorSets ( v - > Device , & alloc_info , & g_DescriptorSet ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
2016-04-03 15:32:53 +00:00
if ( ! g_PipelineLayout )
{
2018-03-02 15:34:47 +00:00
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
2016-08-20 11:08:34 +00:00
VkPushConstantRange push_constants [ 1 ] = { } ;
2016-03-09 15:39:54 +00:00
push_constants [ 0 ] . stageFlags = VK_SHADER_STAGE_VERTEX_BIT ;
push_constants [ 0 ] . offset = sizeof ( float ) * 0 ;
2016-08-20 11:08:34 +00:00
push_constants [ 0 ] . size = sizeof ( float ) * 4 ;
2018-03-02 15:34:47 +00:00
VkDescriptorSetLayout set_layout [ 1 ] = { g_DescriptorSetLayout } ;
2016-03-09 15:39:54 +00: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 11:08:34 +00:00
layout_info . pushConstantRangeCount = 1 ;
2016-03-09 15:39:54 +00:00
layout_info . pPushConstantRanges = push_constants ;
2019-04-04 20:36:12 +00:00
err = vkCreatePipelineLayout ( v - > Device , & layout_info , v - > Allocator , & g_PipelineLayout ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
}
VkPipelineShaderStageCreateInfo stage [ 2 ] = { } ;
stage [ 0 ] . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
stage [ 0 ] . stage = VK_SHADER_STAGE_VERTEX_BIT ;
stage [ 0 ] . module = vert_module ;
stage [ 0 ] . pName = " main " ;
stage [ 1 ] . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
stage [ 1 ] . stage = VK_SHADER_STAGE_FRAGMENT_BIT ;
stage [ 1 ] . module = frag_module ;
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 ;
2018-03-02 15:34:47 +00:00
attribute_desc [ 0 ] . offset = IM_OFFSETOF ( ImDrawVert , pos ) ;
2016-03-09 15:39:54 +00:00
attribute_desc [ 1 ] . location = 1 ;
attribute_desc [ 1 ] . binding = binding_desc [ 0 ] . binding ;
attribute_desc [ 1 ] . format = VK_FORMAT_R32G32_SFLOAT ;
2018-03-02 15:34:47 +00:00
attribute_desc [ 1 ] . offset = IM_OFFSETOF ( ImDrawVert , uv ) ;
2016-03-09 15:39:54 +00:00
attribute_desc [ 2 ] . location = 2 ;
attribute_desc [ 2 ] . binding = binding_desc [ 0 ] . binding ;
attribute_desc [ 2 ] . format = VK_FORMAT_R8G8B8A8_UNORM ;
2018-03-02 15:34:47 +00:00
attribute_desc [ 2 ] . offset = IM_OFFSETOF ( ImDrawVert , col ) ;
2016-03-09 15:39:54 +00:00
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 ;
2016-08-27 17:08:24 +00:00
raster_info . lineWidth = 1.0f ;
2016-03-09 15:39:54 +00:00
VkPipelineMultisampleStateCreateInfo ms_info = { } ;
ms_info . sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO ;
2019-07-31 18:50:50 +00:00
if ( v - > MSAASamples ! = 0 )
ms_info . rasterizationSamples = v - > MSAASamples ;
else
ms_info . rasterizationSamples = VK_SAMPLE_COUNT_1_BIT ;
2016-03-09 15:39:54 +00:00
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 ;
color_attachment [ 0 ] . srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
color_attachment [ 0 ] . dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO ;
color_attachment [ 0 ] . alphaBlendOp = VK_BLEND_OP_ADD ;
2016-04-03 15:32:53 +00:00
color_attachment [ 0 ] . colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT ;
2016-03-09 15:39:54 +00:00
2016-08-27 17:08:24 +00:00
VkPipelineDepthStencilStateCreateInfo depth_info = { } ;
depth_info . sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO ;
2016-03-09 15:39:54 +00:00
VkPipelineColorBlendStateCreateInfo blend_info = { } ;
blend_info . sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO ;
blend_info . attachmentCount = 1 ;
blend_info . pAttachments = color_attachment ;
2016-04-03 15:32:53 +00:00
VkDynamicState dynamic_states [ 2 ] = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
2016-03-09 15:39:54 +00:00
VkPipelineDynamicStateCreateInfo dynamic_state = { } ;
2016-08-20 11:27:03 +00:00
dynamic_state . sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO ;
2018-03-12 16:37:28 +00:00
dynamic_state . dynamicStateCount = ( uint32_t ) IM_ARRAYSIZE ( dynamic_states ) ;
2016-03-09 15:39:54 +00:00
dynamic_state . pDynamicStates = dynamic_states ;
VkGraphicsPipelineCreateInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
info . flags = g_PipelineCreateFlags ;
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 ;
2016-08-27 17:08:24 +00:00
info . pDepthStencilState = & depth_info ;
2016-03-09 15:39:54 +00:00
info . pColorBlendState = & blend_info ;
info . pDynamicState = & dynamic_state ;
info . layout = g_PipelineLayout ;
info . renderPass = g_RenderPass ;
2019-04-04 20:36:12 +00:00
err = vkCreateGraphicsPipelines ( v - > Device , v - > PipelineCache , 1 , & info , v - > Allocator , & g_Pipeline ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2016-03-09 15:39:54 +00:00
2019-04-04 20:36:12 +00:00
vkDestroyShaderModule ( v - > Device , vert_module , v - > Allocator ) ;
vkDestroyShaderModule ( v - > Device , frag_module , v - > Allocator ) ;
2016-03-09 15:39:54 +00:00
return true ;
}
2019-04-03 17:21:06 +00:00
void ImGui_ImplVulkan_DestroyFontUploadObjects ( )
2016-03-09 15:39:54 +00:00
{
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2016-04-03 15:32:53 +00:00
if ( g_UploadBuffer )
{
2019-04-04 20:36:12 +00:00
vkDestroyBuffer ( v - > Device , g_UploadBuffer , v - > Allocator ) ;
2016-03-09 15:39:54 +00:00
g_UploadBuffer = VK_NULL_HANDLE ;
}
2016-04-03 15:32:53 +00:00
if ( g_UploadBufferMemory )
{
2019-04-04 20:36:12 +00:00
vkFreeMemory ( v - > Device , g_UploadBufferMemory , v - > Allocator ) ;
2016-03-09 15:39:54 +00:00
g_UploadBufferMemory = VK_NULL_HANDLE ;
}
}
2016-04-03 15:32:53 +00:00
2019-04-03 17:21:06 +00:00
void ImGui_ImplVulkan_DestroyDeviceObjects ( )
2016-03-09 15:39:54 +00:00
{
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2019-04-05 16:52:40 +00:00
ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers ( v - > Device , v - > Allocator ) ;
2019-04-04 20:36:12 +00:00
ImGui_ImplVulkan_DestroyFontUploadObjects ( ) ;
2019-04-05 15:48:47 +00:00
2019-04-04 20:36:12 +00:00
if ( g_FontView ) { vkDestroyImageView ( v - > Device , g_FontView , v - > Allocator ) ; g_FontView = VK_NULL_HANDLE ; }
if ( g_FontImage ) { vkDestroyImage ( v - > Device , g_FontImage , v - > Allocator ) ; g_FontImage = VK_NULL_HANDLE ; }
if ( g_FontMemory ) { vkFreeMemory ( v - > Device , g_FontMemory , v - > Allocator ) ; g_FontMemory = VK_NULL_HANDLE ; }
if ( g_FontSampler ) { vkDestroySampler ( v - > Device , g_FontSampler , v - > Allocator ) ; g_FontSampler = VK_NULL_HANDLE ; }
if ( g_DescriptorSetLayout ) { vkDestroyDescriptorSetLayout ( v - > Device , g_DescriptorSetLayout , v - > Allocator ) ; g_DescriptorSetLayout = VK_NULL_HANDLE ; }
if ( g_PipelineLayout ) { vkDestroyPipelineLayout ( v - > Device , g_PipelineLayout , v - > Allocator ) ; g_PipelineLayout = VK_NULL_HANDLE ; }
if ( g_Pipeline ) { vkDestroyPipeline ( v - > Device , g_Pipeline , v - > Allocator ) ; g_Pipeline = VK_NULL_HANDLE ; }
2016-03-09 15:39:54 +00:00
}
2018-03-02 22:59:21 +00:00
bool ImGui_ImplVulkan_Init ( ImGui_ImplVulkan_InitInfo * info , VkRenderPass render_pass )
2016-03-09 15:39:54 +00:00
{
2018-11-30 17:24:43 +00:00
// Setup back-end capabilities flags
2018-11-30 17:18:15 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . BackendRendererName = " imgui_impl_vulkan " ;
2019-05-29 14:29:17 +00:00
io . BackendFlags | = ImGuiBackendFlags_RendererHasVtxOffset ; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
2019-06-06 14:16:18 +00:00
io . BackendFlags | = ImGuiBackendFlags_RendererHasViewports ; // We can create multi-viewports on the Renderer side (optional)
2018-11-30 17:18:15 +00:00
2018-08-28 16:22:36 +00: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 21:11:15 +00:00
IM_ASSERT ( info - > MinImageCount > = 2 ) ;
2019-04-05 15:22:24 +00:00
IM_ASSERT ( info - > ImageCount > = info - > MinImageCount ) ;
2018-08-28 16:22:36 +00:00
IM_ASSERT ( render_pass ! = VK_NULL_HANDLE ) ;
2018-03-02 22:59:21 +00:00
2019-04-04 20:36:12 +00:00
g_VulkanInitInfo = * info ;
2018-03-02 22:59:21 +00:00
g_RenderPass = render_pass ;
2018-02-16 21:50:19 +00:00
ImGui_ImplVulkan_CreateDeviceObjects ( ) ;
2018-03-20 21:14:34 +00:00
2019-04-05 16:52:40 +00:00
// Our render function expect RendererUserData to be storing the window render buffer we need (for the main viewport we won't use ->Window)
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
main_viewport - > RendererUserData = IM_NEW ( ImGuiViewportDataVulkan ) ( ) ;
2018-04-10 17:21:52 +00:00
if ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
2018-03-02 18:23:01 +00:00
ImGui_ImplVulkan_InitPlatformInterface ( ) ;
2016-03-09 15:39:54 +00:00
return true ;
}
2018-02-16 21:50:19 +00:00
void ImGui_ImplVulkan_Shutdown ( )
2016-03-09 15:39:54 +00:00
{
2019-07-29 22:52:30 +00:00
// First destroy objects in all viewports
2019-04-03 17:21:06 +00:00
ImGui_ImplVulkan_DestroyDeviceObjects ( ) ;
2019-07-29 22:52:30 +00:00
// Manually delete main viewport render data in-case we haven't initialized for viewports
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
if ( ImGuiViewportDataVulkan * data = ( ImGuiViewportDataVulkan * ) main_viewport - > RendererUserData )
IM_DELETE ( data ) ;
main_viewport - > RendererUserData = NULL ;
// Clean up windows
ImGui_ImplVulkan_ShutdownPlatformInterface ( ) ;
2016-03-09 15:39:54 +00:00
}
2018-02-16 21:50:19 +00:00
void ImGui_ImplVulkan_NewFrame ( )
2016-03-09 15:39:54 +00:00
{
}
2016-11-12 16:49:59 +00:00
2019-04-05 15:48:47 +00:00
void ImGui_ImplVulkan_SetMinImageCount ( uint32_t min_image_count )
2018-09-09 06:04:44 +00:00
{
2019-04-04 21:11:15 +00:00
IM_ASSERT ( min_image_count > = 2 ) ;
2019-04-04 22:25:42 +00:00
if ( g_VulkanInitInfo . MinImageCount = = min_image_count )
return ;
2019-04-05 16:52:40 +00:00
IM_ASSERT ( 0 ) ; // FIXME-VIEWPORT: Unsupported. Need to recreate all swap chains!
2019-04-05 15:48:47 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
VkResult err = vkDeviceWaitIdle ( v - > Device ) ;
check_vk_result ( err ) ;
2019-04-05 16:52:40 +00:00
ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers ( v - > Device , v - > Allocator ) ;
2019-06-06 14:16:18 +00:00
2019-04-04 21:11:15 +00:00
g_VulkanInitInfo . MinImageCount = min_image_count ;
}
2018-08-22 15:59:58 +00:00
2018-06-08 17:37:33 +00:00
//-------------------------------------------------------------------------
2018-08-22 15:59:58 +00:00
// Internal / Miscellaneous Vulkan Helpers
2019-04-03 16:33:13 +00:00
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
2018-03-01 21:16:51 +00:00
//-------------------------------------------------------------------------
2019-01-20 16:56:17 +00:00
// You probably do NOT need to use or care about those functions.
2018-08-22 15:59:58 +00: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.
2019-01-20 16:56:17 +00:00
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
2018-08-22 15:59:58 +00:00
// but it is too much code to duplicate everywhere so we exceptionally expose them.
2019-04-03 16:33:13 +00:00
//
2019-04-04 20:27:29 +00:00
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
2018-08-22 15:59:58 +00: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 16:33:13 +00:00
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
2018-03-01 21:16:51 +00:00
//-------------------------------------------------------------------------
2018-03-02 22:59:21 +00:00
VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat ( VkPhysicalDevice physical_device , VkSurfaceKHR surface , const VkFormat * request_formats , int request_formats_count , VkColorSpaceKHR request_color_space )
2018-03-01 21:16:51 +00:00
{
IM_ASSERT ( request_formats ! = NULL ) ;
IM_ASSERT ( request_formats_count > 0 ) ;
// Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
// Assuming that the default behavior is without setting this bit, there is no need for separate Swapchain image and image view format
// Additionally several new color spaces were introduced with Vulkan Spec v1.0.40,
// hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used.
uint32_t avail_count ;
vkGetPhysicalDeviceSurfaceFormatsKHR ( physical_device , surface , & avail_count , NULL ) ;
ImVector < VkSurfaceFormatKHR > avail_format ;
avail_format . resize ( ( int ) avail_count ) ;
vkGetPhysicalDeviceSurfaceFormatsKHR ( physical_device , surface , & avail_count , avail_format . Data ) ;
// First check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
if ( avail_count = = 1 )
{
if ( avail_format [ 0 ] . format = = VK_FORMAT_UNDEFINED )
{
VkSurfaceFormatKHR ret ;
ret . format = request_formats [ 0 ] ;
ret . colorSpace = request_color_space ;
return ret ;
}
else
{
// No point in searching another format
return avail_format [ 0 ] ;
}
}
else
{
2019-01-20 16:56:17 +00:00
// Request several formats, the first found will be used
2018-03-01 21:16:51 +00: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 ] ;
}
}
2018-03-02 22:59:21 +00:00
VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode ( VkPhysicalDevice physical_device , VkSurfaceKHR surface , const VkPresentModeKHR * request_modes , int request_modes_count )
2018-03-01 21:16:51 +00:00
{
IM_ASSERT ( request_modes ! = NULL ) ;
IM_ASSERT ( request_modes_count > 0 ) ;
// Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
uint32_t avail_count = 0 ;
vkGetPhysicalDeviceSurfacePresentModesKHR ( physical_device , surface , & avail_count , NULL ) ;
ImVector < VkPresentModeKHR > avail_modes ;
avail_modes . resize ( ( int ) avail_count ) ;
vkGetPhysicalDeviceSurfacePresentModesKHR ( physical_device , surface , & avail_count , avail_modes . Data ) ;
2018-08-25 19:15:37 +00: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-03-01 21:16:51 +00: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
}
2018-03-02 18:23:01 +00:00
2019-04-05 15:54:16 +00:00
void ImGui_ImplVulkanH_CreateWindowCommandBuffers ( VkPhysicalDevice physical_device , VkDevice device , ImGui_ImplVulkanH_Window * wd , uint32_t queue_family , const VkAllocationCallbacks * allocator )
2018-03-02 22:59:21 +00:00
{
2019-04-05 15:54:16 +00:00
IM_ASSERT ( physical_device ! = VK_NULL_HANDLE & & device ! = VK_NULL_HANDLE ) ;
2018-10-30 20:15:30 +00:00
( void ) physical_device ;
2018-03-02 23:29:17 +00:00
( void ) allocator ;
2018-03-02 22:59:21 +00:00
2018-03-02 23:29:17 +00:00
// Create Command Buffers
VkResult err ;
2019-04-05 15:22:24 +00:00
for ( uint32_t i = 0 ; i < wd - > ImageCount ; i + + )
2018-03-02 23:29:17 +00:00
{
2019-04-04 21:28:29 +00:00
ImGui_ImplVulkanH_Frame * fd = & wd - > Frames [ i ] ;
2019-04-05 04:50:21 +00:00
ImGui_ImplVulkanH_FrameSemaphores * fsd = & wd - > FrameSemaphores [ i ] ;
2018-03-02 23:29:17 +00: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 04:50:21 +00:00
err = vkCreateSemaphore ( device , & info , allocator , & fsd - > ImageAcquiredSemaphore ) ;
2018-03-02 23:29:17 +00:00
check_vk_result ( err ) ;
2019-04-05 04:50:21 +00:00
err = vkCreateSemaphore ( device , & info , allocator , & fsd - > RenderCompleteSemaphore ) ;
2018-03-02 23:29:17 +00:00
check_vk_result ( err ) ;
}
}
}
2018-03-12 17:43:25 +00:00
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 20:27:29 +00:00
// Also destroy old swap chain and in-flight frames data, if any.
2019-04-05 15:54:16 +00: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-03-02 23:29:17 +00:00
{
2018-03-02 22:59:21 +00:00
VkResult err ;
VkSwapchainKHR old_swapchain = wd - > Swapchain ;
err = vkDeviceWaitIdle ( device ) ;
check_vk_result ( err ) ;
2019-04-04 21:28:29 +00:00
// We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
2018-03-02 22:59:21 +00:00
// Destroy old Framebuffer
2019-04-05 15:22:24 +00:00
for ( uint32_t i = 0 ; i < wd - > ImageCount ; i + + )
2019-04-05 04:50:21 +00:00
{
2019-04-05 15:54:16 +00:00
ImGui_ImplVulkanH_DestroyFrame ( device , & wd - > Frames [ i ] , allocator ) ;
ImGui_ImplVulkanH_DestroyFrameSemaphores ( device , & wd - > FrameSemaphores [ i ] , allocator ) ;
2019-04-05 04:50:21 +00:00
}
2019-04-05 18:27:46 +00:00
IM_FREE ( wd - > Frames ) ;
IM_FREE ( wd - > FrameSemaphores ) ;
2019-04-04 20:27:29 +00:00
wd - > Frames = NULL ;
2019-04-05 04:50:21 +00:00
wd - > FrameSemaphores = NULL ;
2019-04-05 15:22:24 +00:00
wd - > ImageCount = 0 ;
2018-03-02 22:59:21 +00:00
if ( wd - > RenderPass )
vkDestroyRenderPass ( device , wd - > RenderPass , allocator ) ;
2019-01-20 16:56:17 +00:00
2018-03-12 17:43:25 +00: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 ) ;
2018-03-02 22:59:21 +00:00
// Create Swapchain
{
VkSwapchainCreateInfoKHR info = { } ;
info . sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR ;
info . surface = wd - > Surface ;
2019-04-03 15:23:31 +00:00
info . minImageCount = min_image_count ;
2018-03-02 22:59:21 +00: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 19:15:37 +00:00
if ( info . minImageCount < cap . minImageCount )
2019-04-03 15:23:31 +00:00
info . minImageCount = cap . minImageCount ;
else if ( cap . maxImageCount ! = 0 & & info . minImageCount > cap . maxImageCount )
info . minImageCount = cap . maxImageCount ;
2018-03-02 22:59:21 +00: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 ) ;
2019-04-05 15:22:24 +00:00
err = vkGetSwapchainImagesKHR ( device , wd - > Swapchain , & wd - > ImageCount , NULL ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2019-04-03 15:56:18 +00:00
VkImage backbuffers [ 16 ] = { } ;
2019-04-05 15:22:24 +00:00
IM_ASSERT ( wd - > ImageCount > = min_image_count ) ;
IM_ASSERT ( wd - > ImageCount < IM_ARRAYSIZE ( backbuffers ) ) ;
err = vkGetSwapchainImagesKHR ( device , wd - > Swapchain , & wd - > ImageCount , backbuffers ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
2018-09-11 20:18:24 +00:00
2019-04-04 20:27:29 +00:00
IM_ASSERT ( wd - > Frames = = NULL ) ;
2019-04-05 18:27:46 +00: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 15:22:24 +00: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 17:21:06 +00:00
wd - > Frames [ i ] . Backbuffer = backbuffers [ i ] ;
2018-03-02 22:59:21 +00:00
}
if ( old_swapchain )
vkDestroySwapchainKHR ( device , old_swapchain , allocator ) ;
// Create the Render Pass
{
VkAttachmentDescription attachment = { } ;
attachment . format = wd - > SurfaceFormat . format ;
attachment . samples = VK_SAMPLE_COUNT_1_BIT ;
2018-03-15 16:52:53 +00:00
attachment . loadOp = wd - > ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
2018-03-02 22:59:21 +00:00
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 ;
2018-03-20 15:05:31 +00:00
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 ;
2018-03-02 22:59:21 +00:00
VkRenderPassCreateInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO ;
info . attachmentCount = 1 ;
info . pAttachments = & attachment ;
info . subpassCount = 1 ;
info . pSubpasses = & subpass ;
2018-03-20 15:05:31 +00:00
info . dependencyCount = 1 ;
info . pDependencies = & dependency ;
2018-03-02 22:59:21 +00:00
err = vkCreateRenderPass ( device , & info , allocator , & wd - > RenderPass ) ;
check_vk_result ( err ) ;
}
// Create The Image Views
{
VkImageViewCreateInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO ;
info . viewType = VK_IMAGE_VIEW_TYPE_2D ;
info . format = wd - > SurfaceFormat . format ;
info . components . r = VK_COMPONENT_SWIZZLE_R ;
info . components . g = VK_COMPONENT_SWIZZLE_G ;
info . components . b = VK_COMPONENT_SWIZZLE_B ;
info . components . a = VK_COMPONENT_SWIZZLE_A ;
VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT , 0 , 1 , 0 , 1 } ;
info . subresourceRange = image_range ;
2019-04-05 15:22:24 +00:00
for ( uint32_t i = 0 ; i < wd - > ImageCount ; i + + )
2018-03-02 22:59:21 +00:00
{
2019-04-04 21:28:29 +00:00
ImGui_ImplVulkanH_Frame * fd = & wd - > Frames [ i ] ;
2019-04-03 17:21:06 +00:00
info . image = fd - > Backbuffer ;
err = vkCreateImageView ( device , & info , allocator , & fd - > BackbufferView ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
}
}
// Create Framebuffer
{
VkImageView attachment [ 1 ] ;
VkFramebufferCreateInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO ;
info . renderPass = wd - > RenderPass ;
info . attachmentCount = 1 ;
info . pAttachments = attachment ;
info . width = wd - > Width ;
info . height = wd - > Height ;
info . layers = 1 ;
2019-04-05 15:22:24 +00:00
for ( uint32_t i = 0 ; i < wd - > ImageCount ; i + + )
2018-03-02 22:59:21 +00:00
{
2019-04-04 21:28:29 +00:00
ImGui_ImplVulkanH_Frame * fd = & wd - > Frames [ i ] ;
2019-04-03 17:21:06 +00:00
attachment [ 0 ] = fd - > BackbufferView ;
2019-04-03 15:56:18 +00:00
err = vkCreateFramebuffer ( device , & info , allocator , & fd - > Framebuffer ) ;
2018-03-02 22:59:21 +00:00
check_vk_result ( err ) ;
}
}
}
2019-04-04 21:28:29 +00:00
void ImGui_ImplVulkanH_CreateWindow ( 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 16:33:13 +00:00
{
2019-04-05 15:54:16 +00: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 16:33:13 +00:00
}
2019-04-04 21:28:29 +00:00
void ImGui_ImplVulkanH_DestroyWindow ( VkInstance instance , VkDevice device , ImGui_ImplVulkanH_Window * wd , const VkAllocationCallbacks * allocator )
2018-03-02 22:59:21 +00:00
{
2018-03-12 17:43:25 +00:00
vkDeviceWaitIdle ( device ) ; // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
//vkQueueWaitIdle(g_Queue);
2019-04-05 15:22:24 +00:00
for ( uint32_t i = 0 ; i < wd - > ImageCount ; i + + )
2019-04-05 04:50:21 +00:00
{
2019-04-05 15:54:16 +00:00
ImGui_ImplVulkanH_DestroyFrame ( device , & wd - > Frames [ i ] , allocator ) ;
ImGui_ImplVulkanH_DestroyFrameSemaphores ( device , & wd - > FrameSemaphores [ i ] , allocator ) ;
2019-04-05 04:50:21 +00:00
}
2019-04-05 18:27:46 +00:00
IM_FREE ( wd - > Frames ) ;
IM_FREE ( wd - > FrameSemaphores ) ;
2019-04-04 20:27:29 +00:00
wd - > Frames = NULL ;
2019-04-05 04:50:21 +00:00
wd - > FrameSemaphores = NULL ;
2018-03-02 22:59:21 +00:00
vkDestroyRenderPass ( device , wd - > RenderPass , allocator ) ;
vkDestroySwapchainKHR ( device , wd - > Swapchain , allocator ) ;
vkDestroySurfaceKHR ( instance , wd - > Surface , allocator ) ;
2019-04-04 20:27:29 +00:00
2019-04-04 21:28:29 +00:00
* wd = ImGui_ImplVulkanH_Window ( ) ;
2018-03-02 22:59:21 +00:00
}
2019-04-05 15:54:16 +00:00
void ImGui_ImplVulkanH_DestroyFrame ( VkDevice device , ImGui_ImplVulkanH_Frame * fd , const VkAllocationCallbacks * allocator )
2019-04-05 04:50:21 +00:00
{
2018-09-11 20:18:24 +00:00
vkDestroyFence ( device , fd - > Fence , allocator ) ;
vkFreeCommandBuffers ( device , fd - > CommandPool , 1 , & fd - > CommandBuffer ) ;
vkDestroyCommandPool ( device , fd - > CommandPool , allocator ) ;
2019-04-03 13:48:22 +00:00
fd - > Fence = VK_NULL_HANDLE ;
fd - > CommandBuffer = VK_NULL_HANDLE ;
fd - > CommandPool = VK_NULL_HANDLE ;
2019-04-03 15:56:18 +00:00
2019-04-03 17:21:06 +00:00
vkDestroyImageView ( device , fd - > BackbufferView , allocator ) ;
2019-04-03 15:56:18 +00:00
vkDestroyFramebuffer ( device , fd - > Framebuffer , allocator ) ;
2019-04-05 15:48:47 +00:00
}
2019-04-04 20:27:29 +00:00
2019-04-05 15:54:16 +00:00
void ImGui_ImplVulkanH_DestroyFrameSemaphores ( VkDevice device , ImGui_ImplVulkanH_FrameSemaphores * fsd , const VkAllocationCallbacks * allocator )
2019-04-05 15:48:47 +00:00
{
vkDestroySemaphore ( device , fsd - > ImageAcquiredSemaphore , allocator ) ;
vkDestroySemaphore ( device , fsd - > RenderCompleteSemaphore , allocator ) ;
fsd - > ImageAcquiredSemaphore = fsd - > RenderCompleteSemaphore = VK_NULL_HANDLE ;
}
2019-04-04 20:27:29 +00:00
2019-04-05 15:54:16 +00:00
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers ( VkDevice device , ImGui_ImplVulkanH_FrameRenderBuffers * buffers , const VkAllocationCallbacks * allocator )
2019-04-05 15:48:47 +00: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 15:54:16 +00:00
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers ( VkDevice device , ImGui_ImplVulkanH_WindowRenderBuffers * buffers , const VkAllocationCallbacks * allocator )
2019-04-05 15:48:47 +00:00
{
for ( uint32_t n = 0 ; n < buffers - > Count ; n + + )
2019-04-05 15:54:16 +00:00
ImGui_ImplVulkanH_DestroyFrameRenderBuffers ( device , & buffers - > FrameRenderBuffers [ n ] , allocator ) ;
2019-04-05 18:27:46 +00:00
IM_FREE ( buffers - > FrameRenderBuffers ) ;
2019-04-05 15:48:47 +00:00
buffers - > FrameRenderBuffers = NULL ;
buffers - > Index = 0 ;
buffers - > Count = 0 ;
2019-04-04 20:27:29 +00:00
}
2019-04-05 16:52:40 +00:00
void ImGui_ImplVulkanH_DestroyAllViewportsRenderBuffers ( VkDevice device , const VkAllocationCallbacks * allocator )
{
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
for ( int n = 0 ; n < platform_io . Viewports . Size ; n + + )
if ( ImGuiViewportDataVulkan * data = ( ImGuiViewportDataVulkan * ) platform_io . Viewports [ n ] - > RendererUserData )
ImGui_ImplVulkanH_DestroyWindowRenderBuffers ( device , & data - > RenderBuffers , allocator ) ;
}
2019-04-04 21:55:33 +00:00
2018-03-02 22:04:56 +00:00
//--------------------------------------------------------------------------------------------------------
2018-04-24 15:09:50 +00:00
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the back-end to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
2018-03-02 18:23:01 +00:00
2018-03-18 17:44:57 +00:00
static void ImGui_ImplVulkan_CreateWindow ( ImGuiViewport * viewport )
2018-03-02 18:23:01 +00:00
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataVulkan * data = IM_NEW ( ImGuiViewportDataVulkan ) ( ) ;
2018-03-02 18:23:01 +00:00
viewport - > RendererUserData = data ;
2019-04-04 21:55:33 +00:00
ImGui_ImplVulkanH_Window * wd = & data - > Window ;
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2018-03-02 18:23:01 +00:00
2018-03-12 17:43:25 +00:00
// Create surface
2018-03-18 17:44:57 +00:00
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
2019-04-04 21:55:33 +00:00
VkResult err = ( VkResult ) platform_io . Platform_CreateVkSurface ( viewport , ( ImU64 ) v - > Instance , ( const void * ) v - > Allocator , ( ImU64 * ) & wd - > Surface ) ;
2018-03-12 17:43:25 +00:00
check_vk_result ( err ) ;
// Check for WSI support
VkBool32 res ;
2019-04-04 21:55:33 +00:00
vkGetPhysicalDeviceSurfaceSupportKHR ( v - > PhysicalDevice , v - > QueueFamily , wd - > Surface , & res ) ;
2018-03-12 17:43:25 +00:00
if ( res ! = VK_TRUE )
{
2019-04-05 18:28:42 +00:00
IM_ASSERT ( 0 ) ; // Error: no WSI support on physical device
return ;
2018-03-12 17:43:25 +00:00
}
2018-08-25 19:21:14 +00:00
// Select Surface Format
2018-03-12 17:43:25 +00:00
const VkFormat requestSurfaceImageFormat [ ] = { VK_FORMAT_B8G8R8A8_UNORM , VK_FORMAT_R8G8B8A8_UNORM , VK_FORMAT_B8G8R8_UNORM , VK_FORMAT_R8G8B8_UNORM } ;
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR ;
2019-04-04 21:55:33 +00:00
wd - > SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat ( v - > PhysicalDevice , wd - > Surface , requestSurfaceImageFormat , ( size_t ) IM_ARRAYSIZE ( requestSurfaceImageFormat ) , requestSurfaceColorSpace ) ;
2018-03-02 18:23:01 +00:00
2018-08-25 19:21:14 +00:00
// Select Present Mode
// FIXME-VULKAN: Even thought mailbox seems to get us maximum framerate with a single window, it halves framerate with a second window etc. (w/ Nvidia and SDK 1.82.1)
VkPresentModeKHR present_modes [ ] = { VK_PRESENT_MODE_MAILBOX_KHR , VK_PRESENT_MODE_IMMEDIATE_KHR , VK_PRESENT_MODE_FIFO_KHR } ;
2019-04-04 21:55:33 +00:00
wd - > PresentMode = ImGui_ImplVulkanH_SelectPresentMode ( v - > PhysicalDevice , wd - > Surface , & present_modes [ 0 ] , IM_ARRAYSIZE ( present_modes ) ) ;
2018-08-25 19:21:14 +00:00
//printf("[vulkan] Secondary window selected PresentMode = %d\n", wd->PresentMode);
2018-03-12 17:43:25 +00:00
// Create SwapChain, RenderPass, Framebuffer, etc.
2018-03-15 16:52:53 +00:00
wd - > ClearEnable = ( viewport - > Flags & ImGuiViewportFlags_NoRendererClear ) ? false : true ;
2019-04-04 21:55:33 +00:00
ImGui_ImplVulkanH_CreateWindow ( v - > Instance , v - > PhysicalDevice , v - > Device , wd , v - > QueueFamily , v - > Allocator , ( int ) viewport - > Size . x , ( int ) viewport - > Size . y , v - > MinImageCount ) ;
2019-04-05 16:52:40 +00:00
data - > WindowOwned = true ;
2018-03-02 18:23:01 +00:00
}
2018-03-18 17:44:57 +00:00
static void ImGui_ImplVulkan_DestroyWindow ( ImGuiViewport * viewport )
2018-03-02 18:23:01 +00:00
{
2018-04-09 20:01:24 +00:00
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
2018-03-18 21:19:02 +00:00
if ( ImGuiViewportDataVulkan * data = ( ImGuiViewportDataVulkan * ) viewport - > RendererUserData )
2018-03-02 18:23:01 +00:00
{
2019-04-04 21:55:33 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2019-04-05 16:52:40 +00:00
if ( data - > WindowOwned )
ImGui_ImplVulkanH_DestroyWindow ( v - > Instance , v - > Device , & data - > Window , v - > Allocator ) ;
ImGui_ImplVulkanH_DestroyWindowRenderBuffers ( v - > Device , & data - > RenderBuffers , v - > Allocator ) ;
2018-03-02 18:23:01 +00:00
IM_DELETE ( data ) ;
}
viewport - > RendererUserData = NULL ;
}
2018-03-18 17:44:57 +00:00
static void ImGui_ImplVulkan_SetWindowSize ( ImGuiViewport * viewport , ImVec2 size )
2018-03-02 18:23:01 +00:00
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataVulkan * data = ( ImGuiViewportDataVulkan * ) viewport - > RendererUserData ;
2018-03-15 09:54:27 +00:00
if ( data = = NULL ) // This is NULL for the main viewport (which is left to the user/app to handle)
return ;
2019-04-04 21:55:33 +00:00
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
data - > Window . ClearEnable = ( viewport - > Flags & ImGuiViewportFlags_NoRendererClear ) ? false : true ;
2019-04-05 14:33:41 +00:00
ImGui_ImplVulkanH_CreateWindow ( v - > Instance , v - > PhysicalDevice , v - > Device , & data - > Window , v - > QueueFamily , v - > Allocator , ( int ) size . x , ( int ) size . y , v - > MinImageCount ) ;
2018-03-02 18:23:01 +00:00
}
2018-03-19 14:20:47 +00:00
static void ImGui_ImplVulkan_RenderWindow ( ImGuiViewport * viewport , void * )
2018-03-02 18:23:01 +00:00
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataVulkan * data = ( ImGuiViewportDataVulkan * ) viewport - > RendererUserData ;
2019-04-04 21:55:33 +00:00
ImGui_ImplVulkanH_Window * wd = & data - > Window ;
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2018-03-12 17:43:25 +00:00
VkResult err ;
2019-04-04 22:00:29 +00:00
ImGui_ImplVulkanH_Frame * fd = & wd - > Frames [ wd - > FrameIndex ] ;
2019-04-05 04:50:21 +00:00
ImGui_ImplVulkanH_FrameSemaphores * fsd = & wd - > FrameSemaphores [ wd - > SemaphoreIndex ] ;
2018-03-12 17:43:25 +00:00
{
for ( ; ; )
{
2019-04-04 21:55:33 +00:00
err = vkWaitForFences ( v - > Device , 1 , & fd - > Fence , VK_TRUE , 100 ) ;
2018-03-12 17:43:25 +00:00
if ( err = = VK_SUCCESS ) break ;
if ( err = = VK_TIMEOUT ) continue ;
check_vk_result ( err ) ;
}
{
2019-04-05 04:50:21 +00:00
err = vkAcquireNextImageKHR ( v - > Device , wd - > Swapchain , UINT64_MAX , fsd - > ImageAcquiredSemaphore , VK_NULL_HANDLE , & wd - > FrameIndex ) ;
2018-03-12 17:43:25 +00:00
check_vk_result ( err ) ;
2019-04-04 22:00:29 +00:00
fd = & wd - > Frames [ wd - > FrameIndex ] ;
2018-03-12 17:43:25 +00:00
}
{
2019-04-04 21:55:33 +00:00
err = vkResetCommandPool ( v - > Device , fd - > CommandPool , 0 ) ;
2018-03-12 17:43:25 +00:00
check_vk_result ( err ) ;
VkCommandBufferBeginInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO ;
info . flags | = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT ;
err = vkBeginCommandBuffer ( fd - > CommandBuffer , & info ) ;
check_vk_result ( err ) ;
}
{
2018-03-15 16:52:53 +00:00
ImVec4 clear_color = ImVec4 ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
memcpy ( & wd - > ClearValue . color . float32 [ 0 ] , & clear_color , 4 * sizeof ( float ) ) ;
2018-03-12 17:43:25 +00:00
VkRenderPassBeginInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO ;
info . renderPass = wd - > RenderPass ;
2019-04-04 22:00:29 +00:00
info . framebuffer = fd - > Framebuffer ;
2018-03-12 17:43:25 +00:00
info . renderArea . extent . width = wd - > Width ;
info . renderArea . extent . height = wd - > Height ;
2018-03-15 16:52:53 +00:00
info . clearValueCount = ( viewport - > Flags & ImGuiViewportFlags_NoRendererClear ) ? 0 : 1 ;
info . pClearValues = ( viewport - > Flags & ImGuiViewportFlags_NoRendererClear ) ? NULL : & wd - > ClearValue ;
2018-03-12 17:43:25 +00:00
vkCmdBeginRenderPass ( fd - > CommandBuffer , & info , VK_SUBPASS_CONTENTS_INLINE ) ;
}
}
2019-04-05 16:27:15 +00:00
ImGui_ImplVulkan_RenderDrawData ( viewport - > DrawData , fd - > CommandBuffer ) ;
2018-03-12 17:43:25 +00:00
{
vkCmdEndRenderPass ( fd - > CommandBuffer ) ;
{
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
VkSubmitInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_SUBMIT_INFO ;
info . waitSemaphoreCount = 1 ;
2019-04-05 04:50:21 +00:00
info . pWaitSemaphores = & fsd - > ImageAcquiredSemaphore ;
2018-03-12 17:43:25 +00:00
info . pWaitDstStageMask = & wait_stage ;
info . commandBufferCount = 1 ;
info . pCommandBuffers = & fd - > CommandBuffer ;
info . signalSemaphoreCount = 1 ;
2019-04-05 04:50:21 +00:00
info . pSignalSemaphores = & fsd - > RenderCompleteSemaphore ;
2018-03-12 17:43:25 +00:00
err = vkEndCommandBuffer ( fd - > CommandBuffer ) ;
check_vk_result ( err ) ;
2019-04-04 21:55:33 +00:00
err = vkResetFences ( v - > Device , 1 , & fd - > Fence ) ;
2018-03-12 17:43:25 +00:00
check_vk_result ( err ) ;
2019-04-04 21:55:33 +00:00
err = vkQueueSubmit ( v - > Queue , 1 , & info , fd - > Fence ) ;
2018-03-12 17:43:25 +00:00
check_vk_result ( err ) ;
}
}
2018-03-02 18:23:01 +00:00
}
2018-03-19 14:20:47 +00:00
static void ImGui_ImplVulkan_SwapBuffers ( ImGuiViewport * viewport , void * )
2018-03-02 18:23:01 +00:00
{
2018-03-18 21:19:02 +00:00
ImGuiViewportDataVulkan * data = ( ImGuiViewportDataVulkan * ) viewport - > RendererUserData ;
2019-04-04 21:55:33 +00:00
ImGui_ImplVulkanH_Window * wd = & data - > Window ;
ImGui_ImplVulkan_InitInfo * v = & g_VulkanInitInfo ;
2018-03-12 17:43:25 +00:00
VkResult err ;
2019-04-04 22:00:29 +00:00
uint32_t present_index = wd - > FrameIndex ;
2018-03-12 17:43:25 +00:00
2019-04-05 04:50:21 +00:00
ImGui_ImplVulkanH_FrameSemaphores * fsd = & wd - > FrameSemaphores [ wd - > SemaphoreIndex ] ;
2018-03-12 17:43:25 +00:00
VkPresentInfoKHR info = { } ;
info . sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR ;
info . waitSemaphoreCount = 1 ;
2019-04-05 04:50:21 +00:00
info . pWaitSemaphores = & fsd - > RenderCompleteSemaphore ;
2018-03-12 17:43:25 +00:00
info . swapchainCount = 1 ;
info . pSwapchains = & wd - > Swapchain ;
2019-04-04 22:00:29 +00:00
info . pImageIndices = & present_index ;
2019-04-04 21:55:33 +00:00
err = vkQueuePresentKHR ( v - > Queue , & info ) ;
2018-03-12 17:43:25 +00:00
check_vk_result ( err ) ;
2019-04-04 22:00:29 +00:00
2019-04-05 16:52:40 +00:00
wd - > FrameIndex = ( wd - > FrameIndex + 1 ) % wd - > ImageCount ; // This is for the next vkWaitForFences()
2019-04-05 16:27:15 +00:00
wd - > SemaphoreIndex = ( wd - > SemaphoreIndex + 1 ) % wd - > ImageCount ; // Now we can use the next set of semaphores
2018-03-02 18:23:01 +00:00
}
void ImGui_ImplVulkan_InitPlatformInterface ( )
{
2018-03-18 17:44:57 +00:00
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
2018-04-10 17:21:52 +00:00
if ( ImGui : : GetIO ( ) . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
2018-03-18 17:44:57 +00:00
IM_ASSERT ( platform_io . Platform_CreateVkSurface ! = NULL & & " Platform needs to setup the CreateVkSurface handler. " ) ;
platform_io . Renderer_CreateWindow = ImGui_ImplVulkan_CreateWindow ;
platform_io . Renderer_DestroyWindow = ImGui_ImplVulkan_DestroyWindow ;
platform_io . Renderer_SetWindowSize = ImGui_ImplVulkan_SetWindowSize ;
platform_io . Renderer_RenderWindow = ImGui_ImplVulkan_RenderWindow ;
platform_io . Renderer_SwapBuffers = ImGui_ImplVulkan_SwapBuffers ;
2018-03-02 18:23:01 +00:00
}
void ImGui_ImplVulkan_ShutdownPlatformInterface ( )
{
2018-03-18 17:44:57 +00:00
ImGui : : DestroyPlatformWindows ( ) ;
2018-03-02 18:23:01 +00:00
}