From cef87b102c2aa1cb5ae9ec720956b898aa09b929 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 8 Jul 2023 20:10:04 +0200 Subject: [PATCH] vulkan: Cache framebuffer in image Instead of recreating them every frame for every render pass, reuse the same framebuffer. --- gsk/vulkan/gskvulkanimage.c | 47 +++++++++++++++++++++++------- gsk/vulkan/gskvulkanimageprivate.h | 2 ++ gsk/vulkan/gskvulkanrenderpass.c | 20 ++----------- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index cee0cb8764..ee82252a5a 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -41,6 +41,8 @@ struct _GskVulkanImage VkImageUsageFlags vk_usage; VkImage vk_image; VkImageView vk_image_view; + VkFramebuffer vk_framebuffer; + VkImageLayout vk_image_layout; VkAccessFlags vk_access; @@ -1018,24 +1020,22 @@ static void gsk_vulkan_image_finalize (GObject *object) { GskVulkanImage *self = GSK_VULKAN_IMAGE (object); + VkDevice device; + + device = gdk_vulkan_context_get_device (self->vulkan); + + if (self->vk_framebuffer != VK_NULL_HANDLE) + vkDestroyFramebuffer (device, self->vk_framebuffer, NULL); if (self->vk_image_view != VK_NULL_HANDLE) - { - vkDestroyImageView (gdk_vulkan_context_get_device (self->vulkan), - self->vk_image_view, - NULL); - } + vkDestroyImageView (device, self->vk_image_view, NULL); /* memory is NULL for for_swapchain() images, where we don't own * the VkImage */ if (self->memory) - { - vkDestroyImage (gdk_vulkan_context_get_device (self->vulkan), - self->vk_image, - NULL); + vkDestroyImage (device, self->vk_image, NULL); - gsk_vulkan_memory_free (self->memory); - } + g_clear_pointer (&self->memory, gsk_vulkan_memory_free); g_object_unref (self->vulkan); @@ -1053,6 +1053,31 @@ gsk_vulkan_image_init (GskVulkanImage *self) { } +VkFramebuffer +gsk_vulkan_image_get_framebuffer (GskVulkanImage *self, + VkRenderPass render_pass) +{ + if (self->vk_framebuffer) + return self->vk_framebuffer; + + GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan), + &(VkFramebufferCreateInfo) { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = render_pass, + .attachmentCount = 1, + .pAttachments = (VkImageView[1]) { + self->vk_image_view, + }, + .width = self->width, + .height = self->height, + .layers = 1 + }, + NULL, + &self->vk_framebuffer); + + return self->vk_framebuffer; +} + gsize gsk_vulkan_image_get_width (GskVulkanImage *self) { diff --git a/gsk/vulkan/gskvulkanimageprivate.h b/gsk/vulkan/gskvulkanimageprivate.h index 9daae9fd24..828b008e26 100644 --- a/gsk/vulkan/gskvulkanimageprivate.h +++ b/gsk/vulkan/gskvulkanimageprivate.h @@ -83,6 +83,8 @@ VkImage gsk_vulkan_image_get_image (GskVulk VkImageView gsk_vulkan_image_get_image_view (GskVulkanImage *self); VkFormat gsk_vulkan_image_get_vk_format (GskVulkanImage *self); GdkMemoryFormat gsk_vulkan_image_get_format (GskVulkanImage *self); +VkFramebuffer gsk_vulkan_image_get_framebuffer (GskVulkanImage *self, + VkRenderPass pass); static inline void print_image (GString *string, diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index d0b5ec6145..4f2ddf4bb6 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -59,7 +59,6 @@ struct _GskVulkanRenderPass graphene_vec2_t scale; VkRenderPass render_pass; - VkFramebuffer framebuffer; }; struct _GskVulkanParseState @@ -165,21 +164,6 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context, NULL, &self->render_pass); - GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan), - &(VkFramebufferCreateInfo) { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = self->render_pass, - .attachmentCount = 1, - .pAttachments = (VkImageView[1]) { - gsk_vulkan_image_get_image_view (target) - }, - .width = gsk_vulkan_image_get_width (target), - .height = gsk_vulkan_image_get_height (target), - .layers = 1 - }, - NULL, - &self->framebuffer); - #ifdef G_ENABLE_DEBUG if (fallback_pixels_quark == 0) { @@ -213,7 +197,6 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self) g_object_unref (self->vulkan); g_object_unref (self->target); cairo_region_destroy (self->clip); - vkDestroyFramebuffer (device, self->framebuffer, NULL); vkDestroyRenderPass (device, self->render_pass, NULL); g_free (self); @@ -1508,7 +1491,8 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, &(VkRenderPassBeginInfo) { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderPass = self->render_pass, - .framebuffer = self->framebuffer, + .framebuffer = gsk_vulkan_image_get_framebuffer (self->target, + self->render_pass), .renderArea = { { rect.x, rect.y }, { rect.width, rect.height } -- 2.30.2