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.
This commit is contained in:
Kenny Levinsen 2024-07-07 16:07:18 +02:00
parent 752d9f232c
commit fb8921f69c

View file

@ -10,6 +10,7 @@
#include <vulkan/vulkan.h>
#include <wlr/render/color.h>
#include <wlr/render/interface.h>
#include <wlr/render/swapchain.h>
#include <wlr/types/wlr_drm.h>
#include <wlr/util/box.h>
#include <wlr/util/log.h>
@ -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;
}