From 70c9521caee8e4c13cbab40ddf1baad44b5f260e Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 8 Jul 2023 09:04:12 +0200 Subject: [PATCH] vulkan: Put the vertex buffer into the render object Renderpasses get recreated every frame, but we keep render objects around. So if we keep the vertex buffer in the render object, we can also keep it around and just reuse it. Also, we only need one buffer for all the render passes, which is another bonus. The initial buffer size is chosen at 128kB. Maximized Nautilus, gnome-text-editor with an open file and widget-factory take ~100kB when doing a full redraw. Other apps are between 30-50kB usually. So I chose a value that is not too big, but catches ~90% of cases. --- gsk/vulkan/gskvulkanbuffer.c | 6 +++ gsk/vulkan/gskvulkanbufferprivate.h | 1 + gsk/vulkan/gskvulkanoffscreenop.c | 7 +++- gsk/vulkan/gskvulkanrender.c | 36 ++++++++++++++++ gsk/vulkan/gskvulkanrenderpass.c | 55 ++----------------------- gsk/vulkan/gskvulkanrenderpassprivate.h | 5 +++ 6 files changed, 58 insertions(+), 52 deletions(-) diff --git a/gsk/vulkan/gskvulkanbuffer.c b/gsk/vulkan/gskvulkanbuffer.c index a2e850da22..a89dfddcdf 100644 --- a/gsk/vulkan/gskvulkanbuffer.c +++ b/gsk/vulkan/gskvulkanbuffer.c @@ -103,6 +103,12 @@ gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self) return self->vk_buffer; } +gsize +gsk_vulkan_buffer_get_size (GskVulkanBuffer *self) +{ + return self->size; +} + guchar * gsk_vulkan_buffer_map (GskVulkanBuffer *self) { diff --git a/gsk/vulkan/gskvulkanbufferprivate.h b/gsk/vulkan/gskvulkanbufferprivate.h index 9c51586216..009e79da52 100644 --- a/gsk/vulkan/gskvulkanbufferprivate.h +++ b/gsk/vulkan/gskvulkanbufferprivate.h @@ -23,6 +23,7 @@ GskVulkanBuffer * gsk_vulkan_buffer_new_map (GdkVulk void gsk_vulkan_buffer_free (GskVulkanBuffer *buffer); VkBuffer gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self); +gsize gsk_vulkan_buffer_get_size (GskVulkanBuffer *self); guchar * gsk_vulkan_buffer_map (GskVulkanBuffer *self); void gsk_vulkan_buffer_unmap (GskVulkanBuffer *self); diff --git a/gsk/vulkan/gskvulkanoffscreenop.c b/gsk/vulkan/gskvulkanoffscreenop.c index 7be22444dc..b2fc4f4f03 100644 --- a/gsk/vulkan/gskvulkanoffscreenop.c +++ b/gsk/vulkan/gskvulkanoffscreenop.c @@ -57,7 +57,9 @@ static gsize gsk_vulkan_offscreen_op_count_vertex_data (GskVulkanOp *op, gsize n_bytes) { - return n_bytes; + GskVulkanOffscreenOp *self = (GskVulkanOffscreenOp *) op; + + return gsk_vulkan_render_pass_count_vertex_data (self->render_pass, n_bytes); } static void @@ -66,6 +68,9 @@ gsk_vulkan_offscreen_op_collect_vertex_data (GskVulkanOp *op, GskVulkanRender *render, guchar *data) { + GskVulkanOffscreenOp *self = (GskVulkanOffscreenOp *) op; + + gsk_vulkan_render_pass_collect_vertex_data (self->render_pass, render, data); } static void diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index f1c0bf9e62..f997ab0443 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -16,6 +16,7 @@ #include "gdk/gdkvulkancontextprivate.h" #define DESCRIPTOR_POOL_MAXITEMS 50000 +#define VERTEX_BUFFER_SIZE_STEP 128 * 1024 /* 128kB */ #define GDK_ARRAY_NAME gsk_descriptor_image_infos #define GDK_ARRAY_TYPE_NAME GskDescriptorImageInfos @@ -60,6 +61,7 @@ struct _GskVulkanRender GskVulkanImage *target; + GskVulkanBuffer *vertex_buffer; VkSampler samplers[3]; GskVulkanBuffer *storage_buffer; guchar *storage_buffer_memory; @@ -642,6 +644,27 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self) 0, NULL); } +static void +gsk_vulkan_render_collect_vertex_buffer (GskVulkanRender *self) +{ + gsize n_bytes; + guchar *data; + + n_bytes = gsk_vulkan_render_pass_count_vertex_data (self->render_pass, 0); + if (n_bytes == 0) + return; + + if (self->vertex_buffer && gsk_vulkan_buffer_get_size (self->vertex_buffer) < n_bytes) + g_clear_pointer (&self->vertex_buffer, gsk_vulkan_buffer_free); + + if (self->vertex_buffer == NULL) + self->vertex_buffer = gsk_vulkan_buffer_new (self->vulkan, round_up (n_bytes, VERTEX_BUFFER_SIZE_STEP)); + + data = gsk_vulkan_buffer_map (self->vertex_buffer); + gsk_vulkan_render_pass_collect_vertex_data (self->render_pass, self, data); + gsk_vulkan_buffer_unmap (self->vertex_buffer); +} + void gsk_vulkan_render_draw_pass (GskVulkanRender *self, GskVulkanRenderPass *pass, @@ -651,6 +674,15 @@ gsk_vulkan_render_draw_pass (GskVulkanRender *self, command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool); + if (self->vertex_buffer) + vkCmdBindVertexBuffers (command_buffer, + 0, + 1, + (VkBuffer[1]) { + gsk_vulkan_buffer_get_buffer (self->vertex_buffer) + }, + (VkDeviceSize[1]) { 0 }); + gsk_vulkan_render_pass_draw (pass, self, self->pipeline_layout, command_buffer); gsk_vulkan_command_pool_submit_buffer (self->command_pool, @@ -672,6 +704,8 @@ gsk_vulkan_render_draw (GskVulkanRender *self) gsk_vulkan_render_prepare_descriptor_sets (self); + gsk_vulkan_render_collect_vertex_buffer (self); + gsk_vulkan_render_draw_pass (self, self->render_pass, self->fence); @@ -747,6 +781,8 @@ gsk_vulkan_render_free (GskVulkanRender *self) gsk_vulkan_render_cleanup (self); + g_clear_pointer (&self->vertex_buffer, gsk_vulkan_buffer_free); + device = gdk_vulkan_context_get_device (self->vulkan); g_hash_table_iter_init (&iter, self->pipeline_cache); diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index ec54694ce3..d0b5ec6145 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -60,7 +60,6 @@ struct _GskVulkanRenderPass VkRenderPass render_pass; VkFramebuffer framebuffer; - GskVulkanBuffer *vertex_data; }; struct _GskVulkanParseState @@ -181,8 +180,6 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context, NULL, &self->framebuffer); - self->vertex_data = NULL; - #ifdef G_ENABLE_DEBUG if (fallback_pixels_quark == 0) { @@ -219,9 +216,6 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self) vkDestroyFramebuffer (device, self->framebuffer, NULL); vkDestroyRenderPass (device, self->render_pass, NULL); - if (self->vertex_data) - gsk_vulkan_buffer_free (self->vertex_data); - g_free (self); } @@ -241,12 +235,6 @@ gsk_vulkan_render_pass_print (GskVulkanRenderPass *self, } } -static inline gsize -round_up (gsize number, gsize divisor) -{ - return (number + divisor - 1) / divisor * divisor; -} - gpointer gsk_vulkan_render_pass_alloc_op (GskVulkanRenderPass *self, gsize size) @@ -1422,13 +1410,12 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, } } -static gsize -gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self) +gsize +gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self, + gsize n_bytes) { GskVulkanOp *op; - gsize n_bytes; - n_bytes = 0; for (op = gsk_vulkan_render_pass_get_first_op (self); op; op = op->next) { n_bytes = gsk_vulkan_op_count_vertex_data (op, n_bytes); @@ -1437,7 +1424,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self) return n_bytes; } -static void +void gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, GskVulkanRender *render, guchar *data) @@ -1450,28 +1437,6 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, } } -static GskVulkanBuffer * -gsk_vulkan_render_pass_get_vertex_data (GskVulkanRenderPass *self, - GskVulkanRender *render) -{ - if (self->vertex_data == NULL) - { - gsize n_bytes; - guchar *data; - - n_bytes = gsk_vulkan_render_pass_count_vertex_data (self); - if (n_bytes == 0) - return NULL; - - self->vertex_data = gsk_vulkan_buffer_new (self->vulkan, n_bytes); - data = gsk_vulkan_buffer_map (self->vertex_data); - gsk_vulkan_render_pass_collect_vertex_data (self, render, data); - gsk_vulkan_buffer_unmap (self->vertex_data); - } - - return self->vertex_data; -} - void gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, GskVulkanRender *render) @@ -1493,20 +1458,8 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass *self, VkPipeline current_pipeline = VK_NULL_HANDLE; const GskVulkanOpClass *current_pipeline_class = NULL; const char *current_pipeline_clip_type = NULL; - GskVulkanBuffer *vertex_buffer; GskVulkanOp *op; - vertex_buffer = gsk_vulkan_render_pass_get_vertex_data (self, render); - - if (vertex_buffer) - vkCmdBindVertexBuffers (command_buffer, - 0, - 1, - (VkBuffer[1]) { - gsk_vulkan_buffer_get_buffer (vertex_buffer) - }, - (VkDeviceSize[1]) { 0 }); - for (op = gsk_vulkan_render_pass_get_first_op (self); op; op = op->next) { if (op->op_class->shader_name && diff --git a/gsk/vulkan/gskvulkanrenderpassprivate.h b/gsk/vulkan/gskvulkanrenderpassprivate.h index 3040ce624c..4168ca746f 100644 --- a/gsk/vulkan/gskvulkanrenderpassprivate.h +++ b/gsk/vulkan/gskvulkanrenderpassprivate.h @@ -33,6 +33,11 @@ void gsk_vulkan_render_pass_upload (GskVulk GskVulkanUploader *uploader); void gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, GskVulkanRender *render); +gsize gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self, + gsize n_bytes); +void gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, + GskVulkanRender *render, + guchar *data); void gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, GskVulkanRender *render, VkPipelineLayout pipeline_layout, -- 2.30.2