sceVideoOutSubmitChangeBufferAttribute2 threw when a buffer of the group
had a flip pending, and Marvel's Wolverine makes that call with flips in
the queue. A flip now takes its buffer group when it is reserved, in
submission order, so flips submitted before the change keep the
attributes their buffers were rendered with and later flips use the
new ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The flip queue's condition variable went through winpthreads, whose
timed waits end on GetTickCount64 steps: the present thread's 10 ms poll
for SDL events and the pad, taken while no flip is queued, ended 11 to
24 ms later on Windows, and WaitForFlipRoom's 60 s bound had the same
granularity. Use TimedWait::Condition, which waits on an event and a
high-resolution timer, so the poll ends at 10 ms and a submitted flip
still wakes the present thread at once.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A flip packet names a buffer index; the buffer was looked up when the
command buffer was submitted, so a title that registers its buffers
after submitting the first frame failed with "flip buffer is not
registered". The buffer is now resolved when the GPU reaches the flip,
as the hardware does. A flip whose buffer is still unregistered then
presents black and completes (see TechnicalDebt).
Uncharted: Legacy of Thieves Collection (PPSA05684) submits its first flip before registering its buffers and stopped with "flip buffer is not registered".
A title that opens a main and an overlay port flips both, and every flip
was presented as a whole frame, so the window alternated between the two
buses: PPSA01736 shows its intro on the main bus and an empty overlay,
and the intro blinked black on every other frame. Overlay flips now
complete and signal their events without being shown. Compositing the
overlay over the main output is not implemented.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Measured on a PS5 (firmware 13.60) through dlopen of
libSceVideoOut.sprx on a handle the payload opened.
sceVideoOutInitializeOutputOptions writes 0xFF to byte 2 of the 64-byte
options and returns INVALID_ADDRESS for a null pointer.
sceVideoOutIsOutputSupported checks the handle, then the reserved
arguments, then the mode, then the options. It never answers 0: a mode
the display lacks returns UNSUPPORTED_OUTPUT_MODE, and a value that is
not a mode returns 0x8029001E. Options must keep the initialized words,
except word 3.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LibwuIonIBw registers video out event id 16, which the host never triggers because its VRR state does not change; kP2L8t3j-aM returns 0 without effect.
A flip still queued or in presentation when the title closes its port is discarded, as on hardware, rather than stored as a driver failure. A closed port no longer terminates the presentation thread nor surfaces from Shutdown. The lifetime test now expects cancellation and the reopen mode is registered in ctest.
The driver created a windowless Vulkan device at the first dispatch and
replaced it with a windowed one at the first flip. The replacement built a
second device and re-imported every host import, and the first flip paid
for it.
VideoOut now creates its window when it starts (the first VideoOut call),
at the default 1920x1080 output, and attaches it to the driver
(AgcDriverAttachWindow) before the call returns. The driver creates its
device with that window, so GPU work and presentation use one device.
Present no longer creates or replaces a device. A device created by GPU
work before VideoOut started is still replaced, now in AttachWindow.
A failure to create the window or the device is thrown from that first
VideoOut call instead of terminating the presentation thread.
Tests:
- video_out_flip_tests onedevice: GPU work, then a flip, leaves one device.
- pacing makes its first presentation span vblanks with GPU work queued
ahead of the flip; it relied on the device being created at the flip.
- unavailable expects the failure from sceVideoOutOpen.
- guest_video_out_wqhd_detection writes a param.json for the window title
and is skipped without a display or Vulkan device unless
ANYPS5_REQUIRE_DISPLAY is set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceVideoOutRegisterBuffers2 threw "DCC presentation is not implemented"
for category 1 (DCC-compressed) buffers, which PPSA26344 registers. Such
a buffer now needs DCC metadata and the tiled layout, and dcc_control may
only use the CB_DCC_CONTROL block layout bits 0x10026c.
At a flip the keys are read behind their recorded writers, one byte per
256 bytes as in the driver's DCC model. Uncompressed keys present the
stored texels as before; a uniform clear code presents its color with a
GPU clear of the scaler's source image; a pending storage image is used
when it serves the keys. Mixed or unreadable keys, clear codes the
display format has no DCC encoding for, register-clear keys over a
pending image and a clear color wider than 32 bits throw. Buffers
without DCC take the old path.
sceVideoOutRegisterBuffers2 and sceVideoOutSubmitChangeBufferAttribute2
threw for every buffer attribute option other than 0. PPSA26344 builds
its display buffers with option 8 through the libSceAgc helper linked
into it, so its first registration failed.
Option 8, VIDEO_OUT_BUFFER_ATTRIBUTE_OPTION_STRICT_COLORIMETRY (name
and value from KytyPS5), is now accepted and presented as option 0;
every other option still throws. What the console changes for it is
unknown and recorded in TechnicalDebt. The rejection now names the
tiling mode, pitch, aspect ratio and option it was given.
video_out_flip_tests decode checks that option 8 describes the same
buffer as option 0 and that options 1, 32 and 40 are rejected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
and throws for any non-zero word after it. Its layout matches shadPS4's
ServiceThreadParams instead: an unknown first word (16), a set-priority flag
and a priority (256..767), a set-affinity flag and a 64-bit CPU mask at
offset 16. PPSA21564 passes 16, 1, 0x100, 1 and 0x1FFF, so it stops at
startup on main.
sceVideoOutOpen now validates each field and reads the mask only when its
flag is set, so a 16-byte param with both flags clear still works. The
priority and affinity are not applied, since the present and vblank threads
are host threads; this and the unknown first word are listed in the
technical debt.
Ten libSceVideoOut and two libScePad error constants had values that
belong to other errors of the same library (for example INVALID_HANDLE
was 0x80290003 and RESOURCE_BUSY / SLOT_OCCUPIED were swapped). They now
match KytyPS5, shadPS4 and fpPS4, which agree on all of them.
Co-Authored-By: Claude <noreply@anthropic.com>
sceVideoOutOpen threw for any non-null param. PS5 titles pass a 16-byte
open param whose first word is its size, so they could not open a port.
A param whose size word is 16 and whose other three words are zero
requests nothing beyond a null param and is accepted. Any other size,
or any non-zero option word, still throws.
Brings in main up to 9958d26 (homebrew runtime, POSIX wrappers in
libkernel, sce_module guest modules and --skip-sce-module, the --to-intel
general pipeline, libSceRandom, libSceRtc, libScePosixForWebKit,
libRenoirCore, test wiring).
Resolutions where both sides implemented the same thing:
- libkernel pthread: main's structure (lazy static initialisation,
destroyed markers, MutexOperations/CondOperations, mutex protocol and
condattr clock) with this branch's TimedWait deadlines and condition
(precise timed lock/wait on Windows), wait tracing, the adaptive mutex
type 4, POSIX default ERRORCHECK mutexes, EDEADLK/EPERM results instead
of throws, and condition clocks honoured for absolute timeouts.
- libc locale: the guest Dinkumware ABI (_Locimp, facet vtables, short
ctype/case tables, locale ids, stream storage) is kept because guest code
inlines those layouts; main's C character functions are kept on top.
- libc stdio/strings/math: main's stream functions (guest FILE status
sync), strerror/perror, remove, formatting, string and math exports win
over this branch's duplicates.
- libc paths: main's working directory with this branch's path aliases
resolved on the normalised guest path.
- libkernel file: this branch's sceKernel* results as SCE errors, main's
POSIX wrappers and both fstat helpers.
- relinker: this branch's stub lowering keeps its trampolines through the
main executable path; guest modules refuse lowerings that need stubs.
- AGC driver: main's rendering wait is executed by this branch's workers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo