From c269817eddf1f9aac97f21bd41e5486f6de93746 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 4 Nov 2011 18:26:17 +0000 Subject: [PATCH] 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 --- cogl/cogl-context-private.h | 10 +++++++--- cogl/cogl-context.c | 8 +++++--- cogl/cogl-pipeline-progend-glsl.c | 2 +- cogl/cogl-pipeline.c | 23 ++++++++++++----------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h index 8125e7bb7..f0d1655ef 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 58fa44d61..62a048379 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 2c7f8570c..c612d7355 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 1cd93176d..c984219af 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; + if (g_hash_table_lookup_extended (ctx->uniform_name_hash, + uniform_name, + NULL, + &location_ptr)) + return GPOINTER_TO_INT (location_ptr); - location++; - } - - ctx->uniform_names = - g_slist_append (ctx->uniform_names, g_strdup (uniform_name)); + 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++; }