libdragon
Data Structures | Macros | Functions | Variables
rdpq_internal.h File Reference

RDP Command queue: internal functions. More...

Go to the source code of this file.

Data Structures

struct  rdpq_tracking_t
 RDP tracking state. More...
 
struct  rdpq_block_t
 A buffer that piggybacks onto rspq_block_t to store RDP commands. More...
 
struct  rdpq_block_state_t
 RDP block management state. More...
 

Macros

#define rdpq_passthrough_write(rdp_cmd)
 Write a passthrough RDP command into the rspq queue. More...
 

Functions

void rdpq_fence (void)
 Public rdpq_fence API, redefined it.
 
void __rdpq_block_begin ()
 Initialize RDP block mangament. More...
 
rdpq_block_t__rdpq_block_end ()
 Finish creation of a RDP block. More...
 
void __rdpq_block_free (rdpq_block_t *block)
 Free a block. More...
 
void __rdpq_block_run (rdpq_block_t *block)
 Run a block (called by rspq_block_run).
 
void __rdpq_block_next_buffer (void)
 Allocate a new RDP block buffer, chaining it to the current one (if any) More...
 
void __rdpq_block_update (volatile uint32_t *wptr)
 Set a new RDP write pointer, and enqueue a RSP command to run the buffer until there. More...
 
void __rdpq_block_reserve (int num_rdp_commands)
 Reserve space in the RDP static buffer for a number of RDP commands. More...
 
void __rdpq_autosync_use (uint32_t res)
 Autosync engine: mark certain resources as in use.
 
void __rdpq_autosync_change (uint32_t res)
 Autosync engine: mark certain resources as being changed. More...
 
void __rdpq_write8 (uint32_t cmd_id, uint32_t arg0, uint32_t arg1)
 Write a standard 8-byte RDP command.
 
void __rdpq_write16 (uint32_t cmd_id, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3)
 Write a standard 16-byte RDP command

 
void rdpq_triangle_cpu (const rdpq_trifmt_t *fmt, const float *v1, const float *v2, const float *v3)
 RDP triangle primitive assembled on the CPU.
 
void rdpq_triangle_rsp (const rdpq_trifmt_t *fmt, const float *v1, const float *v2, const float *v3)
 RDP triangle primitive assembled on the RSP.
 

Variables

bool __rdpq_inited
 True if the rdpq module was inited. More...
 
rdpq_tracking_t rdpq_tracking
 Tracking state of RDP.
 

Detailed Description

RDP Command queue: internal functions.


Data Structure Documentation

◆ rdpq_tracking_t

struct rdpq_tracking_t

RDP tracking state.

This structure contains information that refer to the state of the RDP, tracked by the CPU as it enqueues RDP instructions.ì

Tracking the RDP state on the CPU is in general possible (as all RDP commands are supposed to go through rdpq, when it is used), but it doesn't fully work across blocks. In fact, blocks can be called in multiple call sites with different RDP states, so it would be wrong to do any assumption on the RDP state while generating the block.

Thus, this structure is reset at some default by __rdpq_block_begin, and then its previous state is restored by __rdpq_block_end.

Data Fields
uint32_t autosync: 17 State of the autosync engine.

The state of the autosync engine is a 32-bit word, where bits are mapped to specific internal resources of the RDP that might be in use. The mapping of the bits is indicated by the AUTOSYNC_TILE, AUTOSYNC_TMEM, and AUTOSYNC_PIPE

When a bit is set to 1, the corresponding resource is "in use" by the RDP. For instance, drawing a textured rectangle can use a tile and the pipe (which contains most of the mode registers).

bool mode_freeze: 1 True if the mode changes are currently frozen.
uint8_t cycle_type_known: 2 0=unknown, 1=standard, 2=copy/fill
uint8_t cycle_type_frozen: 2

◆ rdpq_block_t

struct rdpq_block_t

A buffer that piggybacks onto rspq_block_t to store RDP commands.

In rspq blocks, raw RDP commands are not stored as passthroughs for performance. Instead, they are stored in a parallel buffer in RDRAM and the RSP block contains commands to send (portions of) this buffer directly to RDP via DMA. This saves memory bandwidth compared to doing passthrough for every command.

Since the buffer can grow during creation, it is stored as a linked list of buffers.

Data Fields
rdpq_block_t * next Link to next buffer (or NULL if this is the last one for this block)
rdpq_tracking_t tracking Tracking state at the end of a block (this is populated only on the first link)
uint32_t cmds[] RDP commands.

◆ rdpq_block_state_t

struct rdpq_block_state_t

RDP block management state.

This is the internal state used by rdpq.c to manage block creation.

