mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
A wave64 vertex program runs at one guest lane per invocation, so on a 32-lane host subgroup its lanes 32-63 have no invocation. The vertex entry still set s3 = 64 | 64 << 8, telling the program that its wave holds 64 vertices and 64 primitives. An NGG culling program then keys a full-wave OR on lane < s3's primitive count, lanes 32-63 hold real cull results, and its v_readlane_b32 of lane 63 cannot be built (#2783). The entry now sets s3 = 32 | 32 << 8 for a wave64 program on a 32-lane host, the wave the host runs; the console launches waves with fewer vertices and primitives. The host subgroup width reaches the vertex input the way it reaches the compute and mesh inputs (BuildShaderStageInputInfo from HostSubgroupSize), and the source, prepared-shader and disk cache keys already carry it for every stage. Programs that do not read s3 are unchanged; wave32 programs and other host widths keep the full wave. The keys are then 0 in lanes 32-63, so the read is sound. On a 32-lane host, when the existing half-wave scan rules fail, the scan may also: - run under s_mov_b64 exec, -1 (EXEC constant true); - use bound_ctrl:1 row_shr steps when 0, the fill, is the identity (OR, add, unsigned max), also into another register, whose old value never shows since such a step writes every lane; - take keys shown to be 0 in lanes 32-63: built from 0 through selects under a lane id or v_mbcnt of -1 below at most 32, v_cmp_ne_u32 against 0, ORs, DPP and permlanes, in stages whose entry EXEC is every lane. Lane 63 is then the identity and lane 31 the subgroup reduction of the host's invocations. A shuffle from lane 31 is not enough: an RTX 5070 runs the vertex warps of a non-indexed triangle list with 30 of their 32 invocations. A v_readlane_b32 outside the host subgroup of another value that is 0 in lanes 32-63 reads 0. Only reads that used to throw change, besides lane 31 of such scans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>