Commit Graph
136 Commits
Author SHA1 Message Date
Dean 854a514bbe Merge pull request #7945 from veosett/codex/windows-cache-housekeeping-safety
fix(shader): avoid unsafe Windows cache directory traversal
2026-10-21 20:57:27 +13:00
Dean 1aad07054d Merge pull request #8295 from mazen320/fix/skip-inaccessible-branched-scalar-load
fix(shader): skip unreachable flat SRT loads under a known branch
2026-10-21 19:34:07 +13:00
Dean GalvinandMuhammad Wasif Ali Wasif 490adefc09 Merge origin/main into PR 8134
Co-authored-by: Muhammad Wasif Ali Wasif <76695420+wachi35676@users.noreply.github.com>
2026-10-21 14:56:22 +13:00
Dean Galvinandmazen dc38f31983 Merge main into fix/skip-inaccessible-branched-scalar-load
Shader disk cache FormatVersion 43: main took 42 with #7966, and this
change also changes the cached plan.

Co-authored-by: mazen <mazenshaar@hotmail.com>
2026-10-21 14:23:05 +13:00
Dean 1faa800f08 Merge pull request #7966 from KarthikeyaAnna/fix/agc-1d-depth-compare-2d
fix(agc): back 1D depth comparison textures with 2D images
2026-10-21 14:21:13 +13:00
Dean 57fdffd915 Merge pull request #8697 from oneandonlydean/feat/f32-denorm-preserve
feat(shader): request DenormPreserve 32 where the device preserves f32 denormals
2026-10-21 13:29:41 +13:00
Dean 01fbf1060d Merge pull request #8580 from veosett/codex/windows-prebuilt-cache-discovery
fix(shader): discover prebuilt caches through native Windows paths
2026-10-21 11:45:12 +13:00
Dean Galvin a07ad30578 feat(shader): request DenormPreserve 32 where the device preserves f32 denormals
The recompiler asked for DenormPreserve only for 16-bit and 64-bit floats,
so a device that flushes 32-bit denormals by default (RADV, MoltenVK) flushed
them whatever the guest's float mode said. target.float32DenormPreserve is set
from shaderDenormPreserveFloat32 when denormBehaviorIndependence allows a 32-bit
mode, is part of the cache key and of the request serialization (version 41),
and makes the module declare DenormPreserve 32 unless the 32-bit flush is
already taken in hardware. APS5_NO_HW_F32_PRESERVE=1 turns it off.
2026-10-21 10:45:24 +13:00
Dean 2185dbf92e Merge pull request #5656 from Raghav314/perf/agc-data-hit-user-word-mask
perf(agc): data-only draw hits compare only the user words a stage reads
2026-10-21 08:32:28 +13:00
Kovalev Vladislav b97b122f65 test(shader): isolate prebuilt cache directory discovery 2026-10-20 23:11:57 +06:00
Muhammad Wasif Ali WasifandClaude Opus 5.5 243925113f fix(shader): order wave LDS accesses with a memory barrier on AMD's proprietary driver
A guest wave's lanes see each other's LDS writes without a barrier, so
the recompiler adds a subgroup-scope OpControlBarrier between an LDS
write and the next LDS access when the guest wave is one host subgroup
(WaveLdsScope). AMD's proprietary Windows driver 32.0.21042.62 (Vulkan
driver 2.0.353, "AMD proprietary shader compiler", Radeon 0x13c0)
compiles that barrier to s_barrier, as the pipeline's internal ISA
shows (26 s_barrier for the guest's 9 in a small LDS reduction). In a
workgroup of several waves, the waves that enter a branch holding LDS
accesses then execute extra s_barriers, which pair with the other
waves' barriers, and those waves read LDS before it is written. LLPC
compiles a subgroup-scope control barrier to a wave barrier instead.

PS5LM Plus (PPSA99581) answered with garbage on that driver: the first
compute dispatch of its first graph, an RMS norm with a 512-thread
wave32 LDS tree reduction, scaled every row except its first 32
elements by a partial sum, while NVIDIA matched a NumPy reference and
the inputs were identical.

On that driver the barrier is now a subgroup-scope OpMemoryBarrier,
which it compiles to no instruction. A 32-lane subgroup is one hardware
wave there, which runs its lanes in lockstep and issues its LDS
instructions in order; Vulkan does not guarantee that, so it is
recorded as debt. Other drivers keep the control barrier. The flag is
part of the shader cache key, and agc_shader_replay takes
--wave-lds-memory-barriers to replay a request the way that driver
compiles it.

agc_driver_lds_tree_reduction sums over eight wave32 waves the way the
guest does, with its last four steps inside one wave and no s_barrier
between them: before, thread 32 read 1936 instead of 32896 on the AMD
driver; it passes on AMD and NVIDIA now. agc_subgroup_barrier checks
the driver quirk and the emitted barriers on every runner. PS5LM Plus
now answers " Paris. It is the largest city in Europe ..." on the AMD
iGPU without flash attention, as on NVIDIA and the CPU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 20:24:01 +05:00
Dean bcf29de5d0 Merge pull request #8273 from thuanquang/test/large-cache-file-cleanup
test(agc): remove the large cache file test directory when the test fails
2026-10-21 02:53:04 +13:00
Maz 18da29b898 fix(shader): keep recompiler diagnostics off guest stdio 2026-10-20 16:01:02 +04:00
Maz 53ed35b362 fix(shader): skip unreachable flat SRT loads under a known branch
Capture evaluated every flattened scalar slot even when a clean scalar
branch skipped it, so an inaccessible direct user-data root refused the
draw. Record flat-slot uses on resource control-flow blocks and evaluate
only the reachable ones; keep refusing taken and unresolved paths.

Fixes #8272.
2026-10-20 13:11:24 +04:00
karthikeyaAnna c97e5e0338 fix(agc): back 1D depth comparison textures with 2D images
Back 1D and 1D-array depth comparison textures with 2D Vulkan images and views of height 1. Drivers such as AMD RADV reject 1D depth images (VK_ERROR_FORMAT_NOT_SUPPORTED). The shader recompiler maps 1D depth comparison samplers to 2D image descriptors, and pins the normalized vertical coordinate to 0.5 to sample the center of row 0 without hitting borders.
2026-10-20 14:21:58 +05:30
Romans Pokrovskis 56778c97d2 test(shader): exercise long-path mapped cache persistence
(cherry picked from commit 83ad99879035e1418a5fa500cf061b236ec0a867)
2026-10-20 14:25:57 +06:00
thuanquangandClaude a8f47b3322 test(agc): remove the large cache file test directory when the test fails
runLargeFileWrite writes a 2 GiB pipelines.bin into a randomly named
temporary directory, and only the passing path removed it. A failing
require after the write and the 200 s hang limit (std::_Exit) left the
file behind, and the two skips left the empty directory. A local Cleanup
now removes the directory when the function returns or throws, and the
hang path removes it before std::_Exit and prints the error when it
cannot, as on Windows while the write still holds the file open.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-20 15:01:18 +07:00
JJenkx 16acce08df test(shader): round-trip full user-word dependency masks 2026-10-20 03:57:03 +05:30
Adrià 9b4b3cf463 Merge pull request #6941 from kq62/fix/mesh-barycentric-emulation
feat(shader): emulate barycentrics and per-vertex parameters on the mesh path
2026-10-20 00:17:49 +02:00
sussyandClaude Sonnet 5.5 dd41527ce2 feat(shader): emulate smooth barycentrics on the mesh path
A pixel shader that reads barycentrics on a device without
VK_KHR_fragment_shader_barycentric used to need a vertex shader so a
generated geometry stage could follow it, which a mesh pipeline cannot
have. The mesh program is now compiled a second time with the layout
its pixel shader needs: it writes its clip position as a varying and the
three corner positions of each primitive as per-primitive outputs, and
the pixel shader solves for the weights, for both smooth and linear
interpolation.

The layout is part of the mesh cache key, the stored artifact and the
captured request. Without VK_EXT_mesh_shader the draw still throws, now
saying so. Per-vertex parameters on the mesh path still throw.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 17:26:37 +02:00
Kovalev Vladislav 91853d299b test(shader): isolate cache housekeeping safety regressions 2026-10-19 21:17:12 +06:00
thuanquangandClaude Opus 5.5 1ed8eb6d8b fix(shader): sample a 3D T# through DIM 2D_ARRAY as a volume
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:19:13 +02:00
Dean Galvin 41764f27ac Merge main into pr-4650
# Conflicts:
#	core/shader/recompiler/ShaderDiskCache.cpp
2026-10-19 15:36:07 +13:00
Karan Vora 6d92220829 perf(agc): stage raw buffer elements a dispatch sweeps
Since 2688b7646 a read and written V# element is staged in device memory
up to 16 MiB when the direct dispatch's threads times the V# stride cover
at least half of it. A raw buffer has stride 0, so it never passed and
kept the 2 MiB written window: GL storage buffers compiled by Mesa stay
bound in place in the host import however hard a dispatch sweeps them.

The PS5 OpenGL Showcase's particle update (262,144 threads, each loading
and storing its own 32-byte record of an 8 MiB SSBO) took about 53 ms of
GPU per frame on an RTX 4060 bound in place; staged it takes about 0.1 ms
plus 2.2 ms of bulk copies.

