The guard rejected every patch below the end of the program header
table, which is correct only while the table sits at the start of the
file. Outputs whose table moved into the extra block refused patches
into their first PT_LOAD, so game_patches failed once synthesis added
a header. Overlap is now checked against the ELF header and the table
range itself.
ProgramLayoutRangeTests.cpp includes this header first, and libc++ does
not provide size_t through <cstdint>, so the macOS relinker jobs failed
to compile the test.
macos_fixed_base relinks the fixed-base fixture with and without
--macos-fixed-base 0x400000 and checks that every segment and section
moves by the same amount, __PAGEZERO ends 64 KiB below the base, the
lowest load page is at the base, the entry offset is unchanged, and the
metadata load bias and the relocated slot hold base-relative addresses.
It also checks the lowest base and the refused options and images.
cli_args covers the parsing, range, repetition and --macos requirement.
Ruffle (PPSA68091), VLC (PPSA85300) and XPSemu (PPSA97358) read
app0/imports.txt, whose import slot addresses assume the executable's
lowest ELF load page at 0x400000, and dereference them at once. macOS
output always placed that page at 0x140010000, so all three fault on
their first slot read. Linux and Windows have --linux-fixed-base and
--windows-fixed-base for this; macOS had no equivalent.
--macos-fixed-base <address> builds the load image so that the lowest
ELF load page is at the address, as --windows-fixed-base does. The
Mach-O header takes the 64 KiB below it and __PAGEZERO ends there. The
executable is MH_EXECUTE without MH_PIE, so dyld does not slide it. The
address must be 64 KiB aligned, from 0x20000 through 0x7fffffff0000,
and an image ending past the macOS user address space is refused.
WriteMacOsImage wrote the Windows ImageBase constant into the Mach-O
segment and section addresses, __PAGEZERO, the metadata load bias, the
TLS descriptors and the init pointer, while the relocations it rebases
were computed from the WindowsLoadImage base. Read the base from the
load image everywhere instead. Every caller still builds its image at
ImageBase, so the output is unchanged.
The direct-device case already drains its own work before returning. Skip the shared singleton wait after its explicit shutdown so the full suite can retain the fallback and counter assertions without throwing ProcessShutdown.
Co-Authored-By: Codex <[email protected]>
A CPU read of DISPATCH_INDIRECT arguments waited only through the flush
hook, which waits for the ranges recorded work noted as pending writes.
An address-based store (FLAT/GLOBAL, or through a descriptor the
recompiler cannot resolve to a static buffer) is not recorded as a
pending write: its batch leases the registered allocations, and only the
guest pin waiter finished that batch. So the thread-dimension,
misaligned and disabled paths, the fill-kernel path and the device's CPU
fallback read the arguments from before an address-based producer ran.
GTA V (PPSA04264) dies loading Story on such a read: a 64-thread clear
kernel read {160, 288, 0xffffffff} as thread dimensions
(3x288x4294967295 groups), bytes its 1-thread setup kernel had not yet
overwritten with {n, 1, 1}, and threw "workgroup count
3x288x4294967295 exceeds device limits".
Every CPU read of dispatch arguments at execution now first finishes the
recorder up to the newest batch recorded with a lease
(Graphics::FinishLeaseWork). The group read-ahead still reads without
waiting; a dispatch it resolved is adopted only when the execution-time
read gives the same counts, and one that differs is dropped and counted
in the [groupcap] line. The device limit error names the argument
address and cpuReason, and the driver adds the queue, path and
read-ahead outcome. The [indirect] read time includes the lease wait,
and the [recorder] sync-site table records the offset of
FinishLeaseWork's caller. The CPU reads that still miss address-based
writes (indirect draw arguments and count, the copy kernel's count
record, the awaits-title checks) are listed in the technical debt.
IndirectArgumentsPendingProducer covers the execution-time CPU argument
reads on compute queues and the pending-label CPU fallback in the Vulkan
device. Its sixth case records a real argument label behind a host Vulkan
event in an earlier batch and an address-based producer in the later open
batch. The event releases only after that producer batch is submitted;
a bounded watchdog releases for cleanup but fails the case. It requires
a deferred producer lease, an unsubmitted producer at the argument
decision, cpuReason 2 and the fresh arguments and counter result. Small
valid stale counts keep a broken-wait control finite on every driver.
Exact CPU-reason and watchdog diagnostics identify the failing path. This
replaces a spinning workload whose earlier label could retire before
the fallback decision on lavapipe, allowing a false green with cpuReason 0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Codex <[email protected]>
On Windows, pipe_nid_postfix configured the anonymous pipe with a 4096-byte buffer. When guest executables redirect standard error to a pipe via dup2 and host logging writes to standard error, the pipe buffer fills during startup before or between guest reader drains, blocking writer threads in ZwWriteFile and deadlocking the title. Increase the Windows pipe buffer capacity to 65536 bytes to match FreeBSD BIG_PIPE_SIZE used by the PS5 kernel, and cover multi-page single-shot pipe writes in guest posix scalar IO tests.
agc_driver_mix_precision skipped on devices without Float64 because
v_fma_mixlo_f16 and v_fma_mixhi_f16 were computed in f64. They now
compile on such devices too, so the test runs everywhere.
The hardware rows cover rounding to nearest even only. The test now
also builds one shader per path that evaluates 2,048 random rows in all
32 modes: the eight float modes with each of the four f16 rounding
modes, which v_fma_mixlo_f16 and v_fma_mixhi_f16 use. The rows draw f16
deltas, f32 coordinates and bases from random bits, random finite
values and special values (zeros, subnormals, the largest finites,
infinities, NaNs), and a third of the bases nearly or exactly cancel the
product. Each result must match a CPU reference built on f64: the exact
product, the sum rounded to odd, one rounding at the target precision
in the mode, and the same overflow, zero and NaN rules.
On devices with Float64 the f64 path is checked against the same
reference.
agc_driver_interpolation_modes skipped on devices without Float64. It
now runs its 32 rows measured on RDNA2, for the three 16-bit
interpolation instructions in all eight float modes, through the integer
path on every device, and through the f64 path as well where the device
has Float64. The shader for one row set is built for either path, and
reports which path a mismatch came from.
v_interp_p1ll_f16, v_interp_p1lv_f16 and v_interp_p2_f16 round the exact
P10 * I + P0 once to f32 and P20 * J + S2 once to f16 (#697), and
v_fma_mixlo_f16 and v_fma_mixhi_f16 reuse the f16 step in every f16
rounding mode. The exact sum was computed in f64, so on a device without
Float64 every shader using them failed to compile:
64-bit float instructions need the Float64 capability, which the
device lacks
Apple GPUs have no f64; with MoltenVK 1.4.2 on Apple M2 this stops
ProsperoStore (PPSA99000), PokeMMO Prospero (PPSA98001), Regie5
(PPSA99520) and PS5 OpenGL Showcase (PPSA99005) at their first such
pixel shader.
Without Float64 these operations are now computed in 64-bit integers,
which the shader device profile already requires. The inputs are
flushed as before and decoded to integer significands. The 24 by 24 bit
product is exact in 64 bits. Both terms are normalized to bit 62, the
smaller one is shifted down with the bits it loses kept as a sticky bit,
and the exact sum is rounded once to f32 to nearest even, or to f16 in
the f16 rounding mode, with f32 and f16 subnormal steps. Overflow,
signed zeros, the round-down zero sign, NaN quieting and the order in
which NaN operands win follow the f64 path, without its f64 arithmetic.
The module then declares Int64 instead of Float64. Devices with Float64
keep the f64 path.
FPInterpolateF32 and FPInterpolateF16, which v_interp_p1ll_f16,
v_interp_p1lv_f16, v_interp_p2_f16, v_fma_mixlo_f16 and v_fma_mixhi_f16
translate to, set the same float64 requirement as the f64 instructions,
since their exact sums are computed in f64. They now set
float64Interpolation instead, and the module still declares Float64,
and still throws without it, for either requirement. Nothing changes in
the emitted SPIR-V; the next commit gives these two operations a path
for devices without Float64.
A freed dedicated set kept for reuse recorded every texture of the resources that freed it and kept
them alive, so the kept handles could not be reused while the set referred to them. Up to eight kept
sets held textures the caches had already evicted: their memory stayed in use outside the caches'
budgets, and a title with large image tables ran out of device memory.
The record now holds the textures weakly. A build compares the kept table's views only while every
recorded texture is still alive, so a matching handle is still the same view; when one has died the
table is written in full, as for any other change.