Skip to content

Commit

Permalink
imgui: use fonts upload code from v1.90
Browse files Browse the repository at this point in the history
  • Loading branch information
scribam authored and flyinghead committed Dec 1, 2023
1 parent 105ab95 commit f3a774a
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 53 deletions.
139 changes: 103 additions & 36 deletions core/deps/imgui/backends/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts.
// *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend.
// ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time.
// You can call ImGui_ImplVulkan_CreateFontsTexture() again to recreate the font atlas texture.
// Added ImGui_ImplVulkan_DestroyFontsTexture() but you probably never need to call this.
// 2023-07-04: Vulkan: Added optional support for VK_KHR_dynamic_rendering. User needs to set init_info->UseDynamicRendering = true and init_info->ColorAttachmentFormat.
// 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.
Expand Down Expand Up @@ -120,8 +125,8 @@ struct ImGui_ImplVulkan_Data
VkImage FontImage;
VkImageView FontView;
VkDescriptorSet FontDescriptorSet;
VkDeviceMemory UploadBufferMemory;
VkBuffer UploadBuffer;
VkCommandPool FontCommandPool;
VkCommandBuffer FontCommandBuffer;

// Render buffers for main window
ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers;
Expand Down Expand Up @@ -155,6 +160,7 @@ static bool g_FunctionsLoaded = true;
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkBeginCommandBuffer) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindBufferMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindImageMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindDescriptorSets) \
Expand Down Expand Up @@ -197,6 +203,7 @@ static bool g_FunctionsLoaded = true;
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySurfaceKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySwapchainKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkEndCommandBuffer) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeDescriptorSets) \
Expand All @@ -209,6 +216,9 @@ static bool g_FunctionsLoaded = true;
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetSwapchainImagesKHR) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkMapMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkQueueSubmit) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkQueueWaitIdle) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkResetCommandPool) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUnmapMemory) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets)

Expand Down Expand Up @@ -592,19 +602,55 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
}

bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
bool ImGui_ImplVulkan_CreateFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err;

// Destroy existing texture (if any)
if (bd->FontView || bd->FontImage || bd->FontMemory || bd->FontDescriptorSet)
{
vkQueueWaitIdle(v->Queue);
ImGui_ImplVulkan_DestroyFontsTexture();
}

// Create command pool/buffer
if (bd->FontCommandPool == VK_NULL_HANDLE)
{
VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.queueFamilyIndex = v->QueueFamily;
vkCreateCommandPool(v->Device, &info, nullptr, &bd->FontCommandPool);
}
if (bd->FontCommandBuffer == VK_NULL_HANDLE)
{
VkCommandBufferAllocateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.commandPool = bd->FontCommandPool;
info.commandBufferCount = 1;
err = vkAllocateCommandBuffers(v->Device, &info, &bd->FontCommandBuffer);
check_vk_result(err);
}

// Start command buffer
{
err = vkResetCommandPool(v->Device, bd->FontCommandPool, 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->FontCommandBuffer, &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);

VkResult err;

// Create the Image:
{
VkImageCreateInfo info = {};
Expand Down Expand Up @@ -653,40 +699,42 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
bd->FontDescriptorSet = (VkDescriptorSet)ImGui_ImplVulkan_AddTexture(bd->FontSampler, bd->FontView, 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, &bd->UploadBuffer);
err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &upload_buffer);
check_vk_result(err);
VkMemoryRequirements req;
vkGetBufferMemoryRequirements(v->Device, bd->UploadBuffer, &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 = req.size;
alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->UploadBufferMemory);
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &upload_buffer_memory);
check_vk_result(err);
err = vkBindBufferMemory(v->Device, bd->UploadBuffer, bd->UploadBufferMemory, 0);
err = vkBindBufferMemory(v->Device, upload_buffer, upload_buffer_memory, 0);
check_vk_result(err);
}