The recompiler already records the furthest byte each buffer resource's
accesses reach past their base (maxByteExtent). The binding plan now
carries it per guest buffer element (DescriptorBinding::bufferExtent,
shader disk cache format 37), and a raw element uses it as its record
size in the sweep test. Strided elements are unchanged.
2026-10-19 03:43:19 +02:00
Yunus Shaikh 10b798fb99 Merge main into perf/shader-image-table-reuse-v3-pr
Keeps this branch's tagVariantRuns declaration next to main's dumpRequest suffix parameter in Driver.hpp, and reads #6232's pointer-chain test words from its table's snapshot, where this branch keeps them.
2026-10-18 17:03:39 -07:00
Dean Galvin cf4d1f4a97 Merge main into pr-4650
# Conflicts:
#	core/shader/recompiler/ShaderDiskCache.cpp
2026-10-19 11:15:57 +13:00
Adrià c7e28608b1 Merge pull request #6232 from ANONYMOUSZED-beep/feat/image-table-pointer-chains
feat(shader): follow pointer chains from image-table records to the T#
2026-10-18 22:50:22 +02:00
Adrià fb9a1eb8f3 Merge pull request #6178 from MarcZX10/codex/release-undrawn-resource-plans-6139
perf(agc): release unused registered shader resource plans
2026-10-18 22:20:27 +02:00
ANONYMOUSZED-beep 486f3069ae feat(shader): follow pointer chains from image-table records to the T# 2026-10-18 20:49:04 +02:00
Yunus Shaikh d0325058f7 Merge main into perf/shader-image-table-reuse-v3-pr
#7527's selected-record limit test reads a record's descriptor words through the
table snapshot's shared words list; this branch keeps a snapshot's words per column,
so the test reads them from its column instead.
2026-10-18 11:33:00 -07:00
Gjon Gojcevic a2e79fb3fd fix(shader): bind an unnormalized S# normalized when it samples only null images
An S# that forces unnormalized coordinates was refused when it samples a
T# the shader declares 3D, 2D-array, cube or multisampled, since Vulkan
allows unnormalized coordinates only with a single-level 1D or 2D view.
A null T# reads zeros at any coordinate, and a T# whose channels all
select constants is emitted as those constants without a sample, so when
the S# samples no other T# its coordinates cannot change a result. Such
an S# is now marked in its binding (samplerCoordinatesIgnored) and the
driver creates its sampler without FORCE_UNNORMALIZED. The flag is part
of the binding content key and of the shader disk cache, whose format
version is raised to 38. An S# that also samples a real T# while a null
T# of such a shape shares it is still refused. PPSA01317 pairs an
unnormalized clamped bilinear S# with a null 3D T# and a 3D T# whose
channels all select 0 for image_sample_lz in a compute shader during
boot.

