Skip to content

fix(recompiler): give vertex-path shaders a full NGG merged wave info - #1412

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
TheAggie:fix/recompiler-ngg-vertex-wave-info
Oct 8, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
TheAggie:fix/recompiler-ngg-vertex-wave-info

Conversation

@TheAggie

@TheAggie TheAggie commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

What

On the vertex path (ShaderPath::Vertex, PRIMGEN_EN), the translator's vertex entry set only v5 (vertex index) and v8 (instance index). The NGG merged wave info SGPR s3 stayed 0. NGG shaders build their own EXEC from it. Mesa's ACO emits this at the start of every NGG vertex shader:

s_lshl_b32        s0, s3, 8      ; primitive count to bits 16..22
s_bfe_u64         exec, -1, s0   ; EXEC = (1 << primitive count) - 1
s_pack_ll_b32_b16 s3, 0, s3      ; vertex count to bits 16..22
s_bfe_u64         exec, -1, s3   ; EXEC = (1 << vertex count) - 1

With s3 = 0 both masks are empty, so the shader skipped its vertex fetch and position export and no geometry was rasterized.

Each host invocation on this path is one vertex of a full wave, so the vertex entry now sets s3 to waveSize | waveSize << 8 (vertex and primitive count of a full wave, wave index 0) when the program's user data starts at s8 or later, i.e. s0–s7 are system SGPRs as in NGG programs. Shaders that do not read s3 are unaffected.

  • agc_driver_ngg_vertex_wave_info: an execution test whose vertex shader starts with the prologue above, with user data at s8, and draws a full-screen triangle for wave64 and wave32. Without the change no pixel is written (the test fails with the target's fill value); with it every pixel is.

Tested

Windows 11 Pro (26200), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, NVIDIA GeForce RTX 5070 Ti.

  • All agc_* and shader_* tests pass, including the new one. They were run from the generated CTestTestfile.cmake commands, because antivirus blocks ctest.exe on this machine.
  • Homebrew built on ps5-opengl (Mesa 26.2 on AGC, blackbearreloaded/ps5-opengl, GPL-3.0): PS5 OpenGL Showcase (PPSA99005) and Homebrew UI Lab (PPSA99050) executed thousands of draws per second but presented black frames (APS5_DUMP_FRAMES). Forcing the pixel shader output to a constant colour did not change that. The recompiled vertex shaders evaluated EXEC as the constant 0. With this change their geometry is rasterized. Other fixes are needed before these titles render completely; those follow in separate PRs.

Not tested on AMD, Intel or Linux.

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

@TheAggie

TheAggie commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Before/after frames from APS5_DUMP_FRAMES. Before: UI Lab presents black. After this change: the backdrop and the Showcase's HUD, particles and bloom render. The UI and the 3D scene still need the other pending fixes (#1413, #1414, #1415).
1412-before-ui-lab-black
1412-after-showcase-hud-particles
1412-after-ui-lab-backdrop

TheAggie and others added 2 commits October 8, 2026 15:05
The vertex entry set only the vertex and instance index VGPRs, leaving
the NGG merged wave info SGPR s3 at 0. NGG shaders build EXEC from it
(s_bfe_u64 exec, -1, <count in bits 16..22>), so Mesa's NGG vertex
shaders ran with an empty EXEC and rasterized nothing.

Each host invocation on the vertex path is one vertex of a full wave:
when the user data starts at s8 or later, set s3 to the wave size as
both vertex and primitive count, with wave index 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked on Linux (RADV): build and ctest green on current main, and agc_driver_ngg_vertex_wave_info fails without the translator change and passes with it.

Pushed one commit on top:

  • docs/dev/TechnicalDebt.md ("Unknown function info"): the s3 layout comes from the prologue Mesa's ACO emits, not from a measurement. The line also says that userDataBaseRegister >= 8 is true for every graphics program here (firstUserSgpr = 8, DrawDecode.cpp), so it does not single out NGG shaders, and that a partial last wave still reports a full one.

Merging once the CI runs (they were waiting for approval, I approved them) are green.

@adriadam10
adriadam10 force-pushed the fix/recompiler-ngg-vertex-wave-info branch from b666055 to c394764 Compare October 8, 2026 13:08
@adriadam10
adriadam10 merged commit f402892 into boykopovar:main Oct 8, 2026
2 checks passed
@EdouardSence

Copy link
Copy Markdown
Contributor

Tested on AMD under Linux, since this PR wasn't: RX 9070 XT (RDNA4, GFX1201), RADV / Mesa 26.2.4, Linux 7.2.9 (CachyOS), GCC Release build.

AI-assisted: the runs and this write-up were done by Claude (Claude Code) on my machine.

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.

3 participants