184 lines
6.4 KiB
C
184 lines
6.4 KiB
C
//---
|
|
// azur.render: Specialized rendering pipeline for fx-CG gint
|
|
//
|
|
// On-chip ILRAM and DSP memory bring out the full power of the SH4AL-DSP.
|
|
// Therefore, optimal performance in a game's renderer will rely on using on-
|
|
// chip memory instead of standard RAM for graphics data.
|
|
//
|
|
// The obvious limitation of on-chip memory is its size (20 kiB total), which
|
|
// is much smaller than a full-resolution image (~177 kiB). This prompts for a
|
|
// technique known as "frame streaming", where fragments (strips of VRAM) of
|
|
// each frame are rendered and transferred to the display in sequence.
|
|
// Reasonable efficiency and suitable display driver settings can prevent
|
|
// tearing even though data is not being sent continuously.
|
|
//
|
|
// The main components of this rendering pipeline are the command queue and
|
|
// fragment shaders.
|
|
//
|
|
// The command queue stores all rendering commands, split into fragments. Each
|
|
// fragment needs to read through all commands to produce its output, and
|
|
// because fragments are rendered in order, the sequence of commands must be
|
|
// read several times, therefore stored.
|
|
//
|
|
// Fragment shaders are the programs that render commands into graphics data
|
|
// for each fragments. They are pretty similar to OpenGL shaders, in that they
|
|
// receive vectors of objects (command parameters) and produce graphics data to
|
|
// fragments (even though each fragment is a strip of VRAM, not a pixel), hence
|
|
// the name.
|
|
//
|
|
// The prefix for this module is [azrp] for "azur rendering pipeline".
|
|
//---
|
|
|
|
#pragma once
|
|
#include <azur/defs.h>
|
|
AZUR_BEGIN_DECLS
|
|
|
|
#include <gint/defs/types.h>
|
|
#include <gint/display.h>
|
|
|
|
#include <libprof.h>
|
|
|
|
/* arzp_shader_t: Type of shader functions
|
|
* [uniforms] is a pointer to any data the shader might use as uniform.
|
|
* [command] is a structure of the shader's command type. */
|
|
typedef void azrp_shader_t(void *uniforms, void *command);
|
|
|
|
/* Video memory fragment used as rendering target (in XRAM). */
|
|
extern uint16_t azrp_frag[];
|
|
|
|
/* Maximum number of commands that can be queued. (This is only one of two
|
|
limits, the other being the size of the command data.) */
|
|
#define AZRP_MAX_COMMANDS 512
|
|
|
|
/* Maximum number of shaders that can be defined. (This is a loose limit). */
|
|
#define AZRP_MAX_SHADERS 32
|
|
|
|
//---
|
|
// High and low-level pipeline functions
|
|
//
|
|
// The process of rendering a frame with azrp has four steps:
|
|
// 1. Clear the command queue
|
|
// 2. Queue commands with command generation functions
|
|
// 3. Sort the command queue
|
|
// 4. Render fragments in on-chip memory and send them to the display driver
|
|
//
|
|
// The command queue is empty when the program starts. The azrp_update()
|
|
// performs steps 3 and 4, rendering a frame; then clears the command queue
|
|
// again. Therefore, azrp_update() can be used more or less like dupdate().
|
|
//
|
|
// Functions for command generation are listed in the shader API below, and can
|
|
// be extended with custom shaders.
|
|
//
|
|
// Applications that want to render the same frame several time such as to
|
|
// save screenshots, or reuse commands, or add new commands and use the
|
|
// already-sorted base, can use the low-level functions below which implement
|
|
// steps 1, 3 and 4 individually.
|
|
//---
|
|
|
|
/* azrp_update(): Sort commands, render a frame, and starts another one */
|
|
void azrp_update(void);
|
|
|
|
/* azrp_clear_commands(): Clear the command queue (step 1) */
|
|
void azrp_clear_commands(void);
|
|
|
|
/* azrp_sort_commands(): Sort the command queue (step 3) */
|
|
void azrp_sort_commands(void);
|
|
|
|
/* azrp_render_fragments(): Render and send fragments to the dislay (step 4) */
|
|
void azrp_render_fragments(void);
|
|
|
|
//---
|
|
// Standard shaders
|
|
//---
|
|
|
|
enum {
|
|
/* Clears the entire output with a single color */
|
|
AZRP_SHADER_CLEAR = 0,
|
|
/* Renders RGB565 textures/images */
|
|
AZRP_SHADER_TEX2D,
|
|
|
|
/* First user-attributable ID */
|
|
AZRP_SHADER_USER,
|
|
};
|
|
|
|
/* azrp_clear(): Clear output [ARZP_SHADER_CLEAR] */
|
|
void azrp_clear(uint16_t color);
|
|
|
|
/* azrp_image(): Queue image command [AZRP_SHADER_TEX2D] */
|
|
void azrp_image(int x, int y, uint16_t *pixels, int w, int h, int stride);
|
|
|
|
//---
|
|
// Performance indicators
|
|
//
|
|
// The following performance counters are run through by the rendering module
|
|
// in most stages of the rendering process. The module updates them but doesn't
|
|
// use them, so they are safe to write to and reset when they're not running.
|
|
//---
|
|
|
|
/* This counter runs during command generation and enqueue operations, usually
|
|
between azrp_begin_frame() and azrp_render_frame(). */
|
|
extern prof_t azrp_perf_cmdgen;
|
|
|
|
/* This counter runs during the command sorting step, which occurs at the start
|
|
of azrp_render_frame(). */
|
|
extern prof_t azrp_perf_sort;
|
|
|
|
/* This counter runs during shader executions in arzp_render_frame(). */
|
|
extern prof_t azrp_perf_shaders;
|
|
|
|
/* This counter runs during CPU transfers to the R61524 display. */
|
|
extern prof_t azrp_perf_r61524;
|
|
|
|
/* This counter runs during the whole azrp_frame_render() operation; it is the
|
|
sum of sort, shaders, r61524, plus some logic overhead. */
|
|
extern prof_t azrp_perf_render;
|
|
|
|
/* azrp_perf_clear(): Clear all performance counters
|
|
Generally you want to do this before azrp_frame_begin(). */
|
|
void azrp_perf_clear(void);
|
|
|
|
//---
|
|
// Definitions for custom shaders
|
|
//---
|
|
|
|
/* 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 (which is AZRP_SHADER_USER plus some
|
|
value). Adding new shaders is useful for specialized rendering options (eg.
|
|
tiles with fixed size) or new graphical effects.
|
|
|
|
If the maximum number shaders is exceeded, returns -1. */
|
|
int azrp_register_shader(azrp_shader_t *program);
|
|
|
|
/* azrp_queue_command(): Add a new command to be rendered next frame
|
|
|
|
The command must be a structure starting with an 8-bit shader ID and an
|
|
8-bit fragment ID.
|
|
|
|
Returns true on success, false if the maximum amount of commands or command
|
|
memory is exceeded. */
|
|
bool azrp_queue_command(void *command, size_t size);
|
|
|
|
//---
|
|
// Internal shader definitions (for reference; no API guarantee)
|
|
//---
|
|
|
|
struct azrp_shader_tex2d_command {
|
|
/* Shader ID and fragment number */
|
|
uint8_t shader_id;
|
|
uint8_t fragment_id;
|
|
/* Pixels per line */
|
|
int16_t columns;
|
|
/* Already offset by start row and column */
|
|
void *input;
|
|
/* Destination in XRAM */
|
|
void *output;
|
|
/* Number of lines */
|
|
int16_t lines;
|
|
/* Distance between two lines (columns excluded) */
|
|
int16_t stride;
|
|
};
|
|
|
|
AZUR_END_DECLS
|