Repository navigation
feat(libSceVideoOut): implement sceVideoOutSubmitChangeBufferAttribute - #15247
AlexWhitehouse wants to merge 3 commits into
Conversation
Progress report (6ed10cc → 8ea336b)📈 System libraries: 29.24% (+0.01%, +1 implemented functions) ✅ 1 implemented
Changed libraries (implemented exports)
|
✅ NVIDIA GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (1, not counted against this PR)Validation IDs already present on main (4 IDs in 384 tests)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
2f2b317 to
963fc0e
Compare
BunnyFl
left a comment
There was a problem hiding this comment.
@AlexWhitehouse thanks for this. The firmware has a different check order at the start, and one of the new throws should be a returned code.
The null attribute is checked first, and it returns a code. In firmware 13.42 system/common/lib/libSceVideoOut.sprx (sha256 975b229324655a2d2a945c755fc0339e7feecb62863efc28ad3b2d91a95ad215), sceVideoOutSubmitChangeBufferAttribute (IOdgHlCGU-k, 0x112e0) begins, read from disassembly and not run:
112e0: test %rdx,%rdx
112e3: je 0x1133c ; attribute == nullptr
...
112f8: call 0x13f00 ; port lookup by handle
112fd: test %rax,%rax
11300: je 0x11342
...
1133c: mov $0x80290002,%eax ; returned before any handle lookup
11341: ret
11342: mov $0x8029000b,%eax
So, on the console:
(any handle, i, nullptr)returns0x80290002, which isVIDEO_OUT_ERROR_INVALID_ADDRESS(-2144796670inVideoOutDriver.hpp). That includes an unknown handle.- A non-null attribute with an unknown handle returns
0x8029000b(VIDEO_OUT_ERROR_INVALID_HANDLE), as you have it.
On this head (core/libs/prx/libSceVideoOut/src/Buffer.cpp):
(badHandle, 0, nullptr)returnsINVALID_HANDLE: the handle check is atBuffer.cpp:221, before the null check at:226.(validHandle, 0, nullptr)throwsVIDEO_OUT_ERROR_INVALID_ADDRESS(:227) instead of returning it. ThesetIndexthrow (:223) also comes before the null check here, while the console reaches the handler with any index once the pointer and handle pass.
Suggested fix: make if (attribute == nullptr) return VIDEO_OUT_ERROR_INVALID_ADDRESS; the first statement, then check the handle, and add a test row for each.
After those two checks the module doesn't validate anything itself. It reaches the port's handler through 0x8(%rax) → 0xa8, which is call *%rax at 1131e with (*port, setIndex, attribute) (11315: mov (%rbx),%rdi). If that handler is null it returns 0x8029001b. On a non-negative result it calls 0x1a160(port, setIndex, attribute, -1). So the index, reserved-field, aspect-ratio, pitch and tiling checks and their order sit in the handler, which this export doesn't show. That fits your debt entry, which leaves them as shadPS4's and unverified on the PS5. I didn't follow the handler pointer, so I can't say where it lands.
What I ran: this head merged onto main (merge 14f2bb9558), Windows 11, WinLibs GCC, Release, AMD Radeon RX 9070 XT. With ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, all 28 video_out_flip_* tests pass (28 of 28), video_out_flip_ps4 included. I haven't compared VUID- output: these runs were without -V, and I didn't run main alongside. The finding above is about the CPU-side order and doesn't depend on it.
|
Thanks, done in a760a3e: a null attribute is now checked first and returns |
✅ AMD GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (3, not counted against this PR)Validation IDs already present on main (8 IDs in 467 tests)Skipped (8)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
BunnyFl
left a comment
There was a problem hiding this comment.
@AlexWhitehouse thanks, this matches the 13.42 order I described: the null attribute now returns VIDEO_OUT_ERROR_INVALID_ADDRESS as the first statement (Buffer.cpp:220), before the handle check, and no longer throws. The new rows in Flip.cpp cover a null attribute with indices 0, 1, 3, -1 and VIDEO_OUT_BUFFER_ATTRIBUTE_NUM_MAX, and with handles -1, 0 and VIDEO_OUT_NUM_MAX, and the debt entry now separates the two checks read from the module from the handler's checks, which stay unverified.
What I ran: head a760a3ea0c merged onto main 1c8c0efc8c, Windows 11, WinLibs GCC, Release, AMD Radeon RX 9070 XT, with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:
- all 28
video_out_flip_*tests pass (28 of 28); - mutation A (handle checked before the null attribute):
video_out_flip_ps4fails with "the legacy change checked its handle before a null attribute"; - mutation B (a null attribute throws
VIDEO_OUT_ERROR_INVALID_ADDRESSinstead of returning it):video_out_flip_ps4fails on the uncaught throw; tools/check_conventions.py --base upstream/mainon the head: all checks passed.
I didn't compare VUID- output myself (no -V run on main alongside); your run and the AMD CI comment above report none new. Approving.
✅ NVIDIA GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (1, not counted against this PR)Validation IDs already present on main (8 IDs in 467 tests)Skipped (5)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
a760a3e to
723e10f
Compare
✅ NVIDIA GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (1, not counted against this PR)Validation IDs already present on main (9 IDs in 549 tests)Skipped (2)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
BunnyFl
left a comment
There was a problem hiding this comment.
Re-checked — approved
@AlexWhitehouse re-approved at 723e10f82b. My approval sat on a760a3ea, which you force-pushed over, so I re-ran everything rather than carrying it forward.
What changed since the head I approved. git range-diff from a760a3ea over the two merge bases shows the null-attribute commit identical (=) and the first commit differing only in the debt count line, which the rebase onto newer main re-resolved. No code changed.
The debt count. 174 is right, counted from the file rather than by subtracting: the bullet's number is the length of the table under it, and it reads 174 with 174 rows, against main's 175 with 175 rows. The removed row is sceVideoOutSubmitChangeBufferAttribute, which is also the one placeholder dropped from InventoryExports.cpp and InventoryExports.hpp. Keeping of the original 182, 107 match unchanged is correct now that main phrases that clause against the original set.
The firmware line, re-read. libSceVideoOut.sprx, firmware 13.42, sha256 975b229324655a2d2a945c755fc0339e7feecb62863efc28ad3b2d91a95ad215, from disassembly only, not measured on a console:
112e0: test %rdx,%rdx ; 112e3: je 0x1133c ; attribute == NULL
1133c: mov $0x80290002,%eax ; 11341: ret ; INVALID_ADDRESS, before anything else
112f8: call 0x13f00 ; port lookup from the handle
112fd: test %rax,%rax ; 11300: je 0x11342
11342: mov $0x8029000b,%eax ; INVALID_HANDLE
11305: mov 0x8(%rax),%rax ; 11309: mov 0xa8(%rax),%rax
11310: test %rax,%rax ; 11313: je 0x11349 ; -> 0x8029001b when the handler is absent
1131e: call *%rax ; the port's handler, which I did not read
So the entry's "returns INVALID_ADDRESS for a null attribute, then INVALID_HANDLE; every other check is in the port's handler, not read" is accurate, and the order you now implement is the console's. I followed 0x112e0 to the ret at 0x11341 and to the three error arms above; the handler behind call *%rax is unread here too.
The three new constants also exist in that module as immediates: 0x80290004 three times, 0x80290007 three times, 0x80290008 once. That is corroboration that they are real libSceVideoOut codes, not evidence of which check uses which, since the handler behind 0x1131e is not something I read.
The shadPS4 attribution matches the code it names, read at commit 2183807e592b36d4440384878165b43d930c1dee: video_out.cpp lines 452-460 return INVALID_HANDLE for a missing or closed port and delegate to ChangeBufferAttribute, and driver.cpp lines 198-234 check the index and occupancy, the reserved fields, aspect_ratio, width > pitch_in_pixel and the tiling range, in that order, before copying the attribute. Your relative order is the same for the four checks you share with it, and the entry is right that AnyPS5 diverges by throwing INVALID_INDEX and INVALID_OPTION where shadPS4 returns INVALID_VALUE. Checking setIndex < 0 as well is a genuine improvement on that source, which only rejects the upper bound.
What I ran. Windows 11 Pro, WinLibs GCC, Release, BUILD_TESTING=ON, head merged into current main:
^video_out_flip: 28 of 28, nothing unbuilt and nothing skipped.video_out_flip_ps4is the one that reaches the new export, and it passed. These skip without a display; I checked the log for skips and there were none.- Validation layer on for that run (
ANYPS5_REQUIRE_VULKAN=1,ANYPS5_NO_SHADER_CACHE=1,VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation,ctest -V): no missing-layer line, noVUID-id and noSYNC-HAZARDid. - GPUs tested: AMD Radeon RX 9070 XT, driver 32.0.32015.12012, Windows 11 Pro.
- A plain negative control is not available here: restoring
main'sBuffer.cppleavesFlip.cppcalling an exportmaindoes not declare, so the link fails rather than a test failing. So I used a mutation probe instead, on the merged tree: moving the null-attribute check below theHasConfighandle check, which is exactly what the firmware above rules out. The swap is one block and the diff confirmed it landed only inside the new function; after rebuildinglibsandvideo_out_flip_tests,video_out_flip_ps4failed on its own assertion,the legacy change checked its handle before a null attribute. I restored the file afterwards and the tree came back clean.
Overlap, checked myself at this head with tools/pr_overlap.py --branch. One comparison reported a shared line, and it is with my own open #14954, on the docs/dev/debt/libSceVideoOut.md entry at L68 rather than on code; whichever of the two lands second will re-resolve that line. A search of open pull requests for the export name returns only this one; nothing else implements it. Nine comparisons could not be completed because those pull requests conflict with main, so I looked at the three that share Buffer.cpp through GitHub's own file lists instead of a local diff.
One thing to coordinate, not a change request
#9676 (MERGEABLE) and #6977 both rework this same area, and the interaction is worth settling before either lands rather than after:
- They add a
Ps4TiledPitchhelper and agroup.ps4Pitchfield, and makeDescribeVideoOutBufferuseAgcDriver::DisplayTilingGcnwith that pitch when a PS4 group hastiling_mode == 0. - They change the registration path in
Buffer.cppfromif (attribute->tiling_mode != 1) throw ... "PS4 tiled display buffers are not implemented"toif (attribute->tiling_mode > 1) throw ... INVALID_TILING_MODE, which makes PS4 tiled buffers supported there. - They recompute
group.ps4PitchinsidesceVideoOutSubmitChangeBufferAttribute2for exactly that reason.
Your new sceVideoOutSubmitChangeBufferAttribute keeps main's refusal of tiling_mode != 1, which is correct against main as it stands today (the same refusal is at Buffer.cpp:200 there), and it copies the group before editing, so ps4Pitch survives from registration unrecomputed. If #9676 lands first, a title that registers a tiled PS4 group and then changes its attributes would be refused by the new call, and a group whose width or pitch changes would keep a ps4Pitch computed for the old values. If this one lands first, #9676 needs the same one-line recompute added to the new function. Either way it is one line plus a decision about the tiling refusal, and a Depends on: between you and @ntamas94 would pin the order. I haven't built the two merged together, so I am describing their diffs, not a run.
Optional, non-blocking
Ps5PixelFormat hardcodes its caller's name: Buffer.cpp:84 formats "sceVideoOutRegisterBuffers: unsupported PS4 pixel format 0x%08x". The new export calls it at Buffer.cpp:251, so an unsupported format rejected through that path names the wrong entry point to whoever is debugging. The assertion at Flip.cpp:274 matches only the unsupported PS4 pixel format substring, so it does not notice the prefix. CommitBufferGroup(__func__, ...) in the same file already shows the pattern for threading the name through, if you want it.
Nothing above blocks the merge.
AI-assisted: yes (Claude Code)
723e10f to
08d1a11
Compare
|
Thanks for re-checking. On #9676: this PR keeps main's behaviour and leaves the shared helpers alone, so whichever of the two lands second adds the |
✅ NVIDIA GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (3, not counted against this PR)Validation IDs already present on main (9 IDs in 549 tests)Skipped (3)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
BunnyFl
left a comment
There was a problem hiding this comment.
@AlexWhitehouse re-checked at 08d1a11579. My approval was on 723e10f82b. PS4 tiled display buffer support is now on main (Buffer.cpp:225 on main), merged with #9432 as 85e291c12b; we had both expected it from #9676. That makes the follow-up you described for "if #9676 merges first" due here, and one test row has to go.
What main does now (at 1ff0fe98aa):
- On
main, PS4 registration refuses onlytiling_mode > 1(Buffer.cpp:215onmain). - On
main, registration storesgroup.ps4PitchfromPs4TiledPitch(Buffer.cpp:225onmain). - On
main, the Attribute2 change recomputesps4Pitchfor a PS4 group (Buffer.cpp:258onmain). - On
main,Flip.cpp:204-213registers a tiled PS4 group and checks it is presented asDisplayTilingGcnpadded to 128 pixels, andFlip.cpp:177-187onmainchanges a PS4 group to tiled through...Attribute2. - On
main, the debt entry "PS4 tiled display buffers" (docs/dev/debt/libSceVideoOut.md:38onmain) records that support.
What this head adds against that. The new export still refuses tiling_mode != 1 with "PS4 tiled display buffers are not implemented" (Buffer.cpp:246-247 at this head), and the test pins it:
// Flip.cpp:270-271 at 08d1a11579
invalid.tiling_mode = 0;
rejected([&] { sceVideoOutSubmitChangeBufferAttribute(handle, 0, &invalid); }, "tiled display buffers are not implemented");- That row asserts that an unimplemented path throws, which pins the gap as if it were the contract (the point raised on #14950). It has to be removed either way.
- The message is no longer true on
main: tiled PS4 buffers are implemented there, just not through this call.
Requested change, one of:
- implement the tiled case as you planned: accept
tiling_mode == 0, store the pitch as registration does (Buffer.cpp:224onmain), recomputegroup.ps4Pitch, and replace the pinned row with one that changes a group to tiled and checks the presented tiling and padded pitch, asmain'sFlip.cpp:181-186does for...Attribute2; - or keep the refusal, drop the pinned row, and reword the throw and the debt entry so they say this call doesn't change a group to tiled yet.
One thing to settle if you implement it: main's own tiled registration passes pitch_in_pixel = 0 (Flip.cpp:206 on main). At this head the width > pitch_in_pixel check returns INVALID_PITCH (Buffer.cpp:241) before the tiling check is reached, so a tiled change written the same way would come back INVALID_PITCH. I haven't checked what the console expects in pitch_in_pixel for a tiled PS4 attribute.
A correction to my previous review: I said a group whose width or pitch changes through this call "would keep a ps4Pitch computed for the old values". With only linear changes accepted, that value is never read: DescribeVideoOutBuffer uses ps4Pitch only when tiling_mode == 0 (Buffer.cpp:30 on main). It matters only once the tiled case is accepted.
What I ran. This head merged onto main 1ff0fe98aa (merge 1fe7820f0b, clean), Windows 11 Pro, WinLibs GCC, Release, AMD Radeon RX 9070 XT, with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation and ctest -V:
^video_out_flip: 28 of 28 pass, none unbuilt; no missing-layer line, noVUID-and noSYNC-HAZARDids. The pinned row is among the passing checks: it expects the throw (Flip.cpp:271).tools/pr_overlap.py --branchat this head: no line conflicts. #13486 is listed for the same export; GitHub's file list for its head0bde10d243is three relinker files, none inlibSceVideoOut. Six pull requests conflict withmainand could not be compared (#4040, #5021, #12863, #13486, #13994, #14212).
The rest of what I approved at 723e10f82b still holds: the null-attribute and handle order from the 13.42 module, the returned codes and the converted fields.
AI-assisted: yes (Claude Code)
Replace a legacy PS4 buffer group's attribute through the PS4 call, following shadPS4 commit 2183807e592b36d4440384878165b43d930c1dee (video_out.cpp:452-460, driver.cpp:198-240): an aspect ratio other than 0, a width above the pitch and a tiling mode above linear return their VideoOut errors. The conversion matches legacy registration and the update matches sceVideoOutSubmitChangeBufferAttribute2, keeping buffer addresses and pending flips. Missing groups, reserved fields, null attributes, out-of-range indices and PS5 groups throw, as the registration and Attribute2 paths do for the same inputs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ute first The 13.42 module's sceVideoOutSubmitChangeBufferAttribute (0x112e0) returns 0x80290002 for a null attribute before it looks up the handle, then 0x8029000b for an unknown handle, and leaves every other check to the port's handler. Check the attribute first and return the code instead of throwing, then the handle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main now registers tiled PS4 display buffers, so the PS4 change call accepts tiling mode 0 as well: it stores the attribute without a pitch and recomputes the group's PS4 pitch as registration does. The width against pitch check still applies to tiled attributes, as in shadPS4. The test changes a group to tiled at two pitches and back to linear instead of expecting the old refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
08d1a11 to
8ea336b
Compare
|
Done in 8ea336b, rebased onto current main: the call now accepts a tiled attribute, stores it without a pitch and recomputes |
BunnyFl
left a comment
There was a problem hiding this comment.
@AlexWhitehouse re-checked at 8ea336be64, thanks for taking the tiled case. My change request was on 08d1a11579; both points are addressed.
- Tiled changes: the new export stores a tiled attribute without a pitch and recomputes
ps4Pitch(Buffer.cpp:270-271at this head), the same two lines registration uses (Buffer.cpp:224-225). The pinned "not implemented" row is gone.Flip.cpp:293-303now changes group 0 to tiled at pitches 128 and 256, checks that it is presented asDisplayTilingGcnwith that pitch, and changes it back to linear. - Pitch 0: I read shadPS4 at
2183807e592b36d4440384878165b43d930c1dee. ItsChangeBufferAttributereturnsINVALID_PITCHforwidth > pitch_in_pixelbefore the tiling check, whatever the tiling (driver.cpp#L213-L222), and its registration does the same (driver.cpp#L138-L147). SoBuffer.cpp:258and the test atFlip.cpp:291match that source. The console's handler is still unread, and the debt entry (docs/dev/debt/libSceVideoOut.md:47at this head) says so and records the difference from registration's padding. - Count: in the tree merged with
main7383be1a19,InventoryExports.cpphas 190 throwing stubs (191 onmain) and the debt table has 169 rows, matching the entry's 169.
What I ran. This head merged onto main 7383be1a19 (merge 70c6063b4c, clean), Windows 11 Pro, WinLibs GCC, Release, AMD Radeon RX 9070 XT (driverInfo 26.10.2 (LLPC), driverVersion 2.0.416, Vulkan 1.4.359), with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation and ctest -V:
^video_out_flip: 28 of 28 pass, none unbuilt; no missing-layer line, noVUID-and noSYNC-HAZARDids.- Restoring
main'sBuffer.cppdoesn't link (the test calls the new export), so the controls are four mutations of the new function, each rebuilt and run on the merge. Each one failsvideo_out_flip_ps4:ps4Pitchset to 0 instead of recomputed;- the tiled pitch kept in the stored attribute;
- tiling mode 0 refused (
!= 1); - the pitch check skipped for a tiled attribute.
tools/pr_overlap.py --branchat this head: no line conflicts. #13486 is listed for the same export, but GitHub's file list for its head0bde10d243is three files and none of their patch lines names this export. #4040, #5021, #12863, #13486 and #14212 conflict withmainand couldn't be compared; their GitHub patches have no added or removed line naming this export or its NIDIOdgHlCGU-k.
AI-assisted: yes (Claude Code)
What
Implements
sceVideoOutSubmitChangeBufferAttribute(NIDIOdgHlCGU-k), the PS4-era call that replaces the attribute of a registered legacy buffer group. It was a throwing inventory stub. The PS5 form,sceVideoOutSubmitChangeBufferAttribute2, and legacy registration throughsceVideoOutRegisterBufferswere already implemented.The behaviour follows shadPS4 commit
2183807e592b36d4440384878165b43d930c1dee:video_out.cpplines 452–460 checks the handle, then delegates.driver.cpplines 198–240 checks the group, reserved fields, aspect ratio, width against pitch and tiling mode, then replaces the group's attribute under the port mutex.In
core/libs/prx/libSceVideoOut/src/Buffer.cpp:Returned errors:
VIDEO_OUT_ERROR_INVALID_ADDRESS(0x80290002) for any handle and set index. It is checked first, as in the 13.42 module's disassembly quoted in review;VIDEO_OUT_ERROR_INVALID_HANDLE;INVALID_ASPECT_RATIO(0x80290008);INVALID_PITCH(0x80290004);INVALID_TILING_MODE(0x80290007).The three new codes are added to
VideoOutDriver.hpp.Thrown errors: these throw, as legacy registration and
...Attribute2already do for the same inputs, rather than returning shadPS4'sINVALID_VALUE:A negative index is out of bounds in shadPS4. Changing a PS5 group through the PS4 call isn't settled by any source, so it throws too. Unsupported PS4 pixel formats keep their existing throw.
Update: the legacy attribute is converted the same way
sceVideoOutRegisterBuffersconverts it. Every buffer in the group is checked against guest memory with the new attribute before the group is replaced, as...Attribute2does. Buffer addresses and pending flips are kept.Tiled: a tiled attribute (tiling mode 0) is stored without a pitch and the group's PS4 pitch is recomputed, as registration and
...Attribute2do. Its pitch must still be at least its width, as in shadPS4, so a tiled change with pitch 0 returnsINVALID_PITCH; registration here instead pads a zero tiled pitch to 128.No changes to existing functions: the new export is self-contained, so
sceVideoOutRegisterBuffersand...Attribute2are untouched.Debt (
docs/dev/debt/libSceVideoOut.md):Tested
video_out_flip_*(core/libs/prx/libSceVideoOut/tests/Flip.cpp): the PS4 buffer test now registers a second legacy group with different dimensions and pitch, then changes the first one. Every pre-existing assertion is kept. It checks:INVALID_ADDRESSahead of an invalid handle or set index;INVALID_PITCH, and the change back to linear;ANYPS5_REQUIRE_VULKAN=1,ANYPS5_NO_SHADER_CACHE=1andVK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:main(d60ebec) with only the test added, 27/28 pass; the failure issceVideoOutSubmitChangeBufferAttribute not implemented;VUID-lines and no missing-layer messages in either log.ANYPS5_VIDEO_OUT_TEST_DRIVER=windows), with the same three variables (the validation layer is confirmed loaded in every run):main(d60ebec): 27/28 pass.video_out_flip_ps4fails withsceVideoOutSubmitChangeBufferAttribute not implemented. To build the new test againstmain's throwing stub, only the typed declaration and the three error constants were added.guest_video_out_wqhd_detection_no_vulkanreports noVK_KHR_surface.VUID-lines and no missing-layer messages in any log.video_out_flip_ps4too. So does each of these on the tiled path: dropping theps4Pitchrecompute, keeping the pitch in a tiled attribute, refusing tiled changes, or skipping the pitch check for a tiled attribute.python3 tools/check_conventions.py --base origin/main: all conventions checks passed. The public-header audit passes.python3 tools/pr_overlap.py: no other PR implements this export.libSceVideoOut. PS4 tiled display buffers reachedmainthrough feat(libSceGnmDriver): build PS4 command buffers and submit them #9432 instead, so this PR now converts a tiled change as registration does, the follow-up agreed in review.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code