This reverts merge 7fc0ae6008. On NVIDIA, where helper lanes take part in ballots, clearing helper bits from every pixel ballot breaks derivatives along triangle edges (bright lines and specks on a cloud surface in PPSA21564). See the report on #11199.
v_fma_f32, v_fmac_f32, v_fmamk_f32 and v_fmaak_f32 threw "f32 denormal
mode 2 is not implemented" whenever FLOAT_MODE flushed f32 denormal
inputs but kept denormal results.
On RDNA2 (gfx1036) at round to nearest even, mode 2 flushes the inputs
and rounds the fused result once with gradual underflow, which the host's
Fma gives under DenormPreserve 32. The translation now matches all 5,596
measured triples for the four forms at IEEE 0 and 1. Mode 1 keeps
throwing: there the hardware flushes a result that is tiny after rounding
with an unbounded exponent even when the addend is nonzero.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
All four threw "f32 denormal mode N is not implemented" whenever
FLOAT_MODE kept only one side of the f32 denormals.
On RDNA2 (gfx1036), in every f32 round mode and at IEEE 0 and 1, mode 2
gives the results of mode 0 and mode 1 those of mode 3 with a denormal
result flushed, which only v_fract_f32 of a positive denormal produces.
The translation now matches all 118 measured inputs in modes 1 and 2.
Mode 1 of the three that run host float operations on a kept denormal
needs DenormPreserve 32, as v_min_f32 does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
SPIRV-Cross emits the lock's acquire compare-exchange and release
exchange as relaxed Metal atomics, so the plain LDS loads and stores of
a locked 64-bit update were not ordered against the lock and contended
ds_add_u64 lost updates on an Apple M5 Pro. On MoltenVK the driver now sets
SpirvTarget::ldsLockFences, and the lock brackets its critical section
with workgroup-scope acquire and release OpMemoryBarriers, which become
threadgroup atomic_thread_fence with no execution barrier.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The I/J reads take the BaryCoordSmooth input, but gl_FragCoord was declared
only for the offset kinds, so its w was read as the constant 0 and the
fragment function never read [[position]]; Apple GPUs then return the
weights unnormalized. Declare it with the built-in, and select on
gl_FragCoord.w > 0, which a compiler cannot fold as it can
min(b, b + |w|).
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]>
The 2D-array comparison results were measured with LESSEQUAL only. A
second gfx1036 run over all eight DEPTH_COMPARE_FUNC values (128
kernels) gives the same: a 2D-array address on a 2D T# ignores the
slice, and codes 1 and 56 return 0 under every function. Both entries
now say so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A comparison or plain sample with a 2D-array address on a 2D T#
returns what the same sample with a 2D address returns, whatever the
slice, as measured with the hardware oracle on RDNA2 (gfx1036) for
formats 1, 7, 22 and 56 with point and bilinear filtering, while a
four-layer 2D-array T# over the same memory returns a different result
per slice. Codes 1 and 56 also compare to 0 with 2D-array addresses.
The three comparison debt entries keep gfx1013, cube comparisons and
the other formats' array comparisons as open.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Buffer resources and MIMG samplers at register field 26 read s104,
s105, vcc_lo and vcc_hi, as measured with the hardware oracle on RDNA2
(gfx1036) in wave32 and wave64 with raw encodings, which LLVM's
assembler refuses. Loads, format conversion, bounds and stores through
the buffer tuple, and sampling through the sampler tuple, act as the
same words in ordinary SGPRs do, and a change to each of the four
words shows in the result. Both debt entries now keep gfx1013 as open.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A scalar buffer load through a V# read at run time recorded an
InvalidDescriptor fault when TYPE (word 3, bits 30-31) was nonzero, and
the dispatch wrote nothing. Measured with the hardware oracle on RDNA2
(gfx1036), s_buffer_load ignores the whole fourth word: OOB_SELECT,
TYPE, FORMAT, ADD_TID_ENABLE, INDEX_STRIDE, RESOURCE_LEVEL and DST_SEL
change no result, so the scalar path no longer checks TYPE. Vector
accesses keep the check. The debt entry now records the measurement
and keeps gfx1013 and a null base as open.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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]>
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]>
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]>
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]>
Pixel-stage ballots and EXEC reads count only lanes that are not helper
invocations, so a waterfall loop over a saved whole-quad EXEC picks and
clears live lanes only. In programs that execute s_wqm on EXEC, writing
EXEC from a value keeps a helper invocation active while a live lane of
its quad is, so implicit-LOD sampling after a save/restore still has its
helpers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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]>
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]>
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]>
v_cvt_f32_ubyte0 to v_cvt_f32_ubyte3 take byte N of source 0 after
SRC0_SEL and SRC0_SEXT select and extend it, as measured with the
hardware oracle on RDNA2 (gfx1036) for all seven source selects with
and without SRC0_SEXT. The test checked four combinations derived from
the ISA guide; it now checks every combination against the measured
results, and the debt entry keeps only what is not measured: gfx1013.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The f32 conversions that only flush their inputs follow bit 0 of the
FLOAT_MODE f32 denormal field, as the f32 compares do: mode 1 keeps
denormal inputs like mode 3 and mode 2 flushes them like mode 0.
v_cvt_pk_u8_f32 also follows a round mode set at run time.
Measured on RDNA2 (gfx1036) with the hardware oracle.
Co-Authored-By: Claude Opus 5.5 <[email protected]>