Azur/azur/include/azur/gint/render.h

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