Repository navigation
fix(shader): preserve ancillary proofs across relative VGPR accesses - #4150
oneandonlydean merged 2 commits into
Conversation
|
The fix itself is right for the case it targets, and it's genuinely narrower than #4120/#4057/#4162 — it only engages when a pixel shader's packed ancillary input specifically falls inside the relative-addressing span, keeping that span in SSA with compare/select chains instead of the private window array. The PR body's own overlap diligence deserves real credit for existing at all, but it understates two things worth being precise about, since this is the fourth PR tonight touching this exact subsystem:
Two more textual collisions worth flagging to the author directly: this diff's None of this blocks the fix on its own merits — it's self-consistent, throws rather than silently miscomputing on the one case it can't yet handle, and records its gaps in TechnicalDebt. But given four PRs tonight all touch Written with AI assistance. |
723d61c to
1942bda
Compare
|
Please rebase onto One thing on the second Could you also time the captured request with the select chains against the array form from #3856? |
1942bda to
ae049e7
Compare
|
Rebased onto All eight related tests pass: I timed the captured 5,016-code-word wave64 request with seven alternating fresh-process replays per branch, shader cache disabled, Release/GCC 15.2 on the Ryzen 7 7800X3D, with no concurrent build/game:
These timings include request loading and process startup. The array result is time to rejection, so this does not establish a speed ratio or GPU-time comparison between working shaders. The same captured request still cannot produce a valid array-form module on main. No whole-ancillary composition or invented ancillary bits were added to make that path run. |
ConstantFolder::Fold visits each instruction once, in block order. A loop header phi whose back-edge value is a later phi that folds to it in the same pass, such as the header phi of an inner loop in which an S# is copied out and back, is visited before that phi folds and stays a phi of its one definition and itself. Later folds run only after read-lane or masked-select elimination changed the program, and since #4150 the one after masked-select elimination only runs in programs where a PackedAncillary builtin still has live uses. These phis reach resource tracking, which compares descriptor dwords as IR values, so the phi of an S# and the S# itself become two samplers. Two PPSA11386 (007 First Light) pixel shaders each had 21 direct samplers for 6 distinct S# values; at two heap slots each they exceed the 32 sampler slots, and the shaders stopped at their first draw with "shader sampler pairs exceed runtime heap capacity". After its pass over the instructions, Fold now folds the phis of its blocks again until a pass folds none. Each fold turns a phi into an Identity, so the loop ends. Replayed on an older local branch with #4150's restriction in place, the captured requests plan 6 samplers each, one per distinct S#, and recompile. agc_shader_memory compiles an S# copied out and back in three nested loops and sampled before and inside them, with and without a masked write: one sampler and one sampled pair each, two of each before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
After #3856, a Lost Soul Aside (PPSA26358) pixel shader aborts with
packed pixel ancillary input has an unsupported live use (used by StoreVectorWindow ?). The relative VGPR window stores its packed ancillary prologue input in a private array, hiding its definition from field lowering and the masked-write proof.Keep the relative span in SSA when it contains the loaded pixel ancillary input. Indexed reads, writes and split-offset swaps use compare/select chains with the same unsigned M0 bounds, v0 fallback, EXEC gating and DPP update rules as the existing private-window path. Other programs keep that path. Fold again after masked-select elimination only when a
PackedAncillarybuiltin still has live uses, so newly exposed sample/layer extracts can lower without changing unrelated programs. Unsupported whole-word uses still throw; no primitive-class or unknown-bit values are invented. The SSA span includes implicit entry inputs as well as explicitly named registers, matching main's expanded private-window limit.The opcode behavior is inherited from main's private-window implementation and its RDNA2/gfx1035 measurements recorded in TechnicalDebt and #3856. This changes the IR representation and pass order. Console comparison and the performance cost of selecting over this span remain unverified and are recorded in TechnicalDebt.
Checked open PRs before publication. #4120 mirrors direct SSA writes into read-only windows to preserve sampler definitions; this change removes the window for the ancillary case and supports indexed writes. #4031 composes the whole ancillary word; this change keeps unsupported reads refused. #4057 is now merged and extends private windows for implicit inputs/fetches; this change also extends its ancillary SSA span over the entry inputs. These are overlapping areas, with different fixes.
Tested
Rebased on main
9aa5fd290; candidateae049e775. #3739 is merged and its commit is absent from this PR diff. Windows 11 x64, Ryzen 7 7800X3D, 32 GB RAM, NVIDIA RTX 5070, WinLibs GCC 15.2, Release, BUILD_TESTING=ON, emulator SPIRV-Tools OFF.agc_driver_relative_ancillary,agc_driver_relative_indexing,agc_masked_select,agc_vector_windowandpixel_ancillaryall pass, without skips; the original isolated repeat took 0.79 s total. The latest ten-test dependency stack, including the new implicit-input regression and source-IR reclamation, passes in 1.89 s. No shader-cache dependence; tests use the repository's cache-disabled CTest configuration.StoreVectorWindow. Restoring the candidate passes. Before adding the post-mask fold, the new native test additionally failed with an exposedBitFieldUExtractuse.spirv-val --target-env vulkan1.1spv1.4, built from the repository's bundled sources. The integration capture used format 17 solely for a vertex extension; this pixel-only request was checked to have no vertex/compute context, and only its format version was changed to main's 16 for isolated replay. Shader code, inputs and memory bytes were unchanged.git diff --checkpass. No game assets, captured requests, PCM, screenshots or investigation files are committed.Linux, macOS, console hardware and collaborator-triggered full CI were not run. Earlier broad integration testing had existing failures and a hanging layered-volume submission test; the full suite is not claimed green.
Checklist
main; no other open PR implements this scoped fix (overlaps described above)Review follow-up: #4057 is now in main. Its implicit-input window growth is preserved, and the ancillary SSA path separately includes entry-prologue register definitions in its inferred limit. This resolves the ancillary-plus-implicit-input intersection raised in review. #4120 adds a direct SSA mirror for read-only windows; this branch has not been tested merged with its
vectorWindowIndexedWriteschanges. #4162 forwards private-window stores for half-wave reduction matching; it is a separate mechanism and has not been combined with this branch. #4031 composes the whole ancillary word and inserts lowering beside the same recompiler pass; this branch instead retains unsupported whole-word refusal. #3739 is merged into main.Review validation on the rebased branch: all eight ancillary, masked-select and relative/window tests pass (2.03 s, no skips). Of 255 local requests with no ancillary input, 245 successfully generated modules are byte-identical to main; the other ten fail on the same unavailable SRT runtime-source reads on both branches. The reviewer’s separate 156-request corpus was not available locally.
The captured 5,016-code-word wave64 pixel request was timed in seven alternating, fresh-process
agc_shader_replayinvocations per branch withANYPS5_NO_SHADER_CACHE=1, Release/GCC 15.2, no concurrent build or game. Candidate wall time including process startup and request loading: median 399.30 ms, range 387.08–406.89 ms, successfully emitting 309,229 SPIR-V words. Main’s #3856 array path: median 182.26 ms, range 179.89–209.31 ms, but every invocation rejectsStoreVectorWindowbefore module generation. These are successful replay versus time-to-rejection measurements; GPU time and a valid select-chain/array performance comparison remain unavailable because the array form cannot compile this request.