Skip to content

fix(shader): drop s_barrier in vertex programs that share nothing between waves - #2937

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
oneandonlydean:up3/vertex-barrier
Oct 10, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
oneandonlydean:up3/vertex-barrier

Conversation

@oneandonlydean

Copy link
Copy Markdown
Collaborator

What

Fixes #2871.

EmitBarrier emits OpControlBarrier with Workgroup scope for every stage. The Vertex execution model has no workgroup, so an NGG passthrough program that runs on the vertex path and contains s_barrier produces an invalid module. With ANYPS5_ENABLE_SPIRV_TOOLS=ON (the Linux CI build) a title stops at its first draw:

ShaderRecompiler::Recompile: SPIR-V validation before optimization failed:
[VUID-StandaloneSpirv-OpControlBarrier-04682] in Vulkan environment, OpControlBarrier execution scope must be Subgroup for Fragment, Vertex, ...

Builds without SPIRV-Tools hand the same module to the driver unvalidated.

In the program from #2871 the barrier only orders wave 0's GS_ALLOC_REQ before the other waves export, and the vertex path already drops GS_ALLOC_REQ. A barrier changes a program's results only through memory one wave writes and another reads.

  • In a Vertex-stage program, s_barrier now emits nothing when the program has no LDS or GDS access and no memory write or atomic.
  • A Vertex-stage program with s_barrier and any of those throws s_barrier in a vertex program that accesses LDS or GDS or writes memory is not implemented.
  • Other stages are unchanged.
  • TechnicalDebt entry next to the vertex entry wave info line.

Routing such programs to the mesh path (#1825, #2261) is a separate question; this only stops the vertex path from emitting an invalid module.

Tested

Linux (CachyOS, GCC 16.2, RTX 4090, NVIDIA 610.57), Release, on main 9c5d67f:

  • New agc_vertex_barrier: a vertex program with s_barrier and a position export compiles without OpControlBarrier. On main the module contains one. A vertex program with s_barrier and ds_write_b32 throws the line above.
  • Full ctest (701 tests) passes, except agc_driver_dcc_keys_first_write, which fails on main too.
  • tools/check_conventions.py passes.

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 in TechnicalDebt
  • 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
  • AI-assisted: yes

🤖 Generated with Claude Code

…ween waves

An NGG passthrough program on the vertex path whose s_barrier only orders wave 0's GS_ALLOC_REQ produced a workgroup OpControlBarrier, which the Vertex execution model does not allow; SPIR-V validation rejected the module at the program's first draw. In a Vertex-stage program the barrier now emits nothing when the program has no LDS or GDS access and no memory write or atomic, so no wave can observe another. With any of those it throws.
@github-actions github-actions Bot added build shader core/shader docs agc libSceAgc* labels Oct 10, 2026
@fma-rc

fma-rc commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Tested on an RTX 5080 with Astro Bot PPSA21564 and SPIR-V validation on: main stops on the validation error, and with this PR it does not. The new test also fails without the emitter change and passes with it, on NVIDIA and on RADV.

Setup: Arch Linux 7.2.9, GCC 16.2.1, Release, -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON. RTX 5080 (NVIDIA 615.78.08) and Radeon 610M (RADV, gfx1036). PR head 696b93a merged onto main 4a747c4.

The title (Astro Bot PPSA21564 v01.007.000, RTX 5080, APS5_HOST_IMPORT_MIB=12288; relinked with main 57f96fd; each build run once with an empty shader cache and once with the cache that run left):

Libraries Cache SPIR-V validation failures Result
main empty shader 0x5006bff00 stops on SPIR-V validation before optimization failed with VUID-StandaloneSpirv-OpControlBarrier-04682
main warm shader 0x5006bff00 same stop
main + this PR empty none goes on to LevelDocument Loaded: ui_pause_next
main + this PR warm none goes on to LevelDocument Loaded: ui_pause_next

Both runs with the PR then stop on GetImageResource dword 0 is not a valid runtime value; chain: Phi(ReadConst(GetSrtResource, Immediate), ReadConst(GetSrtResource, Immediate)), the stop #2653 addresses; I did not stack anything else on this PR.

The test (agc_vertex_barrier_tests, ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1):

RTX 5080 Radeon 610M
PR as is passes passes
PR with SpirvFlowEmitter.cpp and SpirvEmitterInstructions.hpp reverted to main fails fails

Both failures are the same OpControlBarrier-04682 validation error.

Not established: whether the picture is right; I did not look at it. The rest of the test suite was not run with this PR.

@oneandonlydean
oneandonlydean merged commit 7c83d02 into boykopovar:main Oct 10, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Astro Bot (PPSA21564) on Linux/NVIDIA: NGG passthrough vertex program with s_barrier fails SPIR-V validation at its first draw on main de5e541d

2 participants