With pipelined draws, queue 0 hands the end-of-pipe labels of a
submission to the draw pipeline and can enter its idle wait before the
pipeline commits them. When such a label raises an end-of-pipe
interrupt behind recorded work, the pipeline attaches the delivery to
the batch as a completion and submits it, but queue 0 only reaps when
it saw completions pending before it went to sleep, and nothing woke
it. The batch was then reaped, and the interrupt delivered, only when
the next submission arrived, so a title that waits for that interrupt
before submitting more work stopped.
Queue 0's idle wait now also ends when completions are pending, and
the pipeline's end of a submission (and the REWIND path's open-work
submit) wakes it when they are.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows (MinGW libstdc++) one std::ofstream::write of 2 GiB or more
never returns: the whole temporary file is written but WriteFileAtomically
hangs, the entry is never replaced and the temporary file stays behind.
A Vulkan pipeline cache of 2.1 GB hung every save and left a 2 GB .tmp
per run. Write in chunks of at most 1 GiB.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XBXM4pgkMHYEtqN1EQni2P
A fill that covers a depth surface's whole stencil plane with four equal
bytes, or its whole depth plane with a value in 0.0-1.0, now reaches the
host image through the pending fast clear the next time the surface is
bound, sampled or stored to. An HTILE fill or HTILE clear kernel noted
afterwards replaces the value with DB_DEPTH_CLEAR/DB_STENCIL_CLEAR.
NoteDepthMetadataFill only reacted to fills of DB_HTILE_DATA_BASE, so the
Cohtml UI of Heretic + Hexen (PPSA26525) and DOOM + DOOM II (PPSA21444),
which resets its stencil plane to 1 with a 0x01010101 fill every frame and
then draws with stencil Equal 1 and 2, kept the stencil of earlier frames
and showed black squares and clipped text. agc_driver_depth_plane_fill
pins the rules.
Since #3878 every vertex program that exports a position also writes
gl_ClipDistance for the all-zero position distance. The tessellation
stages generated for rect lists declared only gl_Position in gl_in, so
their input interface no longer matched the vertex outputs; on MoltenVK
the control stage then reads all-zero positions and every rect-list
draw stops with "rect-list requires finite nondegenerate axis-aligned
positions" (reported in #1).
The control and evaluation stages now declare the vertex program's
gl_ClipDistance array in their per-vertex blocks and forward it. The
generated fourth corner gets the clip distances interpolated with the
same weights as its position, so the all-zero position clip keeps
working for rect lists. Validation accepts gl_ClipDistance as a
tessellation input and as a tessellation-control output.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QXdkh9PHBCPqGcGQPeikAe
Unreal Engine walks the frame-pointer chain until it reads a return
address of 0 and never checks the frame pointer itself. Guest threads
started with whatever rbp the host code held, so the walk ran into host
start-up frames (glibc's saved rbp 0x21 in a LEGO Batman core dump,
address 8 in Returnal on Windows) and faulted. Fibers ended their chain
with a null frame, and makecontext started its function with rbp 0, so
the same walker read address 8 there too.
Guest threads now start through a thunk that points rbp at a
{saved rbp 0, return address 0} record, as the relinker's entry stub
does for the main thread; the fiber trampolines push the same record,
and the makecontext start function is built with frame pointers so its
frame, over the zero return address makecontext stores, ends the chain.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Cult of the Lamb (PPSA06465, #2686) stops at start-up on the first one:
FAIL: unresolved ELF import pXJh3aVk8Ks from libSceContentDelete.prx
Both exports have been on main without an implementation (#2740); the
call itself has not been observed yet.
Orbital (cc408367, tools/ida/db_types.json:541-542) and SharpProspero
(5dfdb4b0, Interop/Content/ContentDelete.cs:25-42) agree on the
signatures: a 64-bit SceContentSearchContentId and a UTF-8 path. The
content library is empty on the host, since libSceContentExport exports
nothing into it, so no id or path can be found. SharpProspero gives only
NoPermission (0x809D5006) and no public source gives the not-found code,
so both calls throw with the id or path named once the null path and the
initialization are checked, like the "not in the host content library"
throws of #3724. sceContentDeleteById moves from
guest_content_unimplemented to the new guest_content_delete test.
NIDs pXJh3aVk8Ks and qC3QW+AltHs match tools/nid_names.py and the shadPS4
aerolib list.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
(cherry picked from commit 928184824a4acdf36a58287034bff8154c861835)
On a device without VK_KHR_fragment_shader_barycentric the draw now
builds the emulation's geometry stage and checks the same results in
wave64 and wave32 as on a device with the extension. It skips only on a
device with neither the extension nor geometry shaders, or without the
Float64 capability the exact sums need.
Without barycentrics the test shader now recompiles with the emulation
active instead of throwing, and with them it does not take it. The
offline target declares Float64, which the exact interpolation sums use.
v_interp_p1ll_f16, v_interp_p1lv_f16 and v_interp_p2_f16 read each
vertex's parameter and threw on a device without
VK_KHR_fragment_shader_barycentric. Without the extension the pixel
shader is translated once for fixed-function interpolation and, when
that cannot express it, again with the barycentric emulation, whose
generated geometry stage passes each vertex's parameter as a flat input.
The throw came in the first pass, before the second could run. Without
it the 16-bit parameters keep the shader off fixed-function
interpolation, so it takes the emulation and reads the halves bit for
bit, as v_interp_mov_f32 already does.
MeasureStackReserve took the distance from the stack top to a local
variable. In an ANYPS5_ENABLE_ASAN build that local lives on
AddressSanitizer's fake stack (detect_stack_use_after_return is on by
default on Linux), away from the thread's stack, so the reserve could
come out negative. scePthreadCreate then asked the guest arena for a
stack of nearly 2^64 bytes and threw 'guest address space arena
exhausted'. The frame address is on the real stack in every build.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
lstat and readlink aborted on an absolute symbolic link because only a relative reparse point was accepted. Read the link text, and still refuse reparse points that are not symbolic links.
Read-only addresses are not part of the dispatch key, so the fresh build after a refused
move replaced the template that serves the other address, and the two addresses
rebuilt each other. A refused dispatch now uses or builds an entry under the exact key
(read-only bases included) and leaves the movable template alone. The [dispmove] line
counts the rebuilds after a refusal, the builds inserted beside the template and the
dispatches served by an exact entry. Restores the MarkGpuWrites comment.
Continuing a pass across a draw that only reads through the table is
right only if no pass end records a target write-back that the read
depends on. agc_driver_address_passes --targets renders a color whose
bytes spell 1.0f into the target, then reads the target's first dword
through the table into the same target, once with a tiled target and
once with a linear one.
The tiled read continues the rendering draw's pass and reads the bytes
from before it: tiled results reach guest memory only by explicit
write-backs, none of which falls between the two draws. The linear read
reads the rendered color: a linear target over a host import is stored
back right after its draw (the store ends the pass), and one without an
import is drawn synchronously. agc_driver_address_passes_targets_split
runs the same cases with APS5_NO_ADDRESS_READ_PASSES=1 and must read the
same bytes; a scratch build that writes the targets back whenever a
draw reading through the table breaks the pass fails it.
relocateDrawEntry copied a cached variant field by field and left out
meshIndexDescriptor, which the variant gained in #5791 before #4943 merged.
lookupDraw compares a mesh stage's descriptor with the draw's index buffer
words before validating anything else, and no draw has an all-zero one, so
every relocated mesh-path stage was refused as a differing front stage. With
no hits the shader set's relocation trial stopped admitting new aliases too.
The copy now takes the donor's descriptor, so a relocated mesh stage matches
the same index buffer the donor was built for and misses on any other.
agc_driver_mesh_draw_relocation draws a mesh-path triangle whose vertex
buffer descriptor is loaded through a user-data pointer, at eight addresses
with the same contents: the last four now hit the cached draw (before: four
differing front stages, no hit).
AI-assisted: yes
The fallback branch's merge of main 1e4ec0e3f7 adds depthCopyFormatTests
to the graphics tests' run list where this branch adds sampleOrderTests.
Run both, this branch's first.