mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-11-04 01:34:32 +00:00 
			
		
		
		
	Backends: Vulkan: added ImGuiBackendFlags_RendererHasTextures support.
# Conflicts: # backends/imgui_impl_vulkan.cpp
This commit is contained in:
		@@ -2,8 +2,9 @@
 | 
			
		||||
// 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. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
 | 
			
		||||
//  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
 | 
			
		||||
//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 | 
			
		||||
//  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
 | 
			
		||||
//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 | 
			
		||||
 | 
			
		||||
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
 | 
			
		||||
@@ -26,7 +27,8 @@
 | 
			
		||||
 | 
			
		||||
// CHANGELOG
 | 
			
		||||
// (minor and older changes stripped away, please see git history for details)
 | 
			
		||||
//  2025-05-07- Vulkan: Fixed validation errors during window detach in multi-viewport mode. (#8600, #8176)
 | 
			
		||||
//  2025-06-11: Vulkan: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplVulkan_CreateFontsTexture() and ImGui_ImplVulkan_DestroyFontsTexture().
 | 
			
		||||
//  2025-05-07: Vulkan: Fixed validation errors during window detach in multi-viewport mode. (#8600, #8176)
 | 
			
		||||
//  2025-05-07: Vulkan: Load dynamic rendering functions using vkGetDeviceProcAddr() + try both non-KHR and KHR versions. (#8600, #8326, #8365)
 | 
			
		||||
//  2025-04-07: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's pColorAttachmentFormats buffer when set, in order to reduce common user-error of specifying a pointer to data that gets out of scope. (#8282)
 | 
			
		||||
//  2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
 | 
			
		||||
@@ -251,7 +253,6 @@ struct ImGui_ImplVulkan_Data
 | 
			
		||||
    VkDescriptorPool            DescriptorPool;
 | 
			
		||||
 | 
			
		||||
    // Texture management
 | 
			
		||||
    ImGui_ImplVulkan_Texture    FontTexture;
 | 
			
		||||
    VkSampler                   TexSampler;
 | 
			
		||||
    VkCommandPool               TexCommandPool;
 | 
			
		||||
    VkCommandBuffer             TexCommandBuffer;
 | 
			
		||||
