From 47c578945cb8a112d3b5599514f0d5a52993a2ba Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 20 Jun 2024 01:56:09 +0200 Subject: [PATCH] render/vulkan: Recycle memory maps for stage spans Remapping buffers on every use causes a lot of unwanted pagefaults. Reuse the mapping to significantly speed up the memcpy. --- include/render/vulkan.h | 1 + render/vulkan/renderer.c | 4 ++++ render/vulkan/texture.c | 21 +++++++++------------ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 6d3da153..5b74b613 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -483,6 +483,7 @@ struct wlr_vk_shared_buffer { VkBuffer buffer; VkDeviceMemory memory; VkDeviceSize buf_size; + void *cpu_mapping; struct wl_array allocs; // struct wlr_vk_allocation }; diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index b0203490..3aa66e5c 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -187,6 +187,10 @@ static void shared_buffer_destroy(struct wlr_vk_renderer *r, if (buffer->memory) { vkFreeMemory(r->dev->dev, buffer->memory, NULL); } + if (buffer->cpu_mapping) { + vkUnmapMemory(r->dev->dev, buffer->memory); + buffer->cpu_mapping = NULL; + } wl_list_remove(&buffer->link); free(buffer); diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 0e7a572b..086f59f8 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -80,19 +80,19 @@ static bool write_pixels(struct wlr_vk_texture *texture, return false; } - void *vmap; - res = vkMapMemory(dev, span.buffer->memory, span.alloc.start, - bsize, 0, &vmap); - if (res != VK_SUCCESS) { - wlr_vk_error("vkMapMemory", res); - free(copies); - return false; + if (!span.buffer->cpu_mapping) { + res = vkMapMemory(dev, span.buffer->memory, 0, VK_WHOLE_SIZE, 0, &span.buffer->cpu_mapping); + if (res != VK_SUCCESS) { + wlr_vk_error("vkMapMemory", res); + free(copies); + return false; + } } - char *map = (char *)vmap; + char *map = (char*)span.buffer->cpu_mapping + span.alloc.start; // upload data - uint32_t buf_off = span.alloc.start + (map - (char *)vmap); + uint32_t buf_off = span.alloc.start; for (int i = 0; i < rects_len; i++) { pixman_box32_t rect = rects[i]; uint32_t width = rect.x2 - rect.x1; @@ -137,9 +137,6 @@ static bool write_pixels(struct wlr_vk_texture *texture, buf_off += height * packed_stride; } - assert((uint32_t)(map - (char *)vmap) == bsize); - vkUnmapMemory(dev, span.buffer->memory); - // record staging cb // will be executed before next frame VkCommandBuffer cb = vulkan_record_stage_cb(renderer);