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...
This commit is contained in:
parent
2c80a4d4aa
commit
4ecc8b6786
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue