AnyPS5/docs/dev/debt/libSceAgc.md

14 KiB

libSceAgc technical debt

Unknown function info

  • PPSA01341 imports declared without parameters, signatures unknown: sceAgcSetSemaphoreMemory. Name from the shadPS4 aerolib NID list
  • sceAgcWaitRegMemPatchMask (libSceAgc) - follows sceAgcWaitRegMemPatchReference: the mask is taken as a 32-bit value and written to the low mask word of a 32- or 64-bit wait, as OpenAGC does; sharpemu writes both words of a 64-bit wait's mask. A mask above 32 bits throws
  • sceAgcDcbSetCfRegisterDirect, sceAgcDcbSetCfRegisterRangeDirect (libSceAgc) - signatures follow OpenAGC and SharpProspero, which agree; the SET_CONFIG_REG (0x68) packet is OpenAGC's. The driver does not execute SET_CONFIG_REG, so a submitted packet throws
  • Command buffer cursors (libSceAgc) - a null cursor_down is taken as a buffer without downward allocations, whose limit is top. PPSA16064 builds one-packet buffers of 8 dwords that way; the console's handling is unconfirmed
  • sceAgcGetRegisterDefaultsInternal (libSceAgc) - returns the version 0 internal table, as sceAgcGetRegisterDefaults returns the version 0 public one; OpenAGC returns the table of the version passed to sceAgcInit instead, and null before it
  • sceAgcSetSubmitMode (libSceAgc) - mode values unknown; only 0 is accepted
  • sceAgcGetGsOversubscription (libSceAgc) - signature and occupancy formula (base and expanded vertex/export capacities, budget shift, GE_PC_ALLOC / SPI_SHADER_PGM_RSRC4_GS encoding) follow KytyPS5 only, not confirmed on hardware or a title; a negative or NaN factor that gives a negative target, a missing GS context register or a zero GE_MAX_OUTPUT_PER_SUBGROUP throws
  • sceAgcCbCondWrite (libSceAgc) - argument order and the 9-dword COND_WRITE layout follow the clean-room OpenAGC and sharpemu, which agree on them; SharpProspero lists another order. The write space is accepted only as 1 (memory), the one value both encode the same way, and other values throw.
  • sceAgcAcbAtomicGds_0900 (libSceAgc) - signature, control/mode bit mapping and the 11-dword ATOMIC_GDS (0x1d) layout follow the clean-room OpenAGC only, which derives them from the library's disassembly; KytyPS5 and shadPS4 have no body for it. Not confirmed on hardware or a title (PPSA07286 imports it, nothing was run), and the driver has no ATOMIC_GDS handler (opcode 0x1d is not executed as an atomic GDS operation)
  • sceAgcGetIsTrinityMode (libSceAgc) - signature from the only PPSA26344 call (a pointer to a one-byte flag, result ignored); a null pointer throws because its error code is unknown
  • sceAgcDcbAtomicGds_0900 (libSceAgc) - name from its NID (zARR5aCmkoY), the DCB counterpart of sceAgcAcbAtomicGds_0900, signature unknown
  • sceAgcDcbContextStateOpGetSize (libSceAgc) - sizes from KytyPS5 only (5, 27, 27 and 32 dwords), equal to what sceAgcDcbContextStateOp_0100 writes; KytyPS5 returns 0 for an operation above 3, here it throws
  • sceAgcBranchPatchSetThenTarget_0300, sceAgcBranchPatchSetElseTarget_0300 (libSceAgc) - names from their NIDs (7Wa3aeJgeVU, rP5xLdOf26k); the (packet, cachePolicy, target, sizeInDwords) signature is inferred from PPSA28416's calls (a branch packet, 0, an aligned target, 4), with the policy stored where sceAgcCbBranch puts it
  • sceAgcDcbSet{Cx,Sh,Uc}RegistersIndirectGetSize (libSceAgc) - the count argument is ignored: PPSA28416 calls them with leftover register contents (0xf5f5039c), so the real functions likely take none; the size is 20 bytes either way
  • sceAgcUpdateInterpolantMapping_0100 (libSceAgc) - name from its NID (k0E7vkgqAuE); the (regs, vs, ps) arguments are the declared ones, behaviour unknown
  • sceAgcWriteDataPatchSetDst, sceAgcWriteDataPatchSetCachePolicy and their Async forms (libSceAgc) - the signatures (packet, uint8 value) are inferred from the other patch functions, as no public declaration was found; the value is taken in the encoding of the dst and cachePolicy arguments of sceAgcDcbWriteData (graphics) and sceAgcAcbWriteData (Async, compute), and the patched packet is the one those calls would write. sceAgcAsyncWriteDataPatchSetAddressOrOffset is assumed to patch the address like sceAgcWriteDataPatchSetAddressOrOffset, as the compute WRITE_DATA packet keeps it in the same dwords
  • dbOlWdppb4o (libSceAgc) - unknown name; same arguments as sceAgcCreateInterpolantMapping_0100; the SPI_PS_INPUT_CNTL bits for is_f16 2 inputs follow KytyPS5, not confirmed on hardware
  • sceAgcGetDataPacketPayloadRange (libSceAgc) - signature, the {base, size in bytes} output and the type 0 range (header + 1, one dword longer than the type 1 payload) from KytyPS5 only, matching sceAgcGetDataPacketPayloadAddress_0090; prosper returns header + 2 for both types from that address function
  • sceAgcAsyncCondExecPatchSetCommandAddress, sceAgcAsyncCondExecPatchSetEnd (libSceAgc) - no reference has a body for them; they are assumed to patch the COND_EXEC packet like sceAgcCondExecPatchSetCommandAddress and sceAgcCondExecPatchSetEnd, since sceAgcAcbCondExec writes the same packet as sceAgcDcbCondExec, as sceAgcAsyncRewindPatchSetRewindState does for REWIND
  • sceAgcAcbAtomicGds_0900 (libSceAgc) - name from its NID (gQkqkLttcpw), signature unknown
  • sceAgcDcbPrimeUtcl2 (libSceAgc) - assumed to write the packet sceAgcAcbPrimeUtcl2 writes: PRIME_UTCL2 has the same 5 dwords on the graphics and compute rings. Not confirmed on a title. Both write a NOP of that size, as there is no TLB to prime
  • sceAgcDcbQueueEndOfShaderActionGetSize (libSceAgc) - the builder is inline in the SDK and not exported; the size is assumed to be that of the RELEASE_MEM packet sceAgcCbReleaseMem writes (32 bytes), the same as sceAgcAcbQueueEndOfShaderActionGetSize, as in OpenAGC and REmu
  • vieBRwlh1Lw (libSceAgc) - unknown name; the (regs, gs, ps) arguments of sceAgcCreateInterpolantMapping_0100 come from OpenAGC only
  • sceAgcDcbSetZPassPredicationEnableGetSize, sceAgcDcbSetPredicationDisableGetSize, sceAgcDcbSetBoolPredicationEnableGetSize (libSceAgc) - the builders are inline in the SDK and not exported; the size is assumed to be that of the SET_PREDICATION packet sceAgcDcbSetPredication writes (16 bytes)
  • vieBRwlh1Lw (libSceAgc) follows OpenAGC only, not confirmed on hardware: the dbOlWdppb4o transform without the identity tail, so it writes one register per pixel shader input and none for a pixel shader without inputs, and a null pixel shader throws. For an is_f16 1 or 3 input whose default_value and default_value_hi differ it throws: OpenAGC takes DEFAULT_VAL from default_value_hi, while KytyPS5, sharpemu and dbOlWdppb4o here take it from default_value
  • sceAgcAcbWaitUntilSafeForRendering (libSceAgc) - (buffer, videoOutHandle, displayBufferIndex), the declared arguments, which PPSA12544 (01.000.010) passes inside waitUntilSafeForRendering and waitUntilSafeForRendering VR markers on an asynchronous compute command buffer, ignoring the result. It writes the same rendering-wait packet as sceAgcDcbWaitUntilSafeForRendering, which the driver now accepts on compute queues too; the wait blocks only that queue's worker. Whether the console encodes the compute variant differently is not known

