diff options
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/intern/gpu_immediate.c | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index b30fbd66670..72e17dce776 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -43,6 +43,14 @@ extern void GPU_matrix_bind(const GPUShaderInterface *); extern bool GPU_matrix_dirty_get(void); +typedef struct ImmediateDrawBuffer { + GLuint vbo_id; + GLubyte *buffer_data; + uint buffer_offset; + uint buffer_size; + uint default_size; +} ImmediateDrawBuffer; + typedef struct { /* TODO: organize this struct by frequency of change (run-time) */ @@ -50,14 +58,14 @@ typedef struct { GPUContext *context; /* current draw call */ - GLubyte *buffer_data; - uint buffer_offset; - uint buffer_bytes_mapped; - uint vertex_len; bool strict_vertex_len; + uint vertex_len; + uint buffer_bytes_mapped; + ImmediateDrawBuffer *active_buffer; GPUPrimType prim_type; - GPUVertFormat vertex_format; + ImmediateDrawBuffer draw_buffer; + ImmediateDrawBuffer draw_buffer_strict; /* current vertex */ uint vertex_idx; @@ -65,7 +73,6 @@ typedef struct { uint16_t unassigned_attr_bits; /* which attributes of current vertex have not been given values? */ - GLuint vbo_id; GLuint vao_id; GLuint bound_program; @@ -76,7 +83,6 @@ typedef struct { /* size of internal buffer */ #define DEFAULT_INTERNAL_BUFFER_SIZE (4 * 1024 * 1024) -static uint imm_buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE; static bool initialized = false; static Immediate imm; @@ -88,9 +94,16 @@ void immInit(void) #endif memset(&imm, 0, sizeof(Immediate)); - imm.vbo_id = GPU_buf_alloc(); - glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); - glBufferData(GL_ARRAY_BUFFER, imm_buffer_size, NULL, GL_DYNAMIC_DRAW); + imm.draw_buffer.vbo_id = GPU_buf_alloc(); + imm.draw_buffer.buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE; + imm.draw_buffer.default_size = DEFAULT_INTERNAL_BUFFER_SIZE; + glBindBuffer(GL_ARRAY_BUFFER, imm.draw_buffer.vbo_id); + glBufferData(GL_ARRAY_BUFFER, imm.draw_buffer.buffer_size, NULL, GL_DYNAMIC_DRAW); + imm.draw_buffer_strict.vbo_id = GPU_buf_alloc(); + imm.draw_buffer_strict.buffer_size = 0; + imm.draw_buffer_strict.default_size = 0; + glBindBuffer(GL_ARRAY_BUFFER, imm.draw_buffer_strict.vbo_id); + glBufferData(GL_ARRAY_BUFFER, imm.draw_buffer_strict.buffer_size, NULL, GL_DYNAMIC_DRAW); imm.prim_type = GPU_PRIM_NONE; imm.strict_vertex_len = true; @@ -124,7 +137,8 @@ void immDeactivate(void) void immDestroy(void) { - GPU_buf_free(imm.vbo_id); + GPU_buf_free(imm.draw_buffer.vbo_id); + GPU_buf_free(imm.draw_buffer_strict.vbo_id); initialized = false; } @@ -213,6 +227,7 @@ void immBegin(GPUPrimType prim_type, uint vertex_len) assert(initialized); assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */ assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type)); + assert(imm.active_buffer == NULL); #endif imm.prim_type = prim_type; imm.vertex_len = vertex_len; @@ -221,54 +236,58 @@ void immBegin(GPUPrimType prim_type, uint vertex_len) /* how many bytes do we need for this draw call? */ const uint bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len); + ImmediateDrawBuffer *active_buffer = imm.strict_vertex_len ? &imm.draw_buffer_strict : + &imm.draw_buffer; + imm.active_buffer = active_buffer; - glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); + glBindBuffer(GL_ARRAY_BUFFER, active_buffer->vbo_id); /* does the current buffer have enough room? */ - const uint available_bytes = imm_buffer_size - imm.buffer_offset; + const uint available_bytes = active_buffer->buffer_size - active_buffer->buffer_offset; bool recreate_buffer = false; - if (bytes_needed > imm_buffer_size) { + if (bytes_needed > active_buffer->buffer_size) { /* expand the internal buffer */ - imm_buffer_size = bytes_needed; + active_buffer->buffer_size = bytes_needed; recreate_buffer = true; } - else if (bytes_needed < DEFAULT_INTERNAL_BUFFER_SIZE && - imm_buffer_size > DEFAULT_INTERNAL_BUFFER_SIZE) { + else if (bytes_needed < active_buffer->default_size && + active_buffer->buffer_size > active_buffer->default_size) { /* shrink the internal buffer */ - imm_buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE; + active_buffer->buffer_size = active_buffer->default_size; recreate_buffer = true; } /* ensure vertex data is aligned */ /* Might waste a little space, but it's safe. */ - const uint pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); + const uint pre_padding = padding(active_buffer->buffer_offset, imm.vertex_format.stride); if (!recreate_buffer && ((bytes_needed + pre_padding) <= available_bytes)) { - imm.buffer_offset += pre_padding; + active_buffer->buffer_offset += pre_padding; } else { /* orphan this buffer & start with a fresh one */ /* this method works on all platforms, old & new */ - glBufferData(GL_ARRAY_BUFFER, imm_buffer_size, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, active_buffer->buffer_size, NULL, GL_DYNAMIC_DRAW); - imm.buffer_offset = 0; + active_buffer->buffer_offset = 0; } /* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */ - imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, - imm.buffer_offset, - bytes_needed, - GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | - (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)); + active_buffer->buffer_data = glMapBufferRange( + GL_ARRAY_BUFFER, + active_buffer->buffer_offset, + bytes_needed, + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | + (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)); #if TRUST_NO_ONE - assert(imm.buffer_data != NULL); + assert(active_buffer->buffer_data != NULL); #endif imm.buffer_bytes_mapped = bytes_needed; - imm.vertex_data = imm.buffer_data; + imm.vertex_data = active_buffer->buffer_data; } void immBeginAtMost(GPUPrimType prim_type, uint vertex_len) @@ -338,7 +357,7 @@ static void immDrawSetup(void) for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; a_idx++) { const GPUVertAttr *a = &imm.vertex_format.attrs[a_idx]; - const uint offset = imm.buffer_offset + a->offset; + const uint offset = imm.active_buffer->buffer_offset + a->offset; const GLvoid *pointer = (const GLubyte *)0 + offset; const uint loc = read_attr_location(&imm.attr_binding, a_idx); @@ -365,6 +384,7 @@ void immEnd(void) { #if TRUST_NO_ONE assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(imm.active_buffer); #endif uint buffer_bytes_used; @@ -421,12 +441,13 @@ void immEnd(void) // glBindBuffer(GL_ARRAY_BUFFER, 0); // glBindVertexArray(0); /* prep for next immBegin */ - imm.buffer_offset += buffer_bytes_used; + imm.active_buffer->buffer_offset += buffer_bytes_used; } /* prep for next immBegin */ imm.prim_type = GPU_PRIM_NONE; imm.strict_vertex_len = true; + imm.active_buffer = NULL; } static void setAttrValueBit(uint attr_id) |