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-15 00:06:20 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-03-15 00:44:27 +0300
commit4ecc8b67861a4869cd6b1231c1f8a1082e031ff5 (patch)
tree650d030a96554301babda58e0d0bdeddf92dcd8e /intern/gawain
parent2c80a4d4aa41d9c91b770ba664fbe0f71d641acf (diff)
GWN: Add primitive restart in element/index buffers.
This allows to draw multiple primitive of the type GWN_PRIM_LINE_STRIP GWN_PRIM_LINE_LOOP GWN_PRIM_TRI_STRIP GWN_PRIM_TRI_FAN GWN_PRIM_LINE_STRIP_ADJ with only one drawcall. This should speed up some areas that are really sensitive to drawcall counts : UV drawing, Hair drawing...
Diffstat (limited to 'intern/gawain')
-rw-r--r--intern/gawain/gawain/gwn_element.h14
-rw-r--r--intern/gawain/src/gwn_batch.c31
-rw-r--r--intern/gawain/src/gwn_element.c42
3 files changed, 73 insertions, 14 deletions
diff --git a/intern/gawain/gawain/gwn_element.h b/intern/gawain/gawain/gwn_element.h
index 3081305769f..3015dc00e47 100644
--- a/intern/gawain/gawain/gwn_element.h
+++ b/intern/gawain/gawain/gwn_element.h
@@ -15,6 +15,8 @@
#define GWN_TRACK_INDEX_RANGE 1
+#define GWN_PRIM_RESTART 0xFFFFFFFF
+
typedef enum {
GWN_INDEX_U8, // GL has this, Vulkan does not
GWN_INDEX_U16,
@@ -32,6 +34,7 @@ typedef struct Gwn_IndexBuf {
#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;
void GWN_indexbuf_use(Gwn_IndexBuf*);
@@ -43,17 +46,18 @@ typedef struct Gwn_IndexBufBuilder {
unsigned index_ct;
Gwn_PrimType prim_type;
unsigned* data;
+ bool use_prim_restart;
} Gwn_IndexBufBuilder;
-// supported primitives:
-// GWN_PRIM_POINTS
-// GWN_PRIM_LINES
-// GWN_PRIM_TRIS
+// supports all primitive types.
+void GWN_indexbuf_init_ex(Gwn_IndexBufBuilder*, Gwn_PrimType, unsigned index_ct, unsigned vertex_ct, bool use_prim_restart);
+
+// supports only GWN_PRIM_POINTS, GWN_PRIM_LINES and GWN_PRIM_TRIS.
void GWN_indexbuf_init(Gwn_IndexBufBuilder*, Gwn_PrimType, unsigned prim_ct, unsigned vertex_ct);
-//void GWN_indexbuf_init_custom(Gwn_IndexBufBuilder*, Gwn_PrimType, unsigned index_ct, unsigned vertex_ct);
void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder*, unsigned v);
+void GWN_indexbuf_add_primitive_restart(Gwn_IndexBufBuilder*);
void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder*, unsigned v);
void GWN_indexbuf_add_line_verts(Gwn_IndexBufBuilder*, unsigned v1, unsigned v2);
diff --git a/intern/gawain/src/gwn_batch.c b/intern/gawain/src/gwn_batch.c
index 9dab2a4d7d9..b7f47b316ed 100644
--- a/intern/gawain/src/gwn_batch.c
+++ b/intern/gawain/src/gwn_batch.c
@@ -489,6 +489,27 @@ void GWN_batch_uniform_4fv(Gwn_Batch* batch, const char* name, const float data[
glUniform4fv(uniform->location, 1, data);
}
+static void primitive_restart_enable(const Gwn_IndexBuf *el)
+{
+ // TODO(fclem) Replace by GL_PRIMITIVE_RESTART_FIXED_INDEX when we have ogl 4.3
+ glEnable(GL_PRIMITIVE_RESTART);
+ GLuint restart_index = (GLuint)0xFFFFFFFF;
+
+#if GWN_TRACK_INDEX_RANGE
+ if (el->index_type == GWN_INDEX_U8)
+ restart_index = (GLuint)0xFF;
+ else if (el->index_type == GWN_INDEX_U16)
+ restart_index = (GLuint)0xFFFF;
+#endif
+
+ glPrimitiveRestartIndex(restart_index);
+}
+
+static void primitive_restart_disable(void)
+{
+ glDisable(GL_PRIMITIVE_RESTART);
+}
+
void GWN_batch_draw(Gwn_Batch* batch)
{
#if TRUST_NO_ONE
@@ -528,11 +549,16 @@ void GWN_batch_draw_range_ex(Gwn_Batch* batch, int v_first, int v_count, bool fo
{
const Gwn_IndexBuf* el = batch->elem;
+ if (el->use_prim_restart)
+ primitive_restart_enable(el);
+
#if GWN_TRACK_INDEX_RANGE
glDrawElementsInstancedBaseVertex(batch->gl_prim_type, el->index_ct, el->gl_index_type, 0, v_count, el->base_index);
#else
glDrawElementsInstanced(batch->gl_prim_type, el->index_ct, GL_UNSIGNED_INT, 0, v_count);
#endif
+ if (el->use_prim_restart)
+ primitive_restart_disable();
}
else
glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_ct, v_count);
@@ -547,6 +573,9 @@ void GWN_batch_draw_range_ex(Gwn_Batch* batch, int v_first, int v_count, bool fo
{
const Gwn_IndexBuf* el = batch->elem;
+ if (el->use_prim_restart)
+ primitive_restart_enable(el);
+
#if GWN_TRACK_INDEX_RANGE
if (el->base_index)
glDrawRangeElementsBaseVertex(batch->gl_prim_type, el->min_index, el->max_index, v_count, el->gl_index_type, 0, el->base_index);
@@ -555,6 +584,8 @@ void GWN_batch_draw_range_ex(Gwn_Batch* batch, int v_first, int v_count, bool fo
#else
glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, 0);
#endif
+ if (el->use_prim_restart)
+ primitive_restart_disable();
}
else
glDrawArrays(batch->gl_prim_type, 0, v_count);
diff --git a/intern/gawain/src/gwn_element.c b/intern/gawain/src/gwn_element.c
index f31b64fa232..a65ec9a18b3 100644
--- a/intern/gawain/src/gwn_element.c
+++ b/intern/gawain/src/gwn_element.c
@@ -61,6 +61,16 @@ void GWN_indexbuf_use(Gwn_IndexBuf* elem)
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;
+ builder->max_allowed_index = vertex_ct - 1;
+ builder->max_index_ct = index_ct;
+ builder->index_ct = 0; // start empty
+ builder->prim_type = prim_type;
+ builder->data = calloc(builder->max_index_ct, sizeof(unsigned));
+ }
+
void GWN_indexbuf_init(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, unsigned prim_ct, unsigned vertex_ct)
{
unsigned verts_per_prim = 0;
@@ -82,11 +92,7 @@ void GWN_indexbuf_init(Gwn_IndexBufBuilder* builder, Gwn_PrimType prim_type, uns
return;
}
- builder->max_allowed_index = vertex_ct - 1;
- builder->max_index_ct = prim_ct * verts_per_prim;
- builder->index_ct = 0; // start empty
- builder->prim_type = prim_type;
- builder->data = calloc(builder->max_index_ct, sizeof(unsigned));
+ GWN_indexbuf_init_ex(builder, prim_type, prim_ct * verts_per_prim, vertex_ct, false);
}
void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder* builder, unsigned v)
@@ -100,6 +106,17 @@ void GWN_indexbuf_add_generic_vert(Gwn_IndexBufBuilder* builder, unsigned v)
builder->data[builder->index_ct++] = v;
}
+void GWN_indexbuf_add_primitive_restart(Gwn_IndexBufBuilder* builder)
+ {
+#if TRUST_NO_ONE
+ assert(builder->data != NULL);
+ assert(builder->index_ct < builder->max_index_ct);
+ assert(builder->use_prim_restart);
+#endif
+
+ builder->data[builder->index_ct++] = GWN_PRIM_RESTART;
+ }
+
void GWN_indexbuf_add_point_vert(Gwn_IndexBufBuilder* builder, unsigned v)
{
#if TRUST_NO_ONE
@@ -149,7 +166,9 @@ static unsigned index_range(const unsigned values[], unsigned value_ct, unsigned
for (unsigned i = 1; i < value_ct; ++i)
{
const unsigned value = values[i];
- if (value < min_value)
+ if (value == GWN_PRIM_RESTART)
+ continue;
+ else if (value < min_value)
min_value = value;
else if (value > max_value)
max_value = value;
@@ -173,7 +192,7 @@ static void squeeze_indices_byte(const unsigned values[], Gwn_IndexBuf* elem)
elem->max_index -= base;
for (unsigned i = 0; i < index_ct; ++i)
- data[i] = (GLubyte)(values[i] - base);
+ data[i] = (values[i] == GWN_PRIM_RESTART) ? 0xFF : (GLubyte)(values[i] - base);
}
else
{
@@ -200,7 +219,7 @@ static void squeeze_indices_short(const unsigned values[], Gwn_IndexBuf* elem)
elem->max_index -= base;
for (unsigned i = 0; i < index_ct; ++i)
- data[i] = (GLushort)(values[i] - base);
+ data[i] = (values[i] == GWN_PRIM_RESTART) ? 0xFFFF : (GLushort)(values[i] - base);
}
else
{
@@ -229,9 +248,14 @@ void GWN_indexbuf_build_in_place(Gwn_IndexBufBuilder* builder, Gwn_IndexBuf* ele
#endif
elem->index_ct = builder->index_ct;
+ elem->use_prim_restart = builder->use_prim_restart;
#if GWN_TRACK_INDEX_RANGE
- const unsigned range = index_range(builder->data, builder->index_ct, &elem->min_index, &elem->max_index);
+ unsigned range = index_range(builder->data, builder->index_ct, &elem->min_index, &elem->max_index);
+
+ // count the primitive restart index.
+ if (elem->use_prim_restart)
+ range += 1;
if (range <= 0xFF)
{