AI-assisted: yes
2026-10-18 09:02:31 -04:00
Dean Galvin b876d43fb1 fix(agc): journal whether a vertex shader reads the depth remap push words
The flag that adds the vertex stage to the push constant stages was not part
of the encoded result, so a journalled remapped vertex shader replayed
without it. Encode and decode it with the invocation and cover it in the
result round trip and the push stage test.
2026-10-18 23:28:51 +13:00
Yunus Shaikh 6720211da1 Merge main into perf/shader-image-table-reuse-v3-pr 2026-10-17 19:24:20 -07:00
Dean 0e94c5d434 Merge pull request #6243 from EagleBearerYS/perf/shader-direct-cpu-evaluable-images
perf(shader): select the record of a T# whose offset the CPU evaluates
2026-10-18 15:00:57 +13:00
Dean 63da333b7a Merge pull request #4048 from Mouad-Scriptz-0/perf/recompiler-select-load-guards
perf(recompiler): select guest memory loads instead of branching around them
2026-10-18 13:56:36 +13:00
Yunus Shaikh a53d23f810 Merge main into perf/shader-image-table-reuse-v3-pr
Main's #6402 stores to image tables: a table with a written entry takes
the fresh path, as it does on main, and so does one without a sampled
table binding, whose entries the fresh path rejects. The shared place
step uses the binding as a pointer. Main's #6614 frees descriptor sets
from shared pools one by one, while this branch keeps only dedicated
pools, so both stay. #7101's bulk key read counts its unmapped-page
skips as unmapped, and its key words sit next to this branch's write
stamp and compared runs.
2026-10-17 16:05:44 -07:00
Yunus Shaikh 4cb0512329 Merge main into perf/shader-direct-cpu-evaluable-images
Main's #7101 reads a key buffer's words in one call where this branch
names the reason a narrowing is skipped. Keep main's bulk read and
count both of its unmapped-page skips as unmapped.
2026-10-17 15:58:42 -07:00
thuanquangandClaude Opus 5.5 7b45d1034e fix(shader): run buffer atomics through a V# off a DWORD boundary
The binding plan refused every buffer atomic through a V# whose base is
not a multiple of 4. On RDNA2 such an atomic works when base + offset is
on a DWORD boundary and stops the dispatch otherwise, which the runtime
buffer atomic already does, so the refusal is dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 03:22:06 +07:00
Adrià FranchandClaude Sonnet 5.5 28b3ce0fe3 fix(main): run the large cache file test alone with a longer hang limit
Windows run 39061030084: agc_shader_disk_cache_large_file wrote 2 GiB in 141 s next to 1399 parallel tests (limit 120 s), and conventions_function_bodies_shard_4 timed out at 30 s on the same loaded runner. The test is now RUN_SERIAL and its hang limit is 200 s (ctest timeout stays 240 s).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 21:26:00 +02:00
Adrià Franch b54018e341 fix(main): unique directory for the large cache file test
Culprit: a03ccc6be (large cache files in chunks); failing run 39057904312.
The test used a fixed directory in the temp dir; the runners of one host
share it, so a concurrent run left a second entry behind.
2026-10-17 20:57:28 +02:00
thibautandClaude Opus 5.5 a03ccc6be1 fix(shader): write cache files of 2 GiB and more in chunks
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XBXM4pgkMHYEtqN1EQni2P
2026-10-17 14:48:47 +02:00
Dean 1e4ec0e3f7 Merge pull request #6415 from GitamarT045T3R/fix/shader-cache-test-windows
test(agc): delete mapped shader cache entries with POSIX semantics on Windows
2026-10-18 00:28:40 +13:00
Mouad-Scriptz-0andClaude Fable 5.1 ccaeeed416 fix(recompiler): point selected guest loads at locations nothing writes
A load selected instead of branched still accesses memory, so its fallback
element must be one no write can race with: scratch keeps element 0, LDS in
workgroup or function memory reads a sentinel dword appended after the
program's LDS and lock, and storage buffers read element 0xfffffffe, which
robustBufferAccess2 turns into a zero load without a memory access. The
device enables robustBufferAccess2 when it has it and the target carries the
flag; without it, and for LDS in device memory, buffer loads keep their
selections. The aligned high word of a buffer read re-reads the low word's
element instead of word 0. agc_guarded_memory_loads traces the emitted loads
in both device modes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-17 12:18:50 +13:00
fdfawef324andClaude Opus 5.5 d8911150d9 test(shader): cover plan reloads behind a relocated push layout
A prepared artifact also serves draws whose push constants start at another
offset. When such a capture reloads a released plan that is missing from the
disk cache, the rebuilt resource program must not stay on the source entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:24:12 +00:00
Alex ColliniandClaude Opus 5.5 7a6cc71786 feat(agc): carry spanned waves in the target and require full subgroups
APS5_SPANNED_WAVE is now read once by the driver, which sets
SpirvTarget::spannedWaves only on a device with 32-lane compute subgroup
control and computeFullSubgroups. The recompiler no longer reads the
environment. The field is part of the cache key and of the request
serialization (version 32), so a cached or replayed module keeps the mode
it was built in.

