diff options
author | Mike Erwin <significant.bit@gmail.com> | 2017-03-14 08:38:42 +0300 |
---|---|---|
committer | Mike Erwin <significant.bit@gmail.com> | 2017-03-14 08:38:42 +0300 |
commit | 225e3a6857b33ac0af8de89cc1b63734caa3e058 (patch) | |
tree | 74b1cb44af5e4d4a8e8996ad6e6c9eb054352e7c | |
parent | 9bf0b246ac495b901362f1cc4e74d9b3772d9195 (diff) |
Gawain: multiple VertexBuffers per Batch
So we can store (for example) vertex positions in one buffer and normals + colors in another buffer. Not super exciting right now, but very useful once we start changing some attribute values.
Supports future work by Clément et al. Only tested with one VBO per Batch since that's all our current code uses.
-rw-r--r-- | source/blender/gpu/gawain/batch.c | 105 | ||||
-rw-r--r-- | source/blender/gpu/gawain/batch.h | 8 | ||||
-rw-r--r-- | source/blender/gpu/gawain/immediate.c | 2 |
3 files changed, 82 insertions, 33 deletions
diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c index 1b86c18cd6f..cac34d445bb 100644 --- a/source/blender/gpu/gawain/batch.c +++ b/source/blender/gpu/gawain/batch.c @@ -34,7 +34,9 @@ void Batch_init(Batch* batch, PrimitiveType prim_type, VertexBuffer* verts, Elem // we will allow other primitive types in a future update #endif - batch->verts = verts; + batch->verts[0] = verts; + for (int v = 1; v < BATCH_MAX_VBO_CT; ++v) + batch->verts[v] = NULL; batch->elem = elem; batch->prim_type = prim_type; batch->phase = READY_TO_DRAW; @@ -50,12 +52,43 @@ void Batch_discard(Batch* batch) void Batch_discard_all(Batch* batch) { - VertexBuffer_discard(batch->verts); + for (int v = 0; v < BATCH_MAX_VBO_CT; ++v) + { + if (batch->verts[v] == NULL) + break; + VertexBuffer_discard(batch->verts[v]); + } + if (batch->elem) ElementList_discard(batch->elem); + Batch_discard(batch); } +int Batch_add_VertexBuffer(Batch* batch, VertexBuffer* verts) + { + for (unsigned v = 0; v < BATCH_MAX_VBO_CT; ++v) + { + if (batch->verts[v] == NULL) + { +#if TRUST_NO_ONE + // for now all VertexBuffers must have same vertex_ct + assert(verts->vertex_ct == batch->verts[0]->vertex_ct); + // in the near future we will enable instanced attribs which have their own vertex_ct +#endif + batch->verts[v] = verts; + // TODO: mark dirty so we can keep attrib bindings up-to-date + return v; + } + } + + // we only make it this far if there is no room for another VertexBuffer +#if TRUST_NO_ONE + assert(false); +#endif + return -1; + } + void Batch_set_program(Batch* batch, GLuint program) { #if TRUST_NO_ONE @@ -70,41 +103,48 @@ void Batch_set_program(Batch* batch, GLuint program) static void Batch_update_program_bindings(Batch* batch) { - const VertexFormat* format = &batch->verts->format; - - const unsigned attrib_ct = format->attrib_ct; - const unsigned stride = format->stride; - // disable all as a precaution // why are we not using prev_attrib_enabled_bits?? see immediate.c for (unsigned a_idx = 0; a_idx < MAX_VERTEX_ATTRIBS; ++a_idx) glDisableVertexAttribArray(a_idx); - VertexBuffer_use(batch->verts); - - for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx) + for (int v = 0; v < BATCH_MAX_VBO_CT; ++v) { - const Attrib* a = format->attribs + a_idx; - - const GLvoid* pointer = (const GLubyte*)0 + a->offset; + VertexBuffer* verts = batch->verts[v]; + if (verts == NULL) + break; - const GLint loc = glGetAttribLocation(batch->program, a->name); + const VertexFormat* format = &verts->format; - if (loc == -1) continue; + const unsigned attrib_ct = format->attrib_ct; + const unsigned stride = format->stride; - glEnableVertexAttribArray(loc); + VertexBuffer_use(verts); - switch (a->fetch_mode) + for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx) { - case KEEP_FLOAT: - case CONVERT_INT_TO_FLOAT: - glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer); - break; - case NORMALIZE_INT_TO_FLOAT: - glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer); - break; - case KEEP_INT: - glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer); + const Attrib* a = format->attribs + a_idx; + + const GLvoid* pointer = (const GLubyte*)0 + a->offset; + + const GLint loc = glGetAttribLocation(batch->program, a->name); + + if (loc == -1) continue; + + glEnableVertexAttribArray(loc); + + switch (a->fetch_mode) + { + case KEEP_FLOAT: + case CONVERT_INT_TO_FLOAT: + glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer); + break; + case NORMALIZE_INT_TO_FLOAT: + glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer); + break; + case KEEP_INT: + glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer); + } } } @@ -226,7 +266,12 @@ static void Batch_prime(Batch* batch) batch->vao_id = vao_id_alloc(); glBindVertexArray(batch->vao_id); - VertexBuffer_use(batch->verts); + for (int v = 0; v < BATCH_MAX_VBO_CT; ++v) + { + if (batch->verts[v] == NULL) + break; + VertexBuffer_use(batch->verts[v]); + } if (batch->elem) ElementList_use(batch->elem); @@ -267,7 +312,7 @@ void Batch_draw(Batch* batch) #endif } else - glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct); + glDrawArrays(batch->prim_type, 0, batch->verts[0]->vertex_ct); Batch_done_using_program(batch); glBindVertexArray(0); @@ -304,7 +349,7 @@ void Batch_draw_stupid(Batch* batch) #endif } else - glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct); + glDrawArrays(batch->prim_type, 0, batch->verts[0]->vertex_ct); // Batch_done_using_program(batch); glBindVertexArray(0); @@ -352,7 +397,7 @@ void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int in glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count); } else - glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count); + glDrawArraysInstanced(batch->prim_type, 0, batch->verts[0]->vertex_ct, instance_count); // Batch_done_using_program(batch); glBindVertexArray(0); diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h index 85d9227ff08..189a586f964 100644 --- a/source/blender/gpu/gawain/batch.h +++ b/source/blender/gpu/gawain/batch.h @@ -21,9 +21,11 @@ typedef enum { READY_TO_DRAW } BatchPhase; -typedef struct Batch{ +#define BATCH_MAX_VBO_CT 3 + +typedef struct Batch { // geometry - VertexBuffer* verts; + VertexBuffer* verts[BATCH_MAX_VBO_CT]; // verts[0] is required, others can be NULL ElementList* elem; // NULL if element list not needed PrimitiveType prim_type; @@ -43,6 +45,8 @@ void Batch_init(Batch*, PrimitiveType, VertexBuffer*, ElementList*); void Batch_discard(Batch*); // verts & elem are not discarded void Batch_discard_all(Batch*); // including verts & elem +int Batch_add_VertexBuffer(Batch*, VertexBuffer*); + void Batch_set_program(Batch*, GLuint program); // Entire batch draws with one shader program, but can be redrawn later with another program. // Vertex shader's inputs must be compatible with the batch's vertex format. diff --git a/source/blender/gpu/gawain/immediate.c b/source/blender/gpu/gawain/immediate.c index cda0e98ac29..f52e9271fe5 100644 --- a/source/blender/gpu/gawain/immediate.c +++ b/source/blender/gpu/gawain/immediate.c @@ -385,7 +385,7 @@ void immEnd(void) { if (buffer_bytes_used != imm.buffer_bytes_mapped) { - VertexBuffer_resize_data(imm.batch->verts, imm.vertex_ct); + VertexBuffer_resize_data(imm.batch->verts[0], imm.vertex_ct); // TODO: resize only if vertex count is much smaller } |