Data Fields
volatile uint32_t * wptr During block creation, current write pointer within the RDP buffer.
volatile uint32_t * wend During block creation, pointer to the end of the RDP buffer.
volatile uint32_t * pending_wptr Previous wptr, swapped out to go back to dynamic buffer.
volatile uint32_t * pending_wend Previous wend, swapped out to go back to dynamic buffer.
rdpq_block_t * last_node Point to the RDP block being created.
rdpq_block_t * first_node Point to the first link of the RDP block being created.
int bufsize Current buffer size for RDP blocks.
volatile uint32_t * last_rdp_append_buffer

During block creation, this variable points to the last RSPQ_CMD_RDP_APPEND_BUFFER command, that can be coalesced in case a pure RDP command is enqueued next.

rdpq_tracking_t previous_tracking Tracking state before starting building the block.

Macro Definition Documentation

◆ rdpq_passthrough_write

#define rdpq_passthrough_write (   rdp_cmd)

Write a passthrough RDP command into the rspq queue.

This macro handles writing a single RDP command into the rspq queue. It must be used only with raw commands aka passthroughs, that is commands that are not intercepted by RSP in any way, but just forwarded to RDP.

In block mode, the RDP command will be written to the static RDP buffer instead, so that it will be sent directly to RDP without going through RSP at all.

Example syntax (notice the double parenthesis):

rdpq_passthrough_write((RDPQ_CMD_SYNC_PIPE, 0, 0));

Function Documentation

◆ __rdpq_block_begin()

void __rdpq_block_begin ( )

Initialize RDP block mangament.

This is called by rspq_block_begin. It resets all the block management state to default.

Notice that no allocation is performed. This is because we do block allocation lazily as soon as a rdpq command is issued. In fact, if the block does not contain rdpq commands, it would be a waste of time and memory to allocate a RDP buffer. The allocations will be performed by __rdpq_block_next_buffer as soon as a rdpq command is written.

See also
rspq_block_begin
__rdpq_block_next_buffer

◆ __rdpq_block_end()

rdpq_block_t * __rdpq_block_end ( )

Finish creation of a RDP block.

This is called by rspq_block_end. It finalizes block creation and return a pointer to the first node of the block, which will be put within the rspq_block_t structure, so to be able to reference it in __rdpq_block_run and __rdpq_block_free.

Returns
rdpq_block_t* The created block (first node)
See also
rspq_block_end
__rdpq_block_run
__rdpq_block_free

◆ __rdpq_block_free()

void __rdpq_block_free ( rdpq_block_t block)

Free a block.

This function is called when a block is freed. It is called by rspq_block_free.

See also
rspq_block_free.

◆ __rdpq_block_next_buffer()

void __rdpq_block_next_buffer ( void  )

Allocate a new RDP block buffer, chaining it to the current one (if any)

This function is called by rdpq_passthrough_write and rdpq_write when we are about to write a rdpq command in a block, and the current RDP buffer is full (wptr + cmdsize >= wend). By extension, it is also called when the current RDP buffer has not been allocated yet (wptr == wend == NULL).

See also
rdpq_write
rdpq_passthrough_write

◆ __rdpq_block_update()

void __rdpq_block_update ( volatile uint32_t *  wptr)

Set a new RDP write pointer, and enqueue a RSP command to run the buffer until there.

This function is called by rdpq_passthrough_write after some RDP commands have been written into the block's RDP buffer. A rspq command RSPQ_CMD_RDP_APPEND_BUFFER will be issued so that the RSP will tell the RDP to fetch and run the new commands, appended at the end of the current buffer.

If possible, though, this function will coalesce the command with an immediately preceding RSPQ_CMD_RDP_APPEND_BUFFER (or even RSPQ_CMD_RDP_SET_BUFFER, if we are at the start of the buffer), so that only a single RSP command is issued, which covers multiple RDP commands.

Parameters
wptrNew block's RDP write pointer

◆ __rdpq_block_reserve()

void __rdpq_block_reserve ( int  num_rdp_commands)

Reserve space in the RDP static buffer for a number of RDP commands.

This is called by rdpq_write when run within a block. It makes sure that the static buffer has enough space for the specified number of RDP commands, and also switch back to the dynamic buffer if the command is going to generate a large or unbounded number of commands.

◆ __rdpq_autosync_change()

void __rdpq_autosync_change ( uint32_t  res)

Autosync engine: mark certain resources as being changed.

This is the core of the autosync engine. Whenever a resource is "changed" while "in use", a SYNC command must be issued. This is a slightly conservative approach, as the RDP might already have finished using that resource, but we have no way to know it. The SYNC command will then reset the "use" status of each respective resource.

Variable Documentation

◆ __rdpq_inited

bool __rdpq_inited
extern

True if the rdpq module was inited.

True if the rdpq module was inited.