Functional

  • sceAgcDebugRaiseException (libSceAgc) - logs the exception id and returns 0, as retail hardware does nothing per OpenAGC; the trap (ud2) OpenAGC describes for development hardware is not reproduced. Neither is verified on a console. The uint32 exception id is KytyPS5's claim; OpenAGC declares no arguments, so the logged id may be leftover register contents
  • sceAgcDcbSetWorkloadsActive and sceAgcDcbSetWorkloadComplete (libSceAgc) and sceAgcDriverRegisterWorkloadStream (libSceAgcDriver) - the driver call records only the stream id (1 to 31; it returns 0 for any argument and keeps no stream record), and the DCB calls write the packets KytyPS5 writes: an 18-dword (active) or 12-dword (complete) IT_NOP packet with the stream id, and for active the 64-bit mask of the workload ids, for complete the workload id and the 64-bit clear mask of that id. Both return null for a null command buffer, an unregistered or out-of-range stream, a workload id above 63, and for active a duplicate id or a count of 0 or above 63. The layouts and checks come from KytyPS5 alone; the console oracle in prosper measures the null return only for unregistered streams, not the packet contents of a registered one. The error codes the console driver returns for an invalid or repeated registration are unknown, so registration never fails here. PPSA29866 calls sceAgcDcbSetWorkloadsActive while building its command buffers (sceAgcDcbSetWorkloadComplete was not observed); nothing else was observed.
  • sceAgcDcbSetWorkloadStreamInactive and sceAgcAcbSetWorkloadsActive, sceAgcAcbSetWorkloadComplete, sceAgcAcbSetWorkloadStreamInactive (libSceAgc) - return null without writing to the buffer for a null command buffer or a stream that is not registered (out-of-range ids included), and throw for a registered stream. The console oracle in prosper measured only that null return, with no stream registered, three argument patterns each and nothing written (ACB, DCB); the packet a registered stream gets is not measured. KytyPS5 has no body for these four, and its IT_NOP layout for the DCB active and complete calls differs from the SET_UCONFIG_REG, WRITE_DATA and SET_WORKLOAD sequence OpenAGC derives from the driver, so neither is taken. The (buf, streamId), (buf, streamId, workloadId) and (buf, streamId, workloadIds, workloadCount) signatures are those of the DCB calls in OpenAGC, which says the ACB calls use the same driver builders; no ACB declaration was found. sceAgcDcbSetWorkloadsActive checks the stream before it reads the workload ids, as OpenAGC does: the console returned null for stream 1 with the ids at address 2 (measured) without faulting
  • sceAgcCreatePrimState (libSceAgc) - the ge_user_vgpr_en special is passed to the user configuration registers at whatever offset the shader header stores, as the SPRX does according to OpenAGC, which copies all four specials verbatim (KytyPS5 stops on any other offset). PPSA99039, PPSA99505, PPSA99515 and PPSA99997 build their headers by hand with it at 0x25c (GE_USER_VGPR1) instead of 0x262 (GE_USER_VGPR_EN), value 0, and run on the console; it is not moved to 0x262, and the driver reads neither register. ge_cntl, vgt_shader_stages_en and a used vgt_gs_out_prim_type must still be at their own offsets, since the driver reads those registers there, so a header that stores one elsewhere throws naming the offset, although by OpenAGC the SPRX would copy it as well