mirror of https://github.com/encounter/SDL.git
render: simplify vertex and uniform data allocation. Improves performance of various SDL_Render functions (bug #4764).
This commit is contained in:
parent
e5acccc7c3
commit
69c6924ccc
|
@ -202,8 +202,6 @@ DebugLogRenderCommands(const SDL_RenderCommand *cmd)
|
||||||
static int
|
static int
|
||||||
FlushRenderCommands(SDL_Renderer *renderer)
|
FlushRenderCommands(SDL_Renderer *renderer)
|
||||||
{
|
{
|
||||||
SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps;
|
|
||||||
SDL_AllocVertGap *gap = prevgap;
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL));
|
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);
|
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. */
|
/* Move the whole render command queue to the unused pool so we can reuse them next time. */
|
||||||
if (renderer->render_commands_tail != NULL) {
|
if (renderer->render_commands_tail != NULL) {
|
||||||
renderer->render_commands_tail->next = renderer->render_commands_pool;
|
renderer->render_commands_tail->next = renderer->render_commands_pool;
|
||||||
|
@ -263,79 +253,23 @@ SDL_RenderFlush(SDL_Renderer * renderer)
|
||||||
return FlushRenderCommands(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 *
|
void *
|
||||||
SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
|
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;
|
const size_t needed = renderer->vertex_data_used + numbytes + alignment;
|
||||||
size_t aligner, aligned;
|
size_t current_offset = renderer->vertex_data_used;
|
||||||
void *retval;
|
|
||||||
|
|
||||||
SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps;
|
size_t aligner = (alignment && ((current_offset & (alignment - 1)) != 0)) ? (alignment - (current_offset & (alignment - 1))) : 0;
|
||||||
SDL_AllocVertGap *gap = prevgap->next;
|
size_t aligned = current_offset + aligner;
|
||||||
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 (renderer->vertex_data_allocation < needed) {
|
||||||
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) {
|
|
||||||
const size_t current_allocation = renderer->vertex_data ? renderer->vertex_data_allocation : 1024;
|
const size_t current_allocation = renderer->vertex_data ? renderer->vertex_data_allocation : 1024;
|
||||||
const size_t newsize = current_allocation * 2;
|
size_t newsize = current_allocation * 2;
|
||||||
void *ptr = SDL_realloc(renderer->vertex_data, newsize);
|
void *ptr;
|
||||||
|
while (newsize < needed) {
|
||||||
|
newsize *= 2;
|
||||||
|
}
|
||||||
|
ptr = SDL_realloc(renderer->vertex_data, newsize);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -344,27 +278,13 @@ SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const
|
||||||
renderer->vertex_data_allocation = newsize;
|
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) {
|
if (offset) {
|
||||||
*offset = aligned;
|
*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;
|
renderer->vertex_data_used += aligner + numbytes;
|
||||||
|
|
||||||
return retval;
|
return ((Uint8 *) renderer->vertex_data) + aligned;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_RenderCommand *
|
static SDL_RenderCommand *
|
||||||
|
@ -3177,8 +3097,6 @@ void
|
||||||
SDL_DestroyRenderer(SDL_Renderer * renderer)
|
SDL_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
SDL_RenderCommand *cmd;
|
SDL_RenderCommand *cmd;
|
||||||
SDL_AllocVertGap *gap;
|
|
||||||
SDL_AllocVertGap *nextgap;
|
|
||||||
|
|
||||||
CHECK_RENDERER_MAGIC(renderer, );
|
CHECK_RENDERER_MAGIC(renderer, );
|
||||||
|
|
||||||
|
@ -3203,16 +3121,6 @@ SDL_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
|
|
||||||
SDL_free(renderer->vertex_data);
|
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 */
|
/* Free existing textures for this renderer */
|
||||||
while (renderer->textures) {
|
while (renderer->textures) {
|
||||||
SDL_Texture *tex = renderer->textures; (void) tex;
|
SDL_Texture *tex = renderer->textures; (void) tex;
|
||||||
|
|
|
@ -110,13 +110,6 @@ typedef struct SDL_RenderCommand
|
||||||
struct SDL_RenderCommand *next;
|
struct SDL_RenderCommand *next;
|
||||||
} SDL_RenderCommand;
|
} SDL_RenderCommand;
|
||||||
|
|
||||||
typedef struct SDL_AllocVertGap
|
|
||||||
{
|
|
||||||
size_t offset;
|
|
||||||
size_t len;
|
|
||||||
struct SDL_AllocVertGap *next;
|
|
||||||
} SDL_AllocVertGap;
|
|
||||||
|
|
||||||
|
|
||||||
/* Define the SDL renderer structure */
|
/* Define the SDL renderer structure */
|
||||||
struct SDL_Renderer
|
struct SDL_Renderer
|
||||||
|
@ -226,8 +219,6 @@ struct SDL_Renderer
|
||||||
void *vertex_data;
|
void *vertex_data;
|
||||||
size_t vertex_data_used;
|
size_t vertex_data_used;
|
||||||
size_t vertex_data_allocation;
|
size_t vertex_data_allocation;
|
||||||
SDL_AllocVertGap vertex_data_gaps;
|
|
||||||
SDL_AllocVertGap *vertex_data_gaps_pool;
|
|
||||||
|
|
||||||
void *driverdata;
|
void *driverdata;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue