ResultKeyMemo declared std::atomic<std::shared_ptr<...>>. libc++ has no
atomic<shared_ptr> specialization, so with Apple clang the recompiler
headers stop at std::atomic's trivially-copyable static assertion
(request_serializer_tests in the macOS relinker build). The memo now uses
AtomicSharedPtr from libc, which is that specialization where the library
provides it and a locked shared_ptr with the same load and store otherwise.
The header joins the shader disk cache key's sources, and
request_serializer_tests gets core/libs on its include path.
The second half of a pipelined draw (stage materialization, cache insert,
enqueue) runs on a finisher thread, overlapping the next draw's packet
work; draws whose stages could write memory are held back. Commits skip
work whose inputs did not change since the last commit, color metadata
passes are ordered through the pipeline, resource and storage-image proofs
are reused within one collect epoch until a write breaks them, and a shape
entry is refreshed in place at the second sight of the same read user words.
APS5_VERIFY_DRAW_PIPELINE checks reused proofs against a full check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A FLAT_SHADE input without pass-through that a pixel shader reads
through v_interp_mov_f32 P20 and not P10 stayed an explicit per-vertex
input and read vertex 2 minus vertex 0. For a flat value that is the same
on every vertex the difference is 0, and with the first provoking vertex
nothing refused it.
ps5-opengl lowers every flat input to a load of one vertex: vertex 1
(P10) by default, which #4030 reads as the provoking vertex, and vertex 2
(P20) for triangles when GL's flatshade_first is set. SuperTuxKart's
deferred point lights are drawn that way, so all twelve flat inputs of
pointlight.frag read 0, the attenuation 0 * -inf was NaN, nothing was
discarded, and the starting-line referee's light quad blacked out the
scene behind it (#8364).
A P20-only read now returns the provoking vertex's value, as P10 and P0
do. The lane was not measured on the console either, so FragmentParameter
records it and a pipeline using the last provoking vertex throws. An input
read through both P10 and P20 keeps its per-vertex differences.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
unchangedUntil skipped a write by the reading instruction itself for every shader, so an RDNA s_load that overwrites its own address pair was taken as a user-data pointer load where main refused it. The skip now applies only to PS4 (GCN) shaders, where it is needed; PS5 shaders take main's path.
The SOPK branch of the GCN decoder never set the literal for
s_setreg_imm32_b32, so the eight-byte instruction was re-encoded as one
word and its decode threw "literal operand word is out of the code span
bounds". The decoder now copies the literal for that opcode; the new
agc_gcn_decode test decodes the reported stream.
Co-authored-by: javierUDP <[email protected]>
Co-authored-by: Savvanis Spyros <[email protected]>
Each GCN instruction is re-encoded to its RDNA form and decoded by the
existing RDNA decoder, so the PS4 path shares the recompiler. Covers the
legacy VS stage (program at the VS slot, user SGPRs from s0, vertex and
instance index in v0-v3), fetch shaders linked as user-data calls, MIMG
(image_sample and friends), PS4 buffer descriptors (GCN DATA_FORMAT /
NUM_FORMAT, 44-bit base) and T# image descriptors (GCN tiling in word 7).
The GCN switch is keyed into the shader disk cache. PS5 behaviour is
unchanged: every PS4-only rule is gated on GcnGuestShaders().
The dynamic path of TessellationPointer passes the control point through
inPatch(), which clamps it with UMin to inputControlPoints - 1 for hull
inputs and to outputControlPoints - 1 for domain inputs. The immediate
path clamped only hull inputs, so a domain read at an immediate address
past the last control point indexed the input array past its end. It
now clamps domain inputs to outputControlPoints - 1 too.
Co-Authored-By: Claude <[email protected]>
A T# loaded as two s_load_dwordx4 halves from a pointer table, where the
second half's offset is formed per lane (v_lshl_add_u32 key, 5, 16) before
v_readfirstlane and the first half's after it (readfirstlane(key) << 5),
was refused: the second half's +16 sat inside ReadFirstLane(Select(exec,
..., old), exec), so TryMakeTableColumn saw a different base and a zero
addend. Compare such offsets in a first-lane normal form (lane value, mask,
shift, addend), peeling selects the mask implies as the SRT walker already
does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A 3D image_store bound to a 2D-array T# addresses the layer as z. Add a 2D-array runtime mode for write-only 3D storage images and drop stores whose layer is past the array.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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]>
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]>
Vulkan needs PointSize above zero. A PA_SU_POINT_SIZE of 0 without
USE_VTX_POINT_SIZE, and a PA_SU_POINT_MINMAX maximum of 0 with it, now
throw. With USE_VTX_POINT_SIZE the clamp's lower bound is at least the
smallest positive float, so an exported size of 0 or less, which a
clamp minimum of 0 lets through, is written as a positive value.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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]>
main 7ce3b1df3e took disk-cache format 43 (#8295) for its own layout, so this
branch's format moves to 44. The request serializer stays at 42: main
still writes 41.
TessellationPointer built the vertex, attribute and component indices of
an attribute access from its address with OpUDiv, OpUMod, OpShiftRightLogical
and OpBitwiseAnd even when the address was an immediate, and without
SPIRV-Tools nothing folded them. AMD's Windows driver (32.0.21045.5002 on an
RX 6700 XT, 32.0.21042.62 on an RDNA 2 iGPU) reads a per-vertex hull output
indexed that way wrongly: a merged hull program's level read came back
wrong, and agc_driver_tessellation drew a different wrong patch on each run.
A read of the program's own record through a constant index failed the same
way, and the test passes once the indices are OpConstants, as glslang emits
them.
The merged hull case now also checks that no access chain index of the hull
stage is arithmetic on constants, so the shape is caught on every device.
Fixes#8861
Co-Authored-By: Claude <[email protected]>