Skip to content

Commit 70bb6d1

Browse files
committed
Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957)
1 parent 82df7c8 commit 70bb6d1

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

backends/imgui_impl_vulkan.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
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

423429
static 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
{

docs/CHANGELOG.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Breaking changes:
4343

4444
Other changes:
4545

46+
- Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957)
4647
- Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238)
4748

4849

0 commit comments

Comments
 (0)