guest_host_standard_error and exception_runtime fork children that end in
SIGABRT on purpose. When kernel.core_pattern pipes cores to a handler, as
Ubuntu's apport and systemd-coredump do, the kernel starts it for every
dumpable crash even with RLIMIT_CORE at 0. apport takes about 1.1 s per
crash here, so guest_host_standard_error spent 2.3 s waiting and timed out
at its 10 s limit under parallel ctest load. Marking those children
non-dumpable on Linux skips the handler: 2.29 s to 0.01 s and
1.17 s to 0.01 s, with the same SIGABRT and message checks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Dinkumware's setw returns a manipulator holding a function pointer and the
width, which the caller applies to the stream; the function stores the
width in the stream's ios_base. The export returns that pair in RAX:RDX and
the function writes ios_base::width, leaving flags and precision alone.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The deadline was built as seconds plus nanoseconds, a nanosecond duration,
and converted implicitly to a system_clock time point. Where system_clock
counts microseconds, as on macOS, that conversion is lossy and does not
compile, so libc did not build there.
The seconds now stay in the clock's unit and only the nanoseconds are
rounded up to it, so the wait never ends before the requested time. With
a nanosecond system_clock nothing changes. Converting the nanosecond sum
instead would compile but overflow above 2^63 nanoseconds, which the
clock range check above allows on macOS: a 10^10 second deadline then
wraps into the past and the wait times out at once.
A deadline of 10^10 seconds does not fit a nanosecond count but fits the
host clock where system_clock counts microseconds, as on macOS. There the
wait must block until it is woken; where the clock cannot hold the
deadline, _Cnd_timedwait must throw the overflow error as for any other
deadline past the clock's range.
The host heap's VK_EXT_memory_budget report lowered a set
APS5_HOST_IMPORT_MIB of 6400 MiB to 4480 MiB on Resident Evil Village
(PPSA01556), where 6400 MiB runs without a vkAllocateMemory failure, and
85,047 imports were refused. A set APS5_HOST_IMPORT_MIB is now never
lowered by the report, and the default is held to the report only once
an import's vkAllocateMemory has failed. The failure ceiling is
unchanged. The first time the report would lower the budget, a [gpu]
host import budget line prints the heap's reported budget and usage and
the live imports, and the refusal line names where its budget came from.
PixelFailure wrote a 128x128 payload, exactly the 64 KiB a default Linux
pipe holds. Once the consumer read the 54-byte header, the whole payload
fit in the pipe, so the write could finish before the reader closed and
the expected EPIPE never came. agc_frame_dump_io failed in 147 of 300 runs
on Linux. A 512x512 payload exceeds the default pipe capacity on Linux and
macOS, so the write always reaches the closed reader.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Reapplies #5791 (reverted by #6552). agc_driver_mesh_index_cache now skips
on llvmpipe like agc_driver_mesh does: llvmpipe aborts compiling these mesh
programs (LLVM ERROR: Cannot emit physreg copy), which is what turned main's
linux job red.
Co-Authored-By: Claude <[email protected]>
agc_pending_key_stores cleared only the first 256 bytes of its 64 KiB block and
then asked for the keys of 512 bytes. The other 256 were whatever the heap
held: when they were not all equal the range read as mixed (correctly) and
the check that it is unknown failed, so the test passed or failed with the
allocator's state (main builds after #5784).
Co-Authored-By: Claude <[email protected]>
The default bindings map the left and right mouse buttons to Square and
R2, and mouse mode maps motion to the right stick. A title that opens the
mouse with sceMouseOpen therefore gets every click twice: as a mouse
button and as a pad press. PPSA15388 treats the pad press as a switch to
gamepad input, re-centres its cursor and drops the click, so menu items
cannot be clicked.
While libSceMouse has a handle open, KeyboardMouse ignores mouse motion
and mouse-button presses. Releases still pass, so a button held before
the title opened the mouse is let go. Keys and the wheel are unchanged,
as with the IME guard next to it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A heap mirror is refreshed from the write watch. acquireMirror checked
the watch only when it made a mirror and reused an existing one as it
was. Once part of the range left the watch, the next address-based build
threw "a heap mirror's range is no longer write-watched" from the
refresh, and a build served from the address-space cache threw the same
from its heap runs. A range leaves the watch for good when a host import
that does not keep the watch covers it: on Windows a direct import of
private memory that is not settled (below the 1 MiB settle floor, or any
when imports cannot be settled), elsewhere any import while imports are
compared.
A heap mirror now records the unwatch serial at which its range was last
seen fully watched. Its reuse, and a cache hit over it, compare that
serial with GuestMemory::UnwatchSerial and look at the watch again only
when a range has left it since. A mirror whose range is no longer
watched is not reused, the cache is not taken (before its imports are
stamped), and the pass plans the range again: an import if the budget
allows, else a copy. A refused heap mirror also drops the registry's
stale one, whose buffer would stay allocated otherwise.
sceSysmoduleIsLoaded, sceSysmoduleLoadModule and sceSysmoduleUnloadModule
return success for an id missing from the module table, because titles that
load or unload such an id aborted otherwise (b4db9fdd6, a2520aa07). Nothing
tested or recorded it, and two commented-out throws were left in the code.
Remove the commented-out throws, list the three functions under Silent stubs
in the library's technical debt file, and test that unknown ids succeed
without changing state while the internal variants still throw.
Written with AI assistance (Claude).
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The committer built a recorded draw's resource key through two temporaries a shader, took the in-place and device read lists by value, and in PrepareDrawBindings built two layout-binding vectors only to test them for emptiness, a std::map of pool sizes a set, and copies of the descriptor buffer and write lists, all on every draw. The key is now built in place with its size reserved, the read lists fill a caller's vector, and the per-draw bookkeeping lives in the thread's scratch (ThreadOwned), as the selected-slot list already did. The queue worker's program list and memory snapshots reserve their size up front.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The grid reference compared the exact path with a composite whose depth
the 3070 had read at the standard 2x locations, so its 3005 depth
mismatches said nothing about the exact path. It now places every
sloped depth sample of each render from the slopes' plane equations: at
the guest's sample location of its pixel and sample, or at the standard
2x location. When even the composite holds depth away from the guest's
locations, the device reads depth drawn at custom sample locations back
elsewhere despite the transitions that name them, no render can be
compared with it bit for bit, and the test skips with the counts.
A scene check that finds a wrong sample index now prints it, and where
the device draws depth at custom sample locations the bench also times
the swaps with the standard locations named at the depth copy's
transitions.
The 3070, whose vulkaninfo reports a maxSampleLocationGridSize of 1x1,
ran the grid reference's native 2x2 render. vulkaninfo prints
VkPhysicalDeviceSampleLocationsPropertiesEXT, the grid every supported
sample count allows; the device setup reads each count's own
VkMultisamplePropertiesEXT (VulkanDevice.cpp), which may be larger at
low counts, and found an even grid at 2 samples there. The setup now
logs each count's largest grid next to the one for every count and
keeps it in the context, and the grid reference prints the one at 2
samples.
The setup's test for a 2x2 grid also took a 0x0 grid, whose sides are
even, for one. HostsSampleLocationGrid requires both sides to be nonzero
and even, and the planning test checks it.
The backward lookup added with the region fix compared the address with a page it could not reach and never ran. The test now queries an ntdll address three pages in, then the first page, then the pages between, and compares each with VirtualQuery. The lookups after the first fail on the cache before the region fix.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
On the 3070 the grid reference read the composite's and the 2x2 grid's
depth at the standard 2x locations: sample 0 of pixel (14,0) held
0x3f00e5b5, the slope's depth at (14.75, 0.75), while the guest's sample
0 lies at (14.75, 0.5), whose depth 0x3f0153f8 the exact path held.
All 3005 samples the slopes cover differed. The depth surface stays in
the general layout for its life (DepthSurface.cpp, and the render
passes in Pipeline.cpp and SampleOrder.cpp), so no layout transition
ever names the sample locations it was drawn with, although the layout
of an image created with SAMPLE_LOCATIONS_COMPATIBLE_DEPTH depends on
them; the 3070 returned such depth at its standard locations when it
was sampled or copied. The exact path's even rows came out right
because its depth pass rewrites them at the stand-in's locations, but
its odd rows came from vkCmdCopyImage, read at the standard locations
and moved to the other sample; the 10 color mismatches, all in odd
rows, are the shade triangle's depth test against those values.
A pass that draws depth at custom sample locations now ends, after its
samples are back in the guest's order, with a transition of the target
to TRANSFER_SRC_OPTIMAL and back to the general layout that names the
locations it drew with, and the depth swap copies its target between
such transitions. The planning test checks both transition pairs, and
that a swap without sample locations still copies in the general layout.
agc_driver_mesh_index_cache aborts on the linux job (lavapipe, LLVM 20.1.2:
"LLVM ERROR: Cannot emit physreg copy instruction") on every main push build
since the merge (first red: 38777177302). The PR was merged on a
windows-only run after a linux-red batch was split.
Co-Authored-By: Claude <[email protected]>
The color swap (SampleOrder.comp) chose a pixel's order word with
order.map[(at.x & 1u) | ((at.y & 1u) << 1u)], a push-constant vector
indexed by a value that differs between the lanes of a wave, returned
early for the pixels the order keeps, and gathered the held samples
through a private array indexed per lane. On the AMD Windows driver
(Radeon 0x1638, wave64) the 2x R8_UNORM round trip found sample 1 of
pixel (0,0) in its sample 0, and the grid reference's exact path read
sample index 1 in sample 0 of the same pixel, although the order keeps
that pixel's samples. Only the invocation of pixel (0,0) stores to it,
so that invocation ran the swap with another class's word.
Each invocation now handles one 2x2 quad and takes every pixel class's
word through a constant index, so the kept classes return uniformly,
and picks the held samples through selects. The depth swap's fragment
shader selects its word the same way. The planning test checks that no
sample order shader indexes a vector or array through a value that
varies between invocations, and a failed swap round trip counts its
wrong samples per pixel class.
The CLZERO case that needs a 32-bit address found no mapping because a
64-bit Mach-O executable reserves 4 GiB as `__PAGEZERO`, not because
Rosetta withholds low memory: the same `mmap` succeeds once the
executable is linked with a smaller zero page. The Apple x86-64 build
links the test that way and the case runs with the other three, so the
skip it had is gone and the Linux mapping failure stays fatal. The arm64
build keeps the 4 GiB zero page, which it requires to start.