Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-03-17 20:23:04 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-03-17 20:23:04 +0300
commitc2f36c35586a40693c066d2111bf9e557b0afd6c (patch)
tree1d9af7a57e59d4547ff50976c449d39697e9a4e6 /intern/gawain
parent87d88581aaec4abc4fc326a213dfc0d68c39cb3a (diff)
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).
Diffstat (limited to 'intern/gawain')
-rw-r--r--intern/gawain/gawain/gwn_element.h1
-rw-r--r--intern/gawain/src/gwn_element.c84
2 files changed, 25 insertions, 60 deletions
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);
}