Repository navigation
Sonic Origins Plus (PPSA05324) on Linux #2021
Replies: 5 comments
Update 2026-10-09 (1): the SEGA logo rendersSame host as the first post. The testing branch is current What changed. The title no longer stops in the first 20 seconds. It presents frames: black, a white fade-in with the loading indicator in the corner, the SEGA logo, and a fade to white. Runs of 6 and 15 minutes end on the time limit, with no crash. What it needs, in the order the stops were hit:
Still local (not for upstream):
What's next.
|
Update 2026-10-09 (2): past the white screen, up to the auto-save noticeSame host as the first post. The testing branch is the one from update 1, with two changes. #2133 replaces my local workaround for #2023, and #2357 is added. What changed. The title now gets past the white screen after the SEGA logo:
Why it was white.
Rendering below 4K. The title reads its own command-line options, and the host's arguments reach it:
Measured on the R9 380 during the boot frames:
At 960x540, the auto-save notice runs at about 23 fps. While the 4K logo movie plays it drops to about 9 fps; the H.264 decode runs on the CPU through FFmpeg. All runs in this update use 960x540. #2023. #2133 and #2140 both fix it here (comments on both). No draw or dispatch is skipped up to the notice, every shader recompiles and the SEGA logo renders, so the local one-slice-volume workaround is gone. What's next. After the notice closes, the screen fades to white. About 25 seconds later the GPU device is lost (
#290 and #423 both conflict with the testing branch, so I'll merge them next and see whether the title screen appears. |
Update 2026-10-09 (3): the device loss after the notice is a GTT size limitSame host and render size (960x540) as update 2. I merged #290 and #423 onto the testing branch from that update, each on its own branch. #290 (import windows, eviction under a budget): the boot is faster. The auto-save notice runs at about 60 fps instead of about 23, and the boot reaches it at 78 s instead of 116 s. The device is still lost after the notice closes (comment). #423 (clip and cull distances): the 8 clip-distance draws are no longer skipped as unsupported. They now fail at Why the device is lost. I tested three memory setups with #290. All three end on
What's next. I'll try a larger GTT (the |
Update 2026-10-09 (4): main menu and Sonic 1 in Green Hill ZoneSame host and render size (960x540) as update 3. The testing branch is the one from that update with #290, plus #454 and my #2479 (closed, see below). #423 isn't on it: it needs a rebase first. What changed on the host. RADV's GTT heap was raised from 7.43 GiB to 10 GiB with the kernel parameter What works now:
What got it here:
Speed (presents per 10 s,
Still open:
Next:
|
Update 2026-10-09 (5): Sonic 1 at full speedSame host, render size (960x540) and testing branch as update 4, plus the three changes below. Sonic 1 went from about 21 fps to 51–60 fps. The game runs one frame per present, so 60 is full speed. Played by hand so far: Green Hill Zone and on into Marble Zone Act 1 with Sonic, and a new game with Knuckles in Green Hill Zone. No crashes, and the dumped frames look right. Speed (presents per 10 s,
The three changes. The repository's intake rule still closes new PRs from authors with fewer than 20 merged ones, so they are branches on my fork, each with a test:
Change 3 measured in one scene (Knuckles standing at a Green Hill checkpoint), old budget against new:
A note for anyone measuring on GNOME Wayland: when another window covers the game window, the FIFO swapchain drops to about one present per second. In the profile it looks like a stall ( Still open:
|


















Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Tested
shaderResourceMinLodand noshaderFloat16.mainf145139.eboot.binandsce_module/{libc,libSceNpCppWebApi}.prxare fake-signed SELF containers. Their segments are plaintext and uncompressed, so they were unwrapped to plain ELF with a small script before relinking (no decryption).fix/agc-alias-one-slice-array,perf/agc-share-one-slice-image,fix/agc-resident-present-uintandperf/agc-device-pool-heap-budget.Status
In game, Sonic 1 only so far. The title runs with the open pull requests below, a local workaround for A, and a larger GTT on the host. It reaches its main menu, and Sonic 1 plays at 51 to 60 fps, where 60 is full speed: Green Hill Zone and Marble Zone Act 1 with Sonic, and Green Hill Zone with Knuckles. That is on the R9 380 at 960x540 with the four speed branches (update 5).
main, the relinked title exits with code 127 at startup:symbol lookup error: undefined symbol: i2l3IYvQ9UE(sce::Json::Object::empty).import_audit.pylists it as the only absent import; 24 imports are stubs that throw (mostly libSceAgc workload-stream and occlusion-query calls).Open blockers
ShaderRecompiler::Recompile: shader image heap capacity exceeded, at shader registration. Storage image group 31 holds 6 entries against a capacity of 4, in a shader with 13 images. With that group raised locally, the next registration stops atshader sampler pairs exceed runtime heap capacity(more than 8 pairs).AGC driver: static ABI refers to a replaced shader header. The title binds compute shaders through a byte-identical copy of the registeredShaderheader, 0x78 bytes below it: 14 shaders, 46 binds in one run, all 96 fixed bytes equal.DB_RENDER_CONTROL0x3 (depth and stencil clear), then repeated 0x1 (depth only),DB_DEPTH_CLEAR0.0,DB_DEPTH_CONTROL0x777. They stop at four checks in turn (details below).image descriptor is incompatible with the static runtime image interface. A draw's shader samples a float image as 3D, and the title binds a 2D R8G8B8A8_UNORM T# (type 9) to it. The materializer only has 3D modes for that slot.sceShareSetContentParamForApplicationTitle not implemented(libSceShare).sceKernelAprSubmitCommandBufferrejected them withEINVAL, so CRI stopped before opening the first movie.--res_x=960 --res_y=540). Sonic 1 ran at about 21 fps and now runs at 51 to 60 with the four speed branches; the main menu went from about 3.7 to 10–11 and is the slow scene now (about 110 draws, 57 ms of GPU time per present). The opening movie ran at about 10 fps before the last three branches and hasn't been measured since. At 3840x2160 it was about 1 to 2 before any of them. Video memory is still tight on the 2 GB card (update 5).VK_ERROR_DEVICE_LOST, after RADV logsNot enough memory for command submission. The address-based imports need about 7.3 GB of GTT, which doesn't fit in RADV's default 7.43 GiB GTT heap next to its own allocations (update 3). Resolved on this host withttm.pages_limit=2621440(10 GiB GTT) and udmabufsize_limit_mb=8192, both root-only settings.PA_CL_VS_OUT_CNTL0x00400001) are skipped: 8 at the title, and about 3 per present in Sonic 1. The dumped frames look right without them.C in detail:
AGC graphics: depth/stencil-only draws without a pixel shader are not implemented. The precheck rejects a draw with no color writes whenSPI_SHADER_PGM_LO_PSwas never written. The draw decoder already reads an unwritten register as 0 and uses the null pixel program for it (fix(agc): draw without a pixel program when SPI_SHADER_PGM_PS is unset #469), so this check only blocks the never-written case. fix(agc): read an unwritten pixel program address as unset #2022 reads an unwritten address as unset inPixelProgramSkippedtoo. With it, these draws reach step 2.prepared shader artifact is missing for the requested static ABI: ... stage=5 wave=64 pushOffset=0 pushCapacity=128 preparedLayouts= [0,128] [0,0]: the null pixel program variants (wave 64 with 0, 4 and 16 user SGPRs). fix(agc): prepare the null pixel program at draw when its variant was not prepared #1902 prepares them at draw (tested).prepared rectangle artifacts are missing: the rect-list pairing of the vertex program with the null pixel program. fix(agc): prepare a rect-list draw's missing rectangle at draw from its prepared stages #1928 prepares it at draw (tested).depth/stencil clear, copy, resummarize or decompress draws (DB_RENDER_CONTROL) is unsupported (register 0x0 = 0x00000003). fix(agc): preserve ClearMRT color writes and validate stencil clears #1534 (which replaced fix(agc): draw with DB_RENDER_CONTROL STENCIL_CLEAR_ENABLE #1479) covers the stencil half and feat(agc-driver): draw DB_RENDER_CONTROL depth clears #2219 the depth half on top of it (tested).After the clears, a compute pass stops on
storage image access to depth/stencil surface ... is not implemented; #425 covers it (tested).Stops on
main, in the order they are hitundefined symbol: i2l3IYvQ9UE(sce::Json::Object::empty, libSceJson2)shader image heap capacity exceeded(storage group 6 of 4)shader sampler pairs exceed runtime heap capacitystatic ABI refers to a replaced shader header(byte-identical copy)depth/stencil-only draws without a pixel shader are not implemented(pixel program registers never written)prepared shader artifact is missing for the requested static ABI(null pixel program variant)prepared rectangle artifacts are missing(rect-list clears with the null pixel program)DB_RENDER_CONTROL0x3 / 0x1 clear drawsstorage image access to depth/stencil surface(compute pass)image descriptor is incompatible with the static runtime image interface(3D access, 2D T#)sceShareSetContentParamForApplicationTitle not implementedFS:Failed in submitCommandBuffer(CRI,0x80020016), white screen after the SEGA logosampling the depth plane of depth surface ... is not implemented(reused depth-surface memory)The order after A was found with the local workarounds listed in the notes, so it may differ once real fixes land.
Notes
/app0is resolved against the process's working directory, not the executable's directory. The title has to be started from the directory that holdsapp0/, otherwise it stops later withparam.json not found.size_limit_mbof 64, the title's 5000 MiB GPU heap and its 256 MiB pool fail atUDMABUF_CREATE(-1000072003) and fall back to copies. With 8192 they import. Either way they need GTT, which is H.All reactions