From fb8921f69c20f04bd2ca9412eddfc1f2b3143897 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 7 Jul 2024 16:07:18 +0200 Subject: [PATCH] render/vulkan: Cache blending buffer on swapchain Our blending buffer is 64 bits per pixel, and triple the amount of memory needed for each swapchain buffer. To save some memory, keep a single blending buffer per swapchain. --- render/vulkan/renderer.c | 62 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 7adcc46da..b0668283e 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -638,6 +639,23 @@ static struct wlr_addon_interface render_buffer_addon_impl = { .destroy = handle_render_buffer_destroy, }; +struct vulkan_swapchain_blend_buffer { + struct wlr_addon swapchain_addon; + struct wlr_vk_blend_buffer *blend_buffer; +}; + +static void handle_swapchain_destroy(struct wlr_addon *addon) { + struct vulkan_swapchain_blend_buffer *bb = + wl_container_of(addon, bb, swapchain_addon); + vulkan_blend_buffer_unref(bb->blend_buffer); + wlr_addon_finish(&bb->swapchain_addon); +} + +static struct wlr_addon_interface vulkan_swapchain_blend_buffer_addon_impl = { + .name = "vulkan_swapchain_blend_buffer", + .destroy = handle_swapchain_destroy, +}; + static struct wlr_vk_blend_buffer *vulkan_create_blend_buffer( struct wlr_vk_renderer *renderer, int width, int height) { VkResult res; @@ -740,14 +758,54 @@ error: return NULL; } +static struct wlr_vk_blend_buffer *vulkan_get_swapchain_blend_buffer( + struct wlr_vk_renderer *renderer, struct wlr_swapchain *swapchain, + int width, int height) { + + if (!swapchain) { + wlr_log(WLR_DEBUG, "No swapchain for blending buffer"); + return vulkan_create_blend_buffer(renderer, width, height); + } + + struct vulkan_swapchain_blend_buffer *sbb; + struct wlr_addon *addon = wlr_addon_find(&swapchain->addons, renderer, + &vulkan_swapchain_blend_buffer_addon_impl); + if (addon) { + wlr_log(WLR_DEBUG, "Reusing blending buffer"); + sbb = wl_container_of(addon, sbb, swapchain_addon); + return sbb->blend_buffer; + } + + sbb = calloc(1, sizeof(*sbb)); + if (!sbb) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + return NULL; + } + + struct wlr_vk_blend_buffer *bb = vulkan_create_blend_buffer(renderer, width, height); + if (!bb) { + free(sbb); + return NULL; + } + sbb->blend_buffer = vulkan_blend_buffer_ref(bb); + + wlr_log(WLR_DEBUG, "New swapchain blending buffer"); + + wlr_addon_init(&sbb->swapchain_addon, &swapchain->addons, renderer, + &vulkan_swapchain_blend_buffer_addon_impl); + return sbb->blend_buffer; +} + bool vulkan_setup_plain_framebuffer(struct wlr_vk_render_buffer *buffer, const struct wlr_dmabuf_attributes *dmabuf) { struct wlr_vk_renderer *renderer = buffer->renderer; VkResult res; VkDevice dev = renderer->dev->dev; - struct wlr_vk_blend_buffer *bb = vulkan_create_blend_buffer(renderer, - dmabuf->width, dmabuf->height); + struct wlr_swapchain *swapchain = + wlr_swapchain_try_from_wlr_buffer(buffer->wlr_buffer); + struct wlr_vk_blend_buffer *bb = vulkan_get_swapchain_blend_buffer(renderer, + swapchain, dmabuf->width, dmabuf->height); if (!bb) { return false; }