From c2f36c35586a40693c066d2111bf9e557b0afd6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sat, 17 Mar 2018 18:23:04 +0100 Subject: GWN: Element Buffer: Refactor / Optimisation. - Upload the data to the GPU directly when creating the element buffer in GWN_indexbuf_build_in_place(). - Convert data in place when squeezing the indices and removing the need for another allocation. - GWN_indexbuf_build_in_place() can be used with already used element buffers and reupload their data without changing vbo id (keeping vaos up to date). --- intern/gawain/gawain/gwn_element.h | 1 - intern/gawain/src/gwn_element.c | 84 ++++++++++++-------------------------- 2 files changed, 25 insertions(+), 60 deletions(-) (limited to 'intern/gawain') diff --git a/intern/gawain/gawain/gwn_element.h b/intern/gawain/gawain/gwn_element.h index 3015dc00e47..7a28ab183f8 100644 --- a/intern/gawain/gawain/gwn_element.h +++ b/intern/gawain/gawain/gwn_element.h @@ -32,7 +32,6 @@ typedef struct Gwn_IndexBuf { unsigned max_index; unsigned base_index; #endif - void* data; // NULL indicates data in VRAM (unmapped) or not yet allocated GLuint vbo_id; // 0 indicates not yet sent to VRAM bool use_prim_restart; } Gwn_IndexBuf; diff --git a/intern/gawain/src/gwn_element.c b/intern/gawain/src/gwn_element.c index a65ec9a18b3..0b7dc675f87 100644 --- a/intern/gawain/src/gwn_element.c +++ b/intern/gawain/src/gwn_element.c @@ -39,28 +39,6 @@ unsigned GWN_indexbuf_size_get(const Gwn_IndexBuf* elem) #endif } -static void ElementList_prime(Gwn_IndexBuf* elem) - { - elem->vbo_id = GWN_buf_id_alloc(); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id); - // fill with delicious data & send to GPU the first time only - glBufferData(GL_ELEMENT_ARRAY_BUFFER, GWN_indexbuf_size_get(elem), elem->data, GL_STATIC_DRAW); - -#if KEEP_SINGLE_COPY - // now that GL has a copy, discard original - free(elem->data); - elem->data = NULL; -#endif - } - -void GWN_indexbuf_use(Gwn_IndexBuf* elem) - { - if (elem->vbo_id) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id); - else - ElementList_prime(elem); - } - void GWN_indexbuf_init_ex(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, unsigned index_ct, unsigned vertex_ct, bool use_prim_restart) { builder->use_prim_restart = use_prim_restart; @@ -178,10 +156,14 @@ static unsigned index_range(const unsigned values[], unsigned value_ct, unsigned return max_value - min_value; } -static void squeeze_indices_byte(const unsigned values[], Gwn_IndexBuf* elem) +static void squeeze_indices_byte(Gwn_IndexBufBuilder *builder, Gwn_IndexBuf* elem) { + const unsigned *values = builder->data; const unsigned index_ct = elem->index_ct; - GLubyte* data = malloc(index_ct * sizeof(GLubyte)); + + // data will never be *larger* than builder->data... + // converting in place to avoid extra allocation + GLubyte *data = (GLubyte *)builder->data; if (elem->max_index > 0xFF) { @@ -201,14 +183,16 @@ static void squeeze_indices_byte(const unsigned values[], Gwn_IndexBuf* elem) for (unsigned i = 0; i < index_ct; ++i) data[i] = (GLubyte)(values[i]); } - - elem->data = data; } -static void squeeze_indices_short(const unsigned values[], Gwn_IndexBuf* elem) +static void squeeze_indices_short(Gwn_IndexBufBuilder *builder, Gwn_IndexBuf* elem) { + const unsigned *values = builder->data; const unsigned index_ct = elem->index_ct; - GLushort* data = malloc(index_ct * sizeof(GLushort)); + + // data will never be *larger* than builder->data... + // converting in place to avoid extra allocation + GLushort *data = (GLushort *)builder->data; if (elem->max_index > 0xFFFF) { @@ -228,8 +212,6 @@ static void squeeze_indices_short(const unsigned values[], Gwn_IndexBuf* elem) for (unsigned i = 0; i < index_ct; ++i) data[i] = (GLushort)(values[i]); } - - elem->data = data; } #endif // GWN_TRACK_INDEX_RANGE @@ -260,60 +242,44 @@ void GWN_indexbuf_build_in_place(Gwn_IndexBufBuilder* builder, Gwn_IndexBuf* ele if (range <= 0xFF) { elem->index_type = GWN_INDEX_U8; - squeeze_indices_byte(builder->data, elem); + squeeze_indices_byte(builder, elem); } else if (range <= 0xFFFF) { elem->index_type = GWN_INDEX_U16; - squeeze_indices_short(builder->data, elem); + squeeze_indices_short(builder, elem); } else { elem->index_type = GWN_INDEX_U32; elem->base_index = 0; - - if (builder->index_ct < builder->max_index_ct) - { - builder->data = realloc(builder->data, builder->index_ct * sizeof(unsigned)); - // TODO: realloc only if index_ct is much smaller than max_index_ct - } - - elem->data = builder->data; } elem->gl_index_type = convert_index_type_to_gl(elem->index_type); -#else - if (builder->index_ct < builder->max_index_ct) - { - builder->data = realloc(builder->data, builder->index_ct * sizeof(unsigned)); - // TODO: realloc only if index_ct is much smaller than max_index_ct - } - - elem->data = builder->data; #endif - // elem->data will never be *larger* than builder->data... how about converting - // in place to avoid extra allocation? + if (elem->vbo_id == 0) + elem->vbo_id = GWN_buf_id_alloc(); - elem->vbo_id = 0; - // TODO: create GL buffer object directly, based on an input flag + // send data to GPU + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, GWN_indexbuf_size_get(elem), builder->data, GL_STATIC_DRAW); // discard builder (one-time use) - if (builder->data != elem->data) - free(builder->data); + free(builder->data); builder->data = NULL; // other fields are safe to leave } +void GWN_indexbuf_use(Gwn_IndexBuf* elem) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id); + } + void GWN_indexbuf_discard(Gwn_IndexBuf* elem) { if (elem->vbo_id) GWN_buf_id_free(elem->vbo_id); -#if KEEP_SINGLE_COPY - else -#endif - if (elem->data) - free(elem->data); free(elem); } -- cgit v1.2.3