[gtk/ngl-setup-once] ngl: Set up buffers and arrays once




commit ffb277ee58613ef6ab04d1e64eaf3cd54c110b40
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Mar 19 01:19:54 2021 -0400

    ngl: Set up buffers and arrays once
    
    Keep the array buffer around, and use glBufferSubData
    to update it when possible, and only set up the vertex
    array once, too.

 gsk/ngl/gsknglbuffer.c              | 21 ++++++++---
 gsk/ngl/gsknglbufferprivate.h       |  2 ++
 gsk/ngl/gsknglcommandqueue.c        | 71 ++++++++++++++++++++-----------------
 gsk/ngl/gsknglcommandqueueprivate.h |  3 ++
 4 files changed, 60 insertions(+), 37 deletions(-)
---
diff --git a/gsk/ngl/gsknglbuffer.c b/gsk/ngl/gsknglbuffer.c
index f65923d003..3a8a340898 100644
--- a/gsk/ngl/gsknglbuffer.c
+++ b/gsk/ngl/gsknglbuffer.c
@@ -45,25 +45,36 @@ gsk_ngl_buffer_init (GskNglBuffer *self,
   self->buffer = g_malloc (self->buffer_len);
   self->target = target;
   self->element_size = element_size;
+  self->vbo_size = 0;
+  self->vbo_id = 0;
 }
 
 GLuint
 gsk_ngl_buffer_submit (GskNglBuffer *buffer)
 {
-  GLuint id;
+  if (buffer->vbo_id == 0)
+    glGenBuffers (1, &buffer->vbo_id);
 
-  glGenBuffers (1, &id);
-  glBindBuffer (buffer->target, id);
-  glBufferData (buffer->target, buffer->buffer_pos, buffer->buffer, GL_STATIC_DRAW);
+  if (buffer->vbo_size < buffer->buffer_pos)
+    {
+      glBindBuffer (buffer->target, buffer->vbo_id);
+      glBufferData (buffer->target, buffer->buffer_pos, buffer->buffer, GL_DYNAMIC_DRAW);
+      buffer->vbo_size = buffer->buffer_pos;
+    }
+  else
+    {
+      glBufferSubData (buffer->target, 0, buffer->buffer_pos, buffer->buffer);
+    }
 
   buffer->buffer_pos = 0;
   buffer->count = 0;
 
-  return id;
+  return buffer->vbo_id;
 }
 
 void
 gsk_ngl_buffer_destroy (GskNglBuffer *buffer)
 {
+  glDeleteBuffers (1, &buffer->vbo_id);
   g_clear_pointer (&buffer->buffer, g_free);
 }
diff --git a/gsk/ngl/gsknglbufferprivate.h b/gsk/ngl/gsknglbufferprivate.h
index cbd21c83da..2b76b8cd8e 100644
--- a/gsk/ngl/gsknglbufferprivate.h
+++ b/gsk/ngl/gsknglbufferprivate.h
@@ -33,6 +33,8 @@ typedef struct _GskNglBuffer
   guint   count;
   GLenum  target;
   gsize   element_size;
+  GLuint  vbo_id;
+  gsize   vbo_size;
 } GskNglBuffer;
 
 void   gsk_ngl_buffer_init    (GskNglBuffer *self,
diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c
index bebd315823..da1ede281f 100644
--- a/gsk/ngl/gsknglcommandqueue.c
+++ b/gsk/ngl/gsknglcommandqueue.c
@@ -402,6 +402,9 @@ gsk_ngl_command_queue_dispose (GObject *object)
   gsk_ngl_command_binds_clear (&self->batch_binds);
   gsk_ngl_command_uniforms_clear (&self->batch_uniforms);
 
+  glDeleteVertexArrays (1, &self->vao_id);
+  self->vao_id = 0;
+
   gsk_ngl_buffer_destroy (&self->vertices);
 
   G_OBJECT_CLASS (gsk_ngl_command_queue_parent_class)->dispose (object);
@@ -929,6 +932,40 @@ gsk_ngl_command_queue_sort_batches (GskNglCommandQueue *self)
   g_free (seen_free);
 }
 