// Upload to Buffer:
{
char* map = nullptr;
err = vkMapMemory(v->Device, bd->UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
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 = bd->UploadBufferMemory;
range[0].memory = upload_buffer_memory;
range[0].size = upload_size;
err = vkFlushMappedMemoryRanges(v->Device, 1, range);
check_vk_result(err);
vkUnmapMemory(v->Device, bd->UploadBufferMemory);
vkUnmapMemory(v->Device, upload_buffer_memory);
}

// Copy to Image:
Expand All @@ -702,15 +750,15 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
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);
vkCmdPipelineBarrier(bd->FontCommandBuffer, 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(command_buffer, bd->UploadBuffer, bd->FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
vkCmdCopyBufferToImage(bd->FontCommandBuffer, upload_buffer, bd->FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);

VkImageMemoryBarrier use_barrier[1] = {};
use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
Expand All @@ -724,15 +772,50 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
use_barrier[0].subresourceRange.levelCount = 1;
use_barrier[0].subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);
vkCmdPipelineBarrier(bd->FontCommandBuffer, 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)bd->FontDescriptorSet);

// End command buffer
VkSubmitInfo end_info = {};
end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
end_info.commandBufferCount = 1;
end_info.pCommandBuffers = &bd->FontCommandBuffer;
err = vkEndCommandBuffer(bd->FontCommandBuffer);
check_vk_result(err);
err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE);
check_vk_result(err);

err = vkDeviceWaitIdle(v->Device);
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;

if (bd->FontDescriptorSet)
{
ImGui_ImplVulkan_RemoveTexture(bd->FontDescriptorSet);
bd->FontDescriptorSet = VK_NULL_HANDLE;
io.Fonts->SetTexID(0);
}

if (bd->FontView) { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }
if (bd->FontImage) { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; }
if (bd->FontMemory) { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; }
}

static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)
{
// Create the shader modules
Expand Down Expand Up @@ -935,34 +1018,16 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
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();
ImGui_ImplVulkan_DestroyFontsTexture();

if (bd->FontCommandPool) { vkDestroyCommandPool(v->Device, bd->FontCommandPool, v->Allocator); bd->FontCommandPool = VK_NULL_HANDLE; }
if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
if (bd->FontView) { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }
if (bd->FontImage) { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; ImGui::GetIO().Fonts->SetTexID(ImTextureID()); }
if (bd->FontMemory) { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; }
if (bd->FontSampler) { vkDestroySampler(v->Device, bd->FontSampler, v->Allocator); bd->FontSampler = VK_NULL_HANDLE; }
if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
Expand Down Expand Up @@ -1060,7 +1125,9 @@ void ImGui_ImplVulkan_NewFrame()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplVulkan_Init()?");
IM_UNUSED(bd);

if (!bd->FontDescriptorSet)
ImGui_ImplVulkan_CreateFontsTexture();
}

void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
Expand Down
4 changes: 2 additions & 2 deletions core/deps/imgui/backends/imgui_impl_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* inf
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(VkCommandBuffer command_buffer);
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
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)

// Register a texture (VkDescriptorSet == ImTextureID)
Expand Down
15 changes: 0 additions & 15 deletions core/rend/vulkan/vulkan_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,21 +311,6 @@ void VulkanContext::InitImgui()
{
die("ImGui initialization failed");
}
if (ImGui::GetIO().Fonts->TexID == 0)
{
// Upload Fonts
device->resetFences(*drawFences.front());
device->resetCommandPool(*commandPools.front(), vk::CommandPoolResetFlagBits::eReleaseResources);
vk::CommandBuffer& commandBuffer = *commandBuffers.front();
commandBuffer.begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit));
ImGui_ImplVulkan_CreateFontsTexture((VkCommandBuffer)commandBuffer);
commandBuffer.end();
vk::SubmitInfo submitInfo(nullptr, nullptr, commandBuffer);
graphicsQueue.submit(submitInfo, *drawFences.front());

device->waitIdle();
ImGui_ImplVulkan_DestroyFontUploadObjects();
}
}

bool VulkanContext::InitDevice()
Expand Down
1 change: 1 addition & 0 deletions core/rend/vulkan/vulkan_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class VulkanDriver final : public ImGuiDriver
}

void newFrame() override {
ImGui_ImplVulkan_NewFrame();
}

void renderDrawData(ImDrawData *drawData, bool gui_open) override
Expand Down

0 comments on commit f3a774a

Please sign in to comment.