Skip to content

fix(shader): preserve flat aliases in barycentric emulation - #12619

Open
CorruptName wants to merge 1 commit into
boykopovar:mainfrom
CorruptName:fix/flat-smooth-input-alias
Open

CorruptName wants to merge 1 commit into
boykopovar:mainfrom
CorruptName:fix/flat-smooth-input-alias

Conversation

@CorruptName

Copy link
Copy Markdown

What

A flat fragment input that aliases the export slot of a smooth input is promoted to a per-vertex array on the barycentric-emulation path. A flat P10 read then takes the vertex-delta path instead of the existing flat-value path. Primitive-constant values become zero; unequal vertices produce the wrong value too.

Keep the flat alias separate from the relocated per-vertex input in input collection, fragment-parameter descriptors and SPIR-V variable binding. Generated geometry/tessellation stages already forward both forms. Validate the existing provoking-vertex restrictions before pipeline-cache lookup: supported and unsupported guest interpolation modes can emit identical host SPIR-V, so constructor-only validation can be bypassed by a cache hit.

The existing PixelBarycentricEmulation fixture now uses unequal vertex values and smooth/flat aliases of the same export slot. It checks the flat value exactly in R/B/A, independently computes perspective interpolation for G, covers supported P10/P20/P0 and first/last-provoking combinations, and warms compatible pipelines before checking both unsupported combinations.

