mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +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..) | // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) | ||||||
|  |  | ||||||
| // Implemented features: | // 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: 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'. | //  [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. | // The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification. | ||||||
| @@ -26,7 +27,8 @@ | |||||||
|  |  | ||||||
| // CHANGELOG | // CHANGELOG | ||||||
| // (minor and older changes stripped away, please see git history for details) | // (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-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-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(). | //  2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions(). | ||||||
| @@ -251,7 +253,6 @@ struct ImGui_ImplVulkan_Data | |||||||
|     VkDescriptorPool            DescriptorPool; |     VkDescriptorPool            DescriptorPool; | ||||||
|  |  | ||||||
|     // Texture management |     // Texture management | ||||||
|     ImGui_ImplVulkan_Texture    FontTexture; |  | ||||||
|     VkSampler                   TexSampler; |     VkSampler                   TexSampler; | ||||||
|     VkCommandPool               TexCommandPool; |     VkCommandPool               TexCommandPool; | ||||||
|     VkCommandBuffer             TexCommandBuffer; |     VkCommandBuffer             TexCommandBuffer; | ||||||
| @@ -502,6 +503,13 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | |||||||
|     if (fb_width <= 0 || fb_height <= 0) |     if (fb_width <= 0 || fb_height <= 0) | ||||||
|         return; |         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_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     if (pipeline == VK_NULL_HANDLE) |     if (pipeline == VK_NULL_HANDLE) | ||||||
| @@ -638,64 +646,50 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | |||||||
|     vkCmdSetScissor(command_buffer, 0, 1, &scissor); |     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_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     VkResult err; |     VkResult err; | ||||||
|  |  | ||||||
|     // Destroy existing texture (if any) |     if (tex->Status == ImTextureStatus_WantCreate) | ||||||
|     if (bd->FontTexture.DescriptorSet) |  | ||||||
|     { |     { | ||||||
|         vkQueueWaitIdle(v->Queue); |         // Create and upload new texture to graphics system | ||||||
|         ImGui_ImplVulkan_DestroyFontsTexture(); |         //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); | ||||||
|     // Create command pool/buffer |         ImGui_ImplVulkan_Texture* backend_tex = IM_NEW(ImGui_ImplVulkan_Texture)(); | ||||||
|     if (bd->TexCommandPool == VK_NULL_HANDLE) |  | ||||||
|     { |  | ||||||
|         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); |  | ||||||
|         check_vk_result(err); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // 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: |         // Create the Image: | ||||||
|     ImGui_ImplVulkan_Texture* backend_tex = &bd->FontTexture; |  | ||||||
|         { |         { | ||||||
|             VkImageCreateInfo info = {}; |             VkImageCreateInfo info = {}; | ||||||
|             info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; |             info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; | ||||||
|             info.imageType = VK_IMAGE_TYPE_2D; |             info.imageType = VK_IMAGE_TYPE_2D; | ||||||
|             info.format = VK_FORMAT_R8G8B8A8_UNORM; |             info.format = VK_FORMAT_R8G8B8A8_UNORM; | ||||||
|         info.extent.width = width; |             info.extent.width = tex->Width; | ||||||
|         info.extent.height = height; |             info.extent.height = tex->Height; | ||||||
|             info.extent.depth = 1; |             info.extent.depth = 1; | ||||||
|             info.mipLevels = 1; |             info.mipLevels = 1; | ||||||
|             info.arrayLayers = 1; |             info.arrayLayers = 1; | ||||||
| @@ -732,12 +726,32 @@ bool ImGui_ImplVulkan_CreateFontsTexture() | |||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     // Create the Descriptor Set: |         // Create the Descriptor Set | ||||||
|         backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); |         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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates) | ||||||
|  |     { | ||||||
|  |         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: |         // Create the Upload Buffer: | ||||||
|         VkDeviceMemory upload_buffer_memory; |         VkDeviceMemory upload_buffer_memory; | ||||||
|  |  | ||||||
|         VkBuffer upload_buffer; |         VkBuffer upload_buffer; | ||||||
|  |         VkDeviceSize upload_pitch = upload_w * tex->BytesPerPixel; | ||||||
|  |         VkDeviceSize upload_size = upload_h * upload_pitch; | ||||||
|         { |         { | ||||||
|             VkBufferCreateInfo buffer_info = {}; |             VkBufferCreateInfo buffer_info = {}; | ||||||
|             buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |             buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | ||||||
| @@ -764,7 +778,8 @@ bool ImGui_ImplVulkan_CreateFontsTexture() | |||||||
|             char* map = nullptr; |             char* map = nullptr; | ||||||
|             err = vkMapMemory(v->Device, upload_buffer_memory, 0, upload_size, 0, (void**)(&map)); |             err = vkMapMemory(v->Device, upload_buffer_memory, 0, upload_size, 0, (void**)(&map)); | ||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|         memcpy(map, pixels, upload_size); |             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] = {}; |             VkMappedMemoryRange range[1] = {}; | ||||||
|             range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; |             range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; | ||||||
|             range[0].memory = upload_buffer_memory; |             range[0].memory = upload_buffer_memory; | ||||||
| @@ -774,6 +789,17 @@ bool ImGui_ImplVulkan_CreateFontsTexture() | |||||||
|             vkUnmapMemory(v->Device, upload_buffer_memory); |             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: |         // Copy to Image: | ||||||
|         { |         { | ||||||
|             VkImageMemoryBarrier copy_barrier[1] = {}; |             VkImageMemoryBarrier copy_barrier[1] = {}; | ||||||
| @@ -792,9 +818,11 @@ bool ImGui_ImplVulkan_CreateFontsTexture() | |||||||
|             VkBufferImageCopy region = {}; |             VkBufferImageCopy region = {}; | ||||||
|             region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |             region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | ||||||
|             region.imageSubresource.layerCount = 1; |             region.imageSubresource.layerCount = 1; | ||||||
|         region.imageExtent.width = width; |             region.imageExtent.width = upload_w; | ||||||
|         region.imageExtent.height = height; |             region.imageExtent.height = upload_h; | ||||||
|             region.imageExtent.depth = 1; |             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); |             vkCmdCopyBufferToImage(bd->TexCommandBuffer, upload_buffer, backend_tex->Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); | ||||||
|  |  | ||||||
|             VkImageMemoryBarrier use_barrier[1] = {}; |             VkImageMemoryBarrier use_barrier[1] = {}; | ||||||
| @@ -812,10 +840,8 @@ bool ImGui_ImplVulkan_CreateFontsTexture() | |||||||
|             vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier); |             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 |         // End command buffer | ||||||
|  |         { | ||||||
|             VkSubmitInfo end_info = {}; |             VkSubmitInfo end_info = {}; | ||||||
|             end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |             end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | ||||||
|             end_info.commandBufferCount = 1; |             end_info.commandBufferCount = 1; | ||||||
| @@ -824,34 +850,18 @@ bool ImGui_ImplVulkan_CreateFontsTexture() | |||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|             err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE); |             err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE); | ||||||
|             check_vk_result(err); |             check_vk_result(err); | ||||||
|  |         } | ||||||
|  |  | ||||||
|     err = vkQueueWaitIdle(v->Queue); |         err = vkQueueWaitIdle(v->Queue); // FIXME-OPT: Suboptimal! | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|  |  | ||||||
|         vkDestroyBuffer(v->Device, upload_buffer, v->Allocator); |         vkDestroyBuffer(v->Device, upload_buffer, v->Allocator); | ||||||
|         vkFreeMemory(v->Device, upload_buffer_memory, v->Allocator); |         vkFreeMemory(v->Device, upload_buffer_memory, v->Allocator); | ||||||
|  |  | ||||||
|     return true; |         tex->SetStatus(ImTextureStatus_OK); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| // You probably never need to call this, as it is called by ImGui_ImplVulkan_CreateFontsTexture() and ImGui_ImplVulkan_Shutdown(). |     if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames >= (int)bd->VulkanInitInfo.ImageCount) | ||||||
| void ImGui_ImplVulkan_DestroyFontsTexture() |         ImGui_ImplVulkan_DestroyTexture(tex); | ||||||
| { |  | ||||||
|     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; } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) | 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); |     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; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1074,7 +1104,11 @@ void    ImGui_ImplVulkan_DestroyDeviceObjects() | |||||||
|     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     ImGui_ImplVulkan_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); |     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->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; } |     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.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendRendererName = "imgui_impl_vulkan"; |     io.BackendRendererName = "imgui_impl_vulkan"; | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. |     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->Instance != VK_NULL_HANDLE); | ||||||
|     IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE); |     IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE); | ||||||
| @@ -1219,7 +1254,7 @@ void ImGui_ImplVulkan_Shutdown() | |||||||
|  |  | ||||||
|     io.BackendRendererName = nullptr; |     io.BackendRendererName = nullptr; | ||||||
|     io.BackendRendererUserData = nullptr; |     io.BackendRendererUserData = nullptr; | ||||||
|     io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; |     io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures); | ||||||
|     IM_DELETE(bd); |     IM_DELETE(bd); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1227,9 +1262,7 @@ void ImGui_ImplVulkan_NewFrame() | |||||||
| { | { | ||||||
|     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?"); |     IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?"); | ||||||
|  |     IM_UNUSED(bd); | ||||||
|     if (!bd->FontTexture.DescriptorSet) |  | ||||||
|         ImGui_ImplVulkan_CreateFontsTexture(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count) | 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..) | // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) | ||||||
|  |  | ||||||
| // Implemented features: | // 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: 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'. | //  [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. | // 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 | #define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Current version of the backend use 1 descriptor for the font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture(). | // Backend uses a small number of descriptors per 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   (8)     // Minimum per atlas | ||||||
| #define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE   (1)     // Minimum per atlas |  | ||||||
|  |  | ||||||
| // Initialization data, for ImGui_ImplVulkan_Init() | // Initialization data, for ImGui_ImplVulkan_Init() | ||||||
| // [Please zero-clear before use!] | // [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_Shutdown(); | ||||||
| IMGUI_IMPL_API void             ImGui_ImplVulkan_NewFrame(); | 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 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) | 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) | // Register a texture (VkDescriptorSet == ImTextureID) | ||||||
| // FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem | // 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. | // Please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ocornut
					ocornut