A spanned module numbers its lanes SubgroupId * 32 +
SubgroupLocalInvocationId, which needs two full 32-lane subgroups. The
artifact records this as fullSubgroups (disk cache and pipeline identity
included), and the driver creates those pipelines with
REQUIRE_FULL_SUBGROUPS. Compute pipeline captures accept the flag with a
required subgroup size.

The two-lane fallback now catches only SpannedWaveUnsupported, thrown for
a shuffle wider than 32 bits; other emit errors surface as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:12:58 +02:00
Yunus Shaikh 19907d6ed4 Merge main into perf/shader-image-table-reuse-v3-pr
Resolves #4943's draw relocation against this branch: tagVariantRuns, which now builds a draw variant's runs and words, also records the captured words it shares with a table's supplied blocks, per region as before. A variant whose runs relocation splits keeps sharing for the draw cache's word compare, and skips the vouched validation, which already requires one run per region.
2026-10-16 03:25:29 -07:00
Yunus Shaikh d21b0801a4 Merge upstream main into perf/shader-image-table-reuse-v3
Brings the series onto main 4e9a2a871 (#1193, #1201, #1202, #6060,
#6333 and the descriptor word tracking of 682b07eb0).

Resolutions:
- ShaderMemory: the column memo's supplied and spilled blocks now sit
  on #1193's page vector, page pool and word masks. Pages are found by
  binary search, since a spilled block can add many pages, and a block
  placed into a lazily read page fills the rest of the 16-word blocks it
  touches, so a later lazy read never overwrites placed words.
- ResourceMaterializer and SharedValues: the selected-record path and
  the words index carry availableDwordMask, as the snapshot hash does.
  A selected record's dwords past the end of its buffer count as read
  zeros, which is what a scalar buffer load returns there, so a key past
  the heap still selects a null image without reading the heap.
- DescriptorCache: kept table sets live beside #1201's recycled sets.
- Tests and CMake: both sides' tests are kept.
2026-10-15 08:54:44 -07:00
Yunus Shaikh 19ab974b03 fix(shader): keep the disk cache keys when the image table reuse is switched off
The shader disk cache keys every plan and variant with the recompiler's APS5_* switches that are
set (ShaderDiskCache's switch key), except the ones listed as neutral. APS5_NO_TABLE_SNAPSHOT_REUSE
and APS5_NO_TABLE_RESOLUTION_REUSE were not listed, so turning the table reuse off for a comparison
run gave every shader a new key: a cache filled with the reuse on missed throughout the boot, and
the other way round, and the comparison measured recompiles instead of the reuse.

Both switches only choose between building a column or a resolution and taking the same contents
by reference, so the output does not depend on them: they are now neutral switches. The cache
format is unchanged and FormatVersion stays as it is; only a process that sets one of them now
finds the entries stored without it.

The plan loading test gains a process with both switches set, which must load every stored plan
and variant without running the front end and produce the same output as the first process.
Before this change it failed with every plan and variant missed (17 plan misses, 17 variant
misses); now it loads all 17 with the same output.
2026-10-15 08:54:43 -07:00
Scott SchusterandClaude Opus 5.5 2ea25c53f7 fix(recompiler): the shader disk cache carries a result's shader-data user words
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:53:53 -05:00
Itamar Medyoni 402a1d0556 test(agc): delete mapped shader cache entries with POSIX semantics on Windows
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.
2026-10-15 17:24:26 +03:00