A remapped vertex shader reads the scale and offset from the push block, but
the pipeline's push constant stages only counted programs with push data of
their own, so a shader with none got no stage in a non-GPL layout and its
scale and offset never arrived. The result now says it reads them, and the
push stages include the vertex stage for it. The draw test gains a fetchless
remapped vertex shader with no push data.
IrProgram::ReclaimUnusedValues put every live value into an
unordered_set, one allocation each, and looked every value of the
program up in it again. Values enter the program only through
CreateValue, which numbers them with nextValueId, so an id names at
most one of them. The marks of those values now live in a vector
indexed by id, after a check that the id's owner is the same pointer.
A value the program does not own, such as one in the resource plan's
value storage, which may reuse an id, still goes into a set. The values
kept and removed are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Onimusha: Way of the Sword (PPSA27836 01.000.001) imports
_ZSt26__throw_bad_variant_accessv (9G6z-nF6njg) from libc, and its
bundled libc.prx does not export it, so the title fails to load with
an unresolved import.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GtXavMkgCTCdmRpweviHcQ
MaskedSelectEliminator::Eliminate runs UnreadLanes::Remove for four
mask families every round, and each Remove walks every instruction of
the program before it knows whether any select belongs to its family.
removeFullWaveSelects now also collects the selects of Once-region
blocks during the walk it already does. A family runs only when one of
them is still in its block, has uses and has a mask of that family,
checked when the family's turn comes. That is the test Remove starts
with, so a skipped family would have returned 0 without changing the
program, and the result is unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#7330 passes the vertex clip distances as separate ClipDistance arrays so
the control stage's input matches the vertex shader's output. SPIRV-Cross,
which MoltenVK uses, cannot translate a separate ClipDistance array in a
tessellation evaluation stage, so on MoltenVK every pipeline of the
barycentric tessellation route failed to compile. The control stage now
reads the separate array the vertex shader writes and passes it on inside
its per-vertex block, which the evaluation stage reads and writes.
A mounted folder uses the junction reparse tag and would otherwise be returned as a relative Volume GUID path. Only a drive path is reported, through the absolute-link text helpers.
A vertex or tessellation evaluation program whose PA_CL_VS_OUT_CNTL
enables eight guest clip distances (CLIP_DIST_ENA 0xff, both distance
vectors) failed to compile with "guest clip distances plus the all-zero
clip position distance exceed 8 clip distances", at registration and at
the draw. A program whose guest clip and cull distances together take
eight (four of each, say) compiled, but its draw failed in the pipeline
validator with "more than eight clip and cull distances in one shader".
The all-zero position distance is now added only while the guest clip and
cull distances leave one of the eight slots free. Otherwise the program
keeps its guest distances, and a primitive with a vertex at clip position
(0,0,0,0) is not removed; the EmitSetAttribute debt entry says so.
agc_position_invariance compiles one program with seven and eight clip
distances, and with three and four clip distances beside four cull
distances: the clip distance arrays are 8, 8, 4 and 4, so the all-zero
position distance is in the first and third only.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Since #454 a written storage image retires every depth surface its described size overlaps, and a retired
surface reads guest memory, which never received the depth image. PPSA15304 writes storage views that
overlap the scene depth without covering it (the largest reaches 0x11e0000 of its 0x12b0000 depth plane),
so the whole depth was thrown away and the scene came out almost black.
A written storage view now retires a surface only when the bytes its written level holds, per array layer
or depth slice (CoveredMipBytes, whole tile blocks, no padding), cover the surface's whole depth or stencil
plane; a partial overlap leaves the surface alive, as before #454. Thick 3D views hold no whole block per
slice and retire nothing. agc_driver_depth_storage_reuse now checks that a half-width write keeps the
surface sampled from the depth image and that a write over the whole plane retires it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GN8FJFTedayRXLHythXkZ4
A queue that delivered an end-of-pipe interrupt from its own release stopped
delivering the flip's event for the rest of the run, so a title that raises a
release interrupt once and then waits on the flip event never saw it again.
Count the flips a queue has taken since its last delivered release interrupt:
four consecutive flips keep the latch, a fifth clears it and raises the event,
so the queue recovers within five flips. Gran Turismo 7 (PPSA01317) pairs two
flips with one release interrupt per frame, which stays under the limit, and a
title that flips without further release interrupts recovers.
Extend agc_driver_eop_interrupts: a latched queue still delivers its own
releases, flips keep reaching the video output while their event is suppressed,
an event returns once the latch clears, and a release followed by two flips
raises none.
Since #6678, a Windows host import under 1 MiB returns to the write watch
once its deferred settle read has completed, and GuestMemory::Rewatch
stamps every block of it as a CPU store. The return waited only while
storage results were pending over the import. A storage image can take
its generation before the stamp and have results pending only after it:
an image's first upload takes its generation and then imports its block,
a recorded draw marks its targets pending once it is recorded, and the
settle is polled at the import lookups between the two. The image's
next refresh then takes the stamp for a CPU store over its results,
drops them and uploads the guest bytes again, so the GPU's output is
lost. On an RTX 3070 this also splits the first two draws of
agc_driver_address_passes into two passes.
A settled import that a live storage image overlaps now stays compared,
as every import under 1 MiB was before #6678. Imports with no image over
them still return to the write watch. Keeping the import compared, rather
than waiting for the image to go, checks each settled import against the
live images once instead of at every poll. The [buffers] line counts the
imports kept compared.
agc_import_settle_storage_image makes an image whose first upload imports
its block, waits for the settle read, clears the image on the GPU, then
refreshes and stores it. On the old code the refresh drops the clear.