pipeline: optimize _compare_differences functions
This optimizes the layer and pipeline _compare_differences functions so neither of them use the GArray api since building up the list of ancestors by appending to a shared GArray was showing quite high on profiles due to how frequently pipeline comparisons are made. Instead we now build up a transient, singly linked list by allocating GList nodes via alloca to build up the parallel lists of ancestors. This tweaked approach actually ends up being a bit more concise than before, we avoid the overhead of the GArray api and now avoid making any function calls while comparing (assuming the _get_parent() calls always inline), we avoiding needing to get the default cogl context. Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
f16d3756df
commit
30f8521790
@ -128,9 +128,6 @@ struct _CoglContext
|
|||||||
gboolean current_pipeline_skip_gl_color;
|
gboolean current_pipeline_skip_gl_color;
|
||||||
unsigned long current_pipeline_age;
|
unsigned long current_pipeline_age;
|
||||||
|
|
||||||
GArray *pipeline0_nodes;
|
|
||||||
GArray *pipeline1_nodes;
|
|
||||||
|
|
||||||
/* Bitmask of attributes enabled. On GLES2 these are the vertex
|
/* Bitmask of attributes enabled. On GLES2 these are the vertex
|
||||||
attribute numbers and on regular GL these are only used for the
|
attribute numbers and on regular GL these are only used for the
|
||||||
texture coordinate arrays */
|
texture coordinate arrays */
|
||||||
|
@ -258,11 +258,6 @@ cogl_context_new (CoglDisplay *display,
|
|||||||
context->current_pipeline_changes_since_flush = 0;
|
context->current_pipeline_changes_since_flush = 0;
|
||||||
context->current_pipeline_skip_gl_color = FALSE;
|
context->current_pipeline_skip_gl_color = FALSE;
|
||||||
|
|
||||||
context->pipeline0_nodes =
|
|
||||||
g_array_sized_new (FALSE, FALSE, sizeof (CoglHandle), 20);
|
|
||||||
context->pipeline1_nodes =
|
|
||||||
g_array_sized_new (FALSE, FALSE, sizeof (CoglHandle), 20);
|
|
||||||
|
|
||||||
_cogl_bitmask_init (&context->arrays_enabled);
|
_cogl_bitmask_init (&context->arrays_enabled);
|
||||||
_cogl_bitmask_init (&context->temp_bitmask);
|
_cogl_bitmask_init (&context->temp_bitmask);
|
||||||
_cogl_bitmask_init (&context->arrays_to_change);
|
_cogl_bitmask_init (&context->arrays_to_change);
|
||||||
|
@ -376,82 +376,72 @@ unsigned long
|
|||||||
_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0,
|
_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0,
|
||||||
CoglPipelineLayer *layer1)
|
CoglPipelineLayer *layer1)
|
||||||
{
|
{
|
||||||
|
GSList *head0 = NULL;
|
||||||
|
GSList *head1 = NULL;
|
||||||
CoglPipelineLayer *node0;
|
CoglPipelineLayer *node0;
|
||||||
CoglPipelineLayer *node1;
|
CoglPipelineLayer *node1;
|
||||||
int len0;
|
int len0 = 0;
|
||||||
int len1;
|
int len1 = 0;
|
||||||
int len0_index;
|
|
||||||
int len1_index;
|
|
||||||
int count;
|
int count;
|
||||||
int i;
|
GSList *common_ancestor0;
|
||||||
CoglPipelineLayer *common_ancestor = NULL;
|
GSList *common_ancestor1;
|
||||||
unsigned long layers_difference = 0;
|
unsigned long layers_difference = 0;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, 0);
|
|
||||||
|
|
||||||
/* Algorithm:
|
/* Algorithm:
|
||||||
*
|
*
|
||||||
* 1) Walk the ancestors of each layer to the root node, adding a
|
* 1) Walk the ancestors of each layer to the root node, adding a
|
||||||
* pointer to each ancester node to two GArrays:
|
* pointer to each ancester node to two linked lists
|
||||||
* ctx->pipeline0_nodes, and ctx->pipeline1_nodes.
|
|
||||||
*
|
*
|
||||||
* 2) Compare the arrays to find the nodes where they stop to
|
* 2) Compare the lists to find the nodes where they start to
|
||||||
* differ.
|
* differ marking the common_ancestor node for each list.
|
||||||
*
|
*
|
||||||
* 3) For each array now iterate from index 0 to the first node of
|
* 3) For each list now iterate starting after the common_ancestor
|
||||||
* difference ORing that nodes ->difference mask into the final
|
* nodes ORing each nodes ->difference mask into the final
|
||||||
* pipeline_differences mask.
|
* differences mask.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g_array_set_size (ctx->pipeline0_nodes, 0);
|
|
||||||
g_array_set_size (ctx->pipeline1_nodes, 0);
|
|
||||||
for (node0 = layer0; node0; node0 = _cogl_pipeline_layer_get_parent (node0))
|
for (node0 = layer0; node0; node0 = _cogl_pipeline_layer_get_parent (node0))
|
||||||
g_array_append_vals (ctx->pipeline0_nodes, &node0, 1);
|
|
||||||
for (node1 = layer1; node1; node1 = _cogl_pipeline_layer_get_parent (node1))
|
|
||||||
g_array_append_vals (ctx->pipeline1_nodes, &node1, 1);
|
|
||||||
|
|
||||||
len0 = ctx->pipeline0_nodes->len;
|
|
||||||
len1 = ctx->pipeline1_nodes->len;
|
|
||||||
/* There's no point looking at the last entries since we know both
|
|
||||||
* layers must have the same default layer as their root node. */
|
|
||||||
len0_index = len0 - 2;
|
|
||||||
len1_index = len1 - 2;
|
|
||||||
count = MIN (len0, len1) - 1;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
node0 = g_array_index (ctx->pipeline0_nodes,
|
GSList *link = alloca (sizeof (GSList));
|
||||||
CoglPipelineLayer *, len0_index--);
|
link->next = head0;
|
||||||
node1 = g_array_index (ctx->pipeline1_nodes,
|
link->data = node0;
|
||||||
CoglPipelineLayer *, len1_index--);
|
head0 = link;
|
||||||
if (node0 != node1)
|
len0++;
|
||||||
{
|
}
|
||||||
common_ancestor = _cogl_pipeline_layer_get_parent (node0);
|
for (node1 = layer1; node1; node1 = _cogl_pipeline_layer_get_parent (node1))
|
||||||
break;
|
{
|
||||||
}
|
GSList *link = alloca (sizeof (GSList));
|
||||||
|
link->next = head1;
|
||||||
|
link->data = node1;
|
||||||
|
head1 = link;
|
||||||
|
len1++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't already find the first the common_ancestor ancestor
|
/* NB: There's no point looking at the head entries since we know both layers
|
||||||
* that's because one pipeline is a direct descendant of the other
|
* must have the same default layer as their root node. */
|
||||||
* and in this case the first common ancestor is the last node we
|
common_ancestor0 = head0;
|
||||||
* looked at. */
|
common_ancestor1 = head1;
|
||||||
if (!common_ancestor)
|
head0 = head0->next;
|
||||||
common_ancestor = node0;
|
head1 = head1->next;
|
||||||
|
count = MIN (len0, len1) - 1;
|
||||||
count = len0 - 1;
|
while (count--)
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
node0 = g_array_index (ctx->pipeline0_nodes, CoglPipelineLayer *, i);
|
if (head0->data != head1->data)
|
||||||
if (node0 == common_ancestor)
|
|
||||||
break;
|
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;
|
||||||
layers_difference |= node0->differences;
|
layers_difference |= node0->differences;
|
||||||
}
|
}
|
||||||
|
for (head1 = common_ancestor1->next; head1; head1 = head1->next)
|
||||||
count = len1 - 1;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
node1 = g_array_index (ctx->pipeline1_nodes, CoglPipelineLayer *, i);
|
node1 = head1->data;
|
||||||
if (node1 == common_ancestor)
|
|
||||||
break;
|
|
||||||
layers_difference |= node1->differences;
|
layers_difference |= node1->differences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1914,87 +1914,76 @@ unsigned long
|
|||||||
_cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
|
_cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
|
||||||
CoglPipeline *pipeline1)
|
CoglPipeline *pipeline1)
|
||||||
{
|
{
|
||||||
|
GSList *head0 = NULL;
|
||||||
|
GSList *head1 = NULL;
|
||||||
CoglPipeline *node0;
|
CoglPipeline *node0;
|
||||||
CoglPipeline *node1;
|
CoglPipeline *node1;
|
||||||
int len0;
|
int len0 = 0;
|
||||||
int len1;
|
int len1 = 0;
|
||||||
int len0_index;
|
|
||||||
int len1_index;
|
|
||||||
int count;
|
int count;
|
||||||
int i;
|
GSList *common_ancestor0;
|
||||||
CoglPipeline *common_ancestor = NULL;
|
GSList *common_ancestor1;
|
||||||
unsigned long pipelines_difference = 0;
|
unsigned long pipelines_difference = 0;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, 0);
|
|
||||||
|
|
||||||
/* Algorithm:
|
/* Algorithm:
|
||||||
*
|
*
|
||||||
* 1) Walk the ancestors of each layer to the root node, adding a
|
* 1) Walk the ancestors of each pipeline to the root node, adding a
|
||||||
* pointer to each ancester node to two GArrays:
|
* pointer to each ancester node to two linked lists
|
||||||
* ctx->pipeline0_nodes, and ctx->pipeline1_nodes.
|
|
||||||
*
|
*
|
||||||
* 2) Compare the arrays to find the nodes where they stop to
|
* 2) Compare the lists to find the nodes where they start to
|
||||||
* differ.
|
* differ marking the common_ancestor node for each list.
|
||||||
*
|
*
|
||||||
* 3) For each array now iterate from index 0 to the first node of
|
* 3) For each list now iterate starting after the common_ancestor
|
||||||
* difference ORing that nodes ->difference mask into the final
|
* nodes ORing each nodes ->difference mask into the final
|
||||||
* pipeline_differences mask.
|
* differences mask.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g_array_set_size (ctx->pipeline0_nodes, 0);
|
|
||||||
g_array_set_size (ctx->pipeline1_nodes, 0);
|
|
||||||
for (node0 = pipeline0; node0; node0 = _cogl_pipeline_get_parent (node0))
|
for (node0 = pipeline0; node0; node0 = _cogl_pipeline_get_parent (node0))
|
||||||
g_array_append_vals (ctx->pipeline0_nodes, &node0, 1);
|
|
||||||
for (node1 = pipeline1; node1; node1 = _cogl_pipeline_get_parent (node1))
|
|
||||||
g_array_append_vals (ctx->pipeline1_nodes, &node1, 1);
|
|
||||||
|
|
||||||
len0 = ctx->pipeline0_nodes->len;
|
|
||||||
len1 = ctx->pipeline1_nodes->len;
|
|
||||||
/* There's no point looking at the last entries since we know both
|
|
||||||
* layers must have the same default layer as their root node. */
|
|
||||||
len0_index = len0 - 2;
|
|
||||||
len1_index = len1 - 2;
|
|
||||||
count = MIN (len0, len1) - 1;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
node0 = g_array_index (ctx->pipeline0_nodes,
|
GSList *link = alloca (sizeof (GSList));
|
||||||
CoglPipeline *, len0_index--);
|
link->next = head0;
|
||||||
node1 = g_array_index (ctx->pipeline1_nodes,
|
link->data = node0;
|
||||||
CoglPipeline *, len1_index--);
|
head0 = link;
|
||||||
if (node0 != node1)
|
len0++;
|
||||||
{
|
}
|
||||||
common_ancestor = _cogl_pipeline_get_parent (node0);
|
for (node1 = pipeline1; node1; node1 = _cogl_pipeline_get_parent (node1))
|
||||||
break;
|
{
|
||||||
}
|
GSList *link = alloca (sizeof (GSList));
|
||||||
|
link->next = head1;
|
||||||
|
link->data = node1;
|
||||||
|
head1 = link;
|
||||||
|
len1++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't already find the first the common_ancestor ancestor
|
/* NB: There's no point looking at the head entries since we know both
|
||||||
* that's because one pipeline is a direct descendant of the other
|
* pipelines must have the same default pipeline as their root node. */
|
||||||
* and in this case the first common ancestor is the last node we
|
common_ancestor0 = head0;
|
||||||
* looked at. */
|
common_ancestor1 = head1;
|
||||||
if (!common_ancestor)
|
head0 = head0->next;
|
||||||
common_ancestor = node0;
|
head1 = head1->next;
|
||||||
|
count = MIN (len0, len1) - 1;
|
||||||
count = len0 - 1;
|
while (count--)
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
node0 = g_array_index (ctx->pipeline0_nodes, CoglPipeline *, i);
|
if (head0->data != head1->data)
|
||||||
if (node0 == common_ancestor)
|
|
||||||
break;
|
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;
|
||||||
pipelines_difference |= node0->differences;
|
pipelines_difference |= node0->differences;
|
||||||
}
|
}
|
||||||
|
for (head1 = common_ancestor1->next; head1; head1 = head1->next)
|
||||||
count = len1 - 1;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
node1 = g_array_index (ctx->pipeline1_nodes, CoglPipeline *, i);
|
node1 = head1->data;
|
||||||
if (node1 == common_ancestor)
|
|
||||||
break;
|
|
||||||
pipelines_difference |= node1->differences;
|
pipelines_difference |= node1->differences;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pipelines_difference;
|
return pipelines_difference;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
Loading…
Reference in New Issue
Block a user