summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2016-08-09 11:24:05 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2016-10-18 11:49:13 +0100
commit0812d691b354415d9a82d05b3d83bc62ed0bc68b (patch)
tree04eb660efa4074cf5e1547ffae00bb82ee745c52 /gsk
parent56c93a7661e46ed542e341757a141c9f83c6204c (diff)
downloadgtk+-0812d691b354415d9a82d05b3d83bc62ed0bc68b.tar.gz
gsk: Reuse VAOs with identical buffers
Just like we reuse texture ids with the same size we can, at the expense of a little memory, reuse vertex buffers if they reference the same attributes and contain the same data. Each VAO is marked as free at the end of the frame, and if it's not reused in the following frame, it gets dropped.
Diffstat (limited to 'gsk')
-rw-r--r--gsk/gskgldriver.c87
-rw-r--r--gsk/gskgldriverprivate.h3
-rw-r--r--gsk/gskglrenderer.c23
3 files changed, 92 insertions, 21 deletions
diff --git a/gsk/gskgldriver.c b/gsk/gskgldriver.c
index a6345259c7..2f045cf7a9 100644
--- a/gsk/gskgldriver.c
+++ b/gsk/gskgldriver.c
@@ -22,6 +22,9 @@ typedef struct {
GLuint buffer_id;
GLuint position_id;
GLuint uv_id;
+ GskQuadVertex *quads;
+ int n_quads;
+ gboolean in_use : 1;
} Vao;
typedef struct {
@@ -97,6 +100,7 @@ vao_free (gpointer data)
{
Vao *v = data;
+ g_free (v->quads);
glDeleteBuffers (1, &v->buffer_id);
glDeleteVertexArrays (1, &v->vao_id);
g_slice_free (Vao, v);
@@ -238,14 +242,17 @@ gsk_gl_driver_end_frame (GskGLDriver *driver)
driver->in_frame = FALSE;
}
-void
+int
gsk_gl_driver_collect_textures (GskGLDriver *driver)
{
GHashTableIter iter;
gpointer value_p = NULL;
+ int old_size;
- g_return_if_fail (GSK_IS_GL_DRIVER (driver));
- g_return_if_fail (!driver->in_frame);
+ g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), 0);
+ g_return_val_if_fail (!driver->in_frame, 0);
+
+ old_size = g_hash_table_size (driver->textures);
g_hash_table_iter_init (&iter, driver->textures);
while (g_hash_table_iter_next (&iter, NULL, &value_p))
@@ -253,10 +260,41 @@ gsk_gl_driver_collect_textures (GskGLDriver *driver)
Texture *t = value_p;
if (t->in_use)
- t->in_use = FALSE;
+ {
+ t->in_use = FALSE;
+ g_clear_pointer (&t->fbos, g_array_unref);
+ }
else
g_hash_table_iter_remove (&iter);
}
+
+ return old_size - g_hash_table_size (driver->textures);
+}
+
+int
+gsk_gl_driver_collect_vaos (GskGLDriver *driver)
+{
+ GHashTableIter iter;
+ gpointer value_p = NULL;
+ int old_size;
+
+ g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), 0);
+ g_return_val_if_fail (!driver->in_frame, 0);
+
+ old_size = g_hash_table_size (driver->vaos);
+
+ g_hash_table_iter_init (&iter, driver->vaos);
+ while (g_hash_table_iter_next (&iter, NULL, &value_p))
+ {
+ Vao *v = value_p;
+
+ if (v->in_use)
+ v->in_use = FALSE;
+ else
+ g_hash_table_iter_remove (&iter);
+ }
+
+ return old_size - g_hash_table_size (driver->vaos);
}
static Texture *
@@ -328,6 +366,8 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
t = find_texture_by_size (driver->textures, width, height);
if (t != NULL && !t->in_use)
{
+ GSK_NOTE (OPENGL, g_print ("Reusing Texture(%d) for size %dx%d\n",
+ t->texture_id, t->width, t->height));
t->in_use = TRUE;
return t->texture_id;
}
@@ -346,6 +386,34 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
return t->texture_id;
}
+static Vao *
+find_vao (GHashTable *vaos,
+ int position_id,
+ int uv_id,
+ int n_quads,
+ GskQuadVertex *quads)
+{
+ GHashTableIter iter;
+ gpointer value_p = NULL;
+
+ g_hash_table_iter_init (&iter, vaos);
+ while (g_hash_table_iter_next (&iter, NULL, &value_p))
+ {
+ Vao *v = value_p;
+
+ if (v->position_id != position_id || v->uv_id != uv_id)
+ continue;
+
+ if (v->n_quads != n_quads)
+ continue;
+
+ if (memcmp (v->quads, quads, sizeof (GskQuadVertex) * n_quads) == 0)
+ return v;
+ }
+
+ return NULL;
+}
+
int
gsk_gl_driver_create_vao_for_quad (GskGLDriver *driver,
int position_id,
@@ -360,6 +428,14 @@ gsk_gl_driver_create_vao_for_quad (GskGLDriver *driver,
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
g_return_val_if_fail (driver->in_frame, -1);
+ v = find_vao (driver->vaos, position_id, uv_id, n_quads, quads);
+ if (v != NULL && !v->in_use)
+ {
+ GSK_NOTE (OPENGL, g_print ("Reusing VAO(%d)\n", v->vao_id));
+ v->in_use = TRUE;
+ return v->vao_id;
+ }
+
glGenVertexArrays (1, &vao_id);
glBindVertexArray (vao_id);
@@ -385,6 +461,9 @@ gsk_gl_driver_create_vao_for_quad (GskGLDriver *driver,
v->buffer_id = buffer_id;
v->position_id = position_id;
v->uv_id = uv_id;
+ v->n_quads = n_quads;
+ v->quads = g_memdup (quads, sizeof (GskQuadVertex) * n_quads);
+ v->in_use = TRUE;
g_hash_table_insert (driver->vaos, GINT_TO_POINTER (vao_id), v);
#ifdef G_ENABLE_DEBUG
diff --git a/gsk/gskgldriverprivate.h b/gsk/gskgldriverprivate.h
index b69a387ca7..f4836f5c56 100644
--- a/gsk/gskgldriverprivate.h
+++ b/gsk/gskgldriverprivate.h
@@ -56,7 +56,8 @@ void gsk_gl_driver_destroy_texture (GskGLDriver *driver
void gsk_gl_driver_destroy_vao (GskGLDriver *driver,
int vao_id);
-void gsk_gl_driver_collect_textures (GskGLDriver *driver);
+int gsk_gl_driver_collect_textures (GskGLDriver *driver);
+int gsk_gl_driver_collect_vaos (GskGLDriver *driver);
G_END_DECLS
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index 7d16ee1f12..ddc6990995 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -795,32 +795,23 @@ gsk_gl_renderer_validate_tree (GskGLRenderer *self,
}
static void
-render_item_clear (RenderItem *item,
- GskGLRenderer *self)
-{
- gsk_gl_driver_destroy_vao (self->gl_driver, item->render_data.vao_id);
-}
-
-static void
gsk_gl_renderer_clear_tree (GskGLRenderer *self)
{
- int i;
+ int removed_textures, removed_vaos;
if (self->gl_context == NULL)
return;
gdk_gl_context_make_current (self->gl_context);
- for (i = 0; i < self->render_items->len; i++)
- {
- RenderItem *item = &g_array_index (self->render_items, RenderItem, i);
-
- render_item_clear (item, self);
- }
-
g_clear_pointer (&self->render_items, g_array_unref);
- gsk_gl_driver_collect_textures (self->gl_driver);
+ removed_textures = gsk_gl_driver_collect_textures (self->gl_driver);
+ removed_vaos = gsk_gl_driver_collect_vaos (self->gl_driver);
+
+ GSK_NOTE (OPENGL, g_print ("Collected: %d textures, %d vaos\n",
+ removed_textures,
+ removed_vaos));
}
static void