Commit Graph
2061 Commits
Author SHA1 Message Date
Adrià 76dec1794b Merge pull request #8998 from MarcZX10/codex/f32-image-store-rtz-8282
fix(agc): round 16-bit float image stores toward zero
2026-10-27 07:59:23 +01:00
Dean a453b29ebe Merge pull request #11434 from LeandroLP23/test/shader-cache-smb-posix-rename
test(shader): skip open-entry cache replacements where SMB has no POSIX rename
2026-10-27 18:38:46 +13:00
Adrià 4c486ca322 Merge pull request #10515 from JJenkx/fix/agc-two-sample-dithered-a2c
fix(agc): emulate two-sample DB_ALPHA_TO_MASK 0xe701 dithered alpha-to-coverage
2026-10-27 04:52:02 +01:00
Dean d471a12b82 Merge pull request #11112 from Bram910/fix/shader-skip-unreachable-words
fix(shader): skip undecodable words that only follow s_branch or s_endpgm
2026-10-27 15:00:43 +13:00
Dean 37c6b4bc25 Merge pull request #8077 from 0xcrstn/ufc6/descriptor-web-fold
fix(shader): split descriptor webs whose paths fold or hold invalid arms
2026-10-27 14:56:47 +13:00
Dean d1de04f943 Merge pull request #7484 from AlxcBTW/pr/robust-loads
perf(recompiler): leave the descriptor-range comparison out of direct buffer loads when the device zeroes past the range
2026-10-27 14:56:32 +13:00
Dean 630211a866 Merge pull request #6612 from milescoviello/feat/tess-geometry
feat(agc): draw tessellation followed by an NGG geometry stage
2026-10-27 14:56:18 +13:00
Dean d0bf428a45 Merge pull request #9906 from TheSovietWaffle/fix/recompiler-stencil-replay-helper-free-ballots
fix(recompiler): let optional-body merges reach ballots that helper lanes cannot contribute to
2026-10-27 14:28:31 +13:00
Dean 82358b124e Merge pull request #10976 from slick-daddy/perf/redundant-sort-hotpath
chore(shader): skip redundant sort/unique on single-element otherReads
2026-10-27 14:27:18 +13:00
Dean 7d1ed9bb1e Merge pull request #8879 from MarcZX10/codex/masked-select-single-pass
perf(shader): stop masked-select elimination after one analysis pass
2026-10-27 14:26:37 +13:00
MarcZX10 9d6b917388 fix(agc): round 16-bit float image stores toward zero 2026-10-26 23:51:54 +00:00
Dean 3ab00f40ed Merge pull request #10980 from tibzejoker/perf/f32-interpolation-fast-path
perf(shader): take an exact f32 path for 16-bit interpolation and v_fma_mix
2026-10-27 08:34:51 +13:00
battleblob1andClaude Opus 5.5 83d2093a9e fix(recompiler): let optional-body merges reach ballots that helper lanes cannot contribute to
quadObserved refuses an optional body whose merged value reaches a
ballot, unless the ballot is only read as each lane's own bit. A ballot
whose argument onHelper proves false on every helper lane is safe for
any reader: helper lanes contribute zero to every word whatever the
merged value holds there, so its words are a function of real lanes
only. quadObserved now skips such a ballot when the mask analysis has
restricted it. This bounds contribution where the own-bit funnel bounds
consumption.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 18:24:47 +02:00
battleblob1andClaude Opus 5.5 bf0589e282 fix(recompiler): accept optional-body merges implied by the skip predicate in stencil replay
An EXEC- or VCC-skipped optional body is accepted when every merge phi's
value from the body equals the skipped value on lanes inactive in the
body. A body value that implies the skip predicate is false on every
inactive lane, so it equals the skipped value when that value is the
predicate itself. inactiveEquals now accepts that case, which covers a
lane's own bit of a ballot of the predicate merged with the predicate.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 18:24:34 +02:00
LeandroLP23andClaude Opus 5.5 b95b22cf16 test(shader): skip open-entry cache replacements where SMB has no POSIX rename
On Windows, WriteFileAtomically replaces a cache entry with a POSIX
rename so that readers and mappings of the old entry keep working.
Through an SMB share that rename fails with ERROR_INVALID_PARAMETER, and
the plain rename it falls back to is refused while the destination is
open or mapped, so agc_shader_disk_cache and shader_cache_file_read
failed with their temporary directory on such a share (#10833).

The POSIX rename moves into PosixReplaceByHandle, unchanged, and
PosixReplaceUnsupported probes it in a directory. Where it reports that
error, the tests skip only the replacements of an entry that a reader
holds open or the cache has mapped, and the disk cache test's cleanup
leaves its directory behind when the POSIX delete fails the same way;
any other failure still fails them. shader_cache_file_read also builds
its \?\ alias of a UNC path as \?\UNC\server\share. The limitation is
recorded in the shader debt file.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 16:45:38 +01:00
Adrià e38fcb00dc Merge pull request #9989 from milescoviello/fix/result-memo-budget
fix(shader): bound the bytes the recompiler's result memos hold
2026-10-26 15:23:48 +01:00
Dean def1f5dd92 Merge pull request #9317 from akkadbakkad89/fix/stencil-replay-quad-observations
fix(recompiler): exempt proven control conditions and own-bit ballots in stencil replay
2026-10-27 02:27:37 +13:00
Adrià 7992f03293 Merge pull request #9703 from frankea/perf/structurizer-construct-walk
refactor(shader): walk each construct when checking the structured constructs
2026-10-26 13:48:49 +01:00
0xcrstnandClaude Opus 5.5 ec06ba2973 fix(agc): read back descriptor faults of shaders that also use image tables
A shader with an image table map read its fault buffer back only when a
table record was poisoned, an SRT read was poisoned, it had window lane
guards or the loop guard was on. A DescriptorFault only set the fault
buffer, so with a valid table and no copied write nothing ran the fault
check, and a lane that took a folded descriptor web path or selected an
undefined arm read arm 0 or zeros with no report.

The compiled artifact now counts its DescriptorFault instructions
(descriptorFaults, stored in the shader disk cache, format 48), and the
readback gate requests the fault check when it is nonzero. The result a
capture materializes copies the count, and also windowLaneGuards, which
that copy had dropped, so the gate's window lane guard condition never
saw it. sizeof(CompiledShaderArtifact) is 288 and sizeof(RecompileResult)
552 with the new field.

agc_driver_descriptor_web_faults adds a wave32 shader that reads an image
table and then the descriptor web, storing only to LDS so no copied write
forces completion: it binds an image table and no BDA address table, a
valid arm and an unselected undefined arm stay clean, the folded path and
a selected undefined arm fault at the read, and nothing faults with EXEC
empty. Without the gate change the folded case does not fault.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 14:46:11 +02:00
0xcrstnandClaude Opus 5.5 ac0c125999 Merge upstream main into ufc6/descriptor-web-fold
Resolve the overlap with main's WindowLaneGuard and image-resource changes
by keeping both sides: DescriptorFault sits next to WindowLaneGuard in the
opcode list, metadata and side-effect switch, and its emitter next to
EmitWindowLaneGuard; optionalDescriptor is serialized after
remappedDepth1D; undefinedImageWords follows the new image helpers; the
descriptor web debt entry follows main's new entries.

The ImageResource field-count assertion is derived from the merged
structure (44 fields: main's 43 plus optionalDescriptor). sizeof
(ImageResource) stays 96 and sizeof(MemoryInfo) stays 80, so those
assertions are unchanged. The undefined-format test keeps its captured
regions in a variable, as MemoryRegionView no longer binds a temporary.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 14:10:30 +02:00
Dean 9bbb7f37c6 Merge pull request #8898 from camezaro-intc/format11-11-10-float-stores
fix(shader_recompiler): pack format 11_11_10 float image stores in shader
2026-10-27 01:03:40 +13:00
Adrià 6641f48356 Merge pull request #9789 from rooklz/fix/agc-uint-color-export
fix(libSceAgcDriver): export raw 32-bit values into UINT color targets as integers
2026-10-26 12:48:04 +01:00
Adrià 97934af20b Merge pull request #9702 from frankea/perf/structurizer-split-search
fix(shader): structurize a 4,750-block graph before Unreal's render thread watchdog fires
2026-10-26 11:54:10 +01:00
Dean Galvin e0bd61fae2 Merge branch 'main' into pr/robust-loads 2026-10-26 23:10:10 +13:00
Bram910andClaude Opus 5.5 cece0ab167 fix(shader): report a skipped word's error on every decode exit
A branch into a skipped word was only reported when the sweep ended at
s_endpgm or s_code_end; a sweep that ran to the end of the code threw
the generic code-boundary error instead. Only the decoder's error types
are skipped now, so other exceptions propagate, and the debt entry
records the exception per skipped word and what a misaligned sweep
through an unreachable span puts in the program.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 11:08:51 +01:00
Bram910 433aa1dac9 Merge origin/main into fix/shader-skip-unreachable-words 2026-10-26 10:57:34 +01:00
Dean d9f5bf4d91 Merge pull request #11120 from shahulmubeen-a/fix/shader-1d-store-through-2d-array
fix(shader): write 1D storage images through 2D-array stores at slice 0
2026-10-26 21:58:24 +13:00
akkadbakkad89andDevin 4a59035543 fix(recompiler): exempt proven control conditions and own-bit ballots in stencil replay
MaskReplaySafety counted every use reaching a conditional branch condition as a quad observation, including EXEC/VCC guards that control() itself already proves replay-safe, and every Ballot regardless of how its bits are read. Nested optional regions (a merged phi re-used as the predicate of an inner execz) and ballots consumed only through the own-lane funnel (word extract, lane<32 select, lane&31 shift, &1 isolate) were refused even though neither crosses lane boundaries; the same reasoning exempts explicit-lod samples, which do not compute implicit quad derivatives.

The check now runs conditional branches through a memoized controlProven() with a visiting set, exempts those condition uses in quadObserved, walks past own-bit ballots into the isolated per-lane bools, and treats explicit-lod samples as lane-local in both quadObserved and helperObserved. optionalBody now uses a local region set so nested control proofs do not corrupt the outer walk. Anything not matching these shapes is refused as before.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-26 08:50:55 +00:00
akkadbakkad89andDevin 9f6dd5b6ed fix(shader): pair structurally equivalent whole-quad evaluations
IrProgram does not intern values, so titles that evaluate the same
whole-quad ballot twice emit distinct WqmU64 nodes for the low and
high mask words. maskStable and helpers paired those words by object
identity and rejected the split form. Compare the two evaluations
structurally instead: same-block ballots must agree on their source
tree and must not be separated by an execution-mask change, and every
newly accepted node is recorded as restricted. Assassins Creed
Shadows (PPSA20397) hits this in shader 0x407325e400.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-26 08:50:52 +00:00
Dean a3b6f688d8 Merge pull request #10338 from Filip722/submit/ir-20261023
perf(shader): avoid scanning the final IR operand use
2026-10-26 18:26:28 +13:00
battleblob1andClaude Opus 5.5 a668165c4b fix(recompiler): accept optional wave bodies of several blocks in stencil replay
MaskReplaySafety accepted an EXEC- or VCC-skipped body only when it was a
single block branching straight to the merge. Bodies with their own
branches (s_cbranch_execz around nested control flow) were refused.
optionalBody now takes the single-entry region of blocks reached from the
body before the merge: every block is entered only from the branch or
the region, none returns, nothing in it is exported or discarded, its
values leave only through merge phis, and every incoming value of a merge
phi equals the skipped value on inactive lanes. inactiveEquals follows
the region's own phis for that.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 05:15:22 +00:00
milescovielloandClaude Opus 5.5 8868e09624 fix(shader): bound the bytes the recompiler's result memos hold
Every shader source keeps up to 256 materialized results of
Recompile(request, capture) in its result memo, and as many patch
recipes in its masked memo, with no limit on their bytes. In Ghost of
Tsushima's opening the memos held about 500 MiB after 5 minutes and
kept growing, at a 13 % hit rate.

Each memo entry now counts the bytes its result's vectors keep (the
bindings' vectors included; the module is shared with the prepared
module cache), plus its patch recipe in the masked memo. A result held
by both tables counts once in each. Past a budget, 256 MiB unless
APS5_RESULT_MEMO_MB sets another (0 sets none), the least recently used
entries of both tables of all sources are dropped until three quarters
of the budget is left. The recency stamps come from one clock for all
sources and both tables so they compare across them. The profile line
also reports the trimmed and held entries and their MiB.

The trim takes its lock blocking and repeats, re-reading the bytes held,
until they are within the budget, so the insertion that pushed them
over has its trim run after any other; it stops when nothing is left to
drop.

SetResultMemoBudget and ResultMemoBytes let agc_shader_result_memo_budget
check that a memo over its budget keeps the most recently used results
and drops the oldest one, with the masked memo off. A one-shot hook
inside the trim (SetResultMemoTrimHook) lets
agc_shader_result_memo_budget_threads insert two results from other
threads after the trim has read the bytes held: the memo must still end
within its budget. agc_shader_result_memo_budget_masked, with the masked
memo on, checks that a first result counts its masked entry too and that
a trim empties the masked memo.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 05:04:18 +00:00
Dean 943ea8acb2 Merge pull request #9957 from mrfelek/fix/shader-runtime-buffer-presence
fix(shader): read a buffer V#'s presence at run time instead of specializing it
2026-10-26 16:54:34 +13:00
Dean b82cc96894 Merge pull request #8886 from thuanquang/fix/dot2-f32-f16-accumulator-modifiers
fix(shader): apply v_dot2_f32_f16's accumulator modifiers as RDNA 2 does
2026-10-26 11:06:40 +13:00
Adrià 3a930342d5 Merge pull request #9701 from frankea/fix/structurizer-scc-iterative
fix(shader): find strongly connected components without recursion
2026-10-25 23:03:07 +01:00
Shahul Mubeen AandClaude Opus 5.5 b9d00c5d80 fix(shader): write 1D storage images through 2D-array stores at slice 0
An image_store with DIM 2D_ARRAY through a 1D T# had no runtime image
mode, so the dispatch stopped with "image descriptor is incompatible
with the static runtime image interface". #2348 added a 1D mode for
DIM 2D stores only.

Write-only 2D-array storage images now get the same 1D mode as the 2D
case. On RDNA2 (gfx1036, hardware oracle) such a store writes texel x
and ignores y when the slice is 0, and writes nothing for any other
slice, with DEPTH 0 or 3, so the store is skipped unless the slice is 0.

New execution test agc_driver_image_store_line_through_plane_array.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 00:10:03 +05:30
Bram910andClaude Opus 5.5 2158c56a88 fix(shader): end the control-flow block at s_code_end
A block that ended in s_code_end fell through to the next block. With
undecodable words skipped after s_code_end, that made a later branch
target a fall-through successor of s_code_end. The graph now starts a
block at the next decoded instruction after s_code_end and ends the
s_code_end block with a return, as it does for s_endpgm.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 19:38:58 +01:00
Bram910andClaude Opus 5.5 e1213fd473 fix(shader): skip undecodable words that only follow s_branch or s_endpgm
The RDNA program decode sweeps linearly up to the last s_endpgm past the
furthest direct branch target, so it also decoded words that no path
reaches and threw on any it could not decode. A word directly after
s_branch, s_endpgm or s_code_end that fails to decode is now skipped;
the decode still throws that word's error when a direct branch or
s_call_b64 targets it, and a failure on a word reachable by fall-through
is unchanged. The control-flow graph starts the block after s_branch and
s_endpgm at the next decoded instruction instead of the next word.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 19:15:40 +01:00
Dean 97c2c0eed8 Merge pull request #9251 from SandstromPL/fix/mimg-gather4-c-a
feat(shader): decode MIMG opcodes 0xc8 and 0xd8 as image_gather4_c_a and image_gather4_c_o_a
2026-10-26 05:42:57 +13:00
Slick Daddy 16507a99f8 perf(shader): skip redundant sort/unique on single-element otherReads 2026-10-25 14:41:31 +03:00
thibautandClaude Opus 5.5 be81531d69 perf(shader): take an exact f32 path for 16-bit interpolation and v_fma_mix
FPInterpolateF32 and FPInterpolateF16 (v_interp_p1ll/p1lv/p2_f16, v_fma_mix*)
were always emulated in f64, or in 64-bit integers without Float64. Each
interpolation function now computes the result in f32 first and calls the exact
function only when that result is not provably exact.

The f32 path uses no Fma, as Vulkan does not require it to be fused: the product
is a Veltkamp-Dekker two-product, the sum with the base a TwoSum, the error terms
are added with round to odd (Boldo-Melquiond), every operation NoContraction.
It is taken when each input is zero or has a biased exponent in [24, 241] (base
[24, 251]) and the product exponents sum to [174, 377]: every intermediate value
is then a multiple of 2^-126 below 2^126, so none is a denormal a device could
flush and none overflows. A zero result takes its sign from the IEEE rule on the
bits. f16 results are rounded from the f32 bits, on the normal and the subnormal
f16 grid, unless the f32 result is an inexact f16 midpoint; directed f16
rounding keeps the exact path.

agc_driver_interpolation_modes gains 8192 chains of 64 f32 and f16
interpolations over all 32 float modes and a --benchmark of 65536 lanes x 4096
chained interpolations: RTX 4090 Float64 path 10.24 -> 2.05 ms (f32) and
9.91 -> 2.19 ms (f16), integer path 3.58 -> 2.03 / 3.65 -> 2.20 ms; Intel UHD 770
(integer path) 176.6 -> 33.6 / 178.4 -> 56.4 ms.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017SNUYRd7sRKZrMYpquAsnU
2026-10-25 12:34:48 +01:00
Adrià 66e6772ca2 Merge pull request #10473 from milescoviello/fix/release-unused-specialized-modules
fix(shader): release specialized modules that no result uses
2026-10-25 11:58:42 +01:00
Adrià e317f41d59 Merge pull request #10440 from SuarezPM/ai/atomic64-keyed-tables
feat(shader): support 64-bit image atomics through keyed image tables
2026-10-25 11:58:35 +01:00
Dean b91a6a60c5 Merge pull request #10595 from TechLevelZero/fix/f32-conversion-denormal-modes
fix(shader): translate f32 conversions in f32 denormal modes 1 and 2
2026-10-25 23:54:07 +13:00
Adrià 75227c7cdc Merge pull request #10423 from meh7an/perf/shader-masked-result-memo
perf(shader): reuse a memoized result by patching its copied words
2026-10-25 11:50:14 +01:00
Dean 6f155e8b56 Merge pull request #10639 from Galluno/perf/shader-cache-version-realpath
fix(shader): resolve each shader cache source and include path once
2026-10-25 21:37:25 +13:00
milescovielloandClaude Opus 5.5 b6da343d20 fix(agc): keep the negated-predicate proof when a negated condition isn't implied
ImpliesNot returned at a negated condition, so a predicate !!a against
the condition !a, or !!a in either order of a conjunction, never reached
the negated-predicate and conjunction cases, which prove it. Lane-bit
lowering makes such a predicate from a complemented own-lane ballot of
!a, and the address evaluator then read both arms of a select on !a
instead of the one the predicate implies. Each case now falls through
when it does not prove the negation. Three hull reads under that
complemented ballot bit, alone and conjoined on either side, check it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 08:32:48 +00:00
milescovielloandClaude Opus 5.5 cd5fc9e838 feat(agc): draw tessellation followed by an NGG geometry stage
Crimson Desert (PPSA25286) draws with VGT_SHADER_STAGES_EN 0x60212d:
local, hull, domain and NGG geometry stages, the hull halves merged in one
registered type-3 program, the domain and geometry halves in one type-2
program. The domain half runs as the tessellation evaluation stage and
captures each vertex's ESGS item, and a mesh shader runs the geometry half
on the captured items.

Registered type-3 merged hulls come from #6679; this adds 16-bit LDS
reads and writes in tessellation stages, which Crimson Desert's merged
hull uses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 08:32:37 +00:00
camezaro-intc e3f644040c fix(shader_recompiler): pack format 11_11_10 float image stores in shader 2026-10-24 21:32:14 -06:00
Dean Galvin eb3dd54501 Merge main into pr/robust-loads 2026-10-25 12:15:18 +13:00