Repository navigation
feat(libs): the Hmd2 reprojection session - #7658
oneandonlydean merged 9 commits into
Conversation
Progress report (e0caf13 → 3226e99)📈 System libraries: 26.27% (+0.02%, +6 implemented functions) ✅ 6 implemented
Changed libraries (implemented exports)
|
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Two existing tests fail with this PR, on Windows and probably elsewhere. Their expected messages still have the With this PR merged alone onto
Separately, AGENTS.md asks for AI-assisted |
|
Two console datapoints for the Hmd2 part, measured on a retail PS5 (firmware 13.60, no headset) by loading
I had the five size queries ready as a follow-up to #7463 with those console values; happy to drop |
|
Datapoint from Gran Turismo 7 (PPSA01317, 01.000.001 base package) on
All three stops are on the same module-load thread (a Horizon Call of the Mountain (PPSA05666, v01.004.011) on the same Two notes on the tree:
stderr, run 2 with this PR alone (abort block)stderr, run 3 with this PR + #7690 (abort block)Tested. Windows 11 (26200), RTX 4090 (NVIDIA 616.92), WinLibs GCC 15.2.0 r7 (UCRT), Release AI-assisted: yes (Claude Code). |
|
@primesoul-web We are preparing a libSceHttp transport contribution in omar-akermi#1 and are coordinating the shared Your change preserves the offline backend's rejection of cookie enabling. Our branch replaces that offline backend with a per-context curl cookie engine, including inherited enable/disable settings and cookie receive callbacks, so it supersedes this particular error path. We are currently integrating and retesting against upstream ca13a56; Windows, native Linux and ASAN results from the previous integrated revision are linked in the fork draft. Proposed merge order: #7658 first, then the HTTP transport. If #7658 lands first, we will merge its resulting main revision and retain the real cookie implementation when resolving this hunk. If the transport lands first, #7658 should drop its cookie-only hunk rather than restore the offline throw. The transport has no functional dependency on the other exports in this PR. Does that order work for you? No agreement is assumed until you reply; we will record the agreed order and any required dependency in the upstream PR checklist. |
|
Thank you for the Windows run and the precise reproductions — both failures are fixed in 93bbeb3.
On the |
|
Thank you for the retail measurement — adopted. 93bbeb3 makes Please keep all four remaining size queries in your #7463 follow-up — this PR deliberately leaves them throwing so your measured The layout confirmation for |
|
Thank you for the three-tree measurement — the stop-walk table and the stderr blocks make the remaining throw chain unambiguous, and the "same module-load thread, before the first frame" observation is a nice confirmation that this is the set-up path and nothing else. Both tree notes are addressed in 93bbeb3:
On the predicted |
|
That order works for us: #7658 first, then the HTTP transport. The branch keeps the offline backend's rejection hunk, and 93bbeb3 updates No dependency from this PR's other exports on the transport. If the maintainer happens to land the transport first, we will drop the cookie-only hunk here as you propose rather than restore the offline throw — please link the upstream PR here when it opens and we will record the agreed order either way. |
…jection session Adopt main's restored reprojection ABI (two-argument Initialize with the reserved parameter, single-argument SetAllowPositionalReprojection, ReprojectionInitializeParameter layouts, typed mirroring/parameter structs) over the session implementations; the measured table is unaffected because the console ignores the extra arguments. ReprojectionInitializeParameter moves to Hmd2.hpp so GuestHmd2 can construct it; GuestHmd2's main drops the QueryBufferSizeAlign throw expectation the implementation supersedes and keeps the wave's before-initialization checks.
|
The ABI sweep landed on The measured table is untouched — frankea's 13.40 rows and T3cm0's 13.60 datapoint answer exactly as before, because the console ignores the arguments the restored ABI drops. Re-measured on the merged tree against |
|
A re-verification against today's The newest neighbour in this file, hypermist's Nothing is needed on our side: the branch is unchanged since 4cf2a20 and merges as-is. |
|
@primesoul-web Some data for the session, from
AI-assisted: yes (Claude Code) |
|
Thank you — this settles both open questions about the session with the module itself, and the adoption is in head 24d4edc. SetTiming: the out-of-range throw is gone; the setting now answers Initialize: the app-info gate is recorded in the debt entry rather than implemented — the module's 0x8a72001f for a failed The in-session table: GetStatus's 0x68-byte record (zeros to 0x28, the four advancing timestamps, then zeros), GetPredictedDisplayTime's 0x8a720019 for every frame id and 0x8a720008 for a null output, SetRenderConfig's bit rules answering 0x8a720009 for (0, 1, 1) and (2, 0, 0), and SetParam's 0x8029000a / 0x80290002 are now in the debt entry as measured reference for whoever implements them — none of them is in this PR's six, so the scope stays the session. The head also carries the new |
|
@primesoul-web thanks for this. Two small things. First, please don't have the test assert that Initialize with auxiliary memory throws. We keep tests to real behaviour and argument validation, because a test that pins a not-yet-implemented path breaks the moment someone implements it. Second, the new Hmd2 debt bullets say "GT7" three times ("inside a GT7 session on firmware 13.40" and the like). We keep game names out of the debt docs; could you describe it as a session on firmware 13.40, or give the title's PPSA id instead? The PPSA ids already in the bullets can stay. |
The initialization-with-auxiliary-memory assertion pinned a not-yet-implemented path and would break the moment auxiliary memory grows an implementation, so the test goes back to the session's real behaviour and argument validation. The debt bullets name the measured session's title id (PPSA01317) instead of its name, per the review.
|
@oneandonlydean both done in head 1f774a2. The test: the initialization-with-auxiliary-memory assertion is gone, together with its buffer and the try/catch that carried it — GuestHmd2 keeps to the session's real behaviour and argument validation: the null-parameter and buffer checks, the initialization writing the default timing into the work memory, the second initialization answering The debt bullets: the three game names are now the title's id — "inside a session on firmware 13.40 (PPSA01317)", "In a session on firmware 13.40 (PPSA01317) GetPredictedDisplayTime answered…" and the SetRenderConfig/SetParam bullet likewise, matching the PPSA ids the bullets already carry. The branch still merges clean against current |
…ction session Main restructured the libSceHmd2 debt file since c547dea: the Additional callable exports section with the inventory table, the Mirroring/PredictedDisplayTime/SetRenderConfig functional bullet (carrying the session measurements from this pull request's discussion), the Older callable NIDs bullet, and the Unknown CBkVZi9WhVo entry. The parameter-submission bullet conflicted with this branch's measured rows; the resolution keeps the measured rows and main's ending.
|
@oneandonlydean @adriadam10 the branch carried current The resolution keeps both: the measured rows stay ( Re-verified on the carried tree: GuestHmd2 passes (session behaviour and argument validation), the negative control against |
What
the Hmd2 reprojection session on its own, split from the earlier revision of this pull request per its review: libSceHmd2 16/153 -> 22/153 on main 926f7dd (26.33%, 9171/34833 -> 26.35%, 9177/34833, +6, no regressions; the denominator grew with the firmware-database declaration waves since the pull request was opened, the implemented delta is unchanged).
sceHmd2ReprojectionQueryBufferSizeAlignanswers the console's requirement as measured in the discussion below (firmware 13.40 and 13.60): 0x100828 bytes at 0x100 while the process's positional setting is unset, and 0x1103000 + n * 0x1000000 at 0x1000 oncesceHmd2ReprojectionSetAllowPositionalReprojectionhas recorded a first argument of n = 1 to 5; the setting is process-wide without an initialization, answers 0 for 0 to 5 andPARAMETER_INVALIDfor anything else with the previous setting kept, and the query never reads its own arguments.sceHmd2ReprojectionInitializeanswersPARAMETER_NULLfor a null param or buffer, throws for an auxiliary-memory buffer and writes the 16-byte state (output mode, timing in microseconds) into the guest's work buffer with the timing the param carries or the 3000 us default; a second initialization answersREPROJECTION_ALREADY_INITIALIZED. The firmware first reads the process's app info and answers 0x8A72001F before its arguments when that fails or the info's nonzero attribute field lacks bit 0x400 (measured, firmware 13.40 — the answer MLB The Show 25 gets on #8645); the emulator's app info does not model the attribute fields, so every caller passes the gate, and the debt entry records the difference. The signatures follow the ABI restored on main (the firmware-database sweep of 2026-10-21): a two-argumentInitializewhosereservedsecond parameter is ignored, a single-argumentSetAllowPositionalReprojection, and the sweep'sReprojectionInitializeParameterfield names at the same offsets this PR's 72-byte validation pinned — the console ignores the extra arguments, so the measured table is unchanged.sceHmd2ReprojectionSetTiminganswersNOT_INITIALIZEDwithout a session,PARAMETER_INVALIDbelow 2000 us and above 7000 us and otherwise rounds the value up to the next hundred microseconds, answering 0 at once when the rounded value equals the current timing (measured, firmware 13.40 — the earlier revision threw out of range); the module forwardssceVideoOutSetDisplayEventPosition's result when the timing changes, which the debt entry holds until VideoOut grows that export.sceHmd2ReprojectionEnableVrModeanswersNOT_INITIALIZEDwithout a session,VIDEO_OUT_ERROR_INVALID_VALUEfor an output mode other than 0x2000C and 0x2000F and otherwiseVIDEO_OUT_ERROR_NO_DEVICE.sceHmd2ReprojectionTerminateends the session (the memory point in the review): it clears the record under the reprojection mutex, so the gated exports answerNOT_INITIALIZEDagain and a new initialization is accepted. The teardown follows the session model and is not a console measurement, and the positional setting survives it. The record is a borrow of the guest's work buffer: the guest keeps the buffer for the session's lifetime and frees it after terminating, every read and write of the record happens inside an export call under the mutex, and a guest that frees the buffer while the session is live corrupts its own heap exactly as it would on hardware. The debt entry carries the full wording.T3cm0's #7690 (the console display and mirroring sizes) landed in the same four files and is carried unchanged in 59f2d3339's resolution: its four implementations, its size-query test and its debt bullet are main's, and the stale "display and see-through stay unimplemented" sentence is dropped from the Silent stubs bullet since the merged tree implements them. His #7798, #7805 and #7826 add other Hmd2 exports in the same files; the hunks do not meet, and whichever lands second rebases.
Tested
GuestHmd2 walks the measured table and the session on top of #7760's without-headset tests, #7690's console size-query session and the ABI-restored signatures carried in 4cf2a20 (the pre-session block and the session walk call the new forms; nikowolf123's two mutations rebuilt as negative controls still abort on the carried head): the rejected settings keep the previous answer, n = 1, 2 and 5 answer 0x2103000 / 0x3103000 / 0x6103000 at 0x1000, n = 0 restores 0x100828 / 0x100, the timing answers
PARAMETER_INVALIDbelow 2000 and above 7000 with the recorded setting kept, 2001 rounds to 2100, a repeat of 2100 answers 0 at once, the range ends 2000 and 7000 succeed, and the terminate teardown answers NOT_INITIALIZED for the gated exports and accepts a re-initialization with the default timing. The measured-timing rows and the app-info gate follow frankea's firmware 13.40 module read and GT7 session measurements (2026-10-26), carried in head 24d4edc together with main's canonical-headers refactor; the negative control against main's markerExport.cppstill aborts at the session exports. oneandonlydean's review asks are addressed in head 1f774a2: the guest test keeps to the session's real behaviour and argument validation (the auxiliary-memory throw is no longer pinned), and the debt bullets name the measured session's title id instead of its name. The branch carried currentmain's Hmd2 debt-file restructure in head 3226e99 with both sides kept, and GuestHmd2 plus the negative control were re-verified on the carried tree (the carry notice of 2026-11-01).Checklist