3333
3434// CHANGELOG
3535// (minor and older changes stripped away, please see git history for details)
36- // 2024-01-11: Vulkan: Fixed MinAllocationSize handing. (#7189)
36+ // 2024-01-11: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size (#3957). Fixed MinAllocationSize handing (#7189).
3737// 2024-01-03: Vulkan: Added MinAllocationSize field in ImGui_ImplVulkan_InitInfo to workaround zealous "best practice" validation layer. (#7189, #4238)
3838// 2024-01-03: Vulkan: Stoped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them.
3939// 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075)
@@ -386,7 +386,13 @@ static void check_vk_result(VkResult err)
386386 v->CheckVkResultFn (err);
387387}
388388
389- static void CreateOrResizeBuffer (VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
389+ // Same as IM_MEMALIGN(). 'alignment' must be a power of two.
390+ static inline VkDeviceSize AlignBufferSize (VkDeviceSize size, VkDeviceSize alignment)
391+ {
392+ return (size + alignment - 1 ) & ~(alignment - 1 );
393+ }
394+
395+ static void CreateOrResizeBuffer (VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
390396{
391397 ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData ();
392398 ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo ;
@@ -396,10 +402,10 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
396402 if (buffer_memory != VK_NULL_HANDLE)
397403 vkFreeMemory (v->Device , buffer_memory, v->Allocator );
398404
399- VkDeviceSize vertex_buffer_size_aligned = (( IM_MAX (v->MinAllocationSize , new_size) - 1 ) / bd->BufferMemoryAlignment + 1 ) * bd-> BufferMemoryAlignment ;
405+ VkDeviceSize buffer_size_aligned = AlignBufferSize ( IM_MAX (v->MinAllocationSize , new_size), bd->BufferMemoryAlignment ) ;
400406 VkBufferCreateInfo buffer_info = {};
401407 buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
402- buffer_info.size = vertex_buffer_size_aligned ;
408+ buffer_info.size = buffer_size_aligned ;
403409 buffer_info.usage = usage;
404410 buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
405411 err = vkCreateBuffer (v->Device , &buffer_info, v->Allocator , &buffer);
@@ -417,7 +423,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
417423
418424 err = vkBindBufferMemory (v->Device , buffer, buffer_memory, 0 );
419425 check_vk_result (err);
420- p_buffer_size = vertex_buffer_size_aligned ;
426+ buffer_size = buffer_size_aligned ;
421427}
422428
423429static void ImGui_ImplVulkan_SetupRenderState (ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
@@ -494,8 +500,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
494500 if (draw_data->TotalVtxCount > 0 )
495501 {
496502 // Create or resize the vertex/index buffers
497- size_t vertex_size = draw_data->TotalVtxCount * sizeof (ImDrawVert);
498- size_t index_size = draw_data->TotalIdxCount * sizeof (ImDrawIdx);
503+ size_t vertex_size = AlignBufferSize ( draw_data->TotalVtxCount * sizeof (ImDrawVert), bd-> BufferMemoryAlignment );
504+ size_t index_size = AlignBufferSize ( draw_data->TotalIdxCount * sizeof (ImDrawIdx), bd-> BufferMemoryAlignment );
499505 if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size)
500506 CreateOrResizeBuffer (rb->VertexBuffer , rb->VertexBufferMemory , rb->VertexBufferSize , vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
501507 if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)
@@ -504,9 +510,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
504510 // Upload vertex/index data into a single contiguous GPU buffer
505511 ImDrawVert* vtx_dst = nullptr ;
506512 ImDrawIdx* idx_dst = nullptr ;
507- VkResult err = vkMapMemory (v->Device , rb->VertexBufferMemory , 0 , rb-> VertexBufferSize , 0 , (void **)&vtx_dst);
513+ VkResult err = vkMapMemory (v->Device , rb->VertexBufferMemory , 0 , vertex_size , 0 , (void **)&vtx_dst);
508514 check_vk_result (err);
509- err = vkMapMemory (v->Device , rb->IndexBufferMemory , 0 , rb-> IndexBufferSize , 0 , (void **)&idx_dst);
515+ err = vkMapMemory (v->Device , rb->IndexBufferMemory , 0 , index_size , 0 , (void **)&idx_dst);
510516 check_vk_result (err);
511517 for (int n = 0 ; n < draw_data->CmdListsCount ; n++)
512518 {
0 commit comments