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,