Skip to content

fix(shader): keep host interpolation across entry EXEC copies - #7811

Open
santhoshkumar-dev wants to merge 1 commit into
boykopovar:mainfrom
santhoshkumar-dev:codex/fix-pixel-wqm-interpolation
Open

santhoshkumar-dev wants to merge 1 commit into
boykopovar:mainfrom
santhoshkumar-dev:codex/fix-pixel-wqm-interpolation

Conversation

@santhoshkumar-dev

@santhoshkumar-dev santhoshkumar-dev commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What

A pixel shader that enables WQM, executes v_interp_p1_f32, saves/restores EXEC, then executes v_interp_p2_f32 unnecessarily enables barycentric emulation after #6291. Copying EXEC preserves helper lanes, but the entry-lane proof only recognized one direct WQM result. Intersections, nested WQM masks, and independently computed low/high halves prevented it from proving that the interpolation still runs for the same starting quads.

The rejected IR retains the P1 result in a SelectU32 guarded by the EXEC predicate before the copy. P2 reads that result under the reconstructed EXEC predicate, so partialOf in HostInterpolationChecker.cpp cannot peel the select: the predicates are different IR values. Folding their proven entry-quad coverage removes that mismatch.

Prove each word's starting-lane coverage through AND/OR and WQM, distinguishing real-lane coverage from whole-quad coverage. This preserves #6291's EXEC-copy behavior and lets the existing interpolation checker recognize the unchanged interpolation pair. Ballots captured after divergent control flow, partial masks, unexpanded real-lane masks, and mismatched word indices remain unproven.

Follow-up to #6291, related to #7693. The failing Stray (PPSA02101) shader capture is still unavailable, so recovery of that title remains unverified. This PR fixes a reproduced checker false negative consistent with the reported fallback.

The GPU regression lives in its own PixelExecInterpolation.cpp test, allowing #7426's barycentric test-helper changes to land independently. A combined merge with #7426's 8f4a50d727 succeeds. The other shared-file notices (#5021 and #5500) concern vertex-bound and ancillary-input folding in different functions; neither is a dependency.

Tested

Windows 11 Pro build 26200, WinLibs GCC 15.2.0 r7 Release, AMD Radeon RX 6700 XT, Windows display driver 32.0.21045.5002. Built with BUILD_TESTING=ON and ANYPS5_ENABLE_SPIRV_TOOLS=ON.

  • Rebased on main 8816fd772; the driver and all nine focused test executables build.
  • Nine CTests pass with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, the RX 6700 XT selected, and no skips: agc_constant_bit_test, agc_masked_select, agc_shader_memory, agc_driver_exec_host_lanes, agc_driver_pixel_barycentric_emulation, agc_driver_pixel_exec_interpolation, agc_driver_pixel_helper_lanes, agc_driver_pixel_implicit_derivatives, and agc_driver_scalar_sop1.
  • The isolated GPU test saves/restores EXEC or repeats WQM between P1/P2 on wave32/wave64, with native barycentrics disabled. All four draws use host interpolation and match 932 interior pixels each. The counterexample that first enables WQM after P1 still compiles with emulation active on both wave sizes.
  • The original implicit-derivative regression passes all 12 native/emulated, wave32/wave64, mip 0/1/2 cases: 7,817 pixels checked per case, zero incorrect selections.
  • Negative control on 8816fd772 with the new tests but the original ConstantFolder.cpp: both the unit test and isolated GPU test fail; the other seven focused tests pass. The GPU failure is changing EXEC between v_interp_p1/p2 needed a generated stage; the unit test fails its intersection, nested-WQM, and independent-halves assertions. Restoring just this proof correction passes all nine tests.
  • Both runs use the same official Khronos Windows validation-layer build (aea761f4d5). Loader logs confirm the layer loads in all six Vulkan tests, neither log reports a missing requested layer, and neither contains a VUID- validation error.
  • python tools/check_conventions.py --base origin/main and whitespace checks pass.

Not tested: Stray, Linux, Intel or NVIDIA hardware, or the full CTest suite.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw; no silent stubs added
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source: none added
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: AMD Radeon RX 6700 XT, Windows display driver 32.0.21045.5002, Windows 11 Pro build 26200
  • AI-assisted: yes (Codex)

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 core/libs/prx/libSceAgcDriver/tests/ConstantBitTest.cpp
core/shader/recompiler/Optimization/src/ConstantFolder.cpp
PR 5500 core/shader/recompiler/Optimization/src/ConstantFolder.cpp

@github-actions github-actions Bot added shader core/shader agc libSceAgc* labels Oct 19, 2026
@santhoshkumar-dev
santhoshkumar-dev force-pushed the codex/fix-pixel-wqm-interpolation branch from 97bb70a to c311129 Compare October 19, 2026 08:59

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apple GPU / MoltenVK run, as a second vendor with a 32-wide subgroup. agc_driver_pixel_exec_interpolation runs its wave32 and wave64 draws on Apple and passes. With ConstantFolder.cpp reverted, it fails with the generated-stage error.

Machine: Apple M2 Max, macOS 27.2, x86-64 build under Rosetta. Drivers: MoltenVK 1.4.2 (Vulkan SDK 1.4.363.0) and MoltenVK main + SPIRV-Cross #2704. Tested at c311129, PR diff applied cleanly. The current head 9b45e78 is a rebase of the same commit (git range-diff shows it unchanged). The device reports subgroup size 32.

