[cogl/wip/neil/pipeline-uniforms: 16/17] Stash
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/neil/pipeline-uniforms: 16/17] Stash
- Date: Wed, 2 Nov 2011 14:06:17 +0000 (UTC)
commit 3e51b248a4554d16b6940ee93b5607f61a4953ce
Author: Neil Roberts <neil linux intel com>
Date: Wed Nov 2 12:43:53 2011 +0000
Stash
cogl/cogl-pipeline-progend-glsl.c | 196 +++++++++++++++++++++---------------
cogl/cogl-pipeline.c | 6 +
2 files changed, 120 insertions(+), 82 deletions(-)
---
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 4ec6f37..84a516c 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -142,12 +142,6 @@ typedef struct
* so know if we need to update all of the uniforms */
CoglPipeline *last_used_for_pipeline;
- /* TRUE if any of the uniforms on this pipeline have been modified
- since it was last flushed. If so then we'll flush all of the
- uniforms that this pipeline overrides (but not necessarily those
- that the parent overrides if we've already flushed them) */
- gboolean uniforms_changed;
-
/* Array of GL uniform locations indexed by Cogl's uniform
location. We are careful only to allocated this array if a custom
uniform is actually set */
@@ -323,7 +317,6 @@ program_state_new (int n_layers)
program_state->program = 0;
program_state->n_tex_coord_attribs = 0;
program_state->unit_state = g_new (UnitState, n_layers);
- program_state->uniforms_changed = TRUE;
program_state->uniform_locations = NULL;
#ifdef HAVE_COGL_GLES2
program_state->tex_coord_attribute_locations = NULL;
@@ -558,17 +551,6 @@ update_builtin_uniforms (CoglPipeline *pipeline,
#endif /* HAVE_COGL_GLES2 */
-static GSList *
-get_ancestors (CoglPipeline *pipeline)
-{
- GSList *ancestors = NULL;
-
- while (pipeline)
- ancestors = g_slist_prepend (ancestors, pipeline);
-
- return ancestors;
-}
-
static void
flush_uniform_boxed_value (CoglContext *ctx,
GLint uniform_location,
@@ -622,23 +604,96 @@ flush_uniform_boxed_value (CoglContext *ctx,
typedef struct
{
CoglPipelineProgramState *program_state;
- CoglPipeline *flushed_ancestor;
- unsigned long *force_flush_uniforms;
- unsigned long *flushed_uniforms;
+ unsigned long *uniform_differences;
+ int n_differences;
CoglPipelineUniformsState *uniforms_state;
- gboolean found_ancestor;
CoglContext *ctx;
CoglPipelineUniformOverride *override;
} FlushUniformsClosure;
+static void
+compare_uniform_differences (FlushUniformsClosure *data,
+ CoglPipeline *pipeline0,
+ CoglPipeline *pipeline1)
+{
+ GSList *head0 = NULL;
+ GSList *head1 = NULL;
+ CoglPipeline *node0;
+ CoglPipeline *node1;
+ int len0 = 0;
+ int len1 = 0;
+ int count;
+ GSList *common_ancestor0;
+ GSList *common_ancestor1;
+
+ /* This algorithm is copied from
+ _cogl_pipeline_compare_differences(). It might be nice to share
+ the code more */
+
+ for (node0 = pipeline0; node0; node0 = _cogl_pipeline_get_parent (node0))
+ {
+ GSList *link = alloca (sizeof (GSList));
+ link->next = head0;
+ link->data = node0;
+ head0 = link;
+ len0++;
+ }
+ for (node1 = pipeline1; node1; node1 = _cogl_pipeline_get_parent (node1))
+ {
+ GSList *link = alloca (sizeof (GSList));
+ link->next = head1;
+ link->data = node1;
+ head1 = link;
+ len1++;
+ }
+
+ /* NB: There's no point looking at the head entries since we know both
+ * pipelines must have the same default pipeline as their root node. */
+ common_ancestor0 = head0;
+ common_ancestor1 = head1;
+ head0 = head0->next;
+ head1 = head1->next;
+ count = MIN (len0, len1) - 1;
+ while (count--)
+ {
+ if (head0->data != head1->data)
+ break;
+ common_ancestor0 = head0;
+ common_ancestor1 = head1;
+ head0 = head0->next;
+ head1 = head1->next;
+ }
+
+ for (head0 = common_ancestor0->next; head0; head0 = head0->next)
+ {
+ node0 = head0->data;
+ if ((node0->differences & COGL_PIPELINE_STATE_UNIFORMS))
+ {
+ const CoglPipelineUniformsState *uniforms_state =
+ &node0->big_state->uniforms_state;
+ _cogl_bitmask_set_flags (&uniforms_state->override_mask,
+ data->uniform_differences);
+ }
+ }
+ for (head1 = common_ancestor1->next; head1; head1 = head1->next)
+ {
+ node1 = head1->data;
+ if ((node1->differences & COGL_PIPELINE_STATE_UNIFORMS))
+ {
+ const CoglPipelineUniformsState *uniforms_state =
+ &node1->big_state->uniforms_state;
+ _cogl_bitmask_set_flags (&uniforms_state->override_mask,
+ data->uniform_differences);
+ }
+ }
+}
+
static gboolean
flush_uniform_cb (int uniform_num, void *user_data)
{
FlushUniformsClosure *data = user_data;
- if (!COGL_FLAGS_GET (data->flushed_uniforms, uniform_num) &&
- (!data->found_ancestor ||
- COGL_FLAGS_GET (data->force_flush_uniforms, uniform_num)))
+ if (COGL_FLAGS_GET (data->uniform_differences, uniform_num))
{
GArray *uniform_locations;
GLint uniform_location;
@@ -682,12 +737,13 @@ flush_uniform_cb (int uniform_num, void *user_data)
uniform_location,
&data->override->value);
- COGL_FLAGS_SET (data->flushed_uniforms, uniform_num, TRUE);
+ data->n_differences--;
+ COGL_FLAGS_SET (data->uniform_differences, uniform_num, FALSE);
}
data->override = COGL_SLIST_NEXT (data->override, list_node);
- return TRUE;
+ return data->n_differences > 0;
}
static void
@@ -702,83 +758,65 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_bitmask_init (&data.force_flush_uniforms);
-
if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
data.uniforms_state = &pipeline->big_state->uniforms_state;
else
data.uniforms_state = NULL;
- data.flushed_ancestor = NULL;
data.program_state = program_state;
data.ctx = ctx;
n_uniform_longs = COGL_FLAGS_N_LONGS_FOR_SIZE (ctx->n_uniform_names);
- data.force_flush_uniforms = g_newa (unsigned long, n_uniform_longs);
- memset (data.force_flush_uniforms, 0,
- n_uniform_longs * sizeof (unsigned long));
- data.flushed_uniforms = g_newa (unsigned long, n_uniform_longs);
- memset (data.flushed_uniforms, 0,
- n_uniform_longs * sizeof (unsigned long));
+ data.uniform_differences = g_newa (unsigned long, n_uniform_longs);
/* Try to find a common ancestor for the values that were already
flushed on the pipeline that this program state was last used for
so we can avoid flushing those */
- if (program_changed)
+ if (program_changed || program_state->last_used_for_pipeline == NULL)
{
- /* The program has changed so we have no common ancestor and we
- need to flush everything. All of the uniform locations are
- invalid */
- if (program_state->uniform_locations)
- g_array_set_size (program_state->uniform_locations, 0);
+ if (program_changed)
+ {
+ /* The program has changed so all of the uniform locations
+ are invalid */
+ if (program_state->uniform_locations)
+ g_array_set_size (program_state->uniform_locations, 0);
+ }
+
+ /* We need to flush everything so mark all of the uniforms as
+ dirty */
+ memset (data.uniform_differences, 0xff,
+ n_uniform_longs * sizeof (unsigned long));
+ data.n_differences = G_MAXINT;
}
- else
+ else if (program_state->last_used_for_pipeline)
{
- GSList *flushed_ancestors =
- get_ancestors (program_state->last_used_for_pipeline);
- GSList *new_ancestors =
- get_ancestors (pipeline);
- GSList *a, *b;
-
- for (a = flushed_ancestors, b = new_ancestors;
- a && b && a->data == b->data;
- a = a->next, b = b->next)
- data.flushed_ancestor = a->data;
+ int i;
- g_slist_free (flushed_ancestors);
- g_slist_free (new_ancestors);
+ memset (data.uniform_differences, 0,
+ n_uniform_longs * sizeof (unsigned long));
+ compare_uniform_differences (&data,
+ program_state->last_used_for_pipeline,
+ pipeline);
/* We need to be sure to flush any uniforms that have changed
since the last flush */
if (data.uniforms_state)
_cogl_bitmask_set_flags (&data.uniforms_state->changed_mask,
- data.force_flush_uniforms);
+ data.uniform_differences);
- /* We need to flush any uniforms that are children of the common
- ancestor up to the last used pipeline */
- while (a)
- {
- CoglPipeline *child_pipeline = a->data;
- if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
- {
- const CoglPipelineUniformsState *uniforms_state =
- &child_pipeline->big_state->uniforms_state;
- _cogl_bitmask_set_flags (&uniforms_state->override_mask,
- data.force_flush_uniforms);
- }
- a = a->next;
- }
- }
+ /* Count the number of differences. This is so we can stop early
+ when we've flushed all of them */
+ data.n_differences = 0;
- data.found_ancestor = FALSE;
+ for (i = 0; i < n_uniform_longs; i++)
+ data.n_differences +=
+ _cogl_util_popcountl (data.uniform_differences[i]);
+ }
- while (pipeline)
+ while (pipeline && data.n_differences > 0)
{
- if (pipeline == data.flushed_ancestor)
- data.found_ancestor = TRUE;
-
if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
{
const CoglPipelineUniformsState *uniforms_state =
@@ -1029,12 +1067,6 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline,
if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
dirty_program_state (pipeline);
- else if ((change & COGL_PIPELINE_STATE_UNIFORMS))
- {
- CoglPipelineProgramState *program_state = get_program_state (pipeline);
- if (program_state)
- program_state->uniforms_changed = TRUE;
- }
#ifdef HAVE_COGL_GLES2
else if (ctx->driver == COGL_DRIVER_GLES2)
{
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 3d2bf3e..1e10a71 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -2231,6 +2231,12 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
_cogl_pipeline_user_shader_equal))
goto done;
+ if (!simple_property_equal (authorities0, authorities1,
+ pipelines_difference,
+ COGL_PIPELINE_STATE_UNIFORMS_INDEX,
+ _cogl_pipeline_uniforms_state_equal))
+ goto done;
+
if (pipelines_difference & COGL_PIPELINE_STATE_LAYERS)
{
CoglPipelineStateIndex state_index = COGL_PIPELINE_STATE_LAYERS_INDEX;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]