2022-07-08 13:06:09 +00:00
// dear imgui: Renderer Backend for Vulkan
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
2020-06-16 12:46:11 +00:00
// Implemented features:
2022-07-08 13:06:09 +00:00
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
// 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)
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// 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
2020-06-16 12:46:11 +00:00
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
2022-07-08 13:06:09 +00:00
// You will use those if you want to use this rendering backend in your engine/app.
2020-06-16 12:46:11 +00:00
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
2022-07-08 13:06:09 +00:00
// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
2020-06-16 12:46:11 +00:00
// Read comments in imgui_impl_vulkan.h.
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
2022-07-08 13:06:09 +00: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-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
// 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
// 2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.
// 2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init).
// 2020-05-04: Vulkan: Fixed crash if initial frame has no vertices.
// 2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices.
2020-06-16 12:46:11 +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: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount().
// 2019-04-04: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
2022-07-08 13:06:09 +00:00
// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.
2020-06-16 12:46:11 +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-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-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2017-05-15: Vulkan: Fix scissor offset being negative. Fix new Vulkan validation warnings. Set required depth member for buffer image copy.
// 2016-11-13: Vulkan: Fix validation layer warnings and errors and redeclare gl_PerVertex.
// 2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources.
// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.
# include "imgui_impl_vulkan.h"
2022-07-08 13:06:09 +00:00
# include "common/vulkan/builders.h"
2020-09-08 01:41:19 +00:00
# include "common/vulkan/context.h"
2020-09-05 07:27:38 +00:00
# include "common/vulkan/texture.h"
2022-07-08 13:06:09 +00:00
# include "common/vulkan/stream_buffer.h"
# include "common/vulkan/util.h"
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
# include <cstdio>
# include <cstring>
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
// Visual Studio warnings
# ifdef _MSC_VER
# pragma warning (disable: 4127) // condition expression is constant
# endif
// If we're doing more than this... wtf?
static constexpr u32 VERTEX_BUFFER_SIZE = 8 * 1024 * 1024 ;
static constexpr u32 INDEX_BUFFER_SIZE = 4 * 1024 * 1024 ;
2020-06-16 12:46:11 +00:00
// Vulkan data
2022-07-08 13:06:09 +00:00
struct ImGui_ImplVulkan_Data
{
VkRenderPass RenderPass = VK_NULL_HANDLE ;
VkPipelineCreateFlags PipelineCreateFlags = 0 ;
VkDescriptorSetLayout DescriptorSetLayout = VK_NULL_HANDLE ;
VkPipelineLayout PipelineLayout = VK_NULL_HANDLE ;
VkPipeline Pipeline = VK_NULL_HANDLE ;
VkShaderModule ShaderModuleVert = VK_NULL_HANDLE ;
VkShaderModule ShaderModuleFrag = VK_NULL_HANDLE ;
VkSampler FontSampler = VK_NULL_HANDLE ;
Vulkan : : StreamBuffer VertexStreamBuffer ;
Vulkan : : StreamBuffer IndexStreamBuffer ;
Vulkan : : Texture FontTexture ;
} ;
2020-06-16 12:46:11 +00:00
// Forward Declarations
2022-07-08 13:06:09 +00:00
static bool ImGui_ImplVulkan_CreateDeviceObjects ( ) ;
static void ImGui_ImplVulkan_DestroyDeviceObjects ( ) ;
2020-06-16 12:46:11 +00:00
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
// glsl_shader.vert, compiled with:
// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
/*
# version 450 core
layout ( location = 0 ) in vec2 aPos ;
layout ( location = 1 ) in vec2 aUV ;
layout ( location = 2 ) in vec4 aColor ;
layout ( push_constant ) uniform uPushConstant { vec2 uScale ; vec2 uTranslate ; } pc ;
out gl_PerVertex { vec4 gl_Position ; } ;
layout ( location = 0 ) out struct { vec4 Color ; vec2 UV ; } Out ;
void main ( )
{
Out . Color = aColor ;
Out . UV = aUV ;
gl_Position = vec4 ( aPos * pc . uScale + pc . uTranslate , 0 , 1 ) ;
}
*/
static uint32_t __glsl_shader_vert_spv [ ] =
{
0x07230203 , 0x00010000 , 0x00080001 , 0x0000002e , 0x00000000 , 0x00020011 , 0x00000001 , 0x0006000b ,
0x00000001 , 0x4c534c47 , 0x6474732e , 0x3035342e , 0x00000000 , 0x0003000e , 0x00000000 , 0x00000001 ,
0x000a000f , 0x00000000 , 0x00000004 , 0x6e69616d , 0x00000000 , 0x0000000b , 0x0000000f , 0x00000015 ,
0x0000001b , 0x0000001c , 0x00030003 , 0x00000002 , 0x000001c2 , 0x00040005 , 0x00000004 , 0x6e69616d ,
0x00000000 , 0x00030005 , 0x00000009 , 0x00000000 , 0x00050006 , 0x00000009 , 0x00000000 , 0x6f6c6f43 ,
0x00000072 , 0x00040006 , 0x00000009 , 0x00000001 , 0x00005655 , 0x00030005 , 0x0000000b , 0x0074754f ,
0x00040005 , 0x0000000f , 0x6c6f4361 , 0x0000726f , 0x00030005 , 0x00000015 , 0x00565561 , 0x00060005 ,
0x00000019 , 0x505f6c67 , 0x65567265 , 0x78657472 , 0x00000000 , 0x00060006 , 0x00000019 , 0x00000000 ,
0x505f6c67 , 0x7469736f , 0x006e6f69 , 0x00030005 , 0x0000001b , 0x00000000 , 0x00040005 , 0x0000001c ,
0x736f5061 , 0x00000000 , 0x00060005 , 0x0000001e , 0x73755075 , 0x6e6f4368 , 0x6e617473 , 0x00000074 ,
0x00050006 , 0x0000001e , 0x00000000 , 0x61635375 , 0x0000656c , 0x00060006 , 0x0000001e , 0x00000001 ,
0x61725475 , 0x616c736e , 0x00006574 , 0x00030005 , 0x00000020 , 0x00006370 , 0x00040047 , 0x0000000b ,
0x0000001e , 0x00000000 , 0x00040047 , 0x0000000f , 0x0000001e , 0x00000002 , 0x00040047 , 0x00000015 ,
0x0000001e , 0x00000001 , 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
} ;
// glsl_shader.frag, compiled with:
// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
/*
# version 450 core
layout ( location = 0 ) out vec4 fColor ;
layout ( set = 0 , binding = 0 ) uniform sampler2D sTexture ;
layout ( location = 0 ) in struct { vec4 Color ; vec2 UV ; } In ;
void main ( )
{
fColor = In . Color * texture ( sTexture , In . UV . st ) ;
}
*/
static uint32_t __glsl_shader_frag_spv [ ] =
{
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
} ;
//-----------------------------------------------------------------------------
// FUNCTIONS
//-----------------------------------------------------------------------------
2022-07-08 13:06:09 +00: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 ( )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
return ImGui : : GetCurrentContext ( ) ? ( ImGui_ImplVulkan_Data * ) ImGui : : GetIO ( ) . BackendRendererUserData : NULL ;
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
static void ImGui_ImplVulkan_SetupRenderState ( ImDrawData * draw_data , VkPipeline pipeline , VkCommandBuffer command_buffer , int fb_width , int fb_height )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
// Bind pipeline:
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
vkCmdBindPipeline ( command_buffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline ) ;
2020-06-16 12:46:11 +00:00
}
// Bind Vertex And Index Buffer:
2022-07-08 13:06:09 +00:00
if ( draw_data - > TotalVtxCount > 0 )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
VkBuffer vertex_buffers [ 1 ] = { bd - > VertexStreamBuffer . GetBuffer ( ) } ;
VkDeviceSize vertex_offset [ 1 ] = { bd - > VertexStreamBuffer . GetCurrentOffset ( ) } ;
2020-06-16 12:46:11 +00:00
vkCmdBindVertexBuffers ( command_buffer , 0 , 1 , vertex_buffers , vertex_offset ) ;
2022-07-08 13:06:09 +00:00
vkCmdBindIndexBuffer ( command_buffer , bd - > IndexStreamBuffer . GetBuffer ( ) , bd - > IndexStreamBuffer . GetCurrentOffset ( ) , sizeof ( ImDrawIdx ) = = 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32 ) ;
2020-06-16 12:46:11 +00:00
}
// Setup viewport:
{
VkViewport viewport ;
viewport . x = 0 ;
viewport . y = 0 ;
viewport . width = ( float ) fb_width ;
viewport . height = ( float ) fb_height ;
viewport . minDepth = 0.0f ;
viewport . maxDepth = 1.0f ;
vkCmdSetViewport ( command_buffer , 0 , 1 , & viewport ) ;
}
// Setup scale and translation:
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
{
float 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 ] ;
2022-07-08 13:06:09 +00: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 ) ;
2020-06-16 12:46:11 +00:00
}
}
// Render function
2022-07-08 13:06:09 +00:00
void ImGui_ImplVulkan_RenderDrawData ( ImDrawData * draw_data )
2020-06-16 12:46:11 +00:00
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
2022-07-08 13:06:09 +00:00
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 )
2020-06-16 12:46:11 +00:00
return ;
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
if ( draw_data - > TotalVtxCount > 0 )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
// Create or resize the vertex/index buffers
const u32 vertex_size = static_cast < u32 > ( draw_data - > TotalVtxCount ) * static_cast < u32 > ( sizeof ( ImDrawVert ) ) ;
const u32 index_size = static_cast < u32 > ( draw_data - > TotalIdxCount ) * static_cast < u32 > ( sizeof ( ImDrawIdx ) ) ;
if ( ! bd - > VertexStreamBuffer . ReserveMemory ( vertex_size , static_cast < u32 > ( sizeof ( ImDrawVert ) ) ) | |
! bd - > IndexStreamBuffer . ReserveMemory ( index_size , static_cast < u32 > ( sizeof ( ImDrawIdx ) ) ) )
{
// this is annoying, because we can't restart the render pass...
return ;
}
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
// Upload vertex/index data into a single contiguous GPU buffer
ImDrawVert * vtx_dst = ( ImDrawVert * ) bd - > VertexStreamBuffer . GetCurrentHostPointer ( ) ;
ImDrawIdx * idx_dst = ( ImDrawIdx * ) bd - > IndexStreamBuffer . GetCurrentHostPointer ( ) ;
2020-06-16 12:46:11 +00:00
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
2022-07-08 13:06:09 +00:00
memcpy ( vtx_dst , cmd_list - > VtxBuffer . Data , static_cast < u32 > ( cmd_list - > VtxBuffer . Size ) * static_cast < u32 > ( sizeof ( ImDrawVert ) ) ) ;
memcpy ( idx_dst , cmd_list - > IdxBuffer . Data , static_cast < u32 > ( cmd_list - > IdxBuffer . Size ) * static_cast < u32 > ( sizeof ( ImDrawIdx ) ) ) ;
vtx_dst + = static_cast < u32 > ( cmd_list - > VtxBuffer . Size ) ;
idx_dst + = static_cast < u32 > ( cmd_list - > IdxBuffer . Size ) ;
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
// Setup desired Vulkan state (must come before buffer commit)
ImGui_ImplVulkan_SetupRenderState ( draw_data , bd - > Pipeline , g_vulkan_context - > GetCurrentCommandBuffer ( ) , fb_width , fb_height ) ;
bd - > VertexStreamBuffer . CommitMemory ( vertex_size ) ;
bd - > IndexStreamBuffer . CommitMemory ( index_size ) ;
}
2020-06-16 12:46:11 +00:00
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data - > DisplayPos ; // (0,0) unless using multi-viewports
2022-07-08 13:06:09 +00:00
ImVec2 clip_scale = draw_data - > FramebufferScale ; // (1,1) unless using retina display which are often (2,2)
2020-06-16 12:46:11 +00:00
// Render command lists
// (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 ;
2022-07-08 13:06:09 +00:00
const Vulkan : : Texture * last_texture = nullptr ;
VkCommandBuffer command_buffer = g_vulkan_context - > GetCurrentCommandBuffer ( ) ;
2020-06-16 12:46:11 +00:00
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
for ( int cmd_i = 0 ; cmd_i < cmd_list - > CmdBuffer . Size ; cmd_i + + )
{
const ImDrawCmd * pcmd = & cmd_list - > CmdBuffer [ cmd_i ] ;
if ( pcmd - > UserCallback ! = NULL )
{
// 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 )
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_SetupRenderState ( draw_data , bd - > Pipeline , command_buffer , fb_width , fb_height ) ;
2020-06-16 12:46:11 +00:00
else
pcmd - > UserCallback ( cmd_list , pcmd ) ;
}
else
{
// Project scissor/clipping rectangles into framebuffer space
2022-07-08 13:06:09 +00: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 ) ;
// 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 ; }
if ( clip_max . x < = clip_min . x | | clip_max . y < = clip_min . y )
continue ;
// Apply scissor/clipping rectangle
VkRect2D scissor ;
scissor . offset . x = ( int32_t ) ( clip_min . x ) ;
scissor . offset . y = ( int32_t ) ( clip_min . y ) ;
scissor . extent . width = ( uint32_t ) ( clip_max . x - clip_min . x ) ;
scissor . extent . height = ( uint32_t ) ( clip_max . y - clip_min . y ) ;
vkCmdSetScissor ( command_buffer , 0 , 1 , & scissor ) ;
// Bind DescriptorSet with font or user texture
const Vulkan : : Texture * tex = ( const Vulkan : : Texture * ) pcmd - > TextureId ;
if ( tex & & last_texture ! = tex )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
// if we can't get a descriptor set, we'll we're in trouble, since we can't restart the render pass from here.
VkDescriptorSet ds = g_vulkan_context - > AllocateDescriptorSet ( bd - > DescriptorSetLayout ) ;
if ( ds = = VK_NULL_HANDLE )
{
continue ;
}
Vulkan : : DescriptorSetUpdateBuilder dsb ;
dsb . AddCombinedImageSamplerDescriptorWrite ( ds , 0 , tex - > GetView ( ) , bd - > FontSampler ) ;
dsb . Update ( g_vulkan_context - > GetDevice ( ) ) ;
vkCmdBindDescriptorSets ( command_buffer , VK_PIPELINE_BIND_POINT_GRAPHICS , bd - > PipelineLayout , 0 , 1 , & ds , 0 , nullptr ) ;
last_texture = tex ;
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
// Draw
vkCmdDrawIndexed ( command_buffer , pcmd - > ElemCount , 1 , pcmd - > IdxOffset + global_idx_offset , pcmd - > VtxOffset + global_vtx_offset , 0 ) ;
2020-06-16 12:46:11 +00:00
}
}
global_idx_offset + = cmd_list - > IdxBuffer . Size ;
global_vtx_offset + = cmd_list - > VtxBuffer . Size ;
}
2022-07-08 13:06:09 +00: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
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
// If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
// In theory we should aim to backup/restore those values but I am not sure this is possible.
// We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
VkRect2D scissor = { { 0 , 0 } , { ( uint32_t ) fb_width , ( uint32_t ) fb_height } } ;
vkCmdSetScissor ( command_buffer , 0 , 1 , & scissor ) ;
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
bool ImGui_ImplVulkan_CreateFontsTexture ( )
2020-06-16 12:46:11 +00:00
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
2020-06-16 12:46:11 +00:00
unsigned char * pixels ;
int width , height ;
io . Fonts - > GetTexDataAsRGBA32 ( & pixels , & width , & height ) ;
2022-07-08 13:06:09 +00:00
if ( bd - > FontTexture . GetWidth ( ) ! = static_cast < u32 > ( width ) | | bd - > FontTexture . GetHeight ( ) ! = static_cast < u32 > ( height ) )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
if ( ! bd - > FontTexture . Create ( width , height , 1 , 1 , VK_FORMAT_R8G8B8A8_UNORM ,
VK_SAMPLE_COUNT_1_BIT , VK_IMAGE_VIEW_TYPE_2D , VK_IMAGE_TILING_OPTIMAL ,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT ) )
{
return false ;
}
2020-06-16 12:46:11 +00:00
}
// Store our identifier
2022-09-26 11:05:44 +00:00
bd - > FontTexture . Update ( 0 , 0 , width , height , 0 , 0 , pixels , sizeof ( u32 ) * width ) ;
2022-07-08 13:06:09 +00:00
io . Fonts - > SetTexID ( ( ImTextureID ) & bd - > FontTexture ) ;
2020-06-16 12:46:11 +00:00
return true ;
}
2022-07-08 13:06:09 +00:00
static bool ImGui_ImplVulkan_CreateShaderModules ( VkDevice device )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
// Create the shader modules
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
if ( bd - > ShaderModuleVert = = VK_NULL_HANDLE )
2020-06-16 12:46:11 +00: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 ;
2022-07-08 13:06:09 +00:00
VkResult err = vkCreateShaderModule ( device , & vert_info , nullptr , & bd - > ShaderModuleVert ) ;
if ( err ! = VK_SUCCESS )
return false ;
}
if ( bd - > ShaderModuleFrag = = VK_NULL_HANDLE )
{
2020-06-16 12:46:11 +00: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 ;
2022-07-08 13:06:09 +00:00
VkResult err = vkCreateShaderModule ( device , & frag_info , nullptr , & bd - > ShaderModuleFrag ) ;
if ( err ! = VK_SUCCESS )
return false ;
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
return true ;
}
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
static bool ImGui_ImplVulkan_CreateFontSampler ( VkDevice device )
{
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
if ( bd - > FontSampler )
return true ;
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
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 ;
2022-10-13 12:53:09 +00:00
info . addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
info . addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
info . addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
2022-07-08 13:06:09 +00:00
info . minLod = - 1000 ;
info . maxLod = 1000 ;
info . maxAnisotropy = 1.0f ;
VkResult err = vkCreateSampler ( device , & info , nullptr , & bd - > FontSampler ) ;
return ( err = = VK_SUCCESS ) ;
}
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
static bool ImGui_ImplVulkan_CreateDescriptorSetLayout ( VkDevice device )
{
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
if ( bd - > DescriptorSetLayout )
return true ;
if ( ! ImGui_ImplVulkan_CreateFontSampler ( device ) )
return false ;
VkSampler sampler [ 1 ] = { bd - > 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 ;
VkResult err = vkCreateDescriptorSetLayout ( device , & info , nullptr , & bd - > DescriptorSetLayout ) ;
return ( err = = VK_SUCCESS ) ;
}
static bool ImGui_ImplVulkan_CreatePipelineLayout ( VkDevice device )
{
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
if ( bd - > PipelineLayout )
return true ;
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
ImGui_ImplVulkan_CreateDescriptorSetLayout ( device ) ;
VkPushConstantRange push_constants [ 1 ] = { } ;
push_constants [ 0 ] . stageFlags = VK_SHADER_STAGE_VERTEX_BIT ;
push_constants [ 0 ] . offset = sizeof ( float ) * 0 ;
push_constants [ 0 ] . size = sizeof ( float ) * 4 ;
VkDescriptorSetLayout set_layout [ 1 ] = { bd - > DescriptorSetLayout } ;
VkPipelineLayoutCreateInfo layout_info = { } ;
layout_info . sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO ;
layout_info . setLayoutCount = 1 ;
layout_info . pSetLayouts = set_layout ;
layout_info . pushConstantRangeCount = 1 ;
layout_info . pPushConstantRanges = push_constants ;
VkResult err = vkCreatePipelineLayout ( device , & layout_info , nullptr , & bd - > PipelineLayout ) ;
return ( err = = VK_SUCCESS ) ;
}
static bool ImGui_ImplVulkan_CreatePipeline ( VkDevice device , VkPipelineCache pipelineCache , VkRenderPass renderPass , VkPipeline * pipeline )
{
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
if ( ! ImGui_ImplVulkan_CreateShaderModules ( device ) )
return false ;
2020-06-16 12:46:11 +00:00
VkPipelineShaderStageCreateInfo stage [ 2 ] = { } ;
stage [ 0 ] . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
stage [ 0 ] . stage = VK_SHADER_STAGE_VERTEX_BIT ;
2022-07-08 13:06:09 +00:00
stage [ 0 ] . module = bd - > ShaderModuleVert ;
2020-06-16 12:46:11 +00:00
stage [ 0 ] . pName = " main " ;
stage [ 1 ] . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
stage [ 1 ] . stage = VK_SHADER_STAGE_FRAGMENT_BIT ;
2022-07-08 13:06:09 +00:00
stage [ 1 ] . module = bd - > ShaderModuleFrag ;
2020-06-16 12:46:11 +00: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 ;
2022-07-08 13:06:09 +00:00
ms_info . rasterizationSamples = VK_SAMPLE_COUNT_1_BIT ;
2020-06-16 12:46:11 +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 ;
2022-07-08 13:06:09 +00:00
color_attachment [ 0 ] . srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE ;
color_attachment [ 0 ] . dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
2020-06-16 12:46:11 +00: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 ;
2022-07-08 13:06:09 +00:00
if ( ! ImGui_ImplVulkan_CreatePipelineLayout ( device ) )
return false ;
2020-06-16 12:46:11 +00:00
VkGraphicsPipelineCreateInfo info = { } ;
info . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
2022-07-08 13:06:09 +00:00
info . flags = bd - > PipelineCreateFlags ;
2020-06-16 12:46:11 +00: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 ;
2022-07-08 13:06:09 +00:00
info . layout = bd - > PipelineLayout ;
info . renderPass = renderPass ;
info . subpass = 0 ;
VkResult err = vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & info , nullptr , pipeline ) ;
return ( err = = VK_SUCCESS ) ;
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
bool ImGui_ImplVulkan_CreateDeviceObjects ( )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
if ( ! bd - > VertexStreamBuffer . Create ( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT , VERTEX_BUFFER_SIZE ) | |
! bd - > IndexStreamBuffer . Create ( VK_BUFFER_USAGE_INDEX_BUFFER_BIT , INDEX_BUFFER_SIZE ) )
2020-06-16 12:46:11 +00:00
{
2022-07-08 13:06:09 +00:00
return false ;
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
if ( ! ImGui_ImplVulkan_CreatePipeline ( g_vulkan_context - > GetDevice ( ) , VK_NULL_HANDLE , bd - > RenderPass , & bd - > Pipeline ) )
return false ;
return true ;
2020-06-16 12:46:11 +00:00
}
void ImGui_ImplVulkan_DestroyDeviceObjects ( )
{
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
bd - > VertexStreamBuffer . Destroy ( false ) ;
bd - > IndexStreamBuffer . Destroy ( false ) ;
bd - > FontTexture . Destroy ( false ) ;
if ( bd - > ShaderModuleVert ) { vkDestroyShaderModule ( g_vulkan_context - > GetDevice ( ) , bd - > ShaderModuleVert , nullptr ) ; bd - > ShaderModuleVert = VK_NULL_HANDLE ; }
if ( bd - > ShaderModuleFrag ) { vkDestroyShaderModule ( g_vulkan_context - > GetDevice ( ) , bd - > ShaderModuleFrag , nullptr ) ; bd - > ShaderModuleFrag = VK_NULL_HANDLE ; }
if ( bd - > FontSampler ) { vkDestroySampler ( g_vulkan_context - > GetDevice ( ) , bd - > FontSampler , nullptr ) ; bd - > FontSampler = VK_NULL_HANDLE ; }
if ( bd - > DescriptorSetLayout ) { vkDestroyDescriptorSetLayout ( g_vulkan_context - > GetDevice ( ) , bd - > DescriptorSetLayout , nullptr ) ; bd - > DescriptorSetLayout = VK_NULL_HANDLE ; }
if ( bd - > PipelineLayout ) { vkDestroyPipelineLayout ( g_vulkan_context - > GetDevice ( ) , bd - > PipelineLayout , nullptr ) ; bd - > PipelineLayout = VK_NULL_HANDLE ; }
if ( bd - > Pipeline ) { vkDestroyPipeline ( g_vulkan_context - > GetDevice ( ) , bd - > Pipeline , nullptr ) ; bd - > Pipeline = VK_NULL_HANDLE ; }
2020-06-16 12:46:11 +00:00
}
2022-07-08 13:06:09 +00:00
bool ImGui_ImplVulkan_Init ( VkRenderPass render_pass )
2020-06-16 12:46:11 +00:00
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
2022-07-08 13:06:09 +00:00
IM_ASSERT ( io . BackendRendererUserData = = NULL & & " Already initialized a renderer backend! " ) ;
// Setup backend capabilities flags
ImGui_ImplVulkan_Data * bd = IM_NEW ( ImGui_ImplVulkan_Data ) ( ) ;
io . BackendRendererUserData = ( void * ) bd ;
2020-06-16 12:46:11 +00:00
io . BackendRendererName = " imgui_impl_vulkan " ;
io . BackendFlags | = ImGuiBackendFlags_RendererHasVtxOffset ; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
IM_ASSERT ( render_pass ! = VK_NULL_HANDLE ) ;
2022-07-08 13:06:09 +00:00
bd - > RenderPass = render_pass ;
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
return ImGui_ImplVulkan_CreateDeviceObjects ( ) ;
2020-06-16 12:46:11 +00:00
}
void ImGui_ImplVulkan_Shutdown ( )
{
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_Data * bd = ImGui_ImplVulkan_GetBackendData ( ) ;
IM_ASSERT ( bd ! = NULL & & " No renderer backend to shutdown, or already shutdown? " ) ;
ImGuiIO & io = ImGui : : GetIO ( ) ;
2020-06-16 12:46:11 +00:00
2022-07-08 13:06:09 +00:00
ImGui_ImplVulkan_DestroyDeviceObjects ( ) ;
io . BackendRendererName = NULL ;
io . BackendRendererUserData = NULL ;
IM_DELETE ( bd ) ;
2020-06-16 12:46:11 +00:00
}