Script Imgui
Script Imgui
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32,
custom..)
// Implemented features:
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read
the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for
discussions.
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
// 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
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-01-02: Vulkan: Fixed sampler passed to ImGui_ImplVulkan_AddTexture() not
being honored + removed a bunch of duplicate code.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api
symetry. (#914, #5738).
// 2022-01-20: Vulkan: Added support for ImTextureID as VkDescriptorSet. User need
to call ImGui_ImplVulkan_AddTexture(). Building for 32-bit targets requires
'#define ImTextureID ImU64'. (#914).
// 2021-10-15: 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.
// 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.
// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be
consistent with other backends.
// 2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined
GLFW+Vulkan example.
// 2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to
setup projection matrix and clipping rectangle.
// 2018-03-03: 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"
#include <stdio.h>
// Vulkan data
struct ImGui_ImplVulkan_Data
{
ImGui_ImplVulkan_InitInfo VulkanInitInfo;
VkRenderPass RenderPass;
VkDeviceSize BufferMemoryAlignment;
VkPipelineCreateFlags PipelineCreateFlags;
VkDescriptorSetLayout DescriptorSetLayout;
VkPipelineLayout PipelineLayout;
VkPipeline Pipeline;
uint32_t Subpass;
VkShaderModule ShaderModuleVert;
VkShaderModule ShaderModuleFrag;
// Font data
VkSampler FontSampler;
VkDeviceMemory FontMemory;
VkImage FontImage;
VkImageView FontView;
VkDescriptorSet FontDescriptorSet;
VkDeviceMemory UploadBufferMemory;
VkBuffer UploadBuffer;
ImGui_ImplVulkan_Data()
{
memset((void*)this, 0, sizeof(*this));
BufferMemoryAlignment = 256;
}
};
// Forward Declarations
bool ImGui_ImplVulkan_CreateDeviceObjects();
void ImGui_ImplVulkan_DestroyDeviceObjects();
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd,
const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device,
ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device,
ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks*
allocator);
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device,
ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks*
allocator);
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device,
VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks*
allocator, int w, int h, uint32_t min_image_count);
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device,
VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const
VkAllocationCallbacks* allocator);
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
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,0x0006
000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x0000
0001,
0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x0000
0015,
0x0000001b,0x0000001c,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69
616d,
0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c
6f43,
0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074
754f,
0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x0006
0005,
0x00000019,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000019,0x0000
0000,
0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001b,0x00000000,0x00040005,0x0000
001c,
0x736f5061,0x00000000,0x00060005,0x0000001e,0x73755075,0x6e6f4368,0x6e617473,0x0000
0074,
0x00050006,0x0000001e,0x00000000,0x61635375,0x0000656c,0x00060006,0x0000001e,0x0000
0001,
0x61725475,0x616c736e,0x00006574,0x00030005,0x00000020,0x00006370,0x00040047,0x0000
000b,
0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x0000
0015,
0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x0003
0047,
0x00000019,0x00000002,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00050048,0x0000
001e,
0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,0x00000001,0x00000023,0x0000
0008,
0x00030047,0x0000001e,0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x0000
0002,
0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x0004
0017,
0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x0004
0020,
0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x0004
0015,
0x0000000c,0x00000020,0x00000001,0x0004002b,0x0000000c,0x0000000d,0x00000000,0x0004
0020,
0x0000000e,0x00000001,0x00000007,0x0004003b,0x0000000e,0x0000000f,0x00000001,0x0004
0020,
0x00000011,0x00000003,0x00000007,0x0004002b,0x0000000c,0x00000013,0x00000001,0x0004
0020,
0x00000014,0x00000001,0x00000008,0x0004003b,0x00000014,0x00000015,0x00000001,0x0004
0020,
0x00000017,0x00000003,0x00000008,0x0003001e,0x00000019,0x00000007,0x00040020,0x0000
001a,
0x00000003,0x00000019,0x0004003b,0x0000001a,0x0000001b,0x00000003,0x0004003b,0x0000
0014,
0x0000001c,0x00000001,0x0004001e,0x0000001e,0x00000008,0x00000008,0x00040020,0x0000
001f,
0x00000009,0x0000001e,0x0004003b,0x0000001f,0x00000020,0x00000009,0x00040020,0x0000
0021,
0x00000009,0x00000008,0x0004002b,0x00000006,0x00000028,0x00000000,0x0004002b,0x0000
0006,
0x00000029,0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x0002
00f8,
0x00000005,0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x0000
0012,
0x0000000b,0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x0000
0016,
0x00000015,0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x0000
0018,
0x00000016,0x0004003d,0x00000008,0x0000001d,0x0000001c,0x00050041,0x00000021,0x0000
0022,
0x00000020,0x0000000d,0x0004003d,0x00000008,0x00000023,0x00000022,0x00050085,0x0000
0008,
0x00000024,0x0000001d,0x00000023,0x00050041,0x00000021,0x00000025,0x00000020,0x0000
0013,
0x0004003d,0x00000008,0x00000026,0x00000025,0x00050081,0x00000008,0x00000027,0x0000
0024,
0x00000026,0x00050051,0x00000006,0x0000002a,0x00000027,0x00000000,0x00050051,0x0000
0006,
0x0000002b,0x00000027,0x00000001,0x00070050,0x00000007,0x0000002c,0x0000002a,0x0000
002b,
0x00000028,0x00000029,0x00050041,0x00000011,0x0000002d,0x0000001b,0x0000000d,0x0003
003e,
0x0000002d,0x0000002c,0x000100fd,0x00010038
};
0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006
000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x0000
0001,
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x0003
0010,
0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69
616d,
0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x0000
0000,
0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x0000
0001,
0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x6572
7574,
0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000
001e,
0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x0000
0021,
0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x0000
0006,
0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x0000
0003,
0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x0000
0006,
0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x0000
0001,
0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x0000
0020,
0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x0000
0001,
0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x0000
0000,
0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x0000
0000,
0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x0000
0018,
0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00050036,0x00000002,0x0000
0004,
0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000
000d,
0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x0000
0017,
0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000
000a,
0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x0005
0085,
0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x0001
00fd,
0x00010038
};
//-----------------------------------------------------------------------------
// FUNCTIONS
//-----------------------------------------------------------------------------
VkMemoryRequirements req;
vkGetBufferMemoryRequirements(v->Device, buffer, &req);
bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd-
>BufferMemoryAlignment : req.alignment;
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = req.size;
alloc_info.memoryTypeIndex =
ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
req.memoryTypeBits);
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &buffer_memory);
check_vk_result(err);
// Bind pipeline:
{
LOGE("RENDER STATE1");
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline);
}
// Setup viewport:
{
LOGE("RENDER STATE6");
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;
LOGE("RENDER STATE7");
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
LOGE("RENDER STATE8");
}
// Render function
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer
command_buffer, VkPipeline pipeline)
{
LOGE("RENDER DRAWDATA");
// 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)
return;
LOGE("RENDER DRAWDATA1");
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (pipeline == VK_NULL_HANDLE)
pipeline = bd->Pipeline;
LOGE("RENDER DRAWDATA2");
// Allocate array to store enough vertex/index buffers
ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers;
if (wrb->FrameRenderBuffers == nullptr)
{
wrb->Index = 0;
wrb->Count = v->ImageCount;
LOGE("RENDER DRAWDATA3");
wrb->FrameRenderBuffers =
(ImGui_ImplVulkanH_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameRende
rBuffers) * wrb->Count);
LOGE("RENDER DRAWDATA4");
memset(wrb->FrameRenderBuffers, 0,
sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
}
IM_ASSERT(wrb->Count == v->ImageCount);
wrb->Index = (wrb->Index + 1) % wrb->Count;
LOGE("RENDER DRAWDATA5");
ImGui_ImplVulkanH_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb-
>Index];
LOGE("RENDER DRAWDATA6");
if (draw_data->TotalVtxCount > 0)
{
// Create or resize the vertex/index buffers
size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
LOGE("RENDER DRAWDAT7");
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);
LOGE("RENDER DRAWDATA8");
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);
// Draw
LOGE("RENDER DRAWDATA25");
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd-
>IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
}
LOGE("RENDER DRAWDATA26");
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
VkResult err;
// 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;
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
err = vkCreateImage(v->Device, &info, v->Allocator, &bd->FontImage);
check_vk_result(err);
VkMemoryRequirements req;
vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req);
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_DEVICE_LOCAL_BIT,
req.memoryTypeBits);
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd-
>FontMemory);
check_vk_result(err);
err = vkBindImageMemory(v->Device, bd->FontImage, bd->FontMemory, 0);
check_vk_result(err);
}
// Upload to Buffer:
{
char* map = nullptr;
err = vkMapMemory(v->Device, bd->UploadBufferMemory, 0, upload_size, 0,
(void**)(&map));
check_vk_result(err);
memcpy(map, pixels, upload_size);
VkMappedMemoryRange range[1] = {};
range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range[0].memory = bd->UploadBufferMemory;
range[0].size = upload_size;
err = vkFlushMappedMemoryRanges(v->Device, 1, range);
check_vk_result(err);
vkUnmapMemory(v->Device, bd->UploadBufferMemory);
}
// Copy to Image:
{
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 = bd->FontImage;
copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_barrier[0].subresourceRange.levelCount = 1;
copy_barrier[0].subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, copy_barrier);
return true;
}
bool ImGui_ImplVulkan_CreateDeviceObjects()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err;
if (!bd->FontSampler)
{
// 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;
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;
info.maxAnisotropy = 1.0f;
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->FontSampler);
check_vk_result(err);
}
if (!bd->DescriptorSetLayout)
{
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd-
>DescriptorSetLayout);
check_vk_result(err);
}
if (!bd->PipelineLayout)
{
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full
3d projection matrix
VkPushConstantRange push_constants[1] = {};
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_constants[0].offset = sizeof(float) * 0;
push_constants[0].size = sizeof(float) * 4;
VkDescriptorSetLayout set_layout[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;
err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &bd-
>PipelineLayout);
check_vk_result(err);
}
return true;
}
void ImGui_ImplVulkan_DestroyFontUploadObjects()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (bd->UploadBuffer)
{
vkDestroyBuffer(v->Device, bd->UploadBuffer, v->Allocator);
bd->UploadBuffer = VK_NULL_HANDLE;
}
if (bd->UploadBufferMemory)
{
vkFreeMemory(v->Device, bd->UploadBufferMemory, v->Allocator);
bd->UploadBufferMemory = VK_NULL_HANDLE;
}
}
void ImGui_ImplVulkan_DestroyDeviceObjects()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd-
>MainWindowRenderBuffers, v->Allocator);
ImGui_ImplVulkan_DestroyFontUploadObjects();
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a
renderer backend!");
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);
IM_ASSERT(info->MinImageCount >= 2);
IM_ASSERT(info->ImageCount >= info->MinImageCount);
IM_ASSERT(render_pass != VK_NULL_HANDLE);
bd->VulkanInitInfo = *info;
bd->RenderPass = render_pass;
bd->Subpass = info->Subpass;
ImGui_ImplVulkan_CreateDeviceObjects();
return true;
}
void ImGui_ImplVulkan_Shutdown()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already
shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplVulkan_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
IM_DELETE(bd);
}
void ImGui_ImplVulkan_NewFrame()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplVulkan_Init()?");
IM_UNUSED(bd);
}
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err = vkDeviceWaitIdle(v->Device);
check_vk_result(err);
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd-
>MainWindowRenderBuffers, v->Allocator);
bd->VulkanInitInfo.MinImageCount = min_image_count;
}
// Register a texture
// FIXME: This is experimental in the sense that we are unsure how to best
design/tackle this problem, please post to
https://github.com/ocornut/imgui/pull/914 if you have suggestions.
VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView
image_view, VkImageLayout image_layout)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used
by your own app.)
//-------------------------------------------------------------------------
// You probably do NOT need to use or care about those functions.
// Those functions only exist because:
// 1) they facilitate the readability and maintenance of the multiple main.cpp
examples files.
// 2) the upcoming multi-viewport feature will need them internally.
// Generally we avoid exposing any kind of superfluous high-level helpers in the
backends,
// but it is too much code to duplicate everywhere so we exceptionally expose them.
//
// Your engine/app will likely _already_ have code to setup all that stuff (swap
chain, render pass, frame buffers, etc.).
// You may read this code to learn about Vulkan, but it is recommended you use you
own custom tailored code to do equivalent work.
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used
by the regular ImGui_ImplVulkan_XXX functions)
//-------------------------------------------------------------------------
VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice
physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int
request_formats_count, VkColorSpaceKHR request_color_space)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions()
if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
IM_ASSERT(request_formats != nullptr);
IM_ASSERT(request_formats_count > 0);
// Per Spec Format and View Format are expected to be the same unless
VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
// Assuming that the default behavior is without setting this bit, there is no
need for separate Swapchain image and image view format
// Additionally several new color spaces were introduced with Vulkan Spec
v1.0.40,
// hence we must make sure that a format with the mostly available color space,
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used.
uint32_t avail_count;
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count,
nullptr);
ImVector<VkSurfaceFormatKHR> avail_format;
avail_format.resize((int)avail_count);
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count,
avail_format.Data);
// If none of the requested image formats could be found, use the first
available
return avail_format[0];
}
}
VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice
physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int
request_modes_count)
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions()
if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
IM_ASSERT(request_modes != nullptr);
IM_ASSERT(request_modes_count > 0);
int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR
present_mode)
{
if (present_mode == VK_PRESENT_MODE_MAILBOX_KHR)
return 3;
if (present_mode == VK_PRESENT_MODE_FIFO_KHR || present_mode ==
VK_PRESENT_MODE_FIFO_RELAXED_KHR)
return 2;
if (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
return 1;
IM_ASSERT(0);
return 1;
}
// Also destroy old swap chain and in-flight frames data, if any.
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device,
VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks*
allocator, int w, int h, uint32_t min_image_count)
{
VkResult err;
VkSwapchainKHR old_swapchain = wd->Swapchain;
wd->Swapchain = VK_NULL_HANDLE;
err = vkDeviceWaitIdle(device);
check_vk_result(err);
// If min image count was not specified, request different count of images
dependent on selected present mode
if (min_image_count == 0)
min_image_count = ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(wd-
>PresentMode);
// Create Swapchain
{
VkSwapchainCreateInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
info.surface = wd->Surface;
info.minImageCount = min_image_count;
info.imageFormat = wd->SurfaceFormat.format;
info.imageColorSpace = wd->SurfaceFormat.colorSpace;
info.imageArrayLayers = 1;
info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
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);
if (info.minImageCount < cap.minImageCount)
info.minImageCount = cap.minImageCount;
else if (cap.maxImageCount != 0 && info.minImageCount > cap.maxImageCount)
info.minImageCount = cap.maxImageCount;
if (cap.currentExtent.width == 0xffffffff)
{
info.imageExtent.width = wd->Width = w;
info.imageExtent.height = wd->Height = h;
}
else
{
info.imageExtent.width = wd->Width = cap.currentExtent.width;
info.imageExtent.height = wd->Height = cap.currentExtent.height;
}
err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);
check_vk_result(err);
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount,
nullptr);
check_vk_result(err);
VkImage backbuffers[16] = {};
IM_ASSERT(wd->ImageCount >= min_image_count);
IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers));
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount,
backbuffers);
check_vk_result(err);
IM_ASSERT(wd->Frames == nullptr);
wd->Frames =
(ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd-
>ImageCount);
wd->FrameSemaphores =
(ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphor
es) * wd->ImageCount);
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++)
wd->Frames[i].Backbuffer = backbuffers[i];
}
if (old_swapchain)
vkDestroySwapchainKHR(device, old_swapchain, allocator);
// 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;
for (uint32_t i = 0; i < wd->ImageCount; i++)
{
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
attachment[0] = fd->BackbufferView;
err = vkCreateFramebuffer(device, &info, allocator, &fd->Framebuffer);
check_vk_result(err);
}
}
}
*wd = ImGui_ImplVulkanH_Window();
}