Status: draft v1 · 2026-09-27 · checkboxes synced with main on 2026-09-30
Status as of 2026-10-01: M0 is done except the upstream-baseline check, a local-only run (bean portps5-sigm). M1 work started before that check passed, as a recorded exception to the start rule below; the exception covers starting only, so M1 cannot exit until the M0 baseline is recorded. M1 has landed most ports (recompiler, relinker, threading, libc, image codecs, offline services, golden corpus, Recorder and HostImport building blocks, write tracker building blocks, the telemetry core and watchdog, the tools/regress.py runner) but not all the runtime wiring: config loads at startup since PR #71, while the Recorder in the submit path, the arena and heap on the extent allocator, and the telemetry call sites are still open. M2 has landed save data fidelity, SDL controllers in scePadRead, depth/stencil state decode, the host depth/stencil surface and the single audio mixer. Landed 2026-09-30 to 2026-10-01: Vulkan 1.3 driver floor (PR #62), driver-lavapipe CI job (PR #82), telemetry core (PR #78), regress runner (PR #76), resident render-target image pool (PR #74), SSE4a lowering of register forms (PR #73), guest-pointer validation (PR #83), direct-memory exports (PR #84), MsgDialog, PlayGo and AudioOut2 ports (PRs #85, #86, #87), per-title /savedata0 mount (PR #53), verbatim libc Unsupported export with the cross-prx import check (PR #68), AVC decode through a pinned LGPL FFmpeg (PR #88). Also landed: config load at startup and the gated frame-timing report (PR #71), the cross-prx mount-table export fix (PR #94) and DualSense output, motion and the hot-plug slot table (PR #81). Also landed: SSE2 texture compare (PR #75) and the write-tracker revalidation skip (PR #77), dormant until the tracker is wired (bean portps5-421p). Every unticked item below names a bean (.beans/) or an open PR where one exists; epics portps5-4ut1 (GPU driver), portps5-w3s8 (guest memory) and portps5-r8mh (runtime wiring and telemetry) group the M1 beans. Every v1 item now has a bean, grouped under milestone beans M0 portps5-s1kj, M1 portps5-7dk3, M2 portps5-dbpx, M3 portps5-oo21, M4 portps5-rd6g, M5 portps5-bxvu and M6 portps5-w6uc. Each bean records its blockers, so beans list --ready shows what can run in parallel. Part II (2.0) items get beans when their milestone seed is written.
This roadmap is phased, with no calendar dates. Capacity is a solo maintainer plus AI agents, part-time. Each milestone has measurable exit criteria and unlocks gate titles in order of risk. A milestone starts only when the previous one's exit criteria pass; any exception is recorded in the status line above and never relaxes the exit criteria. Each milestone becomes its own ooo seed.
Scope
- Rebase
yuriolive/PortPS5onto AnyPS5mainhistory (e06dbff), and credit AnyPS5 in the README. - Keep the GPL-2.0-only licence.
- Change the build: bump to C++23, add CMakePresets, pin the MinGW GCC 15.2 toolchain, copy the MinGW runtime DLLs next to the patched prx, and wire every existing test into
ctest. - Standardize test framework on GoogleTest (GTest + GMock) via FetchContent with
gtest_discover_tests; establishtests/common/TestHarness.hpp(SCE matchers, error code formatters, guest page fixtures); modernise legacy standaloneabort()test binaries into structured GTest suites; update CTest expected counts (TESTING.md, spec/verification.md §5). - Make glslang test-only by moving
tests/DummyShaders.cppout of the shipped recompiler library (spec/build-toolchain.md, PRD R1). - Replace the no-comments rule in CONVENTIONS with "comment why, not what".
- Hosted CI jobs
build,unit,policy, andpython-quality(spec/verification.md §1); Python tooling bar (uv,ruff,pytestcoverage) and RDNA ISA progress telemetry (tools/progress.py,rdna_isa.txt, workflows and badges). - Dump the five gate titles and record their pins in the PRD §4.1 table. Swap any PS4-only build within the same tier (PRD R4).
Exit criteria
-
mainbuilds from a clean clone in CI, andctestis green with GoogleTest runner reporting individual test cases. - The PRD pin table has no TBD cells.
- Baseline preserved. At the start of M0, run Demon's Souls on upstream
main(e06dbff) and record the furthest observable stage (for example "SIE logo presented"). After the rebase, the fork reaches that same stage. No baseline stage is recorded in the repo (beanportps5-sigm).
Scope
- Port from AnyPS5
main(merged PR #5) onto the fork, without its title-specific code:- the Recorder (adapted
Recorderlanded inGraphics/, PR #49). The building block only:sceAgcDriverSubmitDcbdoes not record through it yet (beanportps5-tiod); - host import with a staging fallback (
HostImport, PR #49; unwired, same bean); - GPU detile (
Graphics/src/TextureDetiler.cpp); - GuestArena/GuestHeap behind
IWriteTracker. Building blocks landed (extent allocator PR #32,WriteWatchTrackerwith page-state table and pins PR #40) but the runtime instantiates none of them yet (beanportps5-421p); -
--to-intelSSE4a lowering; - AudioOut2 and ATRAC9;
- the recompiler fixes (saveexec order, atomic-zero, LDS barriers);
- the
agc_shader_replaytool (adapted, PR #31) and request serialisation (RequestSerializer, in the tree since the fork).
- the Recorder (adapted
- Establish foundational subsystem GoogleTest suites ported and adapted from open-source ecosystem references:
- Kernel synchronization & threading: port futex/umtx, pthread mutex/condvar/rwlock priority, and
WaitOnAddressrace perturbation tests from FreeBSD 12, Wine, and KytyPS5 (SyncOnAddressTests) (spec/threading.md); - Event queues: port kqueue/kevent edge/level triggers, user events, and timeout cancellation tests from FreeBSD 12 and KytyPS5 (
EventQueueLifetimeTests); - Virtual memory (spec/guest-memory.md):
- port 16 KB page rounding, direct memory mapping and protect state transitions from FreeBSD 12 and KytyPS5 (
VirtualMemoryAllocationTests: 241 of Kyty's 3,173 lines ported so far; beanportps5-vzmm); - port the memory-tracking behaviour from KytyPS5
MemoryTrackerTestsontoGuestMemoryTracking::Watch(tests/memory/MemoryTrackerTests.cpp: range validation, page rounding, protection/fault resolution, invalidate, resolver contract, concurrency). Kyty's CPU/GPU dirty-ownership, upload/download ranges,RangeSetand region-mask batching have no counterpart until theIWriteTrackerimplementation lands, so they are not ported; - Guest-pointer range validation for PRX libraries (
GuestMemoryValidation, first consumerslibSceJpegEncandlibScePngDec; spec/guest-memory.md "Validation API"; beanportps5-8l0d). -
IWriteTrackerwrite-watch tests (Collect,MarkWritten, generations, pins, flush hook, page-state table):core/libs/tests/WriteTracker.cpp, against the realWriteWatchTracker(PR #40). Aliased-view tests stay open until alias support exists (M5, spec/guest-memory.md; beanportps5-421p). - Direct-memory exports: real
sceKernelDirectMemoryQueryextents and types, largest-free-runsceKernelAvailableDirectMemorySize, overflow and range hardening of allocate/release (tests/memory/DirectMemoryExportTests.cpp; spec/guest-memory.md). - Mapping placement and unmap: advisory address hints,
NO_OVERWRITE,sceKernelMunmapover several mappings, holes and gaps (tests/memory/MemoryMappingTests.cpp,GuestAllocationsUnmapTests.cpp). -
DirectMemory.hppuses the shared SCE error codes, pinned by literal-value tests (beanportps5-mn0m).
- port 16 KB page rounding, direct memory mapping and protect state transitions from FreeBSD 12 and KytyPS5 (
- Kernel error contract, timedwait, thread-self, and host TLS: verify POSIX/SCE errno families,
ETIMEDOUT/SCE_KERNEL_ERROR_ETIMEDOUTconventions, and Win32 TLS isolation (GuestKernelErrors,GuestCondTimedwait,GuestThreadSelf,HostThreadLocal) (spec/threading.md); - Shader recompiler: port instruction decoding bitfield validation, DPP swizzles, SDWA packing, 64-bit LDS, and divergent control-flow tests from Mesa ACO and KytyPS5 (
ShaderRecompilerComputeTests,shaderCfgTests) (spec/shader-recompiler.md). Only partly landed, so this was unticked on 2026-09-30:RecompilerFixesTests(saveexec, atomic-zero, LDS barriers, divergent regions),RdnaPortedInstructionTests(PR #60) and the synthetic golden corpus exist; noShaderRecompilerComputeTests,shaderCfgTests, Mesa ACO or decoderTEST_Psuites exist in the tree (beanportps5-3asdcovers what landed and is completed; the remaining ports are beanportps5-qxip).
- Kernel synchronization & threading: port futex/umtx, pthread mutex/condvar/rwlock priority, and
- Interim FMV correctness: AnyPS5
main's Bink-plane write-back (merged PR #5) is ported as a general mechanism, adjacent block-generation advance, with no switch and no title reference. It serves M1–M2 and is replaced in M3 (spec/video-fmv.md). Not implemented: there is no adjacent-generation code underlibSceAgcDriver/Graphicson main (beanportps5-ux18). - Recompiler: bindless tables with bounds taken from device limits (spec/shader-recompiler.md; bean
portps5-7li6). - Relinker: make the existing
.eh_frame-seeded CFG (CodeInstructionCollector) the only instruction-discovery engine, as one sharedCodeMapreplacing the linear sweep (spec/relinker.md); support Linux load-alignment and--windows-guiPE subsystem switch. - Export ABI: the
APS5_EXPORT_FNexport macro, which declares an exportAPS5_VABIandnoexcept(spec/build-toolchain.md). The macro exists; adopting it at call sites is the open item below. - Guest memory: replace the arena's O(n) first-fit scan with a free-list allocator; add explicit pins, the registry-owned page-state table, and return codes in place of throws (spec/guest-memory.md). Parts landed as unwired building blocks (bean
portps5-421ptracks the wiring):- extent-tree allocator core with a 10^6-operation differential test (PR #32,
GuestArenaExtent); - explicit pin tokens and the page-state table in
WriteWatchTracker(PR #40); - return codes instead of throws in direct memory and memory pools (PR #39);
- the arena, heap spans and registry use them, and the runtime instantiates the tracker (bean
portps5-421p).
- extent-tree allocator core with a 10^6-operation differential test (PR #32,
- Offline behaviour for network stack (
libSceNet), AvPlayer playback state machine (libSceAvPlayer), NP/PSN, trophies, store, and user-service dialogs, so no gate title blocks on them at boot. -
libSceVideodec2AVC decode (host H.264 decoder: FFmpeg built LGPL-only from the pinned3rdparty/FFmpeg, licence gate in spec/build-toolchain.md); HEVC and the AJM MP3 path stay open (spec/video-fmv.md). - Rewrite pthread/umtx/cond on futex words (
WaitOnAddress), with no global mutex and compact guest tids, and make errno returns correct. Unimplemented exports callUnsupported(), which logs and aborts (spec/threading.md). - No host exception crosses an
APS5_VABIboundary: adoptAPS5_EXPORT_FN(noexcept) at every export and remove the remaining throwing exports such aslibSceSysmodule/Export.cpp(spec/threading.md Error policy, TechnicalDebt.md "Host exceptions"; beanportps5-uanr). - Image codecs: shared stb-backed JPEG/PNG layer (
core/Decoder),libSceJpegEncandlibScePngDec(spec/image-codecs.md);libScePngEncremains open. - Per-game TOML config, with
display.present_modeanddisplay.resolution_scalewired. Remove theAPS5_*behaviour switches; keep a typed[debug]section (beansportps5-c06p,portps5-dtwf).-
Configschema, validation and the typed[debug]section (libc/src/Config.cpp,core/libs/tests/Config.cpp); noAPS5_string literals remain incore/and thepolicyjob enforces it; - startup loads config for the
param.jsontitle ID before guest initializers (startup portion of beanportps5-c06p); -
display.present_modeanddisplay.resolution_scalereach the driver: the swapchain is hard-coded to FIFO (beanportps5-dtwf).
-
- Runtime telemetry: frame-time log, watchdog, structured logs, audio underrun and latency counters, and the A/V offset skeleton (
video_latency_ms). The telemetry core, watchdog and mixer counter integration exist (PR #78, beanportps5-f9a3completed; spec/verification.md 4.3); the start-up, presenter and guest-progress call sites are not wired, so this stays open (beanportps5-w1re). - Hosted CI job
recompiler-golden(synthetic corpus green in CI; merged into thebuild_and_testjob by PR #38). - Hosted CI job
driver-lavapipe:ci.ymljobdriver_lavapiperunsctest --preset lavapipeon Mesa lavapipe (beanportps5-ekx3). - Inventory each gate title's imports (NIDs, audio and video codecs, dialogs). One title of five is recorded; a repeatable tool (bean
portps5-zadg) and the other four (beanportps5-3eh1) are open.- Dreaming Sarah (recorded 2026-09-29): 815 relocation refs / 484 unique NIDs, all 484/484 resolve at link time to built prx exports (6 libc locale/iostream data symbols resolve to stubs/host-backed placeholders);
libSceVideoOutConfig::Loaderverbatim exports resolved. Detail in spec/relinker.md Open questions.
- Dreaming Sarah (recorded 2026-09-29): 815 relocation refs / 484 unique NIDs, all 484/484 resolve at link time to built prx exports (6 libc locale/iostream data symbols resolve to stubs/host-backed placeholders);
Exit criteria
- (bean
portps5-0mv7) With title-specific code removed, Demon's Souls reaches the in-engine intro cinematic, the stage AnyPS5 PR #5 reached. Its fill and copy kernels run as the title's own shaders, without replacement. ThepolicyCI job is green. - Sync microbenchmark: uncontended lock/unlock at least 10× faster than the old implementation, and the pthread and
SyncOnAddressGoogleTest suites pass. - The hosted golden corpus contains synthetic shaders that cover every decoded instruction class, and it is green in CI. The local-only game-derived corpus replays with 0 validation failures (bean
portps5-oq4m).
Scope
- Input: XInput, DualSense over USB, and keyboard/mouse mapping in TOML (spec/input.md; bean
portps5-de24).- SDL joystick/HIDAPI are enabled (
CMakeLists.txt:55-58), and SDL game controllers feedscePadReadwith hot-plug, slot assignment, a radial dead zone and keyboard merge (PRs #54 and #57, tests intests/input/ControllerInputTests.cpp). Not verified with a physical controller; - mouse backend (
libSceMouse/src/mouse_impl.cpp) and VideoOut routing exist, but thesceMouse*exports are stillUnsupported()stubs andmouse_testsisDISABLED(beanportps5-afme, low priority); - DualSense output path in software: rumble, light bar, trigger effects, motion, touchpad fingers and a pure hot-plug
SlotTable, with device-free GoogleTests (tests/input/Pad*Tests.cpp, beanportps5-j7ds). Not verified with a physical controller (beanportps5-ds7h); - TOML keyboard/mouse bindings (only
[input] deadzoneis consumed), XInput and DualSense USB on the manual matrix, slot reassignment tests with injected SDL events (beanportps5-de24).
- SDL joystick/HIDAPI are enabled (
- Establish filesystem sandbox, input, and audio GoogleTest suites ported from ecosystem references:
- Filesystem sandbox: port path-traversal containment (
../), mount sandbox isolation, and default-deny permission tests from SharpEMU (KernelSandboxEscapeTests) (spec/save-data.md); - Save data: port directory layout, quota enforcement, atomic commit, and crash-safe snapshot restore tests;
- Input: port DualSense USB report parsing, radial deadzone calculation, rumble motor translation, and hotplug slot assignment tests from KytyPS5 (
PadHapticsTests) (spec/input.md); - Audio: port AudioOut2 port lifecycle, ATRAC9 header decoding, and mixer resampling tests from KytyPS5 (
AudioOut2PortTests) (spec/audio.md).
- Filesystem sandbox: port path-traversal containment (
- Save data: dialogs return scripted and logged results instead of silent stubs; saves are stored per title, with crash-safe snapshots and a one-time copy of the old
_sdlayout (spec/save-data.md). - Audio: a single host mixer with a resampler and a soft limiter, on one device clock (spec/audio.md).
- The disk pipeline cache (bean
portps5-8gdr). - Driver: depth/stencil and conditional colour-write state decode,
VkPipelineDepthStencilStateCreateInfoemission and pipeline-cache keying (Graphics/src/State.cpp). - Driver: host depth/stencil surface (
DB_Z_INFOdecode, hostVkImage, render-pass attachment,DB_RENDER_CONTROLclears, depth bounds,DB_DEPTH_CONTROLbit 31 colour suppression) (Graphics/src/DepthSurface.cpp, spec/gpu-driver.md; PR #55, beanportps5-mij8completed). - Per-title
/savedata0mount for guest file I/O with sandboxed paths (PR #53, beanportps5-10frcompleted).sceKernelLseekreturnsEOVERFLOWat or above 2 GiB; a 64-bit path is beanportps5-65h0. - Driver: retile depth to guest memory (CPU or shader reads of a depth buffer) and guest-memory upload of never-cleared depth surfaces. A draw that depth-tests a surface that was never cleared is rejected until then (bean
portps5-9s7e). -
tools/regresslocal regression plus results JSON upload, with the config hash and the "FMV played" rule (beanportps5-3m3u). Runner, results JSON and pass rule landed astools/regress.py; frame checks, checkpoint replay, shader corpus step and upload remain, so this stays open.
Exit criteria
- Dreaming Sarah and TMNT: Shredder's Revenge pass the full-run protocol (average ≥30 fps, 1% low ≥20 fps, 1080p, 0 crashes and 0 softlocks, save round-trip). Dreaming Sarah: bean
portps5-kmb6. - Their results JSON is published, and the compatibility list is generated (TMNT full run bean
portps5-macl; generator beanportps5-4bkt).
Scope
- Driver:
- split into CommandProcessor, Recorder, Buffer/Texture/Pipeline caches, Rasterizer and Presenter, recording into a GPU IR with explicit resource states and a queue tag (bean
portps5-hkwd; spec/gpu-driver.md Decision); - a GPU-side path for the
DRAW_INDIRECTfamily (beanportps5-y2k5; AnyPS5main@75a8668takesvkCmdDraw[Indexed]Indirect[Count]only when the record fold, shader path, draw index and memory state allow it, and otherwise reads records on the CPU:Draw.hpp:43,Draw.cpp:823-830); - general block-generation write tracking for GPU-written surfaces, replacing the interim adjacent block-generation advance from M1–M2. Tomb Raider and Bugsnax FMV depend on it (bean
portps5-c08m); - redesign capture ordering: resolve buffers on the GPU, resolve images at submit time, and never satisfy a wait from an unexecuted label while a capture depends on it (bean
portps5-ubec).
- split into CommandProcessor, Recorder, Buffer/Texture/Pipeline caches, Rasterizer and Presenter, recording into a GPU IR with explicit resource states and a queue tag (bean
- Establish Vulkan driver cache and recompiler structurizer GoogleTest suites:
- Driver resource caches: port buffer/texture cache overlap, staging ring-buffer exhaustion, and descriptor set lifecycle tests adapted from DXVK and RPCS3 patterns (spec/gpu-driver.md; bean
portps5-oagr); - Structurizer: recompiler fuzz corpus and synthetic unstructured control-flow graphs covering irreducible loops and goto-elimination fallbacks (spec/shader-recompiler.md).
- Driver resource caches: port buffer/texture cache overlap, staging ring-buffer exhaustion, and descriptor set lifecycle tests adapted from DXVK and RPCS3 patterns (spec/gpu-driver.md; bean
- Recompiler: goto-elimination structurizer fallback, and bounded hash-indexed variants (bean
portps5-g580, which also owns the structurizer fuzz corpus). - Save data: the multi-slot list dialog, for Tomb Raider save/load (spec/save-data.md; bean
portps5-uag4).
Exit criteria
- Tomb Raider I-III Remastered passes the full-run protocol (bean
portps5-32ee). - A Demon's Souls stress run of 3 × 150 s of the intro cinematic has 0 wedges, with 0 skipped dispatches from the "guest memory is not readable" class (bean
portps5-273j). - Recompiler fuzz corpus: 0 structurizer throws (bean
portps5-g580).
Scope
- UE4 job-system coverage (event flags, semaphores, fibers) (bean
portps5-mv7o). - Establish fiber and job-system GoogleTest suites (bean
portps5-k34n):- Fibers and event flags: port fiber stack-switching, fiber-local storage (FLS), and event flag race perturbation tests from SharpEMU (
Fiber*Tests) (spec/threading.md); - Wave64 subgroup operations: synthetic compute dispatch validation for 64-wide lanes (spec/shader-recompiler.md).
- Fibers and event flags: port fiber stack-switching, fiber-local storage (FLS), and event flag race perturbation tests from SharpEMU (
- Wave64 through
VK_EXT_subgroup_size_controlwhere supported (beanportps5-cexw). - A GPU-side descriptor heap for bindless (
VK_EXT_descriptor_indexingorVK_EXT_descriptor_buffer) (beanportps5-zqk2). - Fill and copy kernels recognised by general IR patterns (bean
portps5-sio1).
Exit criteria
- Bugsnax passes the full-run protocol (bean
portps5-td65). - Every
[workarounds]key used by a gate title has an entry indocs/workarounds.md(beanportps5-il6p).
Scope
- Demon's Souls from the first level to credits:
- streaming and resource aliasing at full size (bean
portps5-951o); - host-import budget sized automatically (bean
portps5-wvxm; the AnyPS5 PR #5 description on GitHub reports a manual 16 GiBAPS5_HOST_IMPORT_MIBoverride for later stages); - direct-memory aliasing (the same physical range mapped at several guest addresses) with write tracking, which
GetWriteWatchmay not cover (spec/guest-memory.md); - audio object-port panning (spec/audio.md; bean
portps5-hwnz).
- streaming and resource aliasing at full size (bean
- Direct-memory multi-mapping and host-import stress suites: perturbation tests covering concurrent aliased writes and memory tracker cache coherency under 16 GiB budget pressure (bean
portps5-9p2i). - Performance pass against the bar (bean
portps5-vj60; performance track P3). - Spike: llvm-mingw clang with PDBs, adopted only if the DWARF unwinder validates (bean
portps5-qf1m).
Exit criteria
- Demon's Souls passes the full-run protocol, with title-specific behaviour only in its documented TOML (bean
portps5-clbd).
Scope
- A release full run of all five titles on the release commit (bean
portps5-vrfx). - Release docs: user guide (CLI usage, the legal boundary, the ban on sharing converted executables),
docs/workarounds.md, and the compatibility list (beanportps5-zl69). - Record the PRD R1 licence risk status in the release notes (bean
portps5-2t0e).
Exit criteria
- 5/5 gate titles pass the full-run protocol on the release commit (bean
portps5-vrfx). - Hosted CI and local regression are green (bean
portps5-vrfx). - The release notes are published (bean
portps5-zl69).
The track keeps the steady-state invariants of PRD §4.5 true while the milestones land. It runs alongside M2–M5 and gates nothing by itself; the milestone exit criteria still do. Every step measures first: before/after numbers with the same build flags and the same run protocol. Epic bean portps5-7fqk.
P0: Measure (M2)
- Frame-time log, stalls, warm-up and pipeline-creation counts (PRs #76, #78).
- Telemetry call sites wired: start-up, presenter, guest progress (bean
portps5-w1re). - Results JSON frame-time percentiles (p50, p90, p99) and
tools/regress.py compareagainst a stored baseline (beanportps5-rrll). - Per-frame breakdown: CPU record and submit, GPU time from Vulkan timestamp queries, CPU wait on GPU, present wait (bean
portps5-hfiw). - Violation counters for invariants P1, P2, P3 and P5 (bean
portps5-aifo). - Telemetry completeness: a crash event producer (
portps5-yhj7);run.startwith build preset, commit, device, driver, present mode and scale (portps5-g2ll); memory and VRAM peaks (portps5-ybq3); stall attribution (portps5-26s5); boot and load timing (portps5-pk9m); shader and pipeline compile times (portps5-tg51); numericdialog.open(portps5-7qon);preparecopiesconfig/(portps5-3b4e). - Measurement tools: Tracy CPU and GPU zones behind
[debug] profile(portps5-wba0), perf scenes per gate title (portps5-52bs), CPU microbenchmarks with a nightly trend (portps5-i58o).
P1: Per-draw CPU cost (M2–M3, invariants P2 and P5)
- Pooled images for resident render-target sampling (PR #74, bean
portps5-r7qkstep 1). - Frame-timing report only when
debug.profilehasgpu(PR #71). - SSE2 compare of cached textures (PR #75) and the write-tracker skip of unchanged textures (PR #77; it takes effect once bean
portps5-421pwires the tracker). The P5 violation itself is beanportps5-2k6d. - Resident render-target baseline, then decide step 2 (bean
portps5-r7qk).
P2: GPU-side resolution (M3, invariants P1 and P6). The work is the M3 driver scope: the Recorder in the submit path (bean portps5-tiod), the GPU path for the indirect family, block-generation tracking and the capture-ordering redesign. The M3 module split records into a GPU IR with explicit resource states (spec/gpu-driver.md Decision), so barrier optimization, multithreaded recording and frame overlap can come later without a rewrite.
- M3 exit adds: in the Tomb Raider regression result, the P1 and P2 counters are 0 in steady state, or each nonzero counter has a bean (bean
portps5-32ee).
P3: Performance pass (M5). This is the existing M5 item. Every remaining invariant violation is removed or justified in its owner spec, and these open questions are decided with data: the async-compute queue and HTILE/DCC (spec/gpu-driver.md 2–3), multithreaded PM4 recording (gpu-driver 11), pipeline libraries (spec/pipeline-cache.md 3), and host core placement (spec/threading.md 9).
P4: Compiler and host (M2–M5, invariants P2, P3 and GPU time). Release builds ship without the SPIRV-Tools optimizer (PRD R1), so shader quality depends on our own passes.
- Shader optimization: GVN/CSE, copy propagation and control-flow simplification (
portps5-t5qa), uniformity analysis (portps5-1uym), specialization constants for draw state (portps5-9gsx), and a spike on runningspirv-optout of process (portps5-m5n7). - Pipeline compilation off the submit thread with graphics pipeline library fast-link, background optimized relink and parallel warm-up; no draw is ever skipped (
portps5-c1oi). - Driver: upload engine on timeline semaphores (
portps5-dtiq), barrier and redundant-state pass on the GPU IR (portps5-p2qp), frame pacing with present_wait (portps5-jy7n). - Host:
x86-64-v3with-ffp-contract=offand LTO (portps5-8x1k), GCC PGO from perf scenes (portps5-f2r1), guest allocator measured before any change (portps5-03bi). - Large pages for the guest arena and GPU allocations: open question, decided with data in the M5 pass (spec/guest-memory.md). Upscalers, frame generation and HDR are 2.0 (M12). 60/120 fps targets and frame-rate unlock patches are beyond 2.0 (PRD §11).
A lane can start when its blockers are done. Lanes in the same row can run in parallel. The beans record the same edges (blocked_by), so beans list --ready shows what can start now.
| Lane | Beans | Blocked by |
|---|---|---|
| Config copy at conversion | portps5-c06p (startup call landed in PR #71) |
none |
| Results compare | portps5-rrll |
none |
| Tracker wiring | portps5-421p |
none |
| Recorder in submit path | portps5-tiod |
none |
| Telemetry call sites | portps5-w1re |
none (config startup landed in PR #71) |
| Display keys | portps5-dtwf |
none (config startup landed in PR #71) |
| Frame breakdown | portps5-hfiw |
portps5-w1re, portps5-tiod |
| Violation counters | portps5-aifo |
portps5-w1re |
| Resident RT step 2 | portps5-r7qk |
portps5-w1re (baseline needs telemetry) |
| Tracy profiler | portps5-wba0 |
none |
| Build flags | portps5-8x1k |
none |
| Microbenchmarks | portps5-i58o |
none |
| Shader passes | portps5-t5qa, portps5-1uym |
none |
| spirv-opt spike | portps5-m5n7 |
none |
| Regress config copy | portps5-3b4e |
none |
| Perf scenes | portps5-52bs |
portps5-3m3u |
| Specialization constants | portps5-9gsx |
portps5-8gdr |
| Async pipeline compile | portps5-c1oi |
portps5-8gdr |
| Compile-time telemetry, crash, boot, dialogs | portps5-tg51, portps5-yhj7, portps5-pk9m, portps5-7qon |
portps5-w1re |
| Run metadata | portps5-g2ll |
portps5-w1re |
| Memory telemetry | portps5-ybq3 |
portps5-w1re, portps5-l77s |
| Frame pacing | portps5-jy7n |
portps5-dtwf, portps5-w1re |
| Upload engine | portps5-dtiq |
portps5-hkwd |
| Barrier pass | portps5-p2qp |
portps5-hkwd, portps5-hfiw |
| Stall attribution | portps5-26s5 |
portps5-hfiw, portps5-aifo |
| Allocator | portps5-03bi |
portps5-wba0 |
| PGO | portps5-f2r1 |
portps5-52bs, portps5-8x1k |
| P5 texture revalidation | portps5-2k6d |
portps5-421p |
Checks that run on synthetic inputs and so need no GPU and no game data (spec/verification.md §1.1). Epic bean portps5-7n6b.
| Lane | Bean | Blocked by |
|---|---|---|
| Vulkan validation layers | portps5-977n |
none |
| PE structure validation | portps5-s9zz |
none |
| Codegen metrics per PR | portps5-g0n7 |
none |
| C++ coverage report | portps5-02a4 |
none |
| Synthetic guest ELF end to end | portps5-ktrt |
none (portps5-sjuv fixed in PR #94) |
| Unsupported() counts and compat tiers | portps5-ba7d |
portps5-w1re, portps5-4bkt |
| Linux sanitizers | portps5-pbj2 |
portps5-37j0 |
| Fuzzing | portps5-axx6 |
portps5-pbj2 |
| clang-tidy and stricter warnings | portps5-hpx7 |
portps5-qf1m |
| Local nightly regression | portps5-e6xg |
portps5-3m3u, portps5-52bs |
Deliverables:
- Vulkan validation layers on the lavapipe job (bean
portps5-977n). - PE structure validation of relinker output (bean
portps5-s9zz). - Deterministic codegen metrics per PR (bean
portps5-g0n7). - C++ coverage report (bean
portps5-02a4). - Synthetic guest ELF end to end (bean
portps5-ktrt). - Unsupported() counts and compat status tiers (bean
portps5-ba7d). - Linux sanitizer job (ASan, UBSan, TSan) (bean
portps5-pbj2). - Fuzzing of ELF, PM4 and shader decoders (bean
portps5-axx6). - clang-tidy and
-Wcast-function-type(beanportps5-hpx7). - Local nightly regression on the maintainer machine (bean
portps5-e6xg).
Local triage for failures, next to the performance track's measurement. Everything sits behind [debug] keys, so a run that uses it never passes (verification.md §4.2), and captures, dumps and crash reports stay in <install>. Design: spec/gpu-driver.md "Diagnostics", spec/configuration.md, spec/verification.md §1 and §4.4. Epic bean portps5-etxc.
Deliverables:
- Device-loss triage:
VK_EXT_device_faultand per-draw breadcrumbs (beanportps5-636k). - Vulkan validation layer as a debug key for local runs (bean
portps5-c5if); the CI side isportps5-977nin the CI reliability track. - Debug names and labels mapped to guest packets (bean
portps5-ey3w), then a RenderDoc capture trigger (beanportps5-bbxe). - Shader printf at a guest PC (bean
portps5-7e2a). - Symbolised crash reports with a flight recorder (bean
portps5-cmyp). - Per-pipeline shader statistics (bean
portps5-dktm). - On-screen debug overlay (bean
portps5-h2rv). - Sanitizer presets that link on Windows: GCC UBSan in trap mode, plus an llvm-mingw ASan spike for host-only tests (bean
portps5-hmw8); the Linux ASan/UBSan/TSan job isportps5-pbj2.
| Lane | Bean | Blocked by |
|---|---|---|
| Validation layer debug key | portps5-c5if |
none |
| Debug names and labels | portps5-ey3w |
none |
| Shader statistics | portps5-dktm |
none |
| Sanitizer presets | portps5-hmw8 |
none |
| Device-loss triage | portps5-636k |
portps5-tiod |
| RenderDoc trigger | portps5-bbxe |
portps5-ey3w |
| Shader printf | portps5-7e2a |
portps5-c5if |
| Crash reports | portps5-cmyp |
portps5-yhj7 |
| Overlay | portps5-h2rv |
portps5-71o2, portps5-hfiw |
Design for 2.0, implement for 1.0. A seam moves into v1 only when v1 code uses it, it is cheap now, and the 2.0 milestone that plugs into it is named. Nothing here adds a 2.0 feature to 1.0. Epic bean portps5-epoi.
| Seam | v1 implements | 2.0 plugs in | Milestone | Bean |
|---|---|---|---|---|
Host platform layer core/host/ and a Win32 allowlist that only shrinks |
Win32 backend for futex, clock, virtual memory; contract tests | Linux backend (M7) | M2–M3 | portps5-37j0 |
| Proton smoke test | best effort, never blocks a PR | Linux validation (M7) | M2 | portps5-qfac |
| GPU IR with resource states and a queue tag | one queue, single-threaded recording | async compute, multithreaded recording, RT passes (M9–M10) | M3 | portps5-hkwd |
| Residency interface on the driver caches | no budget pressure, simple LRU | VRAM oversubscription manager (M8) | M3 | portps5-hps3 |
| Guest memory registry: physical allocation with N views | 1 view, plus a synthetic 2-view test | aliasing at full size (M5), streaming (M8) | M3 | portps5-gkef |
| One device capability table | subgroup size, descriptor model | ray tracing, mesh shaders (M9) | M3 | portps5-l77s |
| Recompiler decodes RT and NGG/mesh ops into IR | Unsupported() with a log |
RT and mesh lowering (M9) | M4 | portps5-jehk |
| Presenter composition hook and swapchain colour-space selection | final pass is a copy; SDR swapchain | spatial upscale, HDR output, frame generation (M12) | M3 | portps5-71o2 |
Pipeline cache EnvKey hashes enabled features |
current stages | new stages without a format break | M2 | portps5-8gdr |
| Positional file I/O and a request queue | sceKernelAio* |
streaming and decompression pipeline (M8) | M3 | portps5-j4e1 |
Two spikes de-risk 2.0 and can run any time, in parallel with everything: guest TLS on Linux (portps5-u16x) and the guest RT BVH layout against Mesa RADV (portps5-mdu8).
| Lane | Bean | Blocked by |
|---|---|---|
| Host platform layer | portps5-37j0 |
none |
| Proton smoke test | portps5-qfac |
none |
| Capability table | portps5-l77s |
none |
| RT and NGG decode | portps5-jehk |
none |
| TLS spike | portps5-u16x |
none |
| BVH spike | portps5-mdu8 |
none |
| Registry N views | portps5-gkef |
portps5-421p |
| GPU IR split | portps5-hkwd |
portps5-tiod |
| Residency interface | portps5-hps3 |
portps5-hkwd |
| Direct-memory aliasing (M5) | portps5-r2ns |
portps5-gkef |
| Positional file I/O and Aio | portps5-j4e1 |
portps5-37j0 |
| Presenter composition hook | portps5-71o2 |
portps5-l77s |
| 1.0 goal (PRD) | Delivered in | Verified by |
|---|---|---|
| F1 local CLI conversion | M0 (existing), M1 (--to-intel) |
CI build, M2 full runs |
| F2 save/load | M2 (per-title storage, scripted dialogs), M3 (multi-slot list dialog) | Save round-trip in regression and full run |
| F3 audio | M1 (AudioOut2, ATRAC9, codec inventory), M2 (single mixer, resampler, limiter), M5 (object-port panning) | Underrun telemetry, full runs |
| F4 FMV | M1 (saveexec fix, interim adjacent block-generation advance), M3 (general block tracking) | FMV frame checks, A/V offset telemetry, full runs |
| F5 input (XInput, DualSense, keyboard) | M2 | Full runs |
| F6 per-game TOML | M1 | policy CI job, docs/workarounds.md |
| F7 disk pipeline cache | M2 | Warm-cache full runs |
| F8 offline PSN/trophies | M1 | Full runs never blocked |
| F9 telemetry | M1 (core, PR #78), M2 (call sites portps5-w1re, completeness beans in the performance track P0) |
Results JSON present for every run |
| Performance bar (§4.3) | M1 (sync), M2 (depth/stencil), M3 (driver), M4 (subgroups), M5 (perf pass) | Results JSON fps stats |
| Performance invariants (§4.5) | Performance track P0–P3 (M2–M5) | Results JSON violation counters, before/after measurements |
| Ecosystem test suites (GTest, Kyty, SharpEMU, FreeBSD, Mesa, Wine) | M0 (framework), M1 (core runtime), M2 (sandbox/input/audio), M3 (caches/structurizer), M4 (fibers/jobs) | CI unit, recompiler-golden, driver-lavapipe |
| Gate 1: Dreaming Sarah | M2 | Full run |
| Gate 2: TMNT: Shredder's Revenge | M2 | Full run |
| Gate 3: Tomb Raider I-III Remastered | M3 | Full run |
| Gate 4: Bugsnax | M4 | Full run |
| Gate 5: Demon's Souls | M5 | Full run |
| No title-specific code | M1 (policy), all milestones | policy CI job |
| Hosted CI without GPU; local results | M0, M1, M2 | Verification spec |
| R1 licence risk documented | PRD §7, M6 release notes | Doc review |
2.0 objective and gates: PRD §10. Part II starts after M6. Before that only the Part I seams and the two spikes run. Each milestone becomes its own ooo seed, and its beans are created then, with blocked_by links. A milestone starts only when the previous one's exit criteria pass. The exceptions are M8, M9 and M12, which may run in parallel once M7 exits: they touch different subsystems (memory and I/O, GPU features, presentation). M8 and M9 have separate gate titles; M12 has no gate title and does not block M11, but it must land before the 2.0 release.
M6 (1.0) ─▶ M7 platform + tier ─┬─▶ M8 streaming (gate 6) ─┬─▶ M10 scale (gate 8) ─▶ M11 GTA VI (gate 9)
├─▶ M9 RT + geometry (gate 7) ┘
└─▶ M12 PC enhancement layer (no gate; ships with 2.0)
Scope
- Linux backend for every host platform service (spec/host-platform.md), relinker ELF output built and tested in CI, and a hosted Linux build running the same
ctestsuites. - Guest TLS on Linux per the spike result (
portps5-u16x). - The 2.0 reference tier: benchmark floors set from the 1.0 M5 performance-pass data, with ray tracing required (PRD §10.3).
- Pin every 2.0 gate title that can be dumped (PRD §10.1).
Exit criteria
- The five 1.0 gate titles pass their regression on Linux with the 1.0 pass rules.
- The Win32 allowlist outside
core/host/is empty.
Scope
- Residency manager behind the driver-cache interface (
portps5-hps3): a VRAM budget fromVK_EXT_memory_budget, eviction and re-upload, no eviction inside a frame's working set. - Hardware-decompression requests served off the guest thread on the positional I/O queue (PRD V3, licence recorded per V-R4).
- Guest memory beyond host VRAM at full open-world size, with write tracking and aliasing (M5 mechanisms at scale).
Exit criteria
- Horizon Forbidden West passes the full-run protocol on the 2.0 tier, with 0 stalls caused by eviction.
Scope
- Guest acceleration-structure builds and ray queries on Vulkan ray tracing, designed from the BVH spike (
portps5-mdu8). - Primitive (NGG) and mesh shader stages in the recompiler and driver, on the IR ops from
portps5-jehk. - Async compute on a separate host queue through the GPU IR queue tag (gpu-driver open question 3).
Exit criteria
- Ratchet & Clank: Rift Apart passes the full-run protocol on the 2.0 tier in one of its RT modes. Skipping RT work is a fail.
Scope
- Multithreaded recording and bounded CPU/GPU frame overlap (invariant P6, gpu-driver open question 11), decided from frame-breakdown data.
- Every remaining PRD §4.5 violation on gates 6–8 removed or justified.
Exit criteria
- Marvel's Spider-Man 2 passes the full-run protocol on the 2.0 tier.
Scope
- Pin GTA VI once a user-owned dump exists (PRD V-R1); inventory its imports.
- Release full runs of gates 6–9 on Windows and Linux.
Exit criteria
- GTA VI passes the full-run protocol on the 2.0 tier at ≥ 30 fps average and ≥ 20 fps 1% low, with title-specific behaviour only in its documented TOML.
- Gates 6–8 still pass, on both platforms.
All enhancements are opt-in per title, configured through documented [enhancement] keys that name the mechanism, and switched off for every pass measurement (PRD V7).
Scope
- Spatial upscaling (FSR1/CAS, MIT) in the presenter's composition pass (
portps5-71o2), with internal resolution fromdisplay.resolution_scale. - HDR output: the guest VideoOut HDR mode mapped to an HDR10 or scRGB swapchain with
VK_EXT_hdr_metadata, chosen from the capability table. - Temporal upscaling (FSR2+; DLSS and XeSS only if the licence spike
portps5-f4blclears them), fed by the general input recogniser from spikeportps5-8ov1. - Frame generation, presentation only: it never changes guest simulation, input or timing, and it is off while telemetry measures a pass.
- Experimental flip-rate override (
[enhancement] flip_rate_override), off by default, never part of a pass, with the timing risk documented (PRD §11).
Exit criteria
- Each enhancement runs on at least two 2.0 gate titles with no change to their pass results when switched off.
-
docs/workarounds.md(or a newdocs/enhancements.md) lists every[enhancement]key with its mechanism.
v3 candidates and permanent exclusions, with the reason each is out, are in PRD §11. The AI-assisted optimization research there starts with deterministic shader-variant autotuning and profile-guided relinker layout, and keeps every model output as a verified, locally derived cache.
| 2.0 goal (PRD §10) | Delivered in | Seam from Part I |
|---|---|---|
| V1 native Linux | M7 | portps5-37j0, portps5-u16x |
| V2 streaming and residency | M8 | portps5-hps3, portps5-gkef |
| V3 decompression | M8 | portps5-j4e1 |
| V4 ray tracing | M9 | portps5-l77s, portps5-jehk, portps5-mdu8 |
| V5 modern geometry | M9 | portps5-jehk |
| V6 async compute, frame overlap | M9, M10 | portps5-hkwd, performance track |
| V7 PC enhancement layer | M12 | portps5-71o2, portps5-l77s, portps5-hkwd |
| Gate 9 GTA VI at 30 fps | M11 | all of the above |