@@ -502,6 +503,13 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
 | 
			
		||||
    if (fb_width <= 0 || fb_height <= 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
 | 
			
		||||
    // (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
 | 
			
		||||
    if (draw_data->Textures != nullptr)
 | 
			
		||||
        for (ImTextureData* tex : *draw_data->Textures)
 | 
			
		||||
            if (tex->Status != ImTextureStatus_OK)
 | 
			
		||||
                ImGui_ImplVulkan_UpdateTexture(tex);
 | 
			
		||||
 | 
			
		||||
    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
 | 
			
		||||
    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
 | 
			
		||||
    if (pipeline == VK_NULL_HANDLE)
 | 
			
		||||
@@ -638,220 +646,222 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
 | 
			
		||||
    vkCmdSetScissor(command_buffer, 0, 1, &scissor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ImGui_ImplVulkan_CreateFontsTexture()
 | 
			
		||||
static void ImGui_ImplVulkan_DestroyTexture(ImTextureData* tex)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiIO& io = ImGui::GetIO();
 | 
			
		||||
    ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData;
 | 
			
		||||
    if (backend_tex == nullptr)
 | 
			
		||||
        return;
 | 
			
		||||
    IM_ASSERT(backend_tex->DescriptorSet == (VkDescriptorSet)tex->TexID);
 | 
			
		||||
    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
 | 
			
		||||
    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
 | 
			
		||||
    ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
 | 
			
		||||
    vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator);
 | 
			
		||||
    vkDestroyImage(v->Device, backend_tex->Image, v->Allocator);
 | 
			
		||||
    vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator);
 | 
			
		||||
    IM_DELETE(backend_tex);
 | 
			
		||||
 | 
			
		||||
    // Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
 | 
			
		||||
    tex->SetTexID(ImTextureID_Invalid);
 | 
			
		||||
    tex->SetStatus(ImTextureStatus_Destroyed);
 | 
			
		||||
    tex->BackendUserData = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
 | 
			
		||||
{
 | 
			
		||||
    if (tex->Status == ImTextureStatus_OK)
 | 
			
		||||
        return;
 | 
			
		||||
    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
 | 
			
		||||
    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
 | 
			
		||||
    VkResult err;
 | 
			
		||||
 | 
			
		||||
    // Destroy existing texture (if any)
 | 
			
		||||
    if (bd->FontTexture.DescriptorSet)
 | 
			
		||||
    if (tex->Status == ImTextureStatus_WantCreate)
 | 
			
		||||
    {
 | 
			
		||||
        vkQueueWaitIdle(v->Queue);
 | 
			
		||||
        ImGui_ImplVulkan_DestroyFontsTexture();
 | 
			
		||||
        // Create and upload new texture to graphics system
 | 
			
		||||
        //IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
 | 
			
		||||
        IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
 | 
			
		||||
        IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
 | 
			
		||||
        ImGui_ImplVulkan_Texture* backend_tex = IM_NEW(ImGui_ImplVulkan_Texture)();
 | 
			
		||||
 | 
			
		||||
        // Create the Image:
 | 
			
		||||
        {
 | 
			
		||||
            VkImageCreateInfo info = {};
 | 
			
		||||
            info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 | 
			
		||||
            info.imageType = VK_IMAGE_TYPE_2D;
 | 
			
		||||
            info.format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
			
		||||
            info.extent.width = tex->Width;
 | 
			
		||||
            info.extent.height = tex->Height;
 | 
			
		||||
            info.extent.depth = 1;
 | 
			
		||||
            info.mipLevels = 1;
 | 
			
		||||
            info.arrayLayers = 1;
 | 
			
		||||
            info.samples = VK_SAMPLE_COUNT_1_BIT;
 | 
			
		||||
            info.tiling = VK_IMAGE_TILING_OPTIMAL;
 | 
			
		||||
            info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 | 
			
		||||
            info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
			
		||||
            info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 | 
			
		||||
            err = vkCreateImage(v->Device, &info, v->Allocator, &backend_tex->Image);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            VkMemoryRequirements req;
 | 
			
		||||
            vkGetImageMemoryRequirements(v->Device, backend_tex->Image, &req);
 | 
			
		||||
            VkMemoryAllocateInfo alloc_info = {};
 | 
			
		||||
            alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
 | 
			
		||||
            alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);
 | 
			
		||||
            alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
 | 
			
		||||
            err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &backend_tex->Memory);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            err = vkBindImageMemory(v->Device, backend_tex->Image, backend_tex->Memory, 0);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create the Image View:
 | 
			
		||||
        {
 | 
			
		||||
            VkImageViewCreateInfo info = {};
 | 
			
		||||
            info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
 | 
			
		||||
            info.image = backend_tex->Image;
 | 
			
		||||
            info.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
			
		||||
            info.format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
			
		||||
            info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
            info.subresourceRange.levelCount = 1;
 | 
			
		||||
            info.subresourceRange.layerCount = 1;
 | 
			
		||||
            err = vkCreateImageView(v->Device, &info, v->Allocator, &backend_tex->ImageView);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create the Descriptor Set
 | 
			
		||||
        backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 | 
			
		||||
 | 
			
		||||
        // Store identifiers
 | 
			
		||||
        tex->SetTexID((ImTextureID)backend_tex->DescriptorSet);
 | 
			
		||||
        tex->BackendUserData = backend_tex;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create command pool/buffer
 | 
			
		||||
    if (bd->TexCommandPool == VK_NULL_HANDLE)
 | 
			
		||||
    if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
 | 
			
		||||
    {
 | 
			
		||||
        VkCommandPoolCreateInfo info = {};
 | 
			
		||||
        info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
 | 
			
		||||
        info.flags = 0;
 | 
			
		||||
        info.queueFamilyIndex = v->QueueFamily;
 | 
			
		||||
        vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->TexCommandPool);
 | 
			
		||||
    }
 | 
			
		||||
    if (bd->TexCommandBuffer == VK_NULL_HANDLE)
 | 
			
		||||
    {
 | 
			
		||||
        VkCommandBufferAllocateInfo info = {};
 | 
			
		||||
        info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
 | 
			
		||||
        info.commandPool = bd->TexCommandPool;
 | 
			
		||||
        info.commandBufferCount = 1;
 | 
			
		||||
        err = vkAllocateCommandBuffers(v->Device, &info, &bd->TexCommandBuffer);
 | 
			
		||||
        ImGui_ImplVulkan_Texture* backend_tex = (ImGui_ImplVulkan_Texture*)tex->BackendUserData;
 | 
			
		||||
 | 
			
		||||
        // Update full texture or selected blocks. We only ever write to textures regions which have never been used before!
 | 
			
		||||
        // This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions.
 | 
			
		||||
        // We could use the smaller rect on _WantCreate but using the full rect allows us to clear the texture.
 | 
			
		||||
        const int upload_x = (tex->Status == ImTextureStatus_WantCreate) ? 0 : tex->UpdateRect.x;
 | 
			
		||||
        const int upload_y = (tex->Status == ImTextureStatus_WantCreate) ? 0 : tex->UpdateRect.y;
 | 
			
		||||
        const int upload_w = (tex->Status == ImTextureStatus_WantCreate) ? tex->Width : tex->UpdateRect.w;
 | 
			
		||||
        const int upload_h = (tex->Status == ImTextureStatus_WantCreate) ? tex->Height : tex->UpdateRect.h;
 | 
			
		||||
 | 
			
		||||
        // Create the Upload Buffer:
 | 
			
		||||
        VkDeviceMemory upload_buffer_memory;
 | 
			
		||||
 | 
			
		||||
        VkBuffer upload_buffer;
 | 
			
		||||
        VkDeviceSize upload_pitch = upload_w * tex->BytesPerPixel;
 | 
			
		||||
        VkDeviceSize upload_size = upload_h * upload_pitch;
 | 
			
		||||
        {
 | 
			
		||||
            VkBufferCreateInfo buffer_info = {};
 | 
			
		||||
            buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
 | 
			
		||||
            buffer_info.size = upload_size;
 | 
			
		||||
            buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
 | 
			
		||||
            buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
 | 
			
		||||
            err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &upload_buffer);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            VkMemoryRequirements req;
 | 
			
		||||
            vkGetBufferMemoryRequirements(v->Device, upload_buffer, &req);
 | 
			
		||||
            bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;
 | 
			
		||||
            VkMemoryAllocateInfo alloc_info = {};
 | 
			
		||||
            alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
 | 
			
		||||
            alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);
 | 
			
		||||
            alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
 | 
			
		||||
            err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &upload_buffer_memory);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            err = vkBindBufferMemory(v->Device, upload_buffer, upload_buffer_memory, 0);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Upload to Buffer:
 | 
			
		||||
        {
 | 
			
		||||
            char* map = nullptr;
 | 
			
		||||
            err = vkMapMemory(v->Device, upload_buffer_memory, 0, upload_size, 0, (void**)(&map));
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            for (int y = 0; y < upload_h; y++)
 | 
			
		||||
                memcpy(map + upload_pitch * y, tex->GetPixelsAt(upload_x, upload_y + y), (size_t)upload_pitch);
 | 
			
		||||
            VkMappedMemoryRange range[1] = {};
 | 
			
		||||
            range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
 | 
			
		||||
            range[0].memory = upload_buffer_memory;
 | 
			
		||||
            range[0].size = upload_size;
 | 
			
		||||
            err = vkFlushMappedMemoryRanges(v->Device, 1, range);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            vkUnmapMemory(v->Device, upload_buffer_memory);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Start command buffer
 | 
			
		||||
        {
 | 
			
		||||
            err = vkResetCommandPool(v->Device, bd->TexCommandPool, 0);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            VkCommandBufferBeginInfo begin_info = {};
 | 
			
		||||
            begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
 | 
			
		||||
            begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
 | 
			
		||||
            err = vkBeginCommandBuffer(bd->TexCommandBuffer, &begin_info);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Copy to Image:
 | 
			
		||||
        {
 | 
			
		||||
            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 = backend_tex->Image;
 | 
			
		||||
            copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
            copy_barrier[0].subresourceRange.levelCount = 1;
 | 
			
		||||
            copy_barrier[0].subresourceRange.layerCount = 1;
 | 
			
		||||
            vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, copy_barrier);
 | 
			
		||||
 | 
			
		||||
            VkBufferImageCopy region = {};
 | 
			
		||||
            region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
            region.imageSubresource.layerCount = 1;
 | 
			
		||||
            region.imageExtent.width = upload_w;
 | 
			
		||||
            region.imageExtent.height = upload_h;
 | 
			
		||||
            region.imageExtent.depth = 1;
 | 
			
		||||
            region.imageOffset.x = upload_x;
 | 
			
		||||
            region.imageOffset.y = upload_y;
 | 
			
		||||
            vkCmdCopyBufferToImage(bd->TexCommandBuffer, upload_buffer, backend_tex->Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
 | 
			
		||||
 | 
			
		||||
            VkImageMemoryBarrier use_barrier[1] = {};
 | 
			
		||||
            use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
 | 
			
		||||
            use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
			
		||||
            use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
 | 
			
		||||
            use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 | 
			
		||||
            use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
			
		||||
            use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 | 
			
		||||
            use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 | 
			
		||||
            use_barrier[0].image = backend_tex->Image;
 | 
			
		||||
            use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
            use_barrier[0].subresourceRange.levelCount = 1;
 | 
			
		||||
            use_barrier[0].subresourceRange.layerCount = 1;
 | 
			
		||||
            vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // End command buffer
 | 
			
		||||
        {
 | 
			
		||||
            VkSubmitInfo end_info = {};
 | 
			
		||||
            end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
 | 
			
		||||
            end_info.commandBufferCount = 1;
 | 
			
		||||
            end_info.pCommandBuffers = &bd->TexCommandBuffer;
 | 
			
		||||
            err = vkEndCommandBuffer(bd->TexCommandBuffer);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
            err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE);
 | 
			
		||||
            check_vk_result(err);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        err = vkQueueWaitIdle(v->Queue); // FIXME-OPT: Suboptimal!
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        vkDestroyBuffer(v->Device, upload_buffer, v->Allocator);
 | 
			
		||||
        vkFreeMemory(v->Device, upload_buffer_memory, v->Allocator);
 | 
			
		||||
 | 
			
		||||
        tex->SetStatus(ImTextureStatus_OK);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Start command buffer
 | 
			
		||||
    {
 | 
			
		||||
        err = vkResetCommandPool(v->Device, bd->TexCommandPool, 0);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        VkCommandBufferBeginInfo begin_info = {};
 | 
			
		||||
        begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
 | 
			
		||||
        begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
 | 
			
		||||
        err = vkBeginCommandBuffer(bd->TexCommandBuffer, &begin_info);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned char* pixels;
 | 
			
		||||
    int width, height;
 | 
			
		||||
    io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
 | 
			
		||||
    size_t upload_size = width * height * 4 * sizeof(char);
 | 
			
		||||
 | 
			
		||||
    // Create the Image:
 | 
			
		||||
    ImGui_ImplVulkan_Texture* backend_tex = &bd->FontTexture;
 | 
			
		||||
    {
 | 
			
		||||
        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, &backend_tex->Image);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        VkMemoryRequirements req;
 | 
			
		||||
        vkGetImageMemoryRequirements(v->Device, backend_tex->Image, &req);
 | 
			
		||||
        VkMemoryAllocateInfo alloc_info = {};
 | 
			
		||||
        alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
 | 
			
		||||
        alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);
 | 
			
		||||
        alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
 | 
			
		||||
        err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &backend_tex->Memory);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        err = vkBindImageMemory(v->Device, backend_tex->Image, backend_tex->Memory, 0);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create the Image View:
 | 
			
		||||
    {
 | 
			
		||||
        VkImageViewCreateInfo info = {};
 | 
			
		||||
        info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
 | 
			
		||||
        info.image = backend_tex->Image;
 | 
			
		||||
        info.viewType = VK_IMAGE_VIEW_TYPE_2D;
 | 
			
		||||
        info.format = VK_FORMAT_R8G8B8A8_UNORM;
 | 
			
		||||
        info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
        info.subresourceRange.levelCount = 1;
 | 
			
		||||
        info.subresourceRange.layerCount = 1;
 | 
			
		||||
        err = vkCreateImageView(v->Device, &info, v->Allocator, &backend_tex->ImageView);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create the Descriptor Set:
 | 
			
		||||
    backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 | 
			
		||||
 | 
			
		||||
    // Create the Upload Buffer:
 | 
			
		||||
    VkDeviceMemory upload_buffer_memory;
 | 
			
		||||
    VkBuffer 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;
 | 
			
		||||
        err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &upload_buffer);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        VkMemoryRequirements req;
 | 
			
		||||
        vkGetBufferMemoryRequirements(v->Device, upload_buffer, &req);
 | 
			
		||||
        bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;
 | 
			
		||||
        VkMemoryAllocateInfo alloc_info = {};
 | 
			
		||||
        alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
 | 
			
		||||
        alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);
 | 
			
		||||
        alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
 | 
			
		||||
        err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &upload_buffer_memory);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        err = vkBindBufferMemory(v->Device, upload_buffer, upload_buffer_memory, 0);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Upload to Buffer:
 | 
			
		||||
    {
 | 
			
		||||
        char* map = nullptr;
 | 
			
		||||
        err = vkMapMemory(v->Device, upload_buffer_memory, 0, upload_size, 0, (void**)(&map));
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        memcpy(map, pixels, upload_size);
 | 
			
		||||
        VkMappedMemoryRange range[1] = {};
 | 
			
		||||
        range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
 | 
			
		||||
        range[0].memory = upload_buffer_memory;
 | 
			
		||||
        range[0].size = upload_size;
 | 
			
		||||
        err = vkFlushMappedMemoryRanges(v->Device, 1, range);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
        vkUnmapMemory(v->Device, upload_buffer_memory);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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 = backend_tex->Image;
 | 
			
		||||
        copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
        copy_barrier[0].subresourceRange.levelCount = 1;
 | 
			
		||||
        copy_barrier[0].subresourceRange.layerCount = 1;
 | 
			
		||||
        vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, copy_barrier);
 | 
			
		||||
 | 
			
		||||
        VkBufferImageCopy region = {};
 | 
			
		||||
        region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
        region.imageSubresource.layerCount = 1;
 | 
			
		||||
        region.imageExtent.width = width;
 | 
			
		||||
        region.imageExtent.height = height;
 | 
			
		||||
        region.imageExtent.depth = 1;
 | 
			
		||||
        vkCmdCopyBufferToImage(bd->TexCommandBuffer, upload_buffer, backend_tex->Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
 | 
			
		||||
 | 
			
		||||
        VkImageMemoryBarrier use_barrier[1] = {};
 | 
			
		||||
        use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
 | 
			
		||||
        use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 | 
			
		||||
        use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
 | 
			
		||||
        use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
 | 
			
		||||
        use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
			
		||||
        use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 | 
			
		||||
        use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
 | 
			
		||||
        use_barrier[0].image = backend_tex->Image;
 | 
			
		||||
        use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 | 
			
		||||
        use_barrier[0].subresourceRange.levelCount = 1;
 | 
			
		||||
        use_barrier[0].subresourceRange.layerCount = 1;
 | 
			
		||||
        vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Store our identifier
 | 
			
		||||
    io.Fonts->SetTexID((ImTextureID)backend_tex->DescriptorSet);
 | 
			
		||||
 | 
			
		||||
    // End command buffer
 | 
			
		||||
    VkSubmitInfo end_info = {};
 | 
			
		||||
    end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
 | 
			
		||||
    end_info.commandBufferCount = 1;
 | 
			
		||||
    end_info.pCommandBuffers = &bd->TexCommandBuffer;
 | 
			
		||||
    err = vkEndCommandBuffer(bd->TexCommandBuffer);
 | 
			
		||||
    check_vk_result(err);
 | 
			
		||||
    err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE);
 | 
			
		||||
    check_vk_result(err);
 | 
			
		||||
 | 
			
		||||
    err = vkQueueWaitIdle(v->Queue);
 | 
			
		||||
    check_vk_result(err);
 | 
			
		||||
 | 
			
		||||
    vkDestroyBuffer(v->Device, upload_buffer, v->Allocator);
 | 
			
		||||
    vkFreeMemory(v->Device, upload_buffer_memory, v->Allocator);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// You probably never need to call this, as it is called by ImGui_ImplVulkan_CreateFontsTexture() and ImGui_ImplVulkan_Shutdown().
 | 
			
		||||
