azrp: configure shaders automatically
This commit is contained in:
parent
be4e4308cb
commit
fe4b339327
|
@ -44,6 +44,10 @@ AZUR_BEGIN_DECLS
|
|||
* [fragment] is a pointer to azrp_frag. */
|
||||
typedef void azrp_shader_t(void *uniforms, void *command, void *fragment);
|
||||
|
||||
/* azrp_shader_configure_t: Type of shader configuration functions
|
||||
This function is mainly called when fragment settings change. */
|
||||
typedef void azrp_shader_configure_t(void);
|
||||
|
||||
/* Video memory fragment used as rendering target (in XRAM). */
|
||||
extern uint16_t *azrp_frag;
|
||||
|
||||
|
@ -207,15 +211,6 @@ void azrp_triangle(int x1, int y1, int x2, int y2, int x3, int y3, int color);
|
|||
/* See below for more detailed image functions. Dynamic effects are provided
|
||||
with the same naming convention as gint. */
|
||||
|
||||
/* Functions to update uniforms for these shaders. You should call them when:
|
||||
* AZRP_SHADER_CLEAR: Changing super-scaling settings.
|
||||
* AZRP_SHADER_IMAGE_*: Changing super-scaling or or fragment offsets. */
|
||||
void azrp_shader_clear_configure(void);
|
||||
void azrp_shader_image_rgb16_configure(void);
|
||||
void azrp_shader_image_p8_configure(void);
|
||||
void azrp_shader_image_p4_configure(void);
|
||||
void azrp_shader_triangle_configure(void);
|
||||
|
||||
//---
|
||||
// Performance indicators
|
||||
//
|
||||
|
@ -250,13 +245,20 @@ void azrp_perf_clear(void);
|
|||
|
||||
/* azrp_register_shader(): Register a new command type and its shader program
|
||||
|
||||
This function adds the specified shader program to the program array, and
|
||||
returns the corresponding command type. Adding new shaders is useful for
|
||||
specialized rendering options (eg. tiles with fixed size) or new graphical
|
||||
effects.
|
||||
This function registers a new shader program to the program array, along
|
||||
with its configuration function. The configuration function is called
|
||||
immediately upon registration.
|
||||
|
||||
If the maximum number shaders is exceeded, returns -1. */
|
||||
int azrp_register_shader(azrp_shader_t *program);
|
||||
There is often a choice between creating a new shader and generalizing an
|
||||
existing one. The impact is small; the difference only really matters if
|
||||
there is a lot of commands, but in that case command management becomes a
|
||||
stronger bottleneck. The choice should be made for optimal code structure
|
||||
and reuse.
|
||||
|
||||
Returns the shader ID to be set in commands, or -1 if the maximum number of
|
||||
shaders has been exceeded. */
|
||||
int azrp_register_shader(azrp_shader_t *program,
|
||||
azrp_shader_configure_t *configure);
|
||||
|
||||
/* azrp_set_uniforms(): Set a shader's uniforms pointer
|
||||
|
||||
|
|
|
@ -32,9 +32,19 @@ static uint32_t commands_array[AZRP_MAX_COMMANDS];
|
|||
|
||||
static GALIGNED(4) uint8_t commands_data[16384];
|
||||
|
||||
/* Array of shader programs and uniforms. */
|
||||
static azrp_shader_t *shaders[AZRP_MAX_SHADERS] = { NULL };
|
||||
static void *shader_uniforms[AZRP_MAX_SHADERS] = { NULL };
|
||||
/* Shader program information. */
|
||||
typedef struct {
|
||||
/* Rendering function. */
|
||||
azrp_shader_t *shader;
|
||||
/* Uniform parameter. */
|
||||
void *uniform;
|
||||
/* Configuration function (in response to scale, base offset, etc). */
|
||||
azrp_shader_configure_t *configure;
|
||||
|
||||
} shader_info_t;
|
||||
|
||||
/* Array of shader programs. */
|
||||
static shader_info_t shaders[AZRP_MAX_SHADERS] = { 0 };
|
||||
|
||||
/* Next free index in the shader program array. */
|
||||
static uint16_t shaders_next = 0;
|
||||
|
@ -116,9 +126,12 @@ void azrp_render_fragments(void)
|
|||
while(cmd < next_frag_threshold && i < commands_count) {
|
||||
azrp_commands_total++;
|
||||
uint8_t *data = commands_data + (cmd & 0xffff);
|
||||
shader_info_t const *info = &shaders[data[0]];
|
||||
|
||||
prof_enter_norec(azrp_perf_shaders);
|
||||
shaders[data[0]](shader_uniforms[data[0]], data, azrp_frag);
|
||||
info->shader(info->uniform, data, azrp_frag);
|
||||
prof_leave_norec(azrp_perf_shaders);
|
||||
|
||||
cmd = commands_array[++i];
|
||||
}
|
||||
|
||||
|
@ -152,6 +165,14 @@ void azrp_update(void)
|
|||
// Configuration calls
|
||||
//---
|
||||
|
||||
static void reconfigure_all_shaders(void)
|
||||
{
|
||||
for(int i = 0; i < shaders_next; i++) {
|
||||
if(shaders[i].configure)
|
||||
shaders[i].configure();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Use larger fragments in upscales x2 and x3
|
||||
|
||||
static void update_frag_count(void)
|
||||
|
@ -184,6 +205,7 @@ void azrp_config_scale(int scale)
|
|||
azrp_scale = scale;
|
||||
update_size();
|
||||
update_frag_count();
|
||||
reconfigure_all_shaders();
|
||||
}
|
||||
|
||||
void azrp_config_frag_offset(int offset)
|
||||
|
@ -193,9 +215,13 @@ void azrp_config_frag_offset(int offset)
|
|||
|
||||
azrp_frag_offset = offset;
|
||||
update_frag_count();
|
||||
reconfigure_all_shaders();
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
/* Make sure this constructor runs before every shader's registration
|
||||
constructor so we don't configure registered shaders before the settings are
|
||||
initialized. */
|
||||
__attribute__((constructor(101)))
|
||||
static void default_settings(void)
|
||||
{
|
||||
azrp_config_scale(1);
|
||||
|
@ -219,14 +245,19 @@ void azrp_hook_set_prefrag(azrp_hook_prefrag_t *hook)
|
|||
// Custom shaders
|
||||
//---
|
||||
|
||||
int azrp_register_shader(azrp_shader_t *program)
|
||||
int azrp_register_shader(azrp_shader_t *program,
|
||||
azrp_shader_configure_t *configure)
|
||||
{
|
||||
int id = shaders_next;
|
||||
|
||||
if(id >= AZRP_MAX_SHADERS)
|
||||
return -1;
|
||||
|
||||
shaders[shaders_next++] = program;
|
||||
shader_info_t *info = &shaders[id];
|
||||
info->shader = program;
|
||||
info->uniform = NULL;
|
||||
info->configure = configure;
|
||||
shaders_next++;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -234,10 +265,7 @@ void azrp_set_uniforms(int shader_id, void *uniforms)
|
|||
{
|
||||
if((unsigned int)shader_id >= AZRP_MAX_SHADERS)
|
||||
return;
|
||||
if(shaders[shader_id] == NULL)
|
||||
return;
|
||||
|
||||
shader_uniforms[shader_id] = uniforms;
|
||||
shaders[shader_id].uniform = uniforms;
|
||||
}
|
||||
|
||||
bool azrp_queue_command(void *command, size_t size, int fragment, int count)
|
||||
|
|
|
@ -2,17 +2,18 @@
|
|||
|
||||
uint8_t AZRP_SHADER_CLEAR = -1;
|
||||
|
||||
static void configure(void)
|
||||
{
|
||||
int longs_in_fragment = (azrp_width * azrp_frag_height / 2);
|
||||
azrp_set_uniforms(AZRP_SHADER_CLEAR, (void *)longs_in_fragment);
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
static void register_shader(void)
|
||||
{
|
||||
extern azrp_shader_t azrp_shader_clear;
|
||||
AZRP_SHADER_CLEAR = azrp_register_shader(azrp_shader_clear);
|
||||
}
|
||||
|
||||
void azrp_shader_clear_configure(void)
|
||||
{
|
||||
int longs_in_fragment = (azrp_width * azrp_frag_height / 2);
|
||||
azrp_set_uniforms(AZRP_SHADER_CLEAR, (void *)longs_in_fragment);
|
||||
AZRP_SHADER_CLEAR = azrp_register_shader(azrp_shader_clear, configure);
|
||||
configure();
|
||||
}
|
||||
|
||||
//---
|
||||
|
|
|
@ -12,15 +12,16 @@ static void shader_p4(void *uniforms, void *command, void *fragment)
|
|||
cmd->output = fragment + cmd->x * 2;
|
||||
}
|
||||
|
||||
static void configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_IMAGE_P4, (void *)azrp_width);
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
static void register_shader(void)
|
||||
{
|
||||
AZRP_SHADER_IMAGE_P4 = azrp_register_shader(shader_p4);
|
||||
}
|
||||
|
||||
void azrp_shader_image_p4_configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_IMAGE_P4, (void *)azrp_width);
|
||||
AZRP_SHADER_IMAGE_P4 = azrp_register_shader(shader_p4, configure);
|
||||
configure();
|
||||
}
|
||||
|
||||
void azrp_image_p4(int x, int y, image_t const *img, int eff)
|
||||
|
|
|
@ -12,15 +12,16 @@ static void shader_p8(void *uniforms, void *command, void *fragment)
|
|||
cmd->output = fragment + cmd->x * 2;
|
||||
}
|
||||
|
||||
static void configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_IMAGE_P8, (void *)azrp_width);
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
static void register_shader(void)
|
||||
{
|
||||
AZRP_SHADER_IMAGE_P8 = azrp_register_shader(shader_p8);
|
||||
}
|
||||
|
||||
void azrp_shader_image_p8_configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_IMAGE_P8, (void *)azrp_width);
|
||||
AZRP_SHADER_IMAGE_P8 = azrp_register_shader(shader_p8, configure);
|
||||
configure();
|
||||
}
|
||||
|
||||
void azrp_image_p8(int x, int y, image_t const *img, int eff)
|
||||
|
|
|
@ -12,15 +12,16 @@ static void shader_rgb16(void *uniforms, void *command, void *fragment)
|
|||
cmd->output = fragment + cmd->x * 2;
|
||||
}
|
||||
|
||||
static void configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_IMAGE_RGB16, (void *)azrp_width);
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
static void register_shader(void)
|
||||
{
|
||||
AZRP_SHADER_IMAGE_RGB16 = azrp_register_shader(shader_rgb16);
|
||||
}
|
||||
|
||||
void azrp_shader_image_rgb16_configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_IMAGE_RGB16, (void *)azrp_width);
|
||||
AZRP_SHADER_IMAGE_RGB16 = azrp_register_shader(shader_rgb16, configure);
|
||||
configure();
|
||||
}
|
||||
|
||||
void azrp_image_rgb16(int x, int y, image_t const *img, int eff)
|
||||
|
|
|
@ -2,16 +2,18 @@
|
|||
|
||||
uint8_t AZRP_SHADER_TRIANGLE = -1;
|
||||
|
||||
static void configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_TRIANGLE, (void *)azrp_width);
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
static void register_shader(void)
|
||||
{
|
||||
extern azrp_shader_t azrp_shader_triangle;
|
||||
AZRP_SHADER_TRIANGLE = azrp_register_shader(azrp_shader_triangle);
|
||||
}
|
||||
|
||||
void azrp_shader_triangle_configure(void)
|
||||
{
|
||||
azrp_set_uniforms(AZRP_SHADER_TRIANGLE, (void *)azrp_width);
|
||||
AZRP_SHADER_TRIANGLE = azrp_register_shader(azrp_shader_triangle,
|
||||
configure);
|
||||
configure();
|
||||
}
|
||||
|
||||
static int min(int x, int y)
|
||||
|
|
Loading…
Reference in New Issue