Commit Graph

1077 Commits

Author SHA1 Message Date
Dean 2f4cc8983b
Merge pull request #4431 from AlxcBTW/refactor/spirv-specializer-debris
refactor(shader): drop unused folded constants and unreachable blocks after specialization
2026-10-13 08:30:39 +13:00
Dean 9d3629cc91
Merge pull request #4268 from AlxcBTW/fix/vop3p-int-neg
fix(shader): apply VOP3P neg_lo/neg_hi to packed 16-bit integer sources
2026-10-13 07:35:10 +13:00
Dean c90404f97a
Merge pull request #4518 from AlxcBTW/fix/bda-unaligned-dword-write
fix(shader): store unaligned 32-bit BDA writes byte by byte
2026-10-13 07:34:34 +13:00
Dean 0c75934f5f
Merge pull request #4470 from overlordxrz-source/fix/vertex-one-lane-waves
fix(recompiler): run vertex programs as one-lane waves without vertex subgroups
2026-10-13 07:34:13 +13:00
Dean 9f7c40e36f
Merge pull request #4389 from ivica00/fix/rect-list-invariant-position
fix(shader): decorate rect-list gl_Position as Invariant
2026-10-13 07:33:51 +13:00
Dean 5d933db02e
Merge pull request #4364 from SleglJan/fix/structurizer-return-join
fix(recompiler): give an early-return selection a merge when its parent's other arm reaches the same join
2026-10-13 07:33:30 +13:00
AlxcBTW 676622fd78 fix(shader): count only id operands as uses when dropping specialization debris
referencedIds() took every operand word of every instruction as a
possible id, so a literal that happened to equal the id of a dead folded
constant or an unreachable block kept it: the OpTypeInt width 32 kept a
dead constant %32, LocalSize literals kept dead labels.

Visit only the <id> operands of each instruction. Literal operands are
skipped for the instructions that carry them: type widths, counts and
image parameters, constant values, storage classes, memory access and
image operand masks (their trailing ids still count), composite and
shuffle indices, OpArrayLength members, extended instruction numbers,
entry point names, execution modes, merge and function controls, branch
weights, OpSwitch case values (two words for a 64-bit selector) and
group operations. An instruction without a listed layout still counts
every word, so an unknown instruction can only keep debris, never drop
something in use.

The SpirvModule case now also folds a switch whose dead constant has id
32 and whose dead blocks' ids appear as LocalSize literals; it fails
without this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:03:08 +02:00
Dean 8751a29407
Merge pull request #4150 from eljackjoestar-cmd/codex/ancillary-relative-ssa
fix(shader): preserve ancillary proofs across relative VGPR accesses
2026-10-13 03:42:06 +13:00
Dean acb13d1b39
Merge pull request #4030 from AlxcBTW/fix/recompiler-flat-p10-provoking-v2-2
fix(recompiler): read P10 of a flat input as the provoking vertex
2026-10-13 03:41:23 +13:00
Dean cee0290c2c
Merge pull request #4331 from oneandonlydean/up4/fix-3504-shader-prep-time
fix(shader): prove masked lanes unread for every select in one backward pass
2026-10-13 03:07:16 +13:00
AlxcBTW 803a131275 fix(shader): store unaligned 32-bit BDA writes byte by byte
EmitBdaWrite, used for buffer stores through GPU-selected descriptors, recorded an
Unaligned fault and dropped every 32-bit store whose address is not 4-byte aligned.
EmitBdaStore and the BDA reads already take the byte path for unaligned addresses, and
raw buffer accesses use the exact bytes, as RDNA does in unaligned mode. The unaligned
case now stores the four bytes one by one like the 8- and 16-bit stores of the same
function.

Sword of the Sea hit this about once per frame from one compute store, so four bytes
were lost and a fault was reported each time.

The BDA store execution table now also runs through EmitBdaWrite; its unaligned dword
cases failed before this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:06:16 +02:00
overlordxrz-source 0bcff53b2c fix(recompiler): run vertex programs as one-lane waves without vertex subgroups
lavapipe and MoltenVK leave the vertex stage out of subgroupSupportedStages,
so the driver's shader validation refuses every vertex program that declares
GroupNonUniform ("subgroup capability 61 is unsupported for shader stage 1").
Most do, since the entry EXEC is a ballot.

The device target now records whether the vertex stage has subgroups. When
it does not, vertex and local programs get a host subgroup width of 1: s3
reports one vertex and one primitive, the lane id is 0, a ballot is the
invocation's own bit, a shuffle returns the invocation's value, an elect is
true and a half-wave reduction read is the key itself. Reads of other lanes
keep the existing narrow-host rules and throw where they did. Devices with
vertex subgroups emit the same SPIR-V as before.
2026-10-12 08:50:05 -04:00
Dean 0e61bedf9a
Merge pull request #4162 from Celegans12/fix/shader-wave64-lane-reductions
fix(shader): match half-wave reductions over relatively addressed vector registers
2026-10-12 23:54:08 +13:00
AlxcBTW 3ea89674d2 refactor(shader): drop unused folded constants and unreachable blocks after specialization
SpecializeSpirv hoists every instruction it folds into a module-level
constant and keeps that constant after its last use has folded away
too. It also leaves each block that a folded branch cuts off as
OpLabel; OpUnreachable. A formatted buffer helper's 77-case format
switch leaves about 1,800 such blocks.

