AGC Initialization Process in SharpEmu: PS5 Graphics Core Startup Sequence
SharpEmu initializes its Advanced Graphics Core by calling sceAgcInit, which validates the state pointer and register defaults version before populating the AGC state with predefined register groups to enable shader creation and command buffer generation.
The AGC initialization process in SharpEmu faithfully reproduces the PlayStation 5 kernel's graphics startup behavior to support accurate PS5 emulation. This process centers on the AgcExports class in SharpEmu.Libs.Agc, which exposes the core ABI functions that emulated games call to initialize the graphics pipeline. Understanding this initialization sequence is critical for developers debugging GPU emulation issues or implementing custom graphics tools.
The AGC Initialization Sequence
The SharpEmu AGC initialization follows a strict sequence that mirrors the real PS5 kernel. The process begins with the sceAgcInit export and continues through register defaults loading before the system is ready for shader operations.
Step 1: Receiving the Init Request via sceAgcInit
The initialization starts when the emulator receives a call to sceAgcInit (NID 23LRUSvYu1M). Located in src/SharpEmu.Libs/Agc/AgcExports.cs at lines 404-410, this exported function receives two arguments in CPU registers: RDI containing the state address and RSI containing the register-defaults version.
Step 2: Validating State Address and Version
Before proceeding, the Init method performs strict parameter validation at lines 411-415. The function checks that the stateAddress is non-zero and that the version parameter is supported by calling IsSupportedRegisterDefaultsVersion(version). If either check fails, the function immediately returns ORBIS_GEN2_ERROR_INVALID_ARGUMENT, preventing uninitialized memory access or version mismatches.
Step 3: Diagnostic Logging
When tracing is enabled via the SHARPEMU_LOG_AGC=1 environment variable, the initialization process logs diagnostic information at line 418. The TraceAgc call outputs the state address and version number, printing a line formatted as agc.init state=0x… version=… to aid developers in debugging graphics pipeline startup issues.
Step 4: Loading Register Defaults
After successful validation, the emulator must populate the AGC state with known register values. SharpEmu provides two exported helpers for this purpose: sceAgcGetRegisterDefaults2 and sceAgcGetRegisterDefaults2Internal.
These functions, defined at lines 424-428 in AgcExports.cs, act as thin wrappers around ReturnRegisterDefaults. They copy the predefined PrimaryRegisterDefaults and InternalRegisterDefaults tables into guest memory, initializing the CX, UC, and SH register groups required for GPU command generation.
Step 5: Creating Shader Objects
Once the AGC state is initialized and register defaults are loaded, the system proceeds to create graphics objects. The sceAgcCreateShader function validates shader headers, relocates internal pointers, and stores header-to-code mappings. Subsequent calls to sceAgcCreatePrimState and sceAgcCreateInterpolantMapping populate CX/UC/SH registers based on shader metadata, all assuming the AGC state established by the initialization process.
Key Implementation Details in AgcExports.cs
The AGC initialization logic resides primarily in src/SharpEmu.Libs/Agc/AgcExports.cs, which implements all exported AGC ABI functions including sceAgcInit, sceAgcGetRegisterDefaults2, and the shader creation methods.
The exported functions use the SysAbiExportAttribute from SharpEmu.HLE to expose C# methods as kernel exports. The runtime registration occurs in SharpEmu.Core.Runtime.SharpEmuRuntime, which registers the libSceAgc library and makes these functions reachable by the emulated process.
The validation logic uses IsSupportedRegisterDefaultsVersion to ensure compatibility with the emulator's supported register default tables, preventing crashes from unrecognized GPU configurations.
Code Examples: Initializing the AGC in SharpEmu
Below are practical implementations showing how to invoke the AGC initialization sequence from within SharpEmu or test harnesses using CpuContext.
Basic AGC Initialization
// Prepare a CpuContext (context creation is handled in SharpEmu.Core)
var ctx = new CpuContext();
// Allocate guest memory for the AGC state
ulong agcStateAddr = guestMemory.Allocate(0x2000);
// Pass state address in RDI and supported version in RSI
ctx[CpuRegister.Rdi] = agcStateAddr;
ctx[CpuRegister.Rsi] = 7; // Supported version from PrimaryRegisterDefaults
// Call the exported init function
int result = AgcExports.Init(ctx);
// result == ORBIS_GEN2_OK (0) indicates successful initialization
Loading Primary Register Defaults
// Use the same state block from initialization
ctx[CpuRegister.Rdi] = agcStateAddr;
int ret = AgcExports.GetRegisterDefaults2(ctx);
// ret == ORBIS_GEN2_OK indicates the state now contains default CX/SH/UC registers
Loading Internal Register Defaults
// Populate secondary default group for internal GPU pipelines
int ret2 = AgcExports.GetRegisterDefaults2Internal(ctx);
Creating a Shader After Initialization
// Prepare shader creation (requires initialized AGC state)
ctx[CpuRegister.Rdi] = shaderDestPtr; // Destination for header pointer
ctx[CpuRegister.Rsi] = headerAddr; // Shader header location
ctx[CpuRegister.Rdx] = codeAddr; // Shader code location
int shaderRet = AgcExports.CreateShader(ctx);
These examples follow the exact sequence the PS5 kernel expects: init → defaults → shader creation → command-buffer construction.
Summary
- The AGC initialization process begins with
sceAgcInitinsrc/SharpEmu.Libs/Agc/AgcExports.cs, which validates the state pointer and register defaults version. - SharpEmu checks for non-zero state addresses and supported versions using
IsSupportedRegisterDefaultsVersion, returningORBIS_GEN2_ERROR_INVALID_ARGUMENTon failure. - Diagnostic logging via
TraceAgcaids debugging whenSHARPEMU_LOG_AGC=1is enabled. - Register defaults are loaded via
sceAgcGetRegisterDefaults2andsceAgcGetRegisterDefaults2Internal, populatingPrimaryRegisterDefaultsandInternalRegisterDefaultsinto guest memory. - Subsequent graphics operations like
sceAgcCreateShaderdepend on the AGC state established during this initialization sequence.
Frequently Asked Questions
What is the AGC in SharpEmu?
The Advanced Graphics Core (AGC) in SharpEmu is the emulator's implementation of the PS5 graphics pipeline. It provides compatible ABI exports that mimic the real PlayStation 5 kernel, allowing emulated games to initialize graphics hardware, create shaders, and build GPU command buffers. The AGC initialization process sets up the internal state required for these operations.
Why does sceAgcInit validate the register defaults version?
The register defaults version validation ensures compatibility between the emulated game and the emulator's predefined register tables (PrimaryRegisterDefaults and InternalRegisterDefaults). By checking IsSupportedRegisterDefaultsVersion(version) at lines 411-415 in AgcExports.cs, SharpEmu prevents initialization with unknown GPU configurations that could cause undefined behavior or crashes during shader execution.
What happens after AGC initialization completes?
After sceAgcInit returns ORBIS_GEN2_OK, the AGC state is ready for graphics operations. The typical workflow continues with loading register defaults via sceAgcGetRegisterDefaults2, then creating shader objects using sceAgcCreateShader, followed by setting up primitive states and interpolant mappings. Finally, the system generates GPU command packets using functions like sceAgcCbDispatch and sceAgcDcbSetShRegistersIndirect.
Where does the AGC initialization code reside in the repository?
The core AGC initialization logic resides in src/SharpEmu.Libs/Agc/AgcExports.cs, specifically the Init method at lines 404-420. Related functionality for runtime registration is found in src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs, while the export mechanism uses attributes from src/SharpEmu.HLE/SysAbiExportAttribute.cs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →