move pipelines and texture modes to deferred commands

This commit is contained in:
veclav talica 2024-10-15 18:35:08 +03:00
parent 139394c6de
commit 768daf1f54

View File

@ -118,7 +118,6 @@ typedef struct {
bool textured, texture_repeat; bool textured, texture_repeat;
TextureKey texture; TextureKey texture;
TextureMode texture_mode;
GLuint element_buffer; GLuint element_buffer;
GLsizei element_count; GLsizei element_count;
@ -134,19 +133,6 @@ typedef struct {
} DeferredCommandClear; } DeferredCommandClear;
typedef struct {
enum DeferredCommandType {
DEFERRED_COMMAND_TYPE_DRAW_ELEMENTS,
DEFERRED_COMMAND_TYPE_CLEAR,
} type;
union {
DeferredCommandDrawElements draw_elements;
DeferredCommandClear clear;
};
} DeferredCommand;
typedef enum { typedef enum {
PIPELINE_NO, PIPELINE_NO,
PIPELINE_SPACE, PIPELINE_SPACE,
@ -154,6 +140,33 @@ typedef enum {
} Pipeline; } Pipeline;
typedef struct {
Pipeline pipeline;
} DeferredCommandUsePipeline;
typedef struct {
TextureMode mode;
} DeferredCommandUseTextureMode;
typedef struct {
enum DeferredCommandType {
DEFERRED_COMMAND_TYPE_DRAW_ELEMENTS,
DEFERRED_COMMAND_TYPE_CLEAR,
DEFERRED_COMMAND_TYPE_USE_PIPIELINE,
DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE,
} type;
union {
DeferredCommandDrawElements draw_elements;
DeferredCommandClear clear;
DeferredCommandUsePipeline use_pipeline;
DeferredCommandUseTextureMode use_texture_mode;
};
} DeferredCommand;
static Pipeline pipeline_last_used = PIPELINE_NO; static Pipeline pipeline_last_used = PIPELINE_NO;
@ -165,14 +178,16 @@ static Pipeline pipeline_last_used = PIPELINE_NO;
static size_t scratch_va_front_used, scratch_va_back_used; static size_t scratch_va_front_used, scratch_va_back_used;
static GLuint *front_scratch_vertex_arrays, *back_scratch_vertex_arrays; static GLuint *front_scratch_vertex_arrays, *back_scratch_vertex_arrays;
static GLuint **current_scratch_vertex_array = &front_scratch_vertex_arrays; static GLuint **current_scratch_vertex_array = &front_scratch_vertex_arrays;
static void restart_scratch_vertex_arrays(void) { static void restart_scratch_vertex_arrays(void) {
scratch_va_front_used = 0; scratch_va_front_used = 0;
scratch_va_back_used = 0; scratch_va_back_used = 0;
if (ctx.render_double_buffered) if (ctx.render_double_buffered) {
current_scratch_vertex_array = current_scratch_vertex_array == &front_scratch_vertex_arrays ? current_scratch_vertex_array = current_scratch_vertex_array == &front_scratch_vertex_arrays ?
&back_scratch_vertex_arrays : &front_scratch_vertex_arrays; &back_scratch_vertex_arrays : &front_scratch_vertex_arrays;
} }
}
GLuint get_scratch_vertex_array(void) { GLuint get_scratch_vertex_array(void) {
@ -186,14 +201,17 @@ GLuint get_scratch_vertex_array(void) {
} }
(*used)++; (*used)++;
return (*current_scratch_vertex_array)[arrlenu(*current_scratch_vertex_array) - 1]; return (*current_scratch_vertex_array)[*used - 1];
} }
static DeferredCommand *deferred_commands; static void finally_use_2d_pipeline(void);
static void issue_deferred_draw_commands(void) { static void finally_use_space_pipeline(void);
use_2d_pipeline(); static void finally_use_texture_mode(TextureMode mode);
static DeferredCommand *deferred_commands;
static void issue_deferred_draw_commands(void) {
for (size_t i = 0; i < arrlenu(deferred_commands); ++i) { for (size_t i = 0; i < arrlenu(deferred_commands); ++i) {
switch (deferred_commands[i].type) { switch (deferred_commands[i].type) {
case DEFERRED_COMMAND_TYPE_CLEAR: { case DEFERRED_COMMAND_TYPE_CLEAR: {
@ -230,8 +248,6 @@ static void issue_deferred_draw_commands(void) {
command.vertices.stride, command.vertices.stride,
(void *)command.vertices.offset); (void *)command.vertices.offset);
use_texture_mode(command.texture_mode);
if (command.texcoords.arity != 0) { if (command.texcoords.arity != 0) {
SDL_assert(command.texcoords.buffer == command.vertices.buffer); SDL_assert(command.texcoords.buffer == command.vertices.buffer);
@ -293,6 +309,27 @@ static void issue_deferred_draw_commands(void) {
break; break;
} }
case DEFERRED_COMMAND_TYPE_USE_PIPIELINE: {
switch (deferred_commands[i].use_pipeline.pipeline) {
case PIPELINE_2D:
finally_use_2d_pipeline();
break;
case PIPELINE_SPACE:
finally_use_space_pipeline();
break;
case PIPELINE_NO:
default:
SDL_assert(false);
}
break;
}
case DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE: {
finally_use_texture_mode(deferred_commands[i].use_texture_mode.mode);
break;
}
default: default:
SDL_assert(false); SDL_assert(false);
} }
@ -318,7 +355,6 @@ void clear_draw_buffer(void) {
void start_render_frame(void) { void start_render_frame(void) {
restart_scratch_vertex_arrays();
clear_draw_buffer(); clear_draw_buffer();
} }
@ -328,12 +364,14 @@ void end_render_frame(void) {
issue_deferred_draw_commands(); issue_deferred_draw_commands();
SDL_GL_SwapWindow(ctx.window); SDL_GL_SwapWindow(ctx.window);
arrsetlen(deferred_commands, 0); arrsetlen(deferred_commands, 0);
restart_scratch_vertex_arrays();
} else { } else {
/* instead of waiting for frame to finish for the swap, we continue */ /* instead of waiting for frame to finish for the swap, we continue */
/* while issuing new state for the next call, but deferring any fragment emitting calls for later */ /* while issuing new state for the next call, but deferring any fragment emitting calls for later */
/* actual swap will happen when next frame is fully finished, introducing a delay */ /* actual swap will happen when next frame is fully finished, introducing a delay */
SDL_GL_SwapWindow(ctx.window); SDL_GL_SwapWindow(ctx.window);
issue_deferred_draw_commands(); issue_deferred_draw_commands();
restart_scratch_vertex_arrays();
glFlush(); glFlush();
arrsetlen(deferred_commands, 0); arrsetlen(deferred_commands, 0);
} }
@ -341,6 +379,16 @@ void end_render_frame(void) {
void use_space_pipeline(void) { void use_space_pipeline(void) {
DeferredCommand const command = {
.type = DEFERRED_COMMAND_TYPE_USE_PIPIELINE,
.use_pipeline = { PIPELINE_SPACE }
};
arrpush(deferred_commands, command);
}
static void finally_use_space_pipeline(void) {
if (pipeline_last_used == PIPELINE_SPACE) if (pipeline_last_used == PIPELINE_SPACE)
return; return;
@ -378,6 +426,16 @@ void use_space_pipeline(void) {
void use_2d_pipeline(void) { void use_2d_pipeline(void) {
DeferredCommand const command = {
.type = DEFERRED_COMMAND_TYPE_USE_PIPIELINE,
.use_pipeline = { PIPELINE_2D }
};
arrpush(deferred_commands, command);
}
static void finally_use_2d_pipeline(void) {
if (pipeline_last_used == PIPELINE_SPACE) { if (pipeline_last_used == PIPELINE_SPACE) {
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glFlush(); glFlush();
@ -453,6 +511,16 @@ void render_circle(const CirclePrimitive *circle) {
void use_texture_mode(TextureMode mode) { void use_texture_mode(TextureMode mode) {
DeferredCommand const command = {
.type = DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE,
.use_texture_mode = { mode }
};
arrpush(deferred_commands, command);
}
static void finally_use_texture_mode(TextureMode mode) {
static GLuint lists = 0; static GLuint lists = 0;
if (!lists) { if (!lists) {
lists = glGenLists(3); lists = glGenLists(3);
@ -596,7 +664,7 @@ void finally_render_quads(const Primitive2D primitives[],
command.element_count = 6 * (GLsizei)batch.size; command.element_count = 6 * (GLsizei)batch.size;
command.range_end = 6 * (GLsizei)batch.size; command.range_end = 6 * (GLsizei)batch.size;
command.texture_mode = batch.mode; use_texture_mode(batch.mode);
DeferredCommand final_command = { DeferredCommand final_command = {
.type = DEFERRED_COMMAND_TYPE_DRAW_ELEMENTS, .type = DEFERRED_COMMAND_TYPE_DRAW_ELEMENTS,