A draw stage whose captured words differ from a cached variant only at pure
data positions (read by the shader as data, never as an address, descriptor
or decode input) is now a hit: the live words are patched into the cached
compiled result, as the dispatch cache's EqualData hits do. The positions are
recorded at insert from the stage's resource capture, minus the words the
draw decode reads. Patched draws take no draw recipe.
APS5_NO_DRAW_STAGE_DATA_HITS=1 turns it off; APS5_VERIFY_DRAW_DATA_HITS=1
builds the stage anyway and throws on any difference. The draw-cache profile
line counts stage data hits and refreshed words.
Co-Authored-By: Claude <[email protected]>
A 2D image_sample_l through a 1D T# now takes the 1D runtime mode, as
image_sample_lz already does, instead of failing the runtime image
interface. Measured on RDNA2 (gfx1036) with tools/hw-oracle against the
same sample with DIM 1D: u inside, on and past the edges, v of 0, 0.5, 1,
-0.25 and 3, LOD -1 to 6 on a 5-level R32_FLOAT texture, point, linear and
linear-mip filtering, wrap, clamp and border addressing, and HEIGHT or
DEPTH 3. All 4725 rows matched: the 1D T# decides the addressing and v is
ignored.
The execution test samples a 5-level 1D T# with distinct mip contents at
LODs -1 to 6, fractional ones included, with u inside, on and past the
edges, under point filtering with wrap and clamp and linear filtering with
linear mips and wrap, clamp and border addressing. Every result must match
the same image_sample_l with DIM 1D bit for bit; point-filtered results
must also be the expected texel of the expected level, and linear-mip
results the blend of the two levels the LOD selects.
agc_driver_gpu_buffer_format loads the V#'s records and word3 from memory
and moves them into SGPRs with v_readfirstlane, so the recompiler sees a
GPU-selected descriptor and the load goes through the format table. It
checks buffer_load_format x/xy/xyz/xyzw and d16_xyzw on two lanes for
formats 1-77, selectors 0/1/4-7 on 1-, 2- and 4-component formats, loads
with a component past NUM_RECORDS, and that formats 0 and 78 stop the
invocation before its stores.
The expected values were captured on the format switch (2d3a970da) and
are identical with the table.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Gemini <[email protected]>
A formatted load whose V# is selected on the GPU emitted all 77 format
cases in its shared function, and drivers that inline every function,
like RADV, copied all of them into each call site. The load now reads the
format's component count, widths, byte and bit offsets and type from a
constant table and runs one path for its four components, with the
existing conversion of each (type, width) pair selected at run time.
Stores and loads through a prepared V# keep the format switch.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The resolve decode keeps a SW_4KB_S, SW_64KB_S and SW_64KB_R_X destination's tile mode. An execution case
(ctest agc_tiled_resolve) fast-clears a 4x source through its CMASK and resolves it into each of those
targets, reading the resolved color back from guest memory; a linear destination still throws.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A multisample resolve writes into a resident 4 KiB or 64 KiB standard target as well as a 64 KiB render-target one (GTA V's fidelity mode resolves into a SW_64KB_S target).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
On Windows every direct host import leaves the write watch, and a sampled
texture snapshot over it was compared with guest memory at every lookup:
its generation stays 0, so UnchangedSince never holds. ASTRO BOT
(PPSA21564) compared about 31 GB per 10 s at the title.
The lookup now keys such a snapshot by UntrackedHint, NewestStamp,
ForgetSerial and the recorder's newest write note, taken before the
snapshot is read or compared, as StorageTexture::compareUntracked does,
and skips the compare while the key is unchanged and no recorded work
writes the surface. The byte compare still decides after any mark.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A pixel shader of MXGP 26 (PPSA30839) uses 17 samplers, over the limit
of 16 sampler pairs. The sampler heap now holds 64 descriptors, ShaderData
grows by 32 sampler metadata records and the runtime ABI version moves
to 13.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A pixel shader that interpolates its input with v_interp_p1/p2 compiles
to a per-vertex input without vertexOrder and passes a last-vertex
strip; the same input read through v_interp_mov P10 is vertexOrder and
still throws on a strip, not on a list. The synthetic matrix gets
vertexOrder as a third axis. The first check fails with the guard on
perVertex, the second without the v_interp_mov record.
With fragmentShaderBarycentric (RADV, NVIDIA), v_interp_p1_f32 and
v_interp_p2_f32 are translated as P0 + I * P10 + J * P20 over the
per-vertex values, so every smooth input became per-vertex. A triangle
strip drawn with PROVOKING_VTX_LAST then threw "last provoking vertex
with explicit per-vertex triangle-strip interpolation is unsupported"
for any shader that interpolates, which stops OliSe Player (PPSA01153)
and RetroArch's ES-DE frontend (PPSA99169), both ps5-opengl titles
whose shaders use only v_interp_p1/p2.
I and J come from gl_BaryCoordKHR[1] and [2], in the same vertex order
as the pervertexEXT values, so the result is b0 * v0 + b1 * v1 + b2 * v2
whatever order the device gives an odd strip triangle. Only a shader
that reads a slot itself depends on that order. The translator now
records the inputs read through v_interp_mov_f32 or 16-bit
interpolation, FragmentParameter carries that as vertexOrder, and the
strip check refuses those alone. 16-bit interpolation would cancel out
the same way but has not been checked, so it stays refused.
On Windows, select over pipes polls readiness in HostPoll and sleeps
std::this_thread::sleep_for(1 ms) between rounds, and poll with pipes
but no native sockets sleeps sleep_for(slice). winpthreads ends these
sleeps on 15.6 ms timer ticks (#1471), so a guest select or poll with a
short timeout on an idle pipe waits about 15 ms per call instead of its
timeout, and a longer wait checks the pipes only every 15.6 ms.
Both paths now sleep with PreciseSleepUntil. Each sleep requests at
most 1 ms and ends no later than the deadline; the old HostPoll sleep
could pass its deadline by a whole tick. poll on pipes also stops
spinning through the last partial millisecond before its deadline,
where the remaining time truncated to 0 ms and no sleep was made.
Infinite timeouts still sleep 1 ms per round.
The pipes are now checked about every 1.5 ms instead of every 15.6 ms:
a pipe that becomes ready is noticed sooner, and a thread blocked on an
idle pipe wakes about ten times as often. A 1 ms poll on an idle pipe
returns after about 1.5 ms instead of spinning for 1 ms.
guest_poll times 20 polls with a 2 ms timeout on an empty pipe read end
and guest_select times 20 selects with a 1 ms timeout on it; each set
must take less than 200 ms. A 1 ms poll does not reach the old sleep,
because the remaining time truncates to 0 ms and the old loop spins
until the deadline, so the poll check uses 2 ms. On Windows Server 2025
both sets took 312 ms before this change and about 50 ms and 30 ms
after it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Accept every creation rate listed by the public decoder research in
libSceOpusDec and libSceOpusCeltDec, resampling FFmpeg's 48 kHz output.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Crimson Desert (PPSA25286) calls scePadSetVibrationMode(handle, 5)
at start-up, and main rejects any mode above 3 with
SCE_PAD_ERROR_INVALID_ARG (0x80920001). The title then carries on
with the call failed.
The modes are not documented. SharpProspero names 1 (advanced) and 2
(compatible); mode 3 was accepted for PPSA21480. The call now also
accepts 5, which a shipped title passes, and keeps rejecting the values
no title has been seen to use (4, 6 and above). The mode is stored as
before and has no other effect.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Since #5216 a key gets its entry at its second sight, so a shape whose
user words change on every draw never got an entry and its data-only hits
never started. A key whose shape was seen before but has no entry is now
admitted at its first sight. A shape that already has an entry serves
data-only hits from it, and its new keys are still admitted at their
second sight, so per-draw keys don't churn the cache. Shapes are
remembered in a second sightings table of the same size.
agc_driver_draw_cache_reuse draws three times with new pixel user words
over a cached shape (three data-only hits, the vertex stages reused, no
insert), then three keys of a new shape (the second one is admitted), and
runs again with APS5_VERIFY_DRAW_DATA_HITS=1.
Co-Authored-By: Claude <[email protected]>
The Windows TLS builder returns early for a module without PT_TLS. A GS access
there must still be trapped; left in place it would read the host's thread
environment block.
Each form converts and is replaced by ud2 and NOP padding of its own length,
leaving the next instruction in place. The forms are the ones Wine's ntdll in
Prospero Win (PPSA99995) uses, plus a register-address form shorter than the
jump an FS access is rewritten with.
On Windows the host owns GS (the thread environment block), so a guest
instruction that reads or writes through GS cannot be translated the way FS
thread-pointer accesses are. Such an instruction refused the whole module.
Overwrite it in place with ud2 and NOP padding instead, so the module converts
and the instruction reports itself through the crash reporter if it runs.
sceSysmoduleGetModuleInfoForUnwind called VirtualQuery and GetMappedFileNameA on every call. VirtualQuery on a large image section costs time proportional to the section (2 us for 16 KiB, 51 us for 8 MiB, 167 us for 32 MiB), and a title that unwinds exceptions while loading calls it for every frame of every throw.
The region and file name of an address inside an image of the Windows loader's module list are kept per region and used while the loader still reports the same image (base, time stamp and size). Other addresses are queried every time.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>