Tested: the tree is main a373e85 + mugurc's macOS series (ci/macos-series-2) + the PRs needed to build on macOS (#6667, #6668, #7524, #6969, and two files of #7332), not plain main (it doesn't build on macOS yet). Applied together in the same build: #7666, #7811, #7799 and #7803, plus a test-only patch that lets nine AGC fixtures load the Vulkan loader on macOS (branch jotitadev:fix/agc-tests-vulkan-loader-macos). Base on that tree: 40 ^agc failures with MoltenVK 1.4.2 and 26 with MoltenVK main + #2704, plus agc_driver_pooled_buffer_range and agc_performance_overlay, which only run because of the loader patch.

  • With the PR, 3 of 3 on both drivers: agc_driver_pixel_exec_interpolation (host interpolation matched 932 pixels for the 8- and 7-word programs on wave32 and wave64, and expanded EXEC keeps barycentric emulation on both), agc_constant_bit_test, agc_masked_select, agc_shader_memory, agc_driver_exec_host_lanes, agc_driver_pixel_barycentric_emulation, agc_driver_pixel_helper_lanes, agc_driver_pixel_implicit_derivatives and agc_driver_scalar_sop1.
  • With only ConstantFolder.cpp reverted (tests kept), on both drivers: agc_driver_pixel_exec_interpolation fails with changing EXEC between v_interp_p1/p2 needed a generated stage, and agc_constant_bit_test fails the intersected, nested and separate-halves whole-quad cases on wave32 and wave64 (the single expanded mask still passes).
  • Full ^agc suite with the stack: the base failures on each driver, nothing new and nothing gone.

GPUs tested: Apple M2 Max (MoltenVK 1.4.2; MoltenVK main + SPIRV-Cross #2704)

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NVIDIA and lavapipe run of 9b45e784b on Linux, since the description has the RX 6700 XT on Windows only.

Machine: Ubuntu 26.04, i7-8700, GCC 15.2, Release, BUILD_TESTING=ON, every execution test built, ANYPS5_NO_SHADER_CACHE=1, serial CTest with a 30 s timeout. Head 9b45e784b merged onto main 8816fd772 (clean merge).

  • agc_constant_bit_test, agc_masked_select, agc_shader_memory, agc_driver_exec_host_lanes, agc_driver_pixel_barycentric_emulation and agc_driver_pixel_exec_interpolation pass, 3 of 3 runs on NVIDIA and once on lavapipe.
  • The PR's tests on main (recompiler unchanged): agc_constant_bit_test and agc_driver_pixel_exec_interpolation fail on both drivers, the other four pass.
  • ^agc suite: NVIDIA 781/782 and lavapipe 782/782. main is 780/781 and 781/781, so nothing new fails; the one NVIDIA failure is agc_driver_bda_device, which fails on main too.

GPUs tested: NVIDIA GeForce RTX 3070 (driver 595.99.02), lavapipe (Mesa 26.0.3).

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@savvaniss

Copy link
Copy Markdown
Contributor

AMD and Intel Windows data: with this PR's test changes, agc_constant_bit_test and agc_driver_pixel_exec_interpolation fail on main and pass with the PR, on an AMD RX 9070 XT and an Intel UHD 770.

Windows 11 Pro 26300, WinLibs GCC 15.2.0 r7, Release, every execution test built, ANYPS5_NO_SHADER_CACHE=1, serial CTest. Intel UHD Graphics 770 (8086:a780), driver 32.0.101.7088. AMD Radeon RX 9070 XT (1002:7550), driver 32.0.31041.1004, with VkCache emptied first. This head 9b45e784b merged into main 85029a00f. "Without" means only this PR's diff to tests/ConstantBitTest.cpp and the new tests/execution/PixelExecInterpolation.cpp, applied to main 85029a00f.

Tests, ×3 UHD 770 RX 9070 XT
This head: agc_constant_bit_test, agc_driver_pixel_exec_interpolation 2 of 2 pass 2 of 2 pass
Without agc_constant_bit_test fails three cases at both wave 32 and wave 64: intersecting whole-quad entry masks preserves pixel helpers, a nested whole-quad entry mask covers pixel helpers, independent low and high whole-quad masks cover pixel helpers. agc_driver_pixel_exec_interpolation fails: AGC graphics: changing EXEC between v_interp_p1/p2 needed a generated stage same

The other ConstantBitTest cases pass on main, including the plain a whole-quad entry mask covers pixel helpers and every case that must keep the lane bit test.

AI-assisted: yes (Claude Code)

@DavidAmsellem

Copy link
Copy Markdown
Contributor

First AMD-on-Linux (RADV) run of this PR. Merged onto main 43a2abaf7 (clean merge), built in full and compared with the same main, on the same machine.

AMD Radeon RX 7900 XT (RADV NAVI31, gfx1100), Mesa 25.2.8, Linux Mint 22.3 (Ubuntu 24.04 base), kernel 7.0.0-38, GCC 13.3, Release.

Full suite (ANYPS5_REQUIRE_VULKAN=1 ctest -j8): 1637/1639 with this PR, against 1636/1638 on main. The failures are the same two on both, so this PR adds none: agc_driver_image_table_vouched_lookups (#7766, fixed by #7916) and agc_driver_guest_memory_lifetime (#7784). The new agc_driver_pixel_exec_interpolation ran (not skipped) and passed.

GPUs tested: AMD Radeon RX 7900 XT (RADV NAVI31, gfx1100), Mesa 25.2.8, Linux Mint 22.3 / kernel 7.0.0-38

AI-assisted: yes

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants