diff options
author | Mike Erwin <significant.bit@gmail.com> | 2016-09-06 23:56:08 +0300 |
---|---|---|
committer | Mike Erwin <significant.bit@gmail.com> | 2016-09-06 23:56:08 +0300 |
commit | 18d49a8283f2490b0751798685770533cc814d29 (patch) | |
tree | d6b742efcf60af45c1ebe26b97b1a03ef078f652 /source/blender/gpu/intern/gpu_immediate.c | |
parent | 031c5bad87693f263d2ee69192fb6f7512a5f6dc (diff) |
Gawain: add immBeginAtMost
immBegin requires us to know how many vertices will be drawn. Most times this is fine, but sometimes it can be tricky. Do we make the effort to count everything in one pass, then draw it in a second?
immBeginAtMost makes this simple. Example: I'll draw at most 100 vertices. Supply only 6 verts and it draws only 6.
Any unused space is reclaimed and given to the next immBegin.
Diffstat (limited to 'source/blender/gpu/intern/gpu_immediate.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_immediate.c | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index 88a147959a3..98568d14482 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -242,6 +242,7 @@ typedef struct { unsigned buffer_offset; unsigned buffer_bytes_mapped; unsigned vertex_ct; + bool strict_vertex_ct; GLenum primitive; VertexFormat vertex_format; @@ -285,7 +286,8 @@ void immInit() #endif imm.primitive = PRIM_NONE; - + imm.strict_vertex_ct = true; + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); initialized = true; @@ -334,36 +336,38 @@ void immUnbindProgram() imm.bound_program = 0; } -void immBegin(GLenum primitive, unsigned vertex_ct) +static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, GLenum primitive) { -#if TRUST_NO_ONE - assert(initialized); - assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun - // does vertex_ct make sense for this primitive type? - assert(vertex_ct > 0); + if (vertex_ct == 0) + return false; + switch (primitive) { case GL_POINTS: - break; + return true; case GL_LINES: - assert(vertex_ct % 2 == 0); - break; + return vertex_ct % 2 == 0; case GL_LINE_STRIP: case GL_LINE_LOOP: - assert(vertex_ct > 2); // otherwise why bother? - break; + return vertex_ct > 2; // otherwise why bother? case GL_TRIANGLES: - assert(vertex_ct % 3 == 0); - break; + return vertex_ct % 3 == 0; #ifdef WITH_GL_PROFILE_COMPAT case GL_QUADS: - assert(vertex_ct % 4 == 0); - break; + return vertex_ct % 4 == 0; #endif default: - assert(false); + return false; } + } + +void immBegin(GLenum primitive, unsigned vertex_ct) + { +#if TRUST_NO_ONE + assert(initialized); + assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun + assert(vertex_count_makes_sense_for_primitive(vertex_ct, primitive)); #endif imm.primitive = primitive; @@ -417,17 +421,43 @@ void immBegin(GLenum primitive, unsigned vertex_ct) imm.vertex_data = imm.buffer_data; } +void immBeginAtMost(GLenum primitive, unsigned vertex_ct) + { + imm.strict_vertex_ct = false; + immBegin(primitive, vertex_ct); + } + void immEnd() { #if TRUST_NO_ONE assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair - assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined #endif + unsigned buffer_bytes_used; + if (imm.strict_vertex_ct) + { +#if TRUST_NO_ONE + assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined +#endif + buffer_bytes_used = imm.buffer_bytes_mapped; + } + else + { +#if TRUST_NO_ONE + assert(imm.vertex_idx <= imm.vertex_ct); + assert(vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.primitive)); +#endif + // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_ct); + imm.vertex_ct = imm.vertex_idx; + buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_ct); + // unused buffer bytes are available to the next immBegin + // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped); + } + #if APPLE_LEGACY // tell OpenGL what range was modified so it doesn't copy the whole buffer - glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, imm.buffer_bytes_mapped); -// printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + imm.buffer_bytes_mapped - 1); + glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, buffer_bytes_used); +// printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1); #endif glUnmapBuffer(GL_ARRAY_BUFFER); @@ -490,8 +520,9 @@ void immEnd() glBindVertexArray(0); // prep for next immBegin - imm.buffer_offset += imm.buffer_bytes_mapped; + imm.buffer_offset += buffer_bytes_used; imm.primitive = PRIM_NONE; + imm.strict_vertex_ct = true; // further optional cleanup imm.buffer_bytes_mapped = 0; |