The RSX is the PlayStation 3’s hardware-accelerated 3D graphics processor. PSL1GHT provides a complete API for programming the RSX, enabling advanced 3D rendering, texture mapping, and shader programming.
What is the RSX?
The RSX (Reality Synthesizer) is the PS3’s graphics accelerator, capable of:
Hardware-accelerated 3D rendering
Programmable vertex and fragment shaders
Multiple render targets (MRT)
Advanced texture filtering and mapping
Depth buffering and stencil operations
Architecture Overview
The RSX uses a command buffer architecture where the CPU writes rendering commands to a buffer that the RSX processes asynchronously.
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ CPU │ ──────> │Command Buffer│ ──────> │ RSX │
│ (PPU) │ writes │ (Main RAM) │ reads │ (Graphics) │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌──────────────┐
│ RSX Memory │
│ (256MB VRAM) │
└──────────────┘
Initialization
Initializing the RSX involves setting up the command buffer, configuring video output, and allocating framebuffers.
Create RSX Context
Initialize the RSX with a command buffer and I/O memory: #include <rsx/rsx.h>
#define COMMAND_BUFFER_SIZE 0x 80000 // 512KB
#define HOSTBUFFER_SIZE ( 128 * 1024 * 1024 ) // 128MB
gcmContextData * context;
void * host_addr = memalign ( 1024 * 1024 , HOSTBUFFER_SIZE);
// Initialize RSX with command buffer
rsxInit ( & context , COMMAND_BUFFER_SIZE, HOSTBUFFER_SIZE, host_addr);
The rsxInit() function from rsx/rsx.h:106 creates a command buffer context and initializes the RSX memory manager.
Configure Video Output
Set up the video mode and display settings: #include <sysutil/video.h>
videoState state;
videoConfiguration vconfig;
// Get current video state
videoGetState ( 0 , 0 , & state );
// Configure video mode
memset ( & vconfig , 0 , sizeof (videoConfiguration));
vconfig.resolution = state.displayMode.resolution;
vconfig.format = VIDEO_BUFFER_COLOR_FORMAT_X8R8G8B8;
vconfig.pitch = 1920 * 4 ; // Width * bytes per pixel
vconfig.aspect = state.displayMode.aspect;
videoConfigure ( 0 , & vconfig , NULL , 0 );
videoGetState ( 0 , 0 , & state );
Set Flip Mode
Configure screen flipping to synchronize with vertical refresh: // Sync flips with vsync to prevent tearing
gcmSetFlipMode (GCM_FLIP_VSYNC);
Available flip modes from rsx/gcm_sys.h:34-39:
GCM_FLIP_HSYNC - Horizontal sync (accurate)
GCM_FLIP_VSYNC - Vertical sync (recommended)
GCM_FLIP_HSYNC_AND_BREAK_EVERYTHING - Horizontal sync (inaccurate)
Allocate Framebuffers
Create double-buffered framebuffers in RSX memory: #define FRAME_BUFFER_COUNT 2
u32 color_pitch;
u32 color_offset [FRAME_BUFFER_COUNT];
u32 * color_buffer [FRAME_BUFFER_COUNT];
u32 display_width = 1920 ;
u32 display_height = 1080 ;
// Calculate pitch (must be multiple of 64)
color_pitch = display_width * 4 ; // 4 bytes per pixel (ARGB8888)
// Allocate each framebuffer (64-byte aligned)
for ( int i = 0 ; i < FRAME_BUFFER_COUNT; i ++ ) {
color_buffer [i] = (u32 * ) rsxMemalign ( 64 , color_pitch * display_height);
rsxAddressToOffset ( color_buffer [i], & color_offset [i]);
// Configure display buffer
gcmSetDisplayBuffer (i, color_offset [i], color_pitch,
display_width, display_height);
}
The rsxMemalign() function allocates aligned memory in RSX VRAM.
Allocate Depth Buffer
Create a depth buffer for 3D rendering: u32 depth_pitch;
u32 depth_offset;
u32 * depth_buffer;
// Allocate 16-bit depth buffer
depth_pitch = display_width * 2 ; // 2 bytes per pixel
depth_buffer = (u32 * ) rsxMemalign ( 64 , depth_pitch * display_height );
rsxAddressToOffset (depth_buffer, & depth_offset );
Framebuffer Configuration
Surface Setup
Before rendering, configure the render target surface using gcmSurface:
gcmSurface surface;
memset ( & surface , 0 , sizeof (gcmSurface));
// Surface type
surface.type = GCM_SURFACE_TYPE_LINEAR;
// Anti-aliasing
surface.antiAlias = GCM_SURFACE_CENTER_1; // No multisampling
// Color buffer format
surface.colorFormat = GCM_SURFACE_A8R8G8B8;
surface.colorTarget = GCM_SURFACE_TARGET_0;
surface. colorLocation [ 0 ] = GCM_LOCATION_RSX;
surface. colorOffset [ 0 ] = color_offset [curr_fb];
surface. colorPitch [ 0 ] = color_pitch;
// Depth buffer format
surface.depthFormat = GCM_SURFACE_ZETA_Z16;
surface.depthLocation = GCM_LOCATION_RSX;
surface.depthOffset = depth_offset;
surface.depthPitch = depth_pitch;
// Dimensions
surface.width = display_width;
surface.height = display_height;
surface.x = 0 ;
surface.y = 0 ;
// Apply surface configuration
rsxSetSurface (context, & surface );
Available color formats (from rsx/gcm_sys.h:62-76):
16-bit formats
32-bit formats
Special formats
GCM_SURFACE_X1R5G5B5_Z1R5G5B5 // 1-bit alpha, 5-5-5 RGB
GCM_SURFACE_X1R5G5B5_O1R5G5B5 // 1-bit unused, 5-5-5 RGB
GCM_SURFACE_R5G5B5 // 5-5-5 RGB
Depth buffer formats (from rsx/gcm_sys.h:77-80):
GCM_SURFACE_ZETA_Z16 - 16-bit depth buffer
GCM_SURFACE_ZETA_Z24S8 - 24-bit depth + 8-bit stencil
Rendering Loop
A typical rendering loop follows this pattern:
u32 curr_fb = 0 ;
while (running) {
// Wait for previous flip to complete
waitflip ();
// Set render target to back buffer
setRenderTarget (curr_fb);
// Clear buffers
rsxSetClearColor (context, 0x 00000000 );
rsxSetClearDepthStencil (context, 0x ffffff00 );
rsxClearSurface (context, GCM_CLEAR_R | GCM_CLEAR_G |
GCM_CLEAR_B | GCM_CLEAR_A |
GCM_CLEAR_S | GCM_CLEAR_Z);
// Render scene...
drawScene ();
// Flip to display the rendered frame
flip (curr_fb);
// Swap buffers
curr_fb = ! curr_fb;
}
Wait for Flip
void waitflip () {
while ( gcmGetFlipStatus () != 0 ) {
usleep ( 200 ); // Sleep to avoid busy-waiting
}
gcmResetFlipStatus ();
}
Flip Display
void flip (u32 buffer ) {
// Queue flip command
gcmSetFlip (context, buffer);
// Flush command buffer
rsxFlushBuffer (context);
// Wait for flip
gcmSetWaitFlip (context);
}
Memory Management
The RSX has access to two memory regions:
RSX Memory (VRAM)
256MB of dedicated video memory. Fast access from RSX.
// Allocate in RSX memory (64-byte aligned)
void * rsx_buffer = rsxMemalign ( 64 , size);
// Convert address to RSX offset
u32 offset;
rsxAddressToOffset (rsx_buffer, & offset );
// Free RSX memory
rsxFree (rsx_buffer);
Main Memory (I/O Mapped)
System RAM mapped for RSX access. Slower but more flexible.
// Allocate in main memory
void * main_buffer = memalign ( 1024 * 1024 , size);
// Map for RSX access
u32 offset;
gcmMapMainMemory (main_buffer, size, & offset );
// Use offset for RSX commands...
// Free when done
free (main_buffer);
Memory locations are specified with:
GCM_LOCATION_RSX - Data in RSX video memory (faster)
GCM_LOCATION_CELL - Data in main memory (more flexible)
Command Buffer Management
The command buffer is a circular buffer where commands are written:
// Get current command buffer pointer
u32 * current = rsxGetCurrentBuffer ();
// Flush pending commands to RSX
rsxFlushBuffer (context);
// Wait for RSX to finish processing
rsxFinish (context, 1 );
Always flush the command buffer after enqueuing rendering commands to ensure they are sent to the RSX.
Example: Complete Setup
Here’s a complete initialization example from samples/graphics/rsxtest/source/main.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <rsx/rsx.h>
#include <sysutil/video.h>
#define COMMAND_BUFFER_SIZE 0x 80000
#define HOSTBUFFER_SIZE ( 128 * 1024 * 1024 )
#define FRAME_BUFFER_COUNT 2
gcmContextData * context;
u32 display_width = 1920 ;
u32 display_height = 1080 ;
u32 color_pitch;
u32 color_offset [FRAME_BUFFER_COUNT];
u32 * color_buffer [FRAME_BUFFER_COUNT];
u32 depth_pitch;
u32 depth_offset;
u32 * depth_buffer;
void init_screen () {
void * host_addr = memalign ( 1024 * 1024 , HOSTBUFFER_SIZE);
// Initialize RSX
rsxInit ( & context, COMMAND_BUFFER_SIZE, HOSTBUFFER_SIZE, host_addr);
// Get video state
videoState state;
videoGetState ( 0 , 0 , & state);
// Set display mode based on current state
display_width = state . displayMode . resolution . width ;
display_height = state . displayMode . resolution . height ;
// Configure video
videoConfiguration vconfig;
memset ( & vconfig, 0 , sizeof (videoConfiguration));
vconfig . resolution = state . displayMode . resolution ;
vconfig . format = VIDEO_BUFFER_COLOR_FORMAT_X8R8G8B8;
vconfig . pitch = display_width * 4 ;
vconfig . aspect = state . displayMode . aspect ;
videoConfigure ( 0 , & vconfig, NULL , 0 );
videoGetState ( 0 , 0 , & state);
// Set flip mode
gcmSetFlipMode (GCM_FLIP_VSYNC);
// Allocate color buffers
color_pitch = display_width * 4 ;
for ( int i = 0 ; i < FRAME_BUFFER_COUNT; i ++ ) {
color_buffer [i] = (u32 * ) rsxMemalign ( 64 , color_pitch * display_height);
rsxAddressToOffset ( color_buffer [i], & color_offset [i]);
gcmSetDisplayBuffer (i, color_offset [i], color_pitch,
display_width, display_height);
}
// Allocate depth buffer
depth_pitch = display_width * 2 ;
depth_buffer = (u32 * ) rsxMemalign ( 64 , depth_pitch * display_height);
rsxAddressToOffset (depth_buffer, & depth_offset);
gcmResetFlipStatus ();
}
int main () {
init_screen ();
// Render loop...
return 0 ;
}
Next Steps
GCM System Learn about the Graphics Command Manager and command buffer operations
Vertex Shaders Write and compile vertex programs using the Cg Toolkit
Rendering Pipeline Set up the rendering pipeline and draw 3D geometry
Font Rendering Render text using the PSL1GHT font library
API Reference
Core Functions
Location : ppu/include/rsx/rsx.h:106Initialize the RSX context and memory manager. s32 rsxInit (gcmContextData ** context , u32 cmdSize ,
u32 ioSize , const void * ioAddress );
Parameters :
context - Pointer to receive context address
cmdSize - Command buffer size (typically 512KB)
ioSize - I/O buffer size (typically 128MB)
ioAddress - Pointer to allocated I/O buffer
Returns : Zero on success, non-zero on error
Allocate aligned memory in RSX VRAM. void * rsxMemalign (u32 alignment , u32 size );
Parameters :
alignment - Alignment boundary (typically 64 or 128 bytes)
size - Size in bytes to allocate
Returns : Pointer to allocated memory, or NULL on failure
Location : ppu/include/rsx/rsx.h:121Convert RSX memory pointer to offset for use in commands. s32 rsxAddressToOffset ( const void * ptr , u32 * offset );
Parameters :
ptr - RSX memory pointer to convert
offset - Pointer to receive offset value
Returns : Zero on success, non-zero on error
Display Functions
Configure a framebuffer for display. s32 gcmSetDisplayBuffer (u8 bufferId , u32 offset , u32 pitch ,
u32 width , u32 height );
Queue a flip command to display a framebuffer. s32 gcmSetFlip (gcmContextData * context , u8 bufferId );
Check if a flip has occurred. Returns : Zero if flip completed, non-zero otherwise