Commit Graph
61 Commits
Author SHA1 Message Date
Dean 7c7cfacc2d Merge pull request #12173 from MarcZX10/fix/shader-tessellation-instance-patches-zero-control-points
fix(shader): do not divide by zero control points when keying tessellated draws
2026-10-28 22:50:20 +13:00
MarcZX10 59fef11858 test(shader): key a tessellated instanced draw with zero control points
The instance patch count has to be zero instead of crashing, and a regular
configuration still divides the index count by the control points.
2026-10-28 01:05:38 +00:00
Dean Galvin d4a296d863 Merge main into perf-D2-v47: depth export tail moves to request version 49
Main took request serialization version 48 for the fragment barycentric
built-ins flag (#9193). The depth export clamp bounds are now written at
version 49 and read only for versions from 49, so a version 48 request as main
writes it still decodes, with default bounds. Tests: version 49 is the
emitted prefix, 50 the first unsupported one, a depth exporting request
without its bounds decodes at 48, 47 and 46 (the last two without main's
barycentric byte), and a version 48 two-sample dithered request decodes as
written.
2026-10-28 08:24:34 +13:00
Dean Galvin 1bf274a817 Merge main into perf-D2-v47: depth export tail moves to request version 48
Main took request serialization version 47 for the two-sample dithered
alpha-to-coverage value. The depth export clamp bounds are now written at
version 48 and read only for versions from 48, so a version 47 request as main
writes it still decodes, with default bounds. Tests: version 48 is the
emitted prefix, 49 the first unsupported one, and a version 47 two-sample
dithered request (with and without depth export) decodes as written.
2026-10-27 22:37:31 +13:00
Emanueleandyripper a95ced504c feat(recompiler): read I/J from barycentric built-ins on MoltenVK
MoltenVK exposes VK_KHR_fragment_shader_barycentric but its MSL step
rejects PerVertexKHR, so the extension is disabled there and a pixel
shader whose I/J VGPRs outlive their v_interp_p1/p2 pairs takes the
generated barycentric stages, which accept only triangle lists without
primitive restart on a device without geometry shaders.

A new target flag, fragmentBarycentricBuiltins, enables the extension
for its built-ins only. The host interpolation check then keeps the
leftover I/J reads (all perspective or all linear, at the fragment's
default position) and reads them from BaryCoordKHR or
BaryCoordNoPerspKHR, while the interpolated attributes stay hardware
varyings. Raw vertex parameters and I/J at an offset or a sample
position still take the generated stages. Apple GPUs return
unnormalized perspective weights unless the fragment function reads
[[position]], so each perspective read keeps a neutral use of
gl_FragCoord.w, loaded as a float. Devices with the full extension are
unaffected; the request serialization moves to version 45.

Co-authored-by: yripper <[email protected]>
2026-10-27 07:25:48 +01:00
JJenkxandClaude Opus 5.5 2ff14f34e3 fix(agc): emulate two-sample DB_ALPHA_TO_MASK 0xe701 dithered alpha-to-coverage
Bugsnax (PPSA01503) draws with DB_ALPHA_TO_MASK 0xe701 (quad offsets
3, 1, 2, 3 without OFFSET_ROUND) on a two-sample target and stopped on
the refusal of every dither but the eight-sample 0x18701. The pixel
shader now applies an eight-level per-quad table for it, measured
natively on gfx1032, and the request's dither byte selects that table
(serialization version 47). It is accepted only for two matched raster
and DB_EQAA samples, the two measured location pairs and FP16_ABGR or
32_ABGR exports.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 16:40:02 -04:00
Dean Galvin c8f6a33164 Merge main into perf-D2-v47 fix (request serializer version 47 on top of main's 46) 2026-10-25 08:55:48 +13:00
JAB-devandClaude Sonnet 5.5 8d54357e79 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into feat/agc-4-4-4-4-partial-writes
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-23 21:18:00 +02:00
Dean Galvin 13727eebd1 Merge main into perf-D2-v47 2026-10-24 07:59:40 +13:00
Adrià 1e1ab77684 Merge pull request #8495 from yabanana/fix/borrowed-memory-regions
fix(shader): reject temporary owners for borrowed memory regions
2026-10-23 20:47:29 +02:00
Maz 913e458369 fix(shader): deserialize pixel function storage dwords at version 45
The SM-budget threshold writes the storage size after the LDS flag; read it back and keep the fixtures on the fused+pointList trailer.
2026-10-23 20:53:29 +04:00
Maz 40c7ff888c fix(shader): scale pixel LDS Function threshold by SM budget
Max measured a 4 GiB private-memory ceiling on a 4090; use
VK_NV_shader_sm_builtins so denser cards take the buffer path below 4096.
2026-10-23 20:53:24 +04:00
mazen dba7f5466c fix(shader): keep a pixel LDS overflow until the GPU is idle
The slot counter is reset only after earlier fragment writes, and the overflow flag stays until WaitIdle. The storage buffer is limited to NVIDIA's proprietary driver, which is where the large function array does not finish.
2026-10-23 20:53:21 +04:00
Dean Galvin 7ec9ce9132 fix(agc): clamp an exported pixel depth to the viewport depth range
The DB clamps a pixel shader's exported depth to PA_SC_VPORT_ZMIN_0 and
ZMAX_0 unless DB_RENDER_OVERRIDE.DISABLE_VIEWPORT_CLAMP is set. Vulkan only
clamps with depthClamp, which also drops clipping, so the exported value
reached the depth attachment unclamped.

The pixel stage info now carries the two bounds when the shader exports
depth (0 and 1 otherwise), and the exported value is NClamped to them
before it is stored to gl_FragDepth. With
DISABLE_VIEWPORT_CLAMP the value is stored as exported; non-finite or
inverted bounds are rejected. DB_RENDER_OVERRIDE joins the draw key
registers. The bounds
are part of the recompile cache key (only for depth-exporting shaders, so
other keys do not change), the draw key and its register check, and
recompile requests (serialization version 47).

Tests: the pixel stage decode reads the bounds, passes the disable flag through
and rejects bad bounds, and leaves a draw without depth export at 0 and 1; a
recompiled depth export stores the NClamped value, and its bounds survive
serialization and key the cache.

Request version 47: main is at 44 (#8612) and open PRs also claim 44 to 46 (#8564, #7888, #9193 and the #9020, #9335, #9748 stack). Whichever of these lands second renumbers.
2026-10-24 01:38:01 +13:00
Daniele Giovane 13b1892fdd Merge main and address review for PR 8495 2026-10-23 12:45:54 +02:00
EmanueleandYcaro Gabriel 7410c37b6c perf(shader): emit exact f32 add, subtract and multiply as fma on MoltenVK
The recompiler marks every guest f32 add, subtract and multiply
NoContraction, because the guest rounds each one separately.
SPIRV-Cross turns each of them into a call to a helper that Metal
compiles without optimization, which dominates fragment time on
MoltenVK, and its multiply helper, fma(a, b, +0.0), turns a -0.0
product into +0.0.

On MoltenVK they are now GLSL Fma whose second step is exact, which
gives the separately rounded result: a * b is fma(a, b, -0.0), a + b
is fma(1.0, a, b) and a - b is fma(-1.0, b, a). The sin, cos and log2
series and the offset image coordinates and gather texel scale use the
same forms. The choice is a SpirvTarget flag set for
VK_DRIVER_ID_MOLTENVK, part of the shader cache key and of the request
serialization (version 44); other drivers are unchanged.

agc_driver_f32_separate_rounding checks a multiply feeding an add or a
subtract on rows where fusing them changes the result. It,
agc_driver_f32_arithmetic_nan and agc_driver_f32_denormal_flush also
run the fused forms on devices that do not use them, so lavapipe checks
them against the same rows.

Co-authored-by: Ycaro Gabriel <[email protected]>
2026-10-23 12:13:18 +02:00
JAB-devandClaude Sonnet 5.5 d201de3f32 Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into feat/agc-4-4-4-4-partial-writes
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-23 04:09:40 +02:00
JAB-devandClaude Sonnet 5.5 8ed185a51c Merge branch 'main' of https://github.com/boykopovar/AnyPS5 into feat/agc-4-4-4-4-partial-writes
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-21 20:13:17 +02:00
JJenkx b779c90159 test(shader): retain sample order through legacy point replay 2026-10-21 09:13:32 -04:00
JJenkx 19be2835f2 test(shader): preserve legacy point requests after denorm serialization 2026-10-21 09:13:32 -04:00
JJenkx ee9b1c8249 test(shader): upgrade legacy point requests to version 40 2026-10-21 09:13:32 -04:00
JJenkx 70c8476c7c test(shader): align request version guards after float flush merge 2026-10-21 09:13:32 -04:00
JJenkx c750708c8d test(shader): preserve depth remap requests through point replay 2026-10-21 09:13:32 -04:00
JJenkx 8409360d40 test(shader): retain request versions through 34 for point replay 2026-10-21 09:13:32 -04:00
JJenkx 95a2a45fe3 test(shader): preserve version 32 requests with spanned waves 2026-10-21 09:13:32 -04:00
milescovielloandClaude Opus 5.5 89be76cb4c test(shader): check version 39, 41, 42 and 43 requests with merged hull and point state
A tessellated vertex request with the merged hull flag and a point list
serializes as version 43 with both. Without its point tail it reads as
main's version 42, without the pixel sample order as version 41, and
without the f32 denormal preserve flag as version 39, each keeping the
merged hull flag and taking the default point state.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 09:13:32 -04:00
milescovielloandClaude Opus 5.5 11bc7b1686 fix(shader): move the vertex point fields to request version 43
main took request versions 33 to 42 for other fields, the last of them
the pixel sample order, so requests of those versions from main have no
point-list tail. The point fields now come with version 43, after them,
and the tests expect 43 and reject 44.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 09:13:32 -04:00
milescovielloandClaude Opus 5.5 e7ea490325 feat(agc): draw point lists on the vertex path with their point size
A point list routed through the vertex path was refused, and so was
PA_CL_VS_OUT_CNTL.USE_VTX_POINT_SIZE on it. OliSe Player (PPSA01153)
stops on the latter with two of its MilkDrop presets.

The vertex path now draws point lists as Vulkan points. The vertex stage
writes PointSize: the misc export's X clamped to PA_SU_POINT_MINMAX when
USE_VTX_POINT_SIZE is set, and the PA_SU_POINT_SIZE height otherwise.
The point state travels in the recompile request (version 31) and the
cache and draw keys. Non-square register sizes, inverted clamps, point
sprite texture coordinates and, without largePoints, sizes other than
one pixel throw.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 09:13:09 -04:00
Yunus Shaikh 6d09797d6b Merge main into fix/agc-sample-location-grid-exact 2026-10-21 05:39:42 +00: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
JAB-devandClaude Sonnet 5.5 6ccb8c052e fix(agc): refuse memory-writing 4_4_4_4 merges only where tests can reject pixels
The refusal of a merging shader that writes guest memory under late
tests fired in two cases where the early tests change nothing.

The first was a draw with no depth, stencil or depth-bounds test. Early
tests reject no pixel there, so every write the console makes still
happens. The target merge now carries whether the draw has such a
test, and the refusal applies only then. This adds one byte to the
version 40 merge fields of the recompile request.

The second was any GDS binding, including a shader that only reads GDS.
The refusal now looks for GDS writes, atomics, appends and consumes.

Tests: the depth and stencil decode checks the new flag, and the
static shader key depends on it. A counter-adding shader under late
tests compiles without a test and throws with one. A late-test merge
that reads GDS compiles, and one that adds to GDS throws.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-20 19:09:49 +02:00
JAB-devandClaude Sonnet 5.5 27c0004991 fix(agc): merge kill shaders under late tests when the draw writes no depth or stencil
A packed 4_4_4_4 partial write merges inside the pixel shader after early
depth and stencil tests. Moving the tests ahead of a pixel kill only changes
the result when the draw writes depth or stencil, so the target merge now
carries whether the draw does (depth write, or stencil with a write mask and
a non-keep operation), and the late-test kill refusal applies only then.
The flag is part of the static shader key, the serialized request (now
version 40) and the pixel input info.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-20 19:09:48 +02:00
JAB-devandClaude Sonnet 5.5 48a7efcbec feat(agc): merge partial writes into 4_4_4_4 UNORM color targets
A CB_TARGET_MASK that writes fewer than four components of a 4_4_4_4
target leaves the other nibbles of each packed word as they were, which
an R16_UINT attachment cannot do. Such draws now close the attachment's
color write mask, and the pixel shader merges the written nibbles into
the target through a storage image: inside a pixel interlock it reads
the word, keeps the bits the mask leaves alone and stores it back.

The merge (export index, word mask, sample count) is part of the static
shader key, request version 40 and shader disk cache format 42; the
storage image is appended to the shader's images with a single runtime
mode, and its T# is encoded from the target's surface at draw time, so
the draw resolves it to the target's resident image, which Draw
requires. Merging shaders declare early fragment tests; shaders that
kill under late tests, export depth, stencil or coverage, use
alpha-to-coverage or a quad sample mask are refused, as are
multisampled, mipmapped, volume and array targets and more than one
merged target per draw.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-20 19:09:48 +02:00
Jan ŠléglandClaude Opus 5.5 8b8219dcef feat(agc): run registered merged hull programs (binary type 3)
A registered type-3 hull program holds the local and the hull part of a
tessellation draw in one binary, addressed through SPI_SHADER_PGM_LO_LS
(SH 0x148) with no SPI_SHADER_PGM_LO_HS: the local part runs on the lanes
below s3[7:0] and writes LDS, an s_barrier follows, and the hull part runs
on the lanes below s3[15:8] and may store the registers the local part
filled. The draw decode asked 0x148 for a type-5 local half, and
PPSA11386 (007 First Light) stopped in its level load with "registered
program refers to an incompatible shader binary type".

The draw decode now gives a registered type-3 program both the local and
the hull role and marks the tessellation configuration mergedHull. The
local stage only passes gl_VertexIndex and gl_InstanceIndex in a 16-byte
record. The hull stage runs the whole program, one invocation per output
control point: v2 and v5 come from the record of control point
min(gl_InvocationID, inputs - 1), v3 is the relative vertex id, and the
LDS becomes a per-control-point output array that a control point writes
in its own record and reads in any record of its patch after the barrier.
Registers live across the barrier stay in the invocation.

The hull stage of a merged program runs at one lane per invocation on
every device (HostSubgroupSize 1). Its lanes are gl_InvocationID, not host
subgroup invocations, so the s_cbranch_execz around the local part tests
the invocation's own lane. With the device's subgroup it took a subgroup
ballot, and lavapipe, whose subgroup stages lack the tessellation control
stage, rejected the draw ("subgroup capability 61 is unsupported for
shader stage 2").

The lowering refuses more input than output control points, LDS writes
outside the own record, reads outside the patch's records, barriers that
some invocations do not reach or that sit in a loop, reads or writes of
another lane's register, outputs beyond the device limits, and fetch
subroutines. Type 3 is prepared with its stage group like type 5 and
takes its float mode from RSRC1_HS. The hull user-data address (SH
0x102/0x103) is optional for a merged program: s[0:1] take it, unchecked,
when the draw sets it and are zero otherwise.

Both stages refer to one binary, so a draw lists each code and header
region once (AppendProgramMemory); a request's memory regions must not
overlap. An indirect draw's record words go into every program whose user
data holds the register, so the hull stage of a merged program reads
them too.

mergedHull is part of the recompile cache key, the draw decode comparison
and the request serialization (version 39).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 15:55:50 +02:00
Daniele Giovane f923961c66 fix(shader): reject temporary owners for borrowed memory regions 2026-10-20 15:47:24 +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 <[email protected]>
2026-10-19 17:26:37 +02:00
Adrià FranchandClaude Sonnet 5.5 02c5470080 test(shader): drop the stencil operation value byte from the version 35 request
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 12:53:13 +02:00
simonbronkandClaude Opus 5.5 7563b4a480 fix(agc): replace with a stencil operation value the pixel shader exports
With DB_SHADER_CONTROL.STENCIL_OP_VAL_EXPORT_ENABLE the pixel shader
supplies the value that REPLACE_OP and the add and subtract operations
use in place of DB_STENCILREFMASK.STENCILOPVAL. The bit was refused as a
whole, which stopped Onimusha: Way of the Sword (PPSA27836) at a
DB_SHADER_CONTROL 0x45 draw with DB_STENCIL_CONTROL 0x40040 (REPLACE_OP
on depth pass, both faces), write mask 0xff and compare ALWAYS.

The export is accepted with the 32_GR and 32_ABGR Z formats. When no
reachable operation through a non-zero write mask reads the value, it
cannot change the result and is ignored. Without a test value export, a
reachable REPLACE_OP becomes REPLACE with the exported value as
FragStencilRefEXT (or the bounded replay on devices without the
extension), provided both faces compare without the test value and use
no ONES or REPLACE_TEST; early tests throw. The add and subtract
operations, and REPLACE_OP with a test value export, still throw.

The value is read from bits 8-15 of the second MRTZ channel: the
title's pixel shader shifts it left by 8 right before exp mrtz
(v_lshlrev_b32 v0, 8, v0). That is the only evidence for the layout and
it is listed as technical debt. The pixel stage info carries the new
flag into the cache key, the draw keys and request serialization
version 31.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 12:53:13 +02:00
Yunus Shaikh 53cc193a3c Merge main into fix/agc-sample-location-grid-exact
#6503 took request serialization 36 for its float32 flush flag, so this branch's sample order moves to 37. The version relabels in ShaderMemory.cpp and RequestSerializerTests.cpp drop both trailing flags and the sample order.
2026-10-18 22:52:06 -07:00
Adrià Franch 3c95095c21 test(shader): read a version 35 request without the f32 flush flag 2026-10-19 07:00:21 +02:00
ThatsLeo ac14d6317d perf(shader): flush f32 denormals in hardware when a startup probe matches the emulation
Devices with DenormFlushToZero for f32 run the mixed denormal-flush programs with and
without the hardware mode at startup; when every result matches, add, sub, mul, fma,
floor and ceil in the default rounding mode drop their software flush.
2026-10-19 07:00:13 +02:00
Yunus Shaikh 18463ff5c2 Merge main into fix/agc-sample-location-grid-exact
#4650 took request serialization version 35 for its depth remap flag, so this branch's sample order moves to 36. The serialization tests drop #4650's trailing byte from every older version they build, as main's do, along with the iteration fields and the sample order.
2026-10-18 20:56:57 -07:00
Dean Galvin 4d4ae6e5eb Merge main into pr-4650
# Conflicts:
#	core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
#	core/shader/recompiler/ControlFlow/src/RequestSerializer.cpp
#	core/shader/recompiler/tests/RequestSerializerTests.cpp
2026-10-19 14:32:36 +13:00
Yunus Shaikh 745f199d5a Merge main into fix/agc-sample-location-grid-exact
Combines this branch's sample order with #6470's once-per-pixel and once-per-sample inputs. The pixel request keeps both sides' fields: #6470's iteration, position location and sample locations are serialized at version 34, and the sample order after them at version 35. The serialization tests move the sample-order bytes after the iteration fields and drop both from older versions. The pixel info collector adds sample order to the SampleLocationsVary inputs, and the draw keys compare and hash both. EmitSampleOffset's iterated index already goes through GuestSampleIndex, since the SampleId builtin does. The shader cache stays at FormatVersion 40, and the sample-location debt entry takes #6470's sentence on the position inputs.
2026-10-18 18:30:37 -07:00
Dean Galvin 5db206aba0 fix(agc): read the depth remap scale and offset from push constants at run time
The remap mode stays a specialization constant and cache key input. Scale and
offset are two push words at byte 104, patched per draw, so draws that differ
only in depth range share one pipeline. The recipe, journal and serializer
carry the mode only.
2026-10-18 19:01:14 +13:00
Dean Galvin 2ec16fb1c2 test(agc): follow request format 33 in the serializer replay tests
The depth remap fields moved to request format 33 when this branch was rebased onto
main's format 32. The replay tests that rebuild older streams now drop and append the
remap tail on top of the linked call fallbacks and the spanned waves flag, and the
depth remap test downgrades to format 32.
2026-10-18 16:38:36 +13:00
Mouad-Scriptz-0andClaude Fable 5.1 53212b18ac feat(agc): remap a viewport depth range the device cannot express into the vertex shader
Without VK_EXT_depth_range_unrestricted a viewport depth range outside
[0, 1] threw. Minecraft (PPSA17221) draws its world with scale 1 and
offset 0 in negative-one-to-one clip space, so its depth is the raw z/w
clamped by PA_SC_VPORT_ZMIN/ZMAX. On such a device the vertex shader now
scales clip z so z/w is the console's depth, the pipeline clamps depth at
the console's bounds, and two clip distances restore the near and far
planes that depth clamping removes. Mode, scale and offset travel as
pipeline specialization constants from the draw's vertex stage info, in
both the per-draw and the registration-module path; mesh and tessellation
draws with such a range still throw.

The console's depth clamp bounds are clipped to [0, 1]: exact for a
normalized depth target or none, and reported once for a tested or
written float depth target, where a depth below 0 is stored as 0
(Minecraft clamps its float depth target to [-1, 1]). The shader
validator accepts the remap's two extra clip distances next to the one
a program may already export.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-10-18 14:27:48 +13:00
Yunus Shaikh f7e1f5d2e8 Merge branch 'fix/agc-sample-location-grid-fallback' into fix/agc-sample-location-grid-exact
Takes #6451's merge of main. Main's spanned-waves flag took request
serialization version 32, so the sample order moves to version 33; a
version 32 request keeps its spanned-waves flag and reads no sample order.
Multisampled color targets now gain storage usage on their first storage
binding; a target whose samples may be reordered still gets it at creation,
and the recorder's storage-usage checks expect that.
2026-10-16 12:46:37 -07:00
Yunus Shaikh bd09c49374 Merge main into fix/recompiler-once-per-pixel-sample-inputs
Main took request serialization versions 31 (output primitive size) and
32 (spanned waves), and #6683 uses 33, so the pixel iteration fields move
to version 34. A version 32 request keeps its spanned-waves flag and reads
no pixel iteration.
2026-10-16 12:41:06 -07: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 <[email protected]>
2026-10-16 14:12:58 +02:00