[cogl] cogl-pipeline: Use a hash table for faster uniform name lookup



commit c269817eddf1f9aac97f21bd41e5486f6de93746
Author: Neil Roberts <neil linux intel com>
Date:   Fri Nov 4 18:26:17 2011 +0000

    cogl-pipeline: Use a hash table for faster uniform name lookup
    
    The uniform names are now stored in a GPtrArray instead of a linked
    list. There is also a hash table to speed up converting names to
    locations.
    
    Reviewed-by: Robert Bragg <robert linux intel com>

 cogl/cogl-context-private.h       |   10 +++++++---
 cogl/cogl-context.c               |    8 +++++---
 cogl/cogl-pipeline-progend-glsl.c |    2 +-
 cogl/cogl-pipeline.c              |   25 +++++++++++++------------
 4 files changed, 26 insertions(+), 19 deletions(-)
---
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 8125e7b..f0d1655 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -258,12 +258,16 @@ struct _CoglContext
     [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_WINSYS_FEATURE_N_FEATURES)];
   void *winsys;
 
-  /* List of names of uniforms. These are used like quarks to give a
+  /* Array of names of uniforms. These are used like quarks to give a
      unique number to each uniform name except that we ensure that
      they increase sequentially so that we can use the id as an index
      into a bitfield representing the uniforms that a pipeline
-     overrides from its parent */
-  GSList *uniform_names;
+     overrides from its parent. */
+  GPtrArray *uniform_names;
+  /* A hash table to quickly get an index given an existing name. The
+     name strings are owned by the uniform_names array. The values are
+     the uniform location cast to a pointer. */
+  GHashTable *uniform_name_hash;
   int n_uniform_names;
 
   /* This defines a list of function pointers that Cogl uses from
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 58fa44d..62a0483 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -221,7 +221,9 @@ cogl_context_new (CoglDisplay *display,
       g_assert_not_reached ();
     }
 
-  context->uniform_names = NULL;
+  context->uniform_names =
+    g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+  context->uniform_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
   context->n_uniform_names = 0;
 
   /* Initialise the driver specific state */
@@ -484,8 +486,8 @@ _cogl_context_free (CoglContext *context)
 
   _cogl_destroy_texture_units ();
 
-  g_slist_foreach (context->uniform_names, (GFunc) g_free, NULL);
-  g_slist_free (context->uniform_names);
+  g_ptr_array_free (context->uniform_names, TRUE);
+  g_hash_table_destroy (context->uniform_name_hash);
 
   g_byte_array_free (context->buffer_map_fallback_array, TRUE);
 
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 2c7f857..c612d73 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -598,7 +598,7 @@ flush_uniform_cb (int uniform_num, void *user_data)
       if (uniform_location == UNIFORM_LOCATION_UNKNOWN)
         {
           const char *uniform_name =
-            g_slist_nth (data->ctx->uniform_names, uniform_num)->data;
+            g_ptr_array_index (data->ctx->uniform_names, uniform_num);
 
           uniform_location =
             data->ctx->glGetUniformLocation (data->program_state->program,
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 1cd9317..c984219 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -2871,8 +2871,8 @@ int
 cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
                                     const char *uniform_name)
 {
-  GSList *l;
-  int location = 0;
+  void *location_ptr;
+  char *uniform_name_copy;
 
   _COGL_GET_CONTEXT (ctx, -1);
 
@@ -2884,16 +2884,17 @@ cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
      be. */
 
   /* Look for an existing uniform with this name */
-  for (l = ctx->uniform_names; l; l = l->next)
-    {
-      if (!strcmp (uniform_name, l->data))
-        return location;
-
-      location++;
-    }
-
-  ctx->uniform_names =
-    g_slist_append (ctx->uniform_names, g_strdup (uniform_name));
+  if (g_hash_table_lookup_extended (ctx->uniform_name_hash,
+                                    uniform_name,
+                                    NULL,
+                                    &location_ptr))
+    return GPOINTER_TO_INT (location_ptr);
+
+  uniform_name_copy = g_strdup (uniform_name);
+  g_ptr_array_add (ctx->uniform_names, uniform_name_copy);
+  g_hash_table_insert (ctx->uniform_name_hash,
+                       uniform_name_copy,
+                       GINT_TO_POINTER (ctx->n_uniform_names));
 
   return ctx->n_uniform_names++;
 }



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