Graphics Command Manager and command buffer management in PSL1GHT
The GCM (Graphics Command Manager) system is the low-level interface for managing the RSX command buffer. It provides functions for controlling how commands are queued and executed by the graphics processor.
The gcmContextData structure tracks the command buffer state:
// From rsx/gcm_sys.h:722typedef struct _gcmCtxData { u32 *begin; // Start address of command buffer u32 *end; // End address of command buffer u32 *current; // Current write position (CPU) gcmContextCallback callback; // Called when buffer is full} gcmContextData;
The gcmControlRegister structure provides access to hardware registers:
// From rsx/gcm_sys.h:734typedef struct _gcmCtrlRegister { vu32 put; // PUT register: CPU write position vu32 get; // GET register: RSX read position vu32 ref; // REF register: reference value} gcmControlRegister;
The GCM system supports three FIFO modes for managing the command buffer:
Traditional Mode
Optimized Mode
Conditional Mode
GCM_DEFAULT_FIFO_MODE_TRADITIONAL (0)From rsx/gcm_sys.h:19Checks the GET pointer in the traditional way for openings in the next segment. May sleep-wait if the GET pointer is at the next segment.
// Initialize with traditional FIFO modegcmInitDefaultFifoMode(GCM_DEFAULT_FIFO_MODE_TRADITIONAL);
Use when: You need simple, predictable behavior and don’t require optimal performance.
GCM_DEFAULT_FIFO_MODE_OPTIMIZE (1)From rsx/gcm_sys.h:26Uses rsxSetWriteTextureLabel() to manage the command buffer. Handles each segment as an index and monitors states by reading label values.
// Initialize with optimized FIFO mode gcmInitDefaultFifoMode(GCM_DEFAULT_FIFO_MODE_OPTIMIZE);
Use when: You need better performance and can handle label-based synchronization.
GCM_DEFAULT_FIFO_MODE_CONDITIONAL (2)From rsx/gcm_sys.h:32Uses rsxSetWriteCommandLabel() to manage the command buffer. Similar management to optimized mode.
// Initialize with conditional FIFO modegcmInitDefaultFifoMode(GCM_DEFAULT_FIFO_MODE_CONDITIONAL);
Use when: You need conditional rendering and advanced synchronization.
s32 ret = rsxInit(&context, COMMAND_BUFFER_SIZE, IO_BUFFER_SIZE, host_addr);
3
Configure FIFO Mode
Set the command buffer management mode:
// Set optimized FIFO mode for better performancegcmInitDefaultFifoMode(GCM_DEFAULT_FIFO_MODE_OPTIMIZE);
4
Set Buffer Sizes (Optional)
Customize command buffer and segment sizes:
// Set custom sizes (in words, not bytes)u32 bufferSize = 0x20000; // 512KB in wordsu32 segmentSize = 0x8000; // 128KB in wordsgcmSetDefaultFifoSize(bufferSize, segmentSize);
Most RSX commands automatically handle command buffer writes:
// These functions write to the command buffer internallyrsxSetClearColor(context, 0x00000000);rsxSetViewport(context, x, y, w, h, min, max, scale, offset);rsxSetDepthTestEnable(context, GCM_TRUE);
void *buffer = memalign(1024*1024, size);u32 offset;// Map the buffers32 ret = gcmMapMainMemory(buffer, size, &offset);if (ret != 0) { printf("Failed to map memory: %d\n", ret); return ret;}// Use offset in RSX commands...// Buffer is now accessible by RSX at 'offset'
// Get timestamp of last flips64 lastFlip = gcmGetLastFlipTime();// Get VBlank countu64 vblankCount = gcmGetVBlankCount();// Get current display fieldu32 field = gcmGetCurrentField();
// Get report data addressgcmReportData *report = gcmGetReportDataAddress(index);// Query report typeu32 value = gcmGetReport(type, index);// Get timestampu64 timestamp = gcmGetTimeStamp(index);
void vblank_handler(u32 head) { // Called on VBlank printf("VBlank on head %u\n", head);}// Register callbackgcmSetVBlankHandler(vblank_handler);// Set VBlank frequency (in Hz)gcmSetVBlankFrequency(60);
GCM_TRANSFER_LOCAL_TO_LOCAL // RSX to RSXGCM_TRANSFER_MAIN_TO_LOCAL // Main to RSXGCM_TRANSFER_LOCAL_TO_MAIN // RSX to MainGCM_TRANSFER_MAIN_TO_MAIN // Main to Main