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.
This commit is contained in:
Benjamin Otte 2023-07-08 09:04:12 +02:00
parent 1abcf3d48a
commit 70c9521cae
6 changed files with 58 additions and 52 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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 &&

View File

@ -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,