void ImGui_ImplVulkan_DestroyFontsTexture()
 | 
			
		||||
{
 | 
			
		||||
    ImGuiIO& io = ImGui::GetIO();
 | 
			
		||||
    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
 | 
			
		||||
    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
 | 
			
		||||
 | 
			
		||||
    ImGui_ImplVulkan_Texture* backend_tex = &bd->FontTexture;
 | 
			
		||||
 | 
			
		||||
    if (backend_tex->DescriptorSet)
 | 
			
		||||
    {
 | 
			
		||||
        ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
 | 
			
		||||
        backend_tex->DescriptorSet = VK_NULL_HANDLE;
 | 
			
		||||
        io.Fonts->SetTexID(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (backend_tex->ImageView) { vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator); backend_tex->ImageView = VK_NULL_HANDLE; }
 | 
			
		||||
    if (backend_tex->Image)     { vkDestroyImage(v->Device, backend_tex->Image, v->Allocator); backend_tex->Image = VK_NULL_HANDLE; }
 | 
			
		||||
    if (backend_tex->Memory)    { vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator); backend_tex->Memory = VK_NULL_HANDLE; }
 | 
			
		||||
    if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames >= (int)bd->VulkanInitInfo.ImageCount)
 | 
			
		||||
        ImGui_ImplVulkan_DestroyTexture(tex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)
 | 
			
		||||
