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.
This commit is contained in:
parent
dfa5b32c8c
commit
945f8e3f93
|
@ -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;
|
||||
|
|
|
@ -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*);
|
||||
|
|
Loading…
Reference in New Issue