diff options
author | Mike Erwin <significant.bit@gmail.com> | 2016-10-13 21:49:33 +0300 |
---|---|---|
committer | Mike Erwin <significant.bit@gmail.com> | 2016-10-13 22:15:40 +0300 |
commit | 945f8e3f93ac3c2dbc8ee0d8504040b6bcaa41b8 (patch) | |
tree | 658ba86e25e31b9f78b3d4bd4ca85e6a4377a23e /source | |
parent | dfa5b32c8cc4f9df7da660754eae773f5df102e6 (diff) |
Gawain: vertex format now uses fixed allocations (CPU perf++)
API stays exactly the same.
Attribute names can still be of variable length, as long as the average length does not exceed AVG_VERTEX_ATTRIB_NAME_LEN. Since this includes unused attributes (length = 0) the current avg of 5 might even be too high.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/gpu/gawain/vertex_format.c | 48 | ||||
-rw-r--r-- | source/blender/gpu/gawain/vertex_format.h | 6 |
2 files changed, 36 insertions, 18 deletions
diff --git a/source/blender/gpu/gawain/vertex_format.c b/source/blender/gpu/gawain/vertex_format.c index a39e3ca2486..20a4d7d8099 100644 --- a/source/blender/gpu/gawain/vertex_format.c +++ b/source/blender/gpu/gawain/vertex_format.c @@ -21,29 +21,19 @@ void VertexFormat_clear(VertexFormat* format) { - for (unsigned a = 0; a < format->attrib_ct; ++a) - free(format->attribs[a].name); - #if TRUST_NO_ONE memset(format, 0, sizeof(VertexFormat)); #else format->attrib_ct = 0; format->packed = false; + format->name_offset = 0; #endif } void VertexFormat_copy(VertexFormat* dest, const VertexFormat* src) { - // discard dest format's old name strings - for (unsigned a = 0; a < dest->attrib_ct; ++a) - free(dest->attribs[a].name); - // copy regular struct fields memcpy(dest, src, sizeof(VertexFormat)); - - // give dest attribs their own copy of name strings - for (unsigned i = 0; i < src->attrib_ct; ++i) - dest->attribs[i].name = strdup(src->attribs[i].name); } static unsigned comp_sz(GLenum type) @@ -79,6 +69,33 @@ unsigned vertex_buffer_size(const VertexFormat* format, unsigned vertex_ct) return format->stride * vertex_ct; } +static const char* copy_attrib_name(VertexFormat* format, const char* name) + { + // strncpy does 110% of what we need; let's do exactly 100% + char* name_copy = format->names + format->name_offset; + unsigned available = VERTEX_ATTRIB_NAMES_BUFFER_LEN - format->name_offset; + bool terminated = false; + + for (unsigned i = 0; i < available; ++i) + { + const char c = name[i]; + name_copy[i] = c; + if (c == '\0') + { + terminated = true; + format->name_offset += (i + 1); + break; + } + } + +#if TRUST_NO_ONE + assert(terminated); + assert(format->name_offset <= VERTEX_ATTRIB_NAMES_BUFFER_LEN); +#endif + + return name_copy; + } + unsigned add_attrib(VertexFormat* format, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode fetch_mode) { #if TRUST_NO_ONE @@ -114,7 +131,7 @@ unsigned add_attrib(VertexFormat* format, const char* name, GLenum comp_type, un const unsigned attrib_id = format->attrib_ct++; Attrib* attrib = format->attribs + attrib_id; - attrib->name = strdup(name); + attrib->name = copy_attrib_name(format, name); attrib->comp_type = comp_type; attrib->comp_ct = comp_ct; attrib->sz = attrib_sz(attrib); @@ -149,11 +166,8 @@ void VertexFormat_pack(VertexFormat* format) // later we can implement more efficient packing w/ reordering // (keep attrib ID order, adjust their offsets to reorder in buffer) - // TODO: concatentate name strings into attribs[0].name, point attribs[i] to - // offset into the combined string. Free all other name strings. Could save more - // space by storing combined string in VertexFormat, with each attrib having an - // offset into it. Could also append each name string as it's added... pack() - // could alloc just enough to hold the final combo string. And just enough to + // TODO: + // realloc just enough to hold the final combo string. And just enough to // hold used attribs, not all 16. Attrib* a0 = format->attribs + 0; diff --git a/source/blender/gpu/gawain/vertex_format.h b/source/blender/gpu/gawain/vertex_format.h index b58e70fe70a..09c79603b0c 100644 --- a/source/blender/gpu/gawain/vertex_format.h +++ b/source/blender/gpu/gawain/vertex_format.h @@ -14,6 +14,8 @@ #include "common.h" #define MAX_VERTEX_ATTRIBS 16 +#define AVG_VERTEX_ATTRIB_NAME_LEN 5 +#define VERTEX_ATTRIB_NAMES_BUFFER_LEN ((AVG_VERTEX_ATTRIB_NAME_LEN + 1) * MAX_VERTEX_ATTRIBS) typedef enum { KEEP_FLOAT, @@ -28,7 +30,7 @@ typedef struct { unsigned sz; // size in bytes, 1 to 16 unsigned offset; // from beginning of vertex, in bytes VertexFetchMode fetch_mode; - char* name; // TODO: shared allocation of all names within a VertexFormat + const char* name; } Attrib; typedef struct { @@ -36,6 +38,8 @@ typedef struct { unsigned stride; // stride in bytes, 1 to 256 bool packed; Attrib attribs[MAX_VERTEX_ATTRIBS]; // TODO: variable-size attribs array + char names[VERTEX_ATTRIB_NAMES_BUFFER_LEN]; + unsigned name_offset; } VertexFormat; void VertexFormat_clear(VertexFormat*); |