@@ -1066,6 +1076,26 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
 | 
			
		||||
 | 
			
		||||
    ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, &bd->Pipeline, v->Subpass);
 | 
			
		||||
 | 
			
		||||
    // Create command pool/buffer for texture upload
 | 
			
		||||
    if (!bd->TexCommandPool)
 | 
			
		||||
    {
 | 
			
		||||
        VkCommandPoolCreateInfo info = {};
 | 
			
		||||
        info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
 | 
			
		||||
        info.flags = 0;
 | 
			
		||||
        info.queueFamilyIndex = v->QueueFamily;
 | 
			
		||||
        err = vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->TexCommandPool);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
    }
 | 
			
		||||
    if (!bd->TexCommandBuffer)
 | 
			
		||||
    {
 | 
			
		||||
        VkCommandBufferAllocateInfo info = {};
 | 
			
		||||
        info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
 | 
			
		||||
        info.commandPool = bd->TexCommandPool;
 | 
			
		||||
        info.commandBufferCount = 1;
 | 
			
		||||
        err = vkAllocateCommandBuffers(v->Device, &info, &bd->TexCommandBuffer);
 | 
			
		||||
        check_vk_result(err);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1074,7 +1104,11 @@ void    ImGui_ImplVulkan_DestroyDeviceObjects()
 | 
			
		||||
    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
 | 
			
		||||
    ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
 | 
			
		||||
    ImGui_ImplVulkan_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator);
 | 
			
		||||
    ImGui_ImplVulkan_DestroyFontsTexture();
 | 
			
		||||
 | 
			
		||||
    // Destroy all textures
 | 
			
		||||
    for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
 | 
			
		||||
        if (tex->RefCount == 1)
 | 
			
		||||
            ImGui_ImplVulkan_DestroyTexture(tex);
 | 
			
		||||
 | 
			
		||||
    if (bd->TexCommandBuffer)     { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; }
 | 
			
		||||
    if (bd->TexCommandPool)       { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; }
 | 
			
		||||
