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.
v_pk_add_f16 and v_pk_mul_f16 computed each half in f32 and rounded it
back to f16, then fixed the NaN, FP16_OVFL and clamp results on the
bits. On a device with native f16 that rounds to nearest even and keeps
f16 denormals (the Float16, RoundingModeRTE and DenormPreserve
capabilities that #1252 already checks), the arithmetic is now one
f16vec2 OpFAdd or OpFMul decorated NoContraction, and the same NaN,
FP16_OVFL and clamp rules run on its result bits.
The results don't change. f32 has at least 2 * 11 + 2 significand bits,
so rounding an f16 sum or product to f32 and then to f16 gives the
correctly rounded f16 result. Vulkan requires f16 OpFAdd and OpFMul to
be correctly rounded, the module keeps f16 denormals, and any NaN they
produce is replaced by the NaN the existing rules select.
v_pk_fma_f16 and v_pk_fmac_f16 keep the f32 path: Vulkan gives GLSL Fma
only the precision of OpFMul followed by OpFAdd, so a native f16 Fma
may round twice.
New test agc_driver_packed_float16_native compiles one shader with
packed add, mul, fma and fmac (op_sel, op_sel_hi, neg_lo, neg_hi and
clamp variants) with and without Float16, checks that only add and mul
use f16vec2 math, and compares every result bit for bit on random and
special inputs (zeros, denormals, infinities, NaNs, values near the f16
maximum) in nine float modes.
Vulkan starts only quads holding a non-helper lane, so the bit is set in every
lane it runs. Stray's pixel shader 0x2012f90000 keeps the packed ancillary
word where that bit is clear, and failed with an unsupported live use.
(cherry picked from commit 2068089b3d75fae55d0994a0916a22bffd7ee2a4)
A FLAT_SHADE input without pass-through that a pixel shader reads
through v_interp_mov_f32 P10 became an explicit per-vertex input and
read vertex 1 minus vertex 0. With the last provoking vertex the
pipeline then threw ("last provoking vertex with explicit per-vertex
flat interpolation is unsupported"), which stopped all three
ps5-opengl titles in the catalog.
ps5-opengl reads every flat input through P10 when GL's last-vertex
convention is in effect, and its driver passes the GL 4.6 CTS on a PS5
(#1413). Such a read now returns the provoking vertex's value, as P0
does, and only a P20 read keeps a flat input per vertex. The lane was
not measured on the console itself, so FragmentParameter records it
and a pipeline using the first provoking vertex throws.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#2072 taught the SRT evaluator SLessThan32, but IsRuntimeUniformOp still
left it out, so the runtime validator rejected any descriptor dword computed
through a signed comparison before the evaluator could compute it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A lane set contained in X is contained in WQM(X). Containment is proven
through BitwiseAnd and through ballots evaluated in the uniform entry
blocks, where every invocation is active. Under a whole quad mode mask the
masked lanes form whole quads, so implicit-LOD pixel samples, which only
read their own quad, do not observe them.
This removes the selects that kept the packed pixel ancillary input alive
after its fields were extracted in GTA V (PPSA04264) pixel shaders.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
image_sample_c_lz on gfx1035 returns 0 for 8-bit sRGB, so the unorm clamp was the wrong result. Bilinear cube comparison without DISABLE_CUBE_WRAP keeps throwing because that filter blends across faces.
Co-authored-by: Cursor <[email protected]>
Subnautica Below Zero stops while compiling a menu shader that compares an sRGB color texture or a bilinear cube face. sRGB uses the unorm reference clamp, and a bilinear cube sample stays on the face it hits.
Written with AI assistance.
A T# picked per lane with SelectU32 and made uniform with
v_readfirstlane, as in a waterfall loop, left a descriptor web without
Phis that the web walk could not split. CollectDescriptorPhis now steps
through ReadFirstLane, and a Phi-free tuple containing SelectU32 or
ReadFirstLane is split on the shared condition (SelectU32) or wrapped in
a matching ReadFirstLane. The new nodes are placed after the last
original node of the tuple in its block and inserted only when the web
is split; otherwise they are invalidated like the web's Phis.
PPSA26344 compute shader 0x800037f200 selects its T# per lane between
SRT reads or zero and reads the first lane of the result.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
s_buffer_load returns zero for dwords outside the V#'s range. The SRT
evaluator refused such a read instead, so evaluating a descriptor failed
as soon as one arm of a split T# read through a null or short V#, even
when that arm is never taken. The evaluator now returns zero for those
reads, as the hardware does.
PPSA26344 compute shader 0x800037f200 reads one arm's T# through a null
V# and stopped at "SrtWalker::EvaluateRuntimeSources failed to evaluate
runtime sources".
Co-Authored-By: Claude Opus 5.5 <[email protected]>
DecodeShaderStages accepts LS, HS and an NGG passthrough ES, reads the
3-bit VGT_TF_PARAM fields, refuses its other bits but DISTRIBUTION_MODE,
and needs HOS levels that keep [1, 63]; 0x286-0x287 join the draw key.
Local and domain programs are prepared with their stage group: its
headers are merged over one set of defaults, and a local program left
unbound by the hull header is prepared at its first draw.
The local program ends at its jump into the hull half.
TessellationLowering lowers LDS and ring addresses that are affine in
the control point and relative index to tessellation interfaces with
strides from the code, and refuses accesses outside the patch, per-patch
writes from other control points and a modified primitive export. Hull
lanes read their own saved exec bit, also of host-subgroup-masked
copies; other masks are refused, gl_InvocationID loads as a scalar and
factors clamp to 63.
A descriptor dword built by S_BREV_B32, V_BFREV_B32 or S_BREV_B64 from a
constant stayed a runtime value, so the resource could not be resolved
and the shader failed to prepare. The constant folder now reverses the
bits of an immediate the way the hardware does (D[31-i] = S0[i]), like
the existing BitCount32 fold. ConstantBitTest covers the fold.
Co-Authored-By: Claude Haiku 5.5 <[email protected]>
Comparison sampling of a color texture required the view's X channel to select red. A title runs image_sample_c_lz on a 1x1 R8 unorm placeholder whose dst_sel is constant 0 on all four channels.
On hardware the compare result is placed in every channel and each returned channel then applies its own dst_sel: 0 gives 0, 1 gives 1, R/G/B/A give the compare result. Return each dmask register from its own select, and throw only for the reserved selects 2 and 3.
A 1D sample or load of a 2D T# had no runtime image mode after the mode table landed, so it was still refused at materialization. Sampled 1D accesses now also accept a 2D view; the address completion in the emitter reads the missing row as 0.
Multi-level views, and views starting above mip 0, are bound as their base
level only when every use of the image is image_sample_lz through an
unnormalized S# without minimum LOD or LOD bias, the case measured exact on
RDNA2. Selected-LOD, implicit-LOD and offset uses keep throwing.
The recompiler records selected-LOD uses (SamplerUseNonZeroLod) and proves
the case per image (imageUnnormalizedBaseLevel); the shader disk cache
format goes to 27.
Co-Authored-By: Claude <[email protected]>
Explicit-LOD offset samples through FORCE_UNNORMALIZED samplers now add
sign-extended texel offsets to f32 coordinates before clamping, using
OpFAdd with NoContraction and a sampler specialization selector.
Without native nonconstant-offset support, retain only runtime image
modes valid for unnormalized sampling and reject normalized samplers.
Preserve constant-swizzle handling, indirect-image rejection and main's
flat-volume and flat-line compatibility rules when selecting those modes.
Serialize image compatibility and folding flags and the sampler folding
flag in cache format 34, with roundtrip, preparation and execution coverage.
Retain main's request format 15 and runtime ABI 11.