Skip to content

Commit

Permalink
render: simplify vertex and uniform data allocation. Improves perform…
Browse files Browse the repository at this point in the history
…ance of various SDL_Render functions (bug #4764).
  • Loading branch information
slime73 committed Aug 17, 2019
1 parent e5acccc commit 69c6924
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 112 deletions.
114 changes: 11 additions & 103 deletions src/render/SDL_render.c
Expand Up @@ -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));
Expand All @@ -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;
Expand Down Expand Up @@ -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;

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;

/* 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;
}
size_t current_offset = renderer->vertex_data_used;

if (offset) {
*offset = aligned;
}
return ((Uint8 *) renderer->vertex_data) + aligned;
}

/* Try the next gap */
prevgap = gap;
gap = gap->next;
}
size_t aligner = (alignment && ((current_offset & (alignment - 1)) != 0)) ? (alignment - (current_offset & (alignment - 1))) : 0;
size_t aligned = current_offset + aligner;

/* 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;
Expand All @@ -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 *
Expand Down Expand Up @@ -3177,8 +3097,6 @@ void
SDL_DestroyRenderer(SDL_Renderer * renderer)
{
SDL_RenderCommand *cmd;
SDL_AllocVertGap *gap;
SDL_AllocVertGap *nextgap;

CHECK_RENDERER_MAGIC(renderer, );

Expand All @@ -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;
Expand Down
9 changes: 0 additions & 9 deletions src/render/SDL_sysrender.h
Expand Up @@ -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
Expand Down Expand Up @@ -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;
};
Expand Down

0 comments on commit 69c6924

Please sign in to comment.