@@ -1175,6 +1209,7 @@ bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
 | 
			
		||||
    io.BackendRendererUserData = (void*)bd;
 | 
			
		||||
    io.BackendRendererName = "imgui_impl_vulkan";
 | 
			
		||||
    io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
 | 
			
		||||
    io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;   // We can honor ImGuiPlatformIO::Textures[] requests during render.
 | 
			
		||||
 | 
			
		||||
    IM_ASSERT(info->Instance != VK_NULL_HANDLE);
 | 
			
		||||
    IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
 | 
			
		||||
@@ -1219,7 +1254,7 @@ void ImGui_ImplVulkan_Shutdown()
 | 
			
		||||
 | 
			
		||||
    io.BackendRendererName = nullptr;
 | 
			
		||||
    io.BackendRendererUserData = nullptr;
 | 
			
		||||
    io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
 | 
			
		||||
    io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
 | 
			
		||||
    IM_DELETE(bd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1227,9 +1262,7 @@ void ImGui_ImplVulkan_NewFrame()
 | 
			
		||||
{
 | 
			
		||||
    ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
 | 
			
		||||
    IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?");
 | 
			
		||||
 | 
			
		||||
    if (!bd->FontTexture.DescriptorSet)
 | 
			
		||||
        ImGui_ImplVulkan_CreateFontsTexture();
 | 
			
		||||
    IM_UNUSED(bd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,9 @@
 | 
			
		||||
// 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. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
 | 
			
		||||
//  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
 | 
			
		||||
//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 | 
			
		||||
//  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
 | 
			
		||||
//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 | 
			
		||||
 | 
			
		||||
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
 | 
			
		||||
@@ -61,9 +62,8 @@
 | 
			
		||||
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Current version of the backend use 1 descriptor for the font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
 | 
			
		||||
// It is expected that as early as Q1 2025 the backend will use a few more descriptors. Use this value + number of desired calls to ImGui_ImplVulkan_AddTexture().
 | 
			
		||||
#define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE   (1)     // Minimum per atlas
 | 
			
		||||
// Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
 | 
			
		||||
#define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE   (8)     // Minimum per atlas
 | 
			
		||||
 | 
			
		||||
// Initialization data, for ImGui_ImplVulkan_Init()
 | 
			
		||||
// [Please zero-clear before use!]
 | 
			
		||||
@@ -112,10 +112,11 @@ IMGUI_IMPL_API bool             ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo*
 | 
			
		||||
IMGUI_IMPL_API void             ImGui_ImplVulkan_Shutdown();
 | 
			
		||||
IMGUI_IMPL_API void             ImGui_ImplVulkan_NewFrame();
 | 
			
		||||
IMGUI_IMPL_API void             ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
 | 
			
		||||
IMGUI_IMPL_API bool             ImGui_ImplVulkan_CreateFontsTexture();
 | 
			
		||||
IMGUI_IMPL_API void             ImGui_ImplVulkan_DestroyFontsTexture();
 | 
			
		||||
IMGUI_IMPL_API void             ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
 | 
			
		||||
 | 
			
		||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
 | 
			
		||||
IMGUI_IMPL_API void             ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex);
 | 
			
		||||
 | 
			
		||||
// Register a texture (VkDescriptorSet == ImTextureID)
 | 
			
		||||
// 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.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user