RDPQ: Hardware-accelerated drawing API

Interface to the RDP (graphics hardware) for 2D/3D rasterization. More...


file  rdpq.h
 RDP Command queue.
file  rdpq_rect.h
 RDP Command queue.
file  rdpq_sprite.h
 RDP Command queue: high-level sprite loading and blitting.
file  rdpq_tex.h
 RDP Command queue: high-level texture/surface loading and blitting.
file  rdpq.h
 RDP Command queue.

Detailed Description

Interface to the RDP (graphics hardware) for 2D/3D rasterization.

The RDPQ ("RDP command queue") is a library that allows to interface with the RDP ("Reality Display Processor"), the GPU on the N64, through the RSP.

This library is quite vast because RDP is a complex chip to program and full of quirks. Moreover, the needs for 2D vs 3D are quite different, and the library copes with both. An important effort has been made to make this library "just work".

Since the API is wide, the library is split in several header files. Make sure to read them all to have a general overview:

Goals of this library

This library is meant to be used directly for two tasks:

For a full 3D project, libdragon offers a full 3D API via the OpenGL API (see gl.h); OpenGL internally uses rdpq, but it is unlikely that you will need to call rdpq directly when you are using OpenGL.

Architecture and rationale

Normally, RDP commands are generated by both the CPU and the RSP. The normal split is that CPU is in charge of render mode changes (eg: loading textures, defining the alpha blending behavior, etc.), while the RSP executes a full T&L pipeline which terminates with the generation of RDP triangle primitives.

This library allows the CPU to enqueue RDP commands. It covers the full RDP command set, including triangles. Even if for RDP commands generated by CPU, the RSP is involved: in fact, this library is a rspq overlay (see rspq.h). All RDP commands are enqueued in the main RSP command queue, and they are sent to the RDP by the RSP.

There are two main reasons for this design (rather than letting the CPU directly send the commands to the RDP):

The documentation of the public API of this library describes the final behavior of each rdpq command, without explicitly mentioning whether it is obtained via fixups or not. For more information on these, see the documentation of rdpq.c, which gives an overview of many implementation details.

Render modes

The most complicated part of programming RDP is getting the correct render mode configuration. At the lowest level (hardware commands), this can be done via two functions: rdpq_set_other_modes_raw (that maps to the RDP command SET_OTHER_MODES, usually shortened as "SOM") and rdpq_set_combiner_raw (that maps to the RDP command SET_COMBINE). These functions are meant for programmers already familiar with the RDP hardware, and allow you to manipulate configurations freely.

To help with partial SOM changes, rdpq also offers rdpq_change_other_modes_raw that allows to change only some bits of the SOM state. This is done by tracking the current SOM state (within the RSP) so that a partial update can be sent. It is useful to make programming more modular, so that for instance a portion of code can temporarily enable (eg.) fogging, without having to restate the full render mode.

Alternatively, rdpq offers a higher level render mode API, which is hopefully clearer to understand and more accessible, that tries to hide some of the most common pitfalls. This API can be found in the rdpq_mode.h file. It is possible to switch from this the higher level API to the lower level one at any time in the code with no overhead, so that it can be adopted wherever it is a good fit, falling back to lower level programming if/when necessary.

Beginners of RDP programming are strongly encouraged to use rdpq_mode.h, and only later dive into lower-level RDP programming, if necessary.

Blocks and address lookups

Being a RSPQ overlay, it is possible to record rdpq commands in blocks (via rspq_block_begin / rspq_block_end, like for any other overlay), to quickly replay them with zero CPU time.

rdpq has also some special memory-bandwidth optimizations that are used when commands are compiled into blocks (for more details, see documentation of rdpq.c). In general, it is advised to use blocks whenever possible, especially in case of a sequence of 3 or more rdpq function calls.


Debugging: tracer and validator

To help writing correct code, rdpq comes with two very important features:

To initialize the debugging engine, call rdpq_debug_start just after rdpq_init (or as early as possible). This will start intercepting and validating all commands sent to RDP, showing validation errors on the debug spew.

To see a log of RDP commands, call rdpq_debug_log passing true or false. You can activate/deactivate logging around portions of code that you want to analyze, as keeping the log active for a whole frame can produce too many information.