Emit only the folded constants that something still refers to, and
remove OpLabel; OpUnreachable blocks that no instruction names. Merge
and continue targets of live constructs are named, so they stay.

The specialized modules lose words, not behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:17:25 +02:00
eljackjoestar-cmd ae049e7757 fix(shader): restrict ancillary refolding to live builtin uses 2026-10-12 14:09:32 +04:00
eljackjoestar-cmd b3587f9528 fix(shader): preserve ancillary proofs across relative VGPR accesses 2026-10-12 13:36:30 +04:00
ivica00 436e4191c7 fix(shader): decorate rect-list gl_Position as Invariant
The vertex stage already marks Position Invariant, and the rect-list stages have to match that interface.
2026-10-12 10:45:38 +02:00
Adrià 2979ae37a3
Merge pull request #4152 from adriadam10/feat/phase-b
perf(agc): build shader pipeline libraries when shaders are registered
2026-10-12 10:31:42 +02:00
Dean Galvin d37463e76f fix(shader): prove masked lanes unread for every select in one backward pass
MaskedSelectEliminator walked forward from each select to see whether the
lanes its mask excludes are read. Since fda4aa90 the walks pass explicit-LOD
gathers, size queries and guarded image writes, so in a large pixel shader
most of them cover the rest of the program, and the cost grows with the
square of its size (#3504).

The pass now computes, for every value, the set of masks under which it is
unread, from its uses backwards: a use guarded by a condition contributes the
masks that condition implies, a lane-local use adds what its result is unread
under, and any other use contributes nothing. A select is dropped when its
mask is in its own set. Loops are solved as strongly connected components.
The rules for guards, lane-local uses, loops, whole quad masks, selected
execs, rebuilt mask words and guarded first-lane reads are the ones the walk
applied. A first-lane read passes the masks its read mask implies when its
own result is unread outside that read mask, which is solved once per read in
the same way. The walk's step limit, its 64-level implication depth and its
first-lane nesting depth are gone, so a proof no longer depends on the order
of the questions.
2026-10-12 21:16:29 +13:00
Adrià Franch f9b592806c perf(recompiler): keep the buffer base misalignment specialized in registration form
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch 56d5a4985d perf(recompiler): read the formatted buffer helper's V# words as specialization constants when the format is known
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch 60151b66b7 perf(recompiler): keep the format word specialized for buffers accessed with the descriptor's format
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch 672e43ca67 perf(recompiler): keep compute shaders specialized; only prebuilt vertex and pixel shaders take the registration form
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch 361c7e2024 perf(agc): keep oversized shaders specialized and prebuild libraries on their own thread
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch a326fa84f7 fix(recompiler): give registration results a flattened SRT placeholder
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch 67556722e1 perf(recompiler): read vertex attribute component selectors at run time when modules are built at registration
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch 7f64d14772 perf(agc): build the shader pipeline libraries when graphics stages are resolved at registration
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch 4d0b5c7898 perf(agc): give the fragment stage its own descriptor set when modules are built at registration
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:41 +02:00
Adrià Franch baf3437465 perf(recompiler): read depth-compare state and export mappings at run time when modules are built at registration
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:33 +02:00
Adrià Franch 765ea6a10f perf(recompiler): keep descriptor heaps uncompacted and read image modes at run time when modules are built at registration
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:32 +02:00
Adrià Franch ddb6680667 perf(recompiler): read buffer V# words in the shader when modules are built at registration
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-12 09:50:32 +02:00
Jan Šlégl 7f5cd4480d fix(recompiler): give an early-return selection a merge when its parent's other arm reaches the same join
A selection outside loops whose one arm only returns and whose other arm
branches to a join it does not dominate gets an empty block on that edge
as its merge (splitOneReturnJoin), but only when every other predecessor
of the join dominates the selection or is dominated by it. When the
parent selection's other arm is a region that ends in the same join, the
selection has no structured merge and the shader fails to recompile.

When every structurization attempt fails, Structurize now runs them again
and accepts that split for any join the selection does not dominate. The
split only inserts an empty block on the edge from the selection to the
join. Graphs that structurize on main keep their result.

A synthetic CFG and a synthetic program cover the shape; both fail on main
with "conditional block N has no structured merge".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fnrk5Dazjb2tLooVSpdRQq
2026-10-12 09:11:25 +02:00
Dean Galvin 22d662eda7 fix(agc): export the stencil reference from pixel shaders with VK_EXT_shader_stencil_export 2026-10-12 19:44:41 +13:00
Dean d06c065657
Merge pull request #3895 from CouchRiv/fix-shader-vcmpx-f32-family
fix(shader): keep f32 denormals in compares when denormals are kept
2026-10-12 19:39:34 +13:00
Dean 7f7f961bf8
Merge pull request #3739 from eljackjoestar-cmd/codex/masked-first-lane-proof
fix(shader): prove masked writes through guarded first-lane reads
2026-10-12 19:39:13 +13:00
Dean 0ed0d3c9b6
Merge pull request #4033 from MarcZX100/codex/carry-shader-wqm-live-quad-bit-2548
fix(shader): fold current s_wqm pixel lane
2026-10-12 18:19:43 +13:00
fma-rc 9db923e907
fix(shader): clip primitives with an all-zero clip position 2026-10-12 06:46:34 +02:00
Dean 6d1cee6d3f
Merge pull request #3593 from ahir061/fix/recompiler-prime-shared-mutex
fix(shader): lock recompiler shared mutexes once when created
2026-10-12 17:30:28 +13:00
Dean c22957f7b0
Merge pull request #3951 from Scramblrrrr/codex/constant-phi-definitions-current-main
fix(shader): preserve distinct SSA definitions when folding Phi inputs
2026-10-12 17:30:04 +13:00
Dean 32cb3fea95
Merge pull request #3932 from CouchRiv/fix-shader-f16-denorm-flush-family
fix(shader): flush f16 denormals in unary, frexp and conversion ops per the float mode
2026-10-12 17:29:43 +13:00
Dean 6b0ce1513d
Merge pull request #4018 from Mouhand-Kaddo/fix/demons-loop-continue
fix(shader): keep Demon's Souls loop shader valid after optimization
2026-10-12 17:29:21 +13:00
Dean 18af217211
Merge pull request #3645 from alfalfa-star/fix/recompiler-mesh-grid-size-sgpr
fix(recompiler): read NumWorkgroups in every mesh shader so RADV sizes its user data
2026-10-12 17:27:54 +13:00
AlxcBTW a7ed14c74b Merge branch 'main' into fix/recompiler-flat-p10-provoking-v2-2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:09:22 +02:00
AlxcBTW 48654bdc89 fix(shader): apply VOP3P neg_lo/neg_hi to packed 16-bit integer sources
The packed integer ops (v_pk_add/sub/mul_lo/mad/min/max/shift) read their
16-bit sources without the VOP3P negate bits. Hardware negates a 16-bit
source by flipping bit 15 for integer ops too, and Sony's compiler relies
on it: UE5's TSR history update clamps its -1 neighbour offsets with
v_pk_max_i16 v14, neg(lit 0x7fff), v14, i.e. max(-1, minY - y). Without
the modifier that became max(0x7fff, x), the x-1/y-1 taps of the 3x3
input filter read out of bounds as zero, and the history lost ~16 % of
its energy every frame (Sword of the Sea's missing glow).

The new execution test covers every packed integer op with neg_lo and
neg_hi, op_sel interplay, clamp and the TSR literal case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013fa2MbmdFLVr8YHuVjucHE
2026-10-12 04:57:52 +02:00
Celegans12 364d7cf29f fix(shader): match half-wave reductions over relatively addressed vector registers
A program that uses v_movrels_b32 or v_movreld_b32 keeps every vector
register from the lowest relatively addressed one up in a per-invocation
window array, so its plain register accesses become LoadVectorWindow and
StoreVectorWindow. The half-wave reduction matcher followed only SSA values,
so a wave64 scan, v_permlanex16_b32 join and lane 31/63 read through that
array threw that lane 63 is outside the 32-lane host subgroup.

The matcher now reads a window load at a constant slot as the value of the
last store to that slot earlier in its block, unless a store at a runtime
slot lies in between; each invocation owns its array, so that is the value
the load returns. A store in another block, or a v_movreld_b32 at a runtime
M0 in between, still throws. This was the only refused lane 32-63 read left
among Ghost of Yotei's wave64 graphics programs (one pixel program).
2026-10-12 02:07:50 +02:00
eljackjoestar-cmd fded8a7e7f fix(shader): prove masked writes through guarded first-lane reads 2026-10-12 03:57:04 +04:00
jweidenh 5ec6cff3fa fix(recompiler): include implicit inputs in relative vector windows 2026-10-11 19:23:00 -04:00
Alex de54527a8b fix(shader): keep f32 denormals in compares when denormals are kept
With the f32 denormal field of FLOAT_MODE set to keep, v_cmp_X_f32 and
v_cmpx_X_f32 read a denormal operand as zero: NVIDIA, RADV and lavapipe
all flush denormals in their float compares. Compare the operands as
sign-magnitude integers instead, with NaN handled apart. Compares with
flushed denormals are unchanged. This matches RDNA2 (gfx1036) on 256
operand pairs per opcode, with f32 denormals kept and flushed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 18:51:37 -04:00
Adrià 3905e7e2c9
Merge pull request #3827 from CouchRiv/fix-shader-combined-cvt-i16-f16-omod
fix(shader): accept output modifiers on v_cvt_i16_f16 and ignore them as the hardware does
2026-10-12 00:39:20 +02:00
Adrià ae7dbfa9cb
Merge pull request #3770 from A-Akhil/fix/shader-sin-cos-series
fix(shader): take v_sin_f32 and v_cos_f32 from an exact series where the driver's result is more than 4 ulp off
2026-10-12 00:29:31 +02:00