From 69c6924ccc9470eebc405adb97cc8436b8cb112a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 17 Aug 2019 00:43:44 -0300 Subject: [PATCH] render: simplify vertex and uniform data allocation. Improves performance of various SDL_Render functions (bug #4764). --- src/render/SDL_render.c | 114 ++++--------------------------------- src/render/SDL_sysrender.h | 9 --- 2 files changed, 11 insertions(+), 112 deletions(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 5b0c1bf30..6e7ec61b0 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -202,8 +202,6 @@ DebugLogRenderCommands(const SDL_RenderCommand *cmd) static int FlushRenderCommands(SDL_Renderer *renderer) { - SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps; - SDL_AllocVertGap *gap = prevgap; int retval; SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL)); @@ -217,14 +215,6 @@ FlushRenderCommands(SDL_Renderer *renderer) retval = renderer->RunCommandQueue(renderer, renderer->render_commands, renderer->vertex_data, renderer->vertex_data_used); - while (gap) { - prevgap = gap; - gap = gap->next; - } - prevgap->next = renderer->vertex_data_gaps_pool; - renderer->vertex_data_gaps_pool = renderer->vertex_data_gaps.next; - renderer->vertex_data_gaps.next = NULL; - /* Move the whole render command queue to the unused pool so we can reuse them next time. */ if (renderer->render_commands_tail != NULL) { renderer->render_commands_tail->next = renderer->render_commands_pool; @@ -263,79 +253,23 @@ SDL_RenderFlush(SDL_Renderer * renderer) return FlushRenderCommands(renderer); } -static SDL_AllocVertGap * -AllocateVertexGap(SDL_Renderer *renderer) -{ - SDL_AllocVertGap *retval = renderer->vertex_data_gaps_pool; - if (retval) { - renderer->vertex_data_gaps_pool = retval->next; - retval->next = NULL; - } else { - retval = (SDL_AllocVertGap *) SDL_malloc(sizeof (SDL_AllocVertGap)); - if (!retval) { - SDL_OutOfMemory(); - } - } - return retval; -} - - void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset) { const size_t needed = renderer->vertex_data_used + numbytes + alignment; - size_t aligner, aligned; - void *retval; + size_t current_offset = renderer->vertex_data_used; - SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps; - SDL_AllocVertGap *gap = prevgap->next; - while (gap) { - const size_t gapoffset = gap->offset; - aligner = (alignment && ((gap->offset % alignment) != 0)) ? (alignment - (gap->offset % alignment)) : 0; - aligned = gapoffset + aligner; + size_t aligner = (alignment && ((current_offset & (alignment - 1)) != 0)) ? (alignment - (current_offset & (alignment - 1))) : 0; + size_t aligned = current_offset + aligner; - /* Can we use this gap? */ - if ((aligner < gap->len) && ((gap->len - aligner) >= numbytes)) { - /* we either finished this gap off, trimmed the left, trimmed the right, or split it into two gaps. */ - if (gap->len == numbytes) { /* finished it off, remove it */ - SDL_assert(aligned == gapoffset); - prevgap->next = gap->next; - gap->next = renderer->vertex_data_gaps_pool; - renderer->vertex_data_gaps_pool = gap; - } else if (aligned == gapoffset) { /* trimmed the left */ - gap->offset += numbytes; - gap->len -= numbytes; - } else if (((aligned - gapoffset) + numbytes) == gap->len) { /* trimmed the right */ - gap->len -= numbytes; - } else { /* split into two gaps */ - SDL_AllocVertGap *newgap = AllocateVertexGap(renderer); - if (!newgap) { - return NULL; - } - newgap->offset = aligned + numbytes; - newgap->len = gap->len - (aligner + numbytes); - newgap->next = gap->next; - // gap->offset doesn't change. - gap->len = aligner; - gap->next = newgap; - } - - if (offset) { - *offset = aligned; - } - return ((Uint8 *) renderer->vertex_data) + aligned; - } - - /* Try the next gap */ - prevgap = gap; - gap = gap->next; - } - - /* no gaps with enough space; get a new piece of the vertex buffer */ - while (needed > renderer->vertex_data_allocation) { + if (renderer->vertex_data_allocation < needed) { const size_t current_allocation = renderer->vertex_data ? renderer->vertex_data_allocation : 1024; - const size_t newsize = current_allocation * 2; - void *ptr = SDL_realloc(renderer->vertex_data, newsize); + size_t newsize = current_allocation * 2; + void *ptr; + while (newsize < needed) { + newsize *= 2; + } + ptr = SDL_realloc(renderer->vertex_data, newsize); if (ptr == NULL) { SDL_OutOfMemory(); return NULL; @@ -344,27 +278,13 @@ SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const renderer->vertex_data_allocation = newsize; } - aligner = (alignment && ((renderer->vertex_data_used % alignment) != 0)) ? (alignment - (renderer->vertex_data_used % alignment)) : 0; - aligned = renderer->vertex_data_used + aligner; - - retval = ((Uint8 *) renderer->vertex_data) + aligned; if (offset) { *offset = aligned; } - if (aligner) { /* made a new gap... */ - SDL_AllocVertGap *newgap = AllocateVertexGap(renderer); - if (newgap) { /* just let it slide as lost space if malloc fails. */ - newgap->offset = renderer->vertex_data_used; - newgap->len = aligner; - newgap->next = NULL; - prevgap->next = newgap; - } - } - renderer->vertex_data_used += aligner + numbytes; - return retval; + return ((Uint8 *) renderer->vertex_data) + aligned; } static SDL_RenderCommand * @@ -3177,8 +3097,6 @@ void SDL_DestroyRenderer(SDL_Renderer * renderer) { SDL_RenderCommand *cmd; - SDL_AllocVertGap *gap; - SDL_AllocVertGap *nextgap; CHECK_RENDERER_MAGIC(renderer, ); @@ -3203,16 +3121,6 @@ SDL_DestroyRenderer(SDL_Renderer * renderer) SDL_free(renderer->vertex_data); - for (gap = renderer->vertex_data_gaps.next; gap; gap = nextgap) { - nextgap = gap->next; - SDL_free(gap); - } - - for (gap = renderer->vertex_data_gaps_pool; gap; gap = nextgap) { - nextgap = gap->next; - SDL_free(gap); - } - /* Free existing textures for this renderer */ while (renderer->textures) { SDL_Texture *tex = renderer->textures; (void) tex; diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 93865621c..dedd64200 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -110,13 +110,6 @@ typedef struct SDL_RenderCommand struct SDL_RenderCommand *next; } SDL_RenderCommand; -typedef struct SDL_AllocVertGap -{ - size_t offset; - size_t len; - struct SDL_AllocVertGap *next; -} SDL_AllocVertGap; - /* Define the SDL renderer structure */ struct SDL_Renderer @@ -226,8 +219,6 @@ struct SDL_Renderer void *vertex_data; size_t vertex_data_used; size_t vertex_data_allocation; - SDL_AllocVertGap vertex_data_gaps; - SDL_AllocVertGap *vertex_data_gaps_pool; void *driverdata; };