From: Benjamin Otte Date: Sat, 8 Jul 2023 18:40:48 +0000 (+0200) Subject: vulkan: Cache VkRenderPasses in render object X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~60^2~40 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=7fa159e94a4bb257e045e6ff362dfd1b334c9b3c;p=gtk4.git vulkan: Cache VkRenderPasses in render object Instead of recreating the same renderpass object in every frame and for every offscreen, just reuse it. Technically, we can save this per-renderer or even per-display (it should really be cached by VkDevice), but we have no infrastructure for that. --- diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index 81be627779..e3bdc088ce 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -58,6 +58,7 @@ struct _GskVulkanRender VkDescriptorPool descriptor_pool; VkDescriptorSet descriptor_sets[N_DESCRIPTOR_SETS]; GHashTable *pipeline_cache; + GHashTable *render_pass_cache; GskVulkanImage *target; @@ -72,6 +73,7 @@ struct _GskVulkanRender }; typedef struct _PipelineCacheKey PipelineCacheKey; +typedef struct _RenderPassCacheKey RenderPassCacheKey; struct _PipelineCacheKey { @@ -80,6 +82,13 @@ struct _PipelineCacheKey VkFormat format; }; +struct _RenderPassCacheKey +{ + VkFormat format; + VkImageLayout from_layout; + VkImageLayout to_layout; +}; + static guint pipeline_cache_key_hash (gconstpointer data) { @@ -102,6 +111,28 @@ pipeline_cache_key_equal (gconstpointer a, keya->format == keyb->format; } +static guint +render_pass_cache_key_hash (gconstpointer data) +{ + const RenderPassCacheKey *key = data; + + return (key->from_layout << 20) ^ + (key->to_layout << 16) ^ + (key->format); +} + +static gboolean +render_pass_cache_key_equal (gconstpointer a, + gconstpointer b) +{ + const RenderPassCacheKey *keya = a; + const RenderPassCacheKey *keyb = b; + + return keya->from_layout == keyb->from_layout && + keya->to_layout == keyb->to_layout && + keya->format == keyb->format; +} + static void gsk_vulkan_render_verbose_print (GskVulkanRender *self, const char *heading) @@ -310,6 +341,7 @@ gsk_vulkan_render_new (GskRenderer *renderer, self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool); self->pipeline_cache = g_hash_table_new (pipeline_cache_key_hash, pipeline_cache_key_equal); + self->render_pass_cache = g_hash_table_new (render_pass_cache_key_hash, render_pass_cache_key_equal); #ifdef G_ENABLE_DEBUG self->render_pass_counter = g_quark_from_static_string ("render-passes"); @@ -474,6 +506,69 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self, return pipeline; } +VkRenderPass +gsk_vulkan_render_get_render_pass (GskVulkanRender *self, + VkFormat format, + VkImageLayout from_layout, + VkImageLayout to_layout) +{ + RenderPassCacheKey cache_key; + VkRenderPass render_pass; + + cache_key = (RenderPassCacheKey) { + .format = format, + .from_layout = from_layout, + .to_layout = to_layout, + }; + render_pass = g_hash_table_lookup (self->render_pass_cache, &cache_key); + if (render_pass) + return render_pass; + + GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan), + &(VkRenderPassCreateInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = (VkAttachmentDescription[]) { + { + .format = format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .initialLayout = from_layout, + .finalLayout = to_layout + } + }, + .subpassCount = 1, + .pSubpasses = (VkSubpassDescription []) { + { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .inputAttachmentCount = 0, + .colorAttachmentCount = 1, + .pColorAttachments = (VkAttachmentReference []) { + { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + } + }, + .pResolveAttachments = (VkAttachmentReference []) { + { + .attachment = VK_ATTACHMENT_UNUSED, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + } + }, + .pDepthStencilAttachment = NULL, + } + }, + .dependencyCount = 0 + }, + NULL, + &render_pass); + + g_hash_table_insert (self->render_pass_cache, g_memdup (&cache_key, sizeof (RenderPassCacheKey)), render_pass); + + return render_pass; +} + void gsk_vulkan_render_bind_descriptor_sets (GskVulkanRender *self, VkCommandBuffer command_buffer) @@ -793,6 +888,14 @@ gsk_vulkan_render_free (GskVulkanRender *self) } g_hash_table_unref (self->pipeline_cache); + g_hash_table_iter_init (&iter, self->render_pass_cache); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + g_free (key); + vkDestroyRenderPass (device, value, NULL); + } + g_hash_table_unref (self->render_pass_cache); + g_clear_pointer (&self->uploader, gsk_vulkan_uploader_free); diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 1946b19618..3a496a1ad7 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -109,7 +109,6 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context, gboolean is_root) { GskVulkanRenderPass *self; - VkImageLayout final_layout; self = g_new0 (GskVulkanRenderPass, 1); self->vulkan = g_object_ref (context); @@ -120,49 +119,22 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context, self->viewport = *viewport; graphene_vec2_init_from_vec2 (&self->scale, scale); - if (!is_root) // this is a dependent pass - final_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + if (is_root) + { + /* this is a swapchain target */ + self->render_pass = gsk_vulkan_render_get_render_pass (render, + gsk_vulkan_image_get_vk_format (target), + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + } else - final_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan), - &(VkRenderPassCreateInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = (VkAttachmentDescription[]) { - { - .format = gsk_vulkan_image_get_vk_format (target), - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = final_layout - } - }, - .subpassCount = 1, - .pSubpasses = (VkSubpassDescription []) { - { - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .colorAttachmentCount = 1, - .pColorAttachments = (VkAttachmentReference []) { - { - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - } - }, - .pResolveAttachments = (VkAttachmentReference []) { - { - .attachment = VK_ATTACHMENT_UNUSED, - .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - } - }, - .pDepthStencilAttachment = NULL, - } - }, - .dependencyCount = 0 - }, - NULL, - &self->render_pass); + { + /* this is an offscreen */ + self->render_pass = gsk_vulkan_render_get_render_pass (render, + gsk_vulkan_image_get_vk_format (target), + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + } #ifdef G_ENABLE_DEBUG if (fallback_pixels_quark == 0) @@ -182,7 +154,6 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context, void gsk_vulkan_render_pass_free (GskVulkanRenderPass *self) { - VkDevice device = gdk_vulkan_context_get_device (self->vulkan); GskVulkanOp *op; gsize i; @@ -197,7 +168,6 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self) g_object_unref (self->vulkan); g_object_unref (self->target); cairo_region_destroy (self->clip); - vkDestroyRenderPass (device, self->render_pass, NULL); g_free (self); } diff --git a/gsk/vulkan/gskvulkanrenderprivate.h b/gsk/vulkan/gskvulkanrenderprivate.h index 413e9894dd..603f57b241 100644 --- a/gsk/vulkan/gskvulkanrenderprivate.h +++ b/gsk/vulkan/gskvulkanrenderprivate.h @@ -35,6 +35,10 @@ VkPipeline gsk_vulkan_render_get_pipeline (GskVulk const char *clip_type, VkFormat format, VkRenderPass render_pass); +VkRenderPass gsk_vulkan_render_get_render_pass (GskVulkanRender *self, + VkFormat format, + VkImageLayout from_layout, + VkImageLayout to_layout); gsize gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self, GskVulkanImage *source, GskVulkanRenderSampler render_sampler);