A pixel shader loads its colour through a user-data pointer. Drawn from a third address with the same contents it hits the cached draw; with other contents it does not; the addresses seen before still hit exactly.
AI-assisted (Claude Code).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A draw whose user-data words differ only in pointers the capture read through
looks up an alias key built from the contents behind them, shifts the cached
variant's runs by the pointer delta, validates them by value and patches the
forwarded shader-data words.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Retain the regression originally supplied by Pipodi in closed PR5851 (22091410a), adapted here through e1c6af65b. Current-main-equivalent libc/kernel source returns an alias during the open HostWrite and fails this assertion five times. This test is a reproduction, not a new implementation or an upstream PR.
(cherry picked from commit 312170cd0c461104174d655911de876be341cf6a)
Retain Pipodi safety guard from closed PR5851 without its resident alias expansion or automatic AGC alias routing. Main still refuses aliases over partial resident runs. Five unmodified-main regression runs fail before this guard; positive validation pending. Fork proposal only; no duplicate upstream PR intended.
(cherry picked from commit 078a5740b40c3b5b6384eec8f92363360c75b758)
A draw whose sample locations vary between the pixels of the guest's
2x2 pattern threw "sample locations varying between pixels require a
2x2 sample location grid for the draw's sample count" on a device
whose maxSampleLocationGridSize for that sample count is not a
multiple of 2x2. An RTX 3070 Laptop GPU reports 1x1 for every count,
so Resident Evil Village's 2x checkerboard pattern stopped there
before its title.
The pipeline now decides the grid when it is created: such a pattern
is drawn through a 1x1 grid with pixel (0,0)'s locations, the first
registers of the pattern and the pixel the guest's grid is anchored
at, and the first such pipeline of each sample count logs it. The
render pass begin takes the pipeline's grid, so a sample-location-
compatible depth image is begun with the locations it is drawn with.
Devices with the grid keep it, and uniform patterns are unchanged.
On macOS the RLIMIT_NOFILE soft limit is not a bound on the descriptor table: setrlimit accepts soft limits above kern.maxfilesperproc, RLIM_INFINITY included, and getrlimit reports what was set, so returning the guest soft limit alone could report up to INT_MAX for a table of about 122880 descriptors, and a closefrom-style loop up to that value would run billions of iterations instead of about 122k. Return the smaller of the guest soft limit and the host's ::getdtablesize(), which is the FreeBSD sys_getdtablesize result. The guest test derives its expectation from the host call instead of the implementation's formula, and the debt entry no longer claims the limit is raised when libkernel loads outside Linux. Reported by jotitadev in review of the getdtablesize implementation.
Equivalent descriptor reloads in loops must retain runtime table planning. Reuse the existing invariant proof and cover accepted and varying descriptor cases.
The SRT evaluator records every raw read with the user-data word its address is
based on, and marks a word used as a plain value. The result also names the
user-data word behind each shader-data dword.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The disk cache keeps loaded and persisted entries mapped for the life of
the process. On Windows 10 DeleteFileW refuses a file that still has a
mapped view with ERROR_ACCESS_DENIED, so agc_shader_disk_cache failed in
its final remove_all after every check had passed and left its directory
in the temp folder.
Delete each file with FILE_DISPOSITION_FLAG_POSIX_SEMANTICS before
removing the directories, as WriteFileAtomically already renames with
POSIX semantics. The mapped views stay valid, and the test still fails
when a file or the directory cannot be removed. Linux is unchanged.
A static, read-only image slot whose T# has TYPE 1 is now bound as a null
image, like TYPE 0 since #5473 and #4779. On gfx1010, image_sample_lz,
image_sample_b, image_load and image_get_resinfo through a format-22
TYPE 1 T# return zeros without a fault, and gfx1035 reads it as zeros
too. Written, atomic and table slots still throw, and the reserved
types 2-7 stay refused.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
mergeBesideReturns ignores the edges into blocks that only lead to a return
when it looks for the merge of a selection whose arms do not meet. It only
recognized a straight run of single-predecessor blocks ending in a return,
so an arm whose return path branches again (an early return inside a
nested if/else) still counted as a block of its own, the arms had no
common post-dominator, and the whole program fell back to flag
structurization ("conditional block 0 has no structured merge").
A block now returns when it has one predecessor, is dominated by the
header and every successor returns. Flag structurization turns every
original block into a guarded region, and the register phis at the region
joins carry values from paths that never reach a later use: in Resident
Evil 4 (PPSA07411) pixel program 0x20762add00 the T# of an image_load
became Phi(0, load through Phi(user data, compare mask)) and resource
analysis refused it. Structured, the T# is the load through the user-data
pointer and the program prepares, captures and materializes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Morrowind imports fchown and stops at it once rtprio_thread and the pthread concurrency controls are in. Accept the guest's own owner and group (0) or unchanged (-1), fail an invalid descriptor with EBADF, and throw for another owner or group, since ownership is not modelled.
UnchangedSince and UnchangedSinceAll answered by the stamps of the 64 KiB blocks a range
touches, so a CPU or driver store anywhere in a shared block failed every unchanged proof
over it. When a block's stamp is newer, they now look at what wrote the block: the CPU page
stamps over the range and the block's driver-store pieces, as StoredOver does.
For that answer to see every driver stamp, the walk after an own store stamps the pages it
finds dirty in a page map of their own. The unchanged proofs count those pages, so a guest
store beside the stored bytes in the same page is not hidden. StoredOver counts them only in
a block without driver pieces: where pieces exist it answers as before. They take no
driver-piece slot and do not count for the complete coverage StoredAllSince proves. On
Windows, a private mapping made over a block that has driver pieces marks them as
forgotten instead of dropping them.
StoredOver no longer answers stored over for a block whose newer stamp comes only from CPU
stores to other pages.
Co-Authored-By: Claude Opus 5.5 <[email protected]>