+static void
+init_vertex_array (GskNglCommandQueue *self)
+{
+  if (self->vao_id == 0)
+    {
+      glGenVertexArrays (1, &self->vao_id);
+      glBindVertexArray (self->vao_id);
+
+      /* 0 = position location */
+      glEnableVertexAttribArray (0);
+      glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE,
+                             sizeof (GskNglDrawVertex),
+                             (void *) G_STRUCT_OFFSET (GskNglDrawVertex, position));
+
+      /* 1 = texture coord location */
+      glEnableVertexAttribArray (1);
+      glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE,
+                             sizeof (GskNglDrawVertex),
+                             (void *) G_STRUCT_OFFSET (GskNglDrawVertex, uv));
+
+      /* 2 = color location */
+      glEnableVertexAttribArray (2);
+      glVertexAttribPointer (2, 4, GL_FLOAT, GL_FALSE,
+                             sizeof (GskNglDrawVertex),
+                             (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color));
+
+      /* 3 = color2 location */
+      glEnableVertexAttribArray (3);
+      glVertexAttribPointer (3, 4, GL_FLOAT, GL_FALSE,
+                             sizeof (GskNglDrawVertex),
+                             (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color2));
+    }
+}
+
 /**
  * gsk_ngl_command_queue_execute:
  * @self: a #GskNglCommandQueue
@@ -954,8 +991,6 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue   *self,
   guint n_binds = 0;
   guint n_fbos = 0;
   guint n_uniforms = 0;
-  guint vao_id;
-  guint vbo_id;
   int textures[4];
   int framebuffer = -1;
   int next_batch_index;
@@ -987,34 +1022,9 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue   *self,
   glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
   glBlendEquation (GL_FUNC_ADD);
 
-  glGenVertexArrays (1, &vao_id);
-  glBindVertexArray (vao_id);
-
-  vbo_id = gsk_ngl_buffer_submit (&self->vertices);
-
-  /* 0 = position location */
-  glEnableVertexAttribArray (0);
-  glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE,
-                         sizeof (GskNglDrawVertex),
-                         (void *) G_STRUCT_OFFSET (GskNglDrawVertex, position));
+  gsk_ngl_buffer_submit (&self->vertices);
 
-  /* 1 = texture coord location */
-  glEnableVertexAttribArray (1);
-  glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE,
-                         sizeof (GskNglDrawVertex),
-                         (void *) G_STRUCT_OFFSET (GskNglDrawVertex, uv));
-
-  /* 2 = color location */
-  glEnableVertexAttribArray (2);
-  glVertexAttribPointer (2, 4, GL_FLOAT, GL_FALSE,
-                         sizeof (GskNglDrawVertex),
-                         (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color));
-
-  /* 3 = color2 location */
-  glEnableVertexAttribArray (3);
-  glVertexAttribPointer (3, 4, GL_FLOAT, GL_FALSE,
-                         sizeof (GskNglDrawVertex),
-                         (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color2));
+  init_vertex_array (self);
 
   /* Setup initial scissor clip */
   if (scissor != NULL)
@@ -1141,9 +1151,6 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue   *self,
       next_batch_index = batch->any.next_batch_index;
     }
 
-  glDeleteBuffers (1, &vbo_id);
-  glDeleteVertexArrays (1, &vao_id);
-
   gdk_profiler_set_int_counter (self->metrics.n_binds, n_binds);
   gdk_profiler_set_int_counter (self->metrics.n_uniforms, n_uniforms);
   gdk_profiler_set_int_counter (self->metrics.n_fbos, n_fbos);
diff --git a/gsk/ngl/gsknglcommandqueueprivate.h b/gsk/ngl/gsknglcommandqueueprivate.h
index 9a35326cee..abf43ba0a5 100644
--- a/gsk/ngl/gsknglcommandqueueprivate.h
+++ b/gsk/ngl/gsknglcommandqueueprivate.h
@@ -228,6 +228,9 @@ struct _GskNglCommandQueue
   /* String storage for debug groups */
   GStringChunk *debug_groups;
 
+  /* The vertex array */
+  GLuint vao_id;
+
   /* Discovered max texture size when loading the command queue so that we
    * can either scale down or slice textures to fit within this size. Assumed
    * to be both height and width.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]