replace per-tick allocations in push_text with an arena/bump allocator
This commit is contained in:
parent
0481962859
commit
078e68387b
@ -37,13 +37,8 @@ static void title_tick(State *state) {
|
|||||||
},
|
},
|
||||||
(Color) { 0, 0, 0, 255 }
|
(Color) { 0, 0, 0, 255 }
|
||||||
);
|
);
|
||||||
push_text(
|
push_text(text_str, (Vec2){ 0, 0 }, text_h, (Color) { 255, 255, 255, 255 }, font);
|
||||||
text_str,
|
|
||||||
(Vec2){ 0, 0 },
|
|
||||||
text_h,
|
|
||||||
(Color) { 255, 255, 255, 255 },
|
|
||||||
font
|
|
||||||
);
|
|
||||||
free(text_str);
|
free(text_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,13 +22,7 @@ Matrix4 camera_look_at_matrix;
|
|||||||
|
|
||||||
|
|
||||||
void render_queue_clear(void) {
|
void render_queue_clear(void) {
|
||||||
/* this doesn't even _deserve_ a TODO */
|
text_cache_reset_arena(&ctx.text_cache);
|
||||||
/* if you're gonna remove it, this is also being done in main.c */
|
|
||||||
for (size_t i = 0; i < arrlenu(ctx.render_queue_2d); ++i) {
|
|
||||||
if (ctx.render_queue_2d[i].type == PRIMITIVE_2D_TEXT) {
|
|
||||||
SDL_free(ctx.render_queue_2d[i].text.text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* since i don't intend to free the queues, */
|
/* since i don't intend to free the queues, */
|
||||||
/* it's faster and simpler to just "start over" */
|
/* it's faster and simpler to just "start over" */
|
||||||
|
@ -154,6 +154,8 @@ void text_cache_init(TextCache *cache);
|
|||||||
|
|
||||||
void text_cache_deinit(TextCache *cache);
|
void text_cache_deinit(TextCache *cache);
|
||||||
|
|
||||||
|
void text_cache_reset_arena(TextCache *cache);
|
||||||
|
|
||||||
/* vertex buffer */
|
/* vertex buffer */
|
||||||
|
|
||||||
VertexBuffer create_vertex_buffer(void);
|
VertexBuffer create_vertex_buffer(void);
|
||||||
|
@ -11,6 +11,88 @@
|
|||||||
#define ASCII_END 128
|
#define ASCII_END 128
|
||||||
#define NUM_DISPLAY_ASCII ((ASCII_END - ASCII_START) + 1)
|
#define NUM_DISPLAY_ASCII ((ASCII_END - ASCII_START) + 1)
|
||||||
|
|
||||||
|
/* should be large enough that there's virtually never more than one block */
|
||||||
|
#define STRING_ARENA_BLOCK_SIZE 512000
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct StringArenaBlock {
|
||||||
|
struct StringArenaBlock *next;
|
||||||
|
char *buffer;
|
||||||
|
size_t used;
|
||||||
|
} StringArenaBlock;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct StringArena {
|
||||||
|
StringArenaBlock *head;
|
||||||
|
StringArenaBlock *current_block;
|
||||||
|
char *ptr;
|
||||||
|
} StringArena;
|
||||||
|
|
||||||
|
static StringArena string_arena;
|
||||||
|
|
||||||
|
|
||||||
|
static void string_arena_init(StringArena *arena) {
|
||||||
|
arena->head = cmalloc(sizeof *arena->head);
|
||||||
|
arena->current_block = arena->head;
|
||||||
|
arena->ptr = arena->current_block->buffer;
|
||||||
|
|
||||||
|
arena->current_block->next = NULL;
|
||||||
|
arena->current_block->buffer = cmalloc(STRING_ARENA_BLOCK_SIZE);
|
||||||
|
arena->current_block->used = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void string_arena_deinit(StringArena *arena) {
|
||||||
|
StringArenaBlock *p = arena->head;
|
||||||
|
while (p != NULL) {
|
||||||
|
StringArenaBlock *block = p;
|
||||||
|
p = block->next; /* need to keep this before freeing */
|
||||||
|
|
||||||
|
SDL_free(block->buffer);
|
||||||
|
SDL_free(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void string_arena_reset(StringArena *arena) {
|
||||||
|
arena->current_block = arena->head;
|
||||||
|
arena->current_block->used = 0;
|
||||||
|
arena->ptr = arena->current_block->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *string_arena_alloc(StringArena *arena, size_t size) {
|
||||||
|
/* will never fit! */
|
||||||
|
if (size > STRING_ARENA_BLOCK_SIZE) {
|
||||||
|
/* is there a more graceful way to handle this without risking some sort of horror? */
|
||||||
|
CRY("String arena allocation failure", "Tried to allocate a size larger than the block size");
|
||||||
|
die_abruptly();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* won't fit, we need a new block first */
|
||||||
|
if (arena->current_block->used + size > STRING_ARENA_BLOCK_SIZE) {
|
||||||
|
log_info("String arena block size exceeded, moving on to the next...");
|
||||||
|
|
||||||
|
/* only allocate if there wasn't one ready to go already */
|
||||||
|
if (arena->current_block->next == NULL) {
|
||||||
|
log_info("Allocating string arena block...");
|
||||||
|
|
||||||
|
arena->current_block->next = cmalloc(sizeof *arena->head);
|
||||||
|
arena->current_block->next->next = NULL;
|
||||||
|
arena->current_block->next->buffer = cmalloc(STRING_ARENA_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
arena->current_block = arena->current_block->next;
|
||||||
|
arena->current_block->used = 0;
|
||||||
|
arena->ptr = arena->current_block->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *chunk = arena->ptr;
|
||||||
|
arena->ptr += size;
|
||||||
|
arena->current_block->used += size * (sizeof *arena->ptr);
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static FontData *text_load_font_data(const char *path, int height_px) {
|
static FontData *text_load_font_data(const char *path, int height_px) {
|
||||||
FontData *font_data = ccalloc(1, sizeof *font_data);
|
FontData *font_data = ccalloc(1, sizeof *font_data);
|
||||||
@ -146,6 +228,7 @@ void render_text(const TextPrimitive *text) {
|
|||||||
|
|
||||||
void text_cache_init(TextCache *cache) {
|
void text_cache_init(TextCache *cache) {
|
||||||
arrsetlen(cache->data, 0);
|
arrsetlen(cache->data, 0);
|
||||||
|
string_arena_init(&string_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -155,6 +238,13 @@ void text_cache_deinit(TextCache *cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
arrfree(cache->data);
|
arrfree(cache->data);
|
||||||
|
string_arena_deinit(&string_arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void text_cache_reset_arena(TextCache *cache) {
|
||||||
|
(void)cache;
|
||||||
|
string_arena_reset(&string_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -162,8 +252,9 @@ void push_text(char *string, Vec2 position, int height_px, Color color, const ch
|
|||||||
ensure_font_cache(font_path, height_px);
|
ensure_font_cache(font_path, height_px);
|
||||||
|
|
||||||
/* the original string might not be around by the time it's used, so copy it */
|
/* the original string might not be around by the time it's used, so copy it */
|
||||||
/* TODO: arena */
|
size_t str_length = SDL_strlen(string) + 1;
|
||||||
char *dup_string = SDL_strdup(string);
|
char *dup_string = string_arena_alloc(&string_arena, str_length);
|
||||||
|
SDL_strlcpy(dup_string, string, str_length);
|
||||||
|
|
||||||
TextPrimitive text = {
|
TextPrimitive text = {
|
||||||
.color = color,
|
.color = color,
|
||||||
|
@ -371,19 +371,12 @@ static void clean_up(void) {
|
|||||||
scripting_deinit(ctx);
|
scripting_deinit(ctx);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
input_state_deinit(&ctx.game.input);
|
input_state_deinit(&ctx.game.input);
|
||||||
|
|
||||||
/* if you're gonna remove this, it's also being done in rendering.c */
|
|
||||||
for (size_t i = 0; i < arrlenu(ctx.render_queue_2d); ++i) {
|
|
||||||
if (ctx.render_queue_2d[i].type == PRIMITIVE_2D_TEXT) {
|
|
||||||
SDL_free(ctx.render_queue_2d[i].text.text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arrfree(ctx.render_queue_2d);
|
|
||||||
|
|
||||||
text_cache_deinit(&ctx.text_cache);
|
text_cache_deinit(&ctx.text_cache);
|
||||||
textures_cache_deinit(&ctx.texture_cache);
|
textures_cache_deinit(&ctx.texture_cache);
|
||||||
|
|
||||||
|
arrfree(ctx.render_queue_2d);
|
||||||
|
|
||||||
PHYSFS_deinit();
|
PHYSFS_deinit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user