From 1f13bc72fea2ad9bb82909c761d4ecd35cf79f1a Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 4 Nov 2024 22:56:16 +0100 Subject: [PATCH] render/vulkan: Garbage collect unused buffers Perform a primitive garbage collection of buffers that have not been used in the past 10 seconds, an arbitrarily selected number. As garbage collection also makes span buffer allocation happen much more often, logging on allocation activity leads to a lot of log noise so get rid of that while at it. --- include/render/vulkan.h | 1 + render/vulkan/renderer.c | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/render/vulkan.h b/include/render/vulkan.h index 7ad2f8339..abeb11cc5 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -500,6 +500,7 @@ struct wlr_vk_shared_buffer { VkDeviceSize buf_size; void *cpu_mapping; struct wl_array allocs; // struct wlr_vk_allocation + int64_t last_used_ms; }; // Suballocated range on a buffer. diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index a2fb867d6..44eb89f96 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -28,6 +28,7 @@ #include "render/vulkan/shaders/output.frag.h" #include "types/wlr_buffer.h" #include "types/wlr_matrix.h" +#include "util/time.h" // TODO: // - simplify stage allocation, don't track allocations but use ringbuffer-like @@ -322,7 +323,6 @@ struct wlr_vk_buffer_span vulkan_get_stage_span(struct wlr_vk_renderer *r, goto error; } - wlr_log(WLR_DEBUG, "Created new vk staging buffer of size %" PRIu64, bsize); buf->buf_size = bsize; wl_list_insert(&r->stage.buffers, &buf->link); @@ -456,7 +456,7 @@ bool vulkan_wait_command_buffer(struct wlr_vk_command_buffer *cb, } static void release_command_buffer_resources(struct wlr_vk_command_buffer *cb, - struct wlr_vk_renderer *renderer) { + struct wlr_vk_renderer *renderer, int64_t now) { struct wlr_vk_texture *texture, *texture_tmp; wl_list_for_each_safe(texture, texture_tmp, &cb->destroy_textures, destroy_link) { wl_list_remove(&texture->destroy_link); @@ -467,6 +467,7 @@ static void release_command_buffer_resources(struct wlr_vk_command_buffer *cb, struct wlr_vk_shared_buffer *buf, *buf_tmp; wl_list_for_each_safe(buf, buf_tmp, &cb->stage_buffers, link) { buf->allocs.size = 0; + buf->last_used_ms = now; wl_list_remove(&buf->link); wl_list_insert(&renderer->stage.buffers, &buf->link); @@ -490,12 +491,22 @@ static struct wlr_vk_command_buffer *get_command_buffer( return NULL; } + + // Garbage collect any buffers that have remained unused for too long + int64_t now = get_current_time_msec(); + struct wlr_vk_shared_buffer *buf, *buf_tmp; + wl_list_for_each_safe(buf, buf_tmp, &renderer->stage.buffers, link) { + if (buf->allocs.size == 0 && buf->last_used_ms + 10000 < now) { + shared_buffer_destroy(renderer, buf); + } + } + // Destroy textures for completed command buffers for (size_t i = 0; i < VULKAN_COMMAND_BUFFERS_CAP; i++) { struct wlr_vk_command_buffer *cb = &renderer->command_buffers[i]; if (cb->vk != VK_NULL_HANDLE && !cb->recording && cb->timeline_point <= current_point) { - release_command_buffer_resources(cb, renderer); + release_command_buffer_resources(cb, renderer, now); } } @@ -1055,7 +1066,7 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) { if (cb->vk == VK_NULL_HANDLE) { continue; } - release_command_buffer_resources(cb, renderer); + release_command_buffer_resources(cb, renderer, 0); if (cb->binary_semaphore != VK_NULL_HANDLE) { vkDestroySemaphore(renderer->dev->dev, cb->binary_semaphore, NULL); }