summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2011-09-20 01:24:16 +0100
committerRobert Bragg <robert@linux.intel.com>2011-09-21 15:50:08 +0100
commitd739892a5cf08084835795337b4444f1678ba8c8 (patch)
treea12f75581db307b90b3e06d77013145bc26acf0d
parent791773987ca70e34b550bae2687b1777459cd8ff (diff)
downloadcogl-d739892a5cf08084835795337b4444f1678ba8c8.tar.gz
primitive: micro optimize primitive allocations
We've started seeing cases where we want to allocate lots of one-shot primitives per-frame and the cost of allocating primitives becomes important in this case since it can start being noticeable in profiles. The main cost for allocating primitives was the GArray allocation and appending the attributes to the array. This updates the code to simply over allocate the primitive storage so we can embed the list of attributes directly in that allocation. If the user later sets new attributes and there isn't enough embedded space then a separate slice allocation for the new attributes is made but still this should be far less costly than using a GArray as before. Most of the time we would expect when setting new attributes there will still be the same number of attributes, so the embedded space can simple be reused. Reviewed-by: Neil Roberts <neil@linux.intel.com>
-rw-r--r--cogl/cogl-primitive-private.h7
-rw-r--r--cogl/cogl-primitive.c104
2 files changed, 64 insertions, 47 deletions
diff --git a/cogl/cogl-primitive-private.h b/cogl/cogl-primitive-private.h
index c50181f5..3deb1e79 100644
--- a/cogl/cogl-primitive-private.h
+++ b/cogl/cogl-primitive-private.h
@@ -39,9 +39,14 @@ struct _CoglPrimitive
int first_vertex;
int n_vertices;
CoglIndices *indices;
- GArray *attributes;
int immutable_ref;
+
+ CoglAttribute **attributes;
+ int n_attributes;
+
+ int n_embedded_attributes;
+ CoglAttribute *embedded_attribute;
};
CoglPrimitive *
diff --git a/cogl/cogl-primitive.c b/cogl/cogl-primitive.c
index dace7c69..145bc8b0 100644
--- a/cogl/cogl-primitive.c
+++ b/cogl/cogl-primitive.c
@@ -35,6 +35,7 @@
#include "cogl-attribute-private.h"
#include <stdarg.h>
+#include <string.h>
static void _cogl_primitive_free (CoglPrimitive *primitive);
@@ -46,17 +47,20 @@ cogl_primitive_new_with_attributes (CoglVerticesMode mode,
CoglAttribute **attributes,
int n_attributes)
{
- CoglPrimitive *primitive = g_slice_new (CoglPrimitive);
+ CoglPrimitive *primitive;
int i;
+ primitive = g_slice_alloc (sizeof (CoglPrimitive) +
+ sizeof (CoglAttribute *) * (n_attributes - 1));
primitive->mode = mode;
primitive->first_vertex = 0;
primitive->n_vertices = n_vertices;
primitive->indices = NULL;
- primitive->attributes =
- g_array_new (TRUE, FALSE, sizeof (CoglAttribute *));
primitive->immutable_ref = 0;
+ primitive->n_attributes = n_attributes;
+ primitive->n_embedded_attributes = n_attributes;
+ primitive->attributes = &primitive->embedded_attribute;
for (i = 0; i < n_attributes; i++)
{
CoglAttribute *attribute = attributes[i];
@@ -64,7 +68,7 @@ cogl_primitive_new_with_attributes (CoglVerticesMode mode,
g_return_val_if_fail (cogl_is_attribute (attribute), NULL);
- g_array_append_val (primitive->attributes, attribute);
+ primitive->attributes[i] = attribute;
}
return _cogl_primitive_object_new (primitive);
@@ -354,27 +358,20 @@ cogl_primitive_new_p3t2c4 (CoglVerticesMode mode,
}
static void
-free_attributes_list (CoglPrimitive *primitive)
+_cogl_primitive_free (CoglPrimitive *primitive)
{
int i;
- for (i = 0; i < primitive->attributes->len; i++)
- {
- CoglAttribute *attribute =
- g_array_index (primitive->attributes, CoglAttribute *, i);
- cogl_object_unref (attribute);
- }
- g_array_set_size (primitive->attributes, 0);
-}
-
-static void
-_cogl_primitive_free (CoglPrimitive *primitive)
-{
- free_attributes_list (primitive);
+ for (i = 0; i < primitive->n_attributes; i++)
+ cogl_object_unref (primitive->attributes[i]);
- g_array_free (primitive->attributes, TRUE);
+ if (primitive->attributes != &primitive->embedded_attribute)
+ g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes,
+ primitive->attributes);
- g_slice_free (CoglPrimitive, primitive);
+ g_slice_free1 (sizeof (CoglPrimitive) +
+ sizeof (CoglAttribute *) *
+ (primitive->n_embedded_attributes - 1), primitive);
}
static void
@@ -383,7 +380,7 @@ warn_about_midscene_changes (void)
static gboolean seen = FALSE;
if (!seen)
{
- g_warning ("Mid-scene modification of buffers has "
+ g_warning ("Mid-scene modification of primitives has "
"undefined results\n");
seen = TRUE;
}
@@ -404,15 +401,42 @@ cogl_primitive_set_attributes (CoglPrimitive *primitive,
return;
}
- free_attributes_list (primitive);
-
- g_array_set_size (primitive->attributes, 0);
+ /* NB: we don't unref the previous attributes before refing the new
+ * in case we would end up releasing the last reference for an
+ * attribute thats actually in the new list too. */
for (i = 0; i < n_attributes; i++)
{
- cogl_object_ref (attributes[i]);
g_return_if_fail (cogl_is_attribute (attributes[i]));
- g_array_append_val (primitive->attributes, attributes[i]);
+ cogl_object_ref (attributes[i]);
+ }
+
+ for (i = 0; i < primitive->n_attributes; i++)
+ cogl_object_unref (primitive->attributes[i]);
+
+ /* First try to use the embedded storage assocated with the
+ * primitive, else fallback to slice allocating separate storage for
+ * the attribute pointers... */
+
+ if (n_attributes <= primitive->n_embedded_attributes)
+ {
+ if (primitive->attributes != &primitive->embedded_attribute)
+ g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes,
+ primitive->attributes);
+ primitive->attributes = &primitive->embedded_attribute;
}
+ else
+ {
+ if (primitive->attributes != &primitive->embedded_attribute)
+ g_slice_free1 (sizeof (CoglAttribute *) * primitive->n_attributes,
+ primitive->attributes);
+ primitive->attributes =
+ g_slice_alloc (sizeof (CoglAttribute *) * n_attributes);
+ }
+
+ memcpy (primitive->attributes, attributes,
+ sizeof (CoglAttribute *) * n_attributes);
+
+ primitive->n_attributes = n_attributes;
}
int
@@ -506,12 +530,8 @@ _cogl_primitive_immutable_ref (CoglPrimitive *primitive)
primitive->immutable_ref++;
- for (i = 0; i < primitive->attributes->len; i++)
- {
- CoglAttribute *attribute =
- g_array_index (primitive->attributes, CoglAttribute *, i);
- _cogl_attribute_immutable_ref (attribute);
- }
+ for (i = 0; i < primitive->n_attributes; i++)
+ _cogl_attribute_immutable_ref (primitive->attributes[i]);
return primitive;
}
@@ -526,33 +546,25 @@ _cogl_primitive_immutable_unref (CoglPrimitive *primitive)
primitive->immutable_ref--;
- for (i = 0; i < primitive->attributes->len; i++)
- {
- CoglAttribute *attribute =
- g_array_index (primitive->attributes, CoglAttribute *, i);
- _cogl_attribute_immutable_unref (attribute);
- }
+ for (i = 0; i < primitive->n_attributes; i++)
+ _cogl_attribute_immutable_unref (primitive->attributes[i]);
}
/* XXX: cogl_draw_primitive() ? */
void
cogl_primitive_draw (CoglPrimitive *primitive)
{
- CoglAttribute **attributes =
- (CoglAttribute **)primitive->attributes->data;
-
if (primitive->indices)
cogl_draw_indexed_attributes (primitive->mode,
primitive->first_vertex,
primitive->n_vertices,
primitive->indices,
- attributes,
- primitive->attributes->len);
+ primitive->attributes,
+ primitive->n_attributes);
else
cogl_draw_attributes (primitive->mode,
primitive->first_vertex,
primitive->n_vertices,
- attributes,
- primitive->attributes->len);
+ primitive->attributes,
+ primitive->n_attributes);
}
-