This preserves existing instruction semantics and their support boundary, documented in docs/dev/debt/libSceAgcDriver.md (the provoking-vertex entry and ps5-opengl #1413). It does not claim a new PS5 hardware-oracle measurement. Native fragment-barycentric mixed aliases, mesh-path aliases and mixed-alias rect lists are outside the new regression coverage. No performance improvement is claimed.

Provenance: the changes and regression were developed against AnyPS5 and retain its GPL-2.0 license. No third-party implementation, application assets, captured guest shaders, executables or external project files are added. AI assistance was used for analysis, implementation, test orchestration and this description.

Tested

Linux hardware comparison on AMD BC-250 (RADV GFX1013, PCI 1002:13fe), Mesa/RADV 26.2.5, CachyOS kernel 7.3.0-4-cachyos; Khronos validation layer 1.4.363. GCC 16.2.1, CMake 4.4.5, Ninja 1.13.2. Separate checkout/build; no changes to driver or hardware settings.

Baseline: 66248d1d5de390f57df82df2b27b8834996ada7a. Candidate: a582c98640dc9593fe179dbcfde6aededa7854f7.

Four focused CTests: agc_driver_pixel_barycentric_emulation, agc_driver_zero_position_vertex, agc_driver_provoking_vertex, agc_driver_pixel_exec_interpolation. Each is run on the same GPU with the following environment and with the pipeline cache both enabled and disabled:

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_CXX_FLAGS_RELEASE='-O1 -DNDEBUG' -DBUILD_TESTING=ON \
  -DANYPS5_ENABLE_SPIRV_TOOLS=ON \
  '-DANYPS5_AGC_EXECUTION_TESTS=PixelBarycentricEmulation;ZeroPositionVertex;ProvokingVertex;PixelExecInterpolation'
cmake --build build --parallel 2 --target \
  agc_driver_pixel_barycentric_emulation_tests agc_driver_zero_position_vertex_tests \
  agc_driver_provoking_vertex_tests agc_driver_pixel_exec_interpolation_tests
export ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1
export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
export VK_DRIVER_FILES=/usr/share/vulkan/icd.d/radeon_icd.json
pattern='^agc_driver_(pixel_barycentric_emulation|zero_position_vertex|provoking_vertex|pixel_exec_interpolation)$'
env -u APS5_NO_PIPELINE_CACHE ctest --test-dir build -R "$pattern" -V
APS5_NO_PIPELINE_CACHE=1 ctest --test-dir build -R "$pattern" -V
Revision Pipeline cache enabled Pipeline cache disabled
main 66248d1d5d 4/4 passed 4/4 passed
candidate a582c98640 4/4 passed 4/4 passed

All four verbose logs confirm the BC-250 selection, contain zero VUID- or Validation Error messages, and do not contain was not found but was requested by env var VK_INSTANCE_LAYERS. No selected tests were skipped. The candidate therefore adds no validation diagnostics compared with main.

The new fixture checks eight positive cases (four per geometry/tessellation route), each covering 932 interior pixels, and four expected rejections. Equal vertex colors cannot hide the regression. Checks with the candidate's new fixture on c9207624 without implementation changes fail at P10/last with actual=3.050000 (expected -0.25). A separate control with only the pre-cache validation call removed fails with mixed alias bypassed an unmeasured provoking-vertex restriction when caching is enabled, but passes when it is disabled. Both controls were confined to the test checkout and restored before the final run.

Native VK_KHR_fragment_shader_barycentric mixed aliases and mixed-alias rect-list/mesh paths are not validated here. No Windows run, full-suite run or timing/performance claim is made. The existing focused tests include rect-list and non-emulated interpolation checks; these do not establish mixed-alias coverage for those other paths.

python3 tools/check_conventions.py --base origin/main and git diff --check pass. tools/pr_overlap.py --branch fix/flat-smooth-input-alias was run against upstream. It found no comparable overlapping lines, but reported shared files in conflicting PRs #5609, #5925, #6235, #6970, #7275, #7642, #8004, #9020, #9335, #9356, #9387, #9489, #9508, #9748 and #10193. Their affected hunks were inspected: they concern cache/prebuild work, descriptors, mesh fallbacks, output formats, line modes or subgroup changes rather than this alias correction. In particular #5925 edits CachedPipeline but does not add this pre-lookup support validation. No dependency on those changes is required.

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 (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: AMD BC-250 (RADV GFX1013), Mesa/RADV 26.2.5, CachyOS Linux 7.3.0-4-cachyos
  • AI-assisted: yes

@oneandonlydean oneandonlydean self-assigned this Oct 28, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@CorruptName could you drop the new expected-rejection loop in CheckMixedAlias (PixelBarycentricEmulation.cpp, lines 428-438) and keep the positive mixed-alias pixel checks? It requires P10/first and P20/last to throw with "not measured". Our standing test rule is to test supported behavior and argument validation, without pinning a valid unimplemented form to throw, because that breaks when the form is implemented. This asks only to remove those new assertions; the runtime support guard can stay. Please retain the supported interpolation/provoking cases and cache-enabled/disabled validation coverage.

@github-actions

github-actions Bot commented Oct 28, 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 5609 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 6235 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 6970 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 7275 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PixelBarycentricEmulation.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 8004 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvInputOutput.cpp
PR 9020 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
PR 9335 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
PR 9356 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 9387 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 9508 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PixelBarycentricEmulation.cpp
core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 9748 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PixelBarycentricEmulation.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 10351 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 10867 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 11551 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 11914 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 12790 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
PR 12944 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 13928 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PixelBarycentricEmulation.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 13929 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PixelBarycentricEmulation.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 14870 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 14871 core/shader/recompiler/Optimization/src/ShaderInfoCollector.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 15334 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 15548 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 15668 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 15670 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 15918 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp

@github-actions github-actions Bot added shader core/shader agc libSceAgc* needs rebase Conflicts with main, rebase needed labels Oct 29, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head a582c98 merged onto main 52c09d5 · tested 2026-10-29 11:30 UTC · 23 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,198 passed · 6 failed (0 new, 5 also fail on main, 1 unstable on main) · 39 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,243 of 2,873 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (855 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) none
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_submit_progress: failed in 2 of the last 4 main runs
Failing on main too (5, not counted against this PR)
agc_compute_pipeline_inspection
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 405 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (405 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alpha_to_coverage, agc_driver_array_layer_target_cpu, agc_driver_bc_block_copy, and 397 more
VUID-vkCmdCopyImage-srcImage-01548 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_storage_dispatch, and 3 more
VUID-vkCmdCopyImage-srcImage-01551 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_storage_dispatch, and 3 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (39)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_msaa_dcc_compared_import_2: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_4: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_8: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fresh: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_labels: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SD
Reproduce
git fetch origin a582c98640dc9593fe179dbcfde6aededa7854f7 52c09d567d2fa453494dd720fcf53a98149468e4
git checkout 52c09d567d2fa453494dd720fcf53a98149468e4 && git merge --no-ff a582c98640dc9593fe179dbcfde6aededa7854f7
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@bunbeans2-arch

Copy link
Copy Markdown
Contributor

A Windows run with AMD's own driver, since the GPUs tested are RADV on Linux: AMD RDNA 4, a582c98640 as is. It conflicts with current main in PixelBarycentricEmulation.cpp, so I built the head itself (base 66248d1d5d).

Windows 11 Pro 10.0.22631, AMD Radeon RX 9070 XT (1002:7550, driver 32.0.32015.7029, amdvlk64), MSYS2 UCRT64 g++ 16.1.0, Release. ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation; with VK_LOADER_DEBUG=layer the loader logs Insert instance layer "VK_LAYER_KHRONOS_validation" in every run of every test below that creates a Vulkan instance. 3 runs:

  • agc_driver_pixel_barycentric_emulation passes 3 of 3. The emulation runs through the geometry, tessellation and rect-list stages here, not just the built-in path.
  • The new mixed alias case, twice per run: mixed flat/smooth alias passed for mode 0 last, mode 1 first, and mode 2 first and last, at pixels=932 each. Mode 0 first and mode 1 last are refused with v_interp_mov p10 of a flat input with the first provoking vertex is not measured and the p20 / last counterpart.
  • No VUID- line.

AI-assisted: yes (Claude Code)

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* needs rebase Conflicts with main, rebase needed shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants