Skip to content

fix(agc): read an unwritten pixel program address as unset - #2022

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
NahuelGenchi:fix/agc-unwritten-pixel-program
Oct 10, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
NahuelGenchi:fix/agc-unwritten-pixel-program

Conversation

@NahuelGenchi

Copy link
Copy Markdown
Contributor

What

A depth/stencil-only draw whose pixel program address (SPI_SHADER_PGM_LO/HI_PS) was never written is rejected on main with:

AGC graphics: depth/stencil-only draws without a pixel shader are not implemented

The draw decoder already reads an unwritten address as 0 and binds the null pixel program for it (DecodeGraphicsPrograms, since #469). Only PixelProgramSkipped required both registers to be present and 0, and the precheck in DrawPrecheck.cpp rejected the never-written case before the draw got there.

  • PixelProgramSkipped now reads an unwritten SPI_SHADER_PGM_LO/HI_PS as unset, like a written 0. NullPixelProgramRejection then applies to such a draw too, so one that writes color is rejected as "a draw without a pixel program writes color", as with a written 0.
  • The precheck no longer rejects these draws. It still drops the ones that test neither depth nor stencil, as before.
  • The graphics test fixture makeState() now names a pixel program at 0x100. Its draws relied on an absent address being read as a real pixel program.

Tested

Ubuntu 26.04, GCC 15.2, Release build, AMD Radeon R9 380 (RADV, Mesa 26.0.8).

  • agc_driver_graphics passes. New checks: with both registers erased, the draw is read as having no pixel program, is rejected if it writes color, and is accepted as depth-only otherwise. Without the PixelProgramSkipped change the new check fails with an unwritten pixel program address was not read as unset.
  • Full ctest: 492/494. agc_driver_emulated_color_compare (needs shaderResourceMinLod, which GFX8 lacks) and agc_driver_f32_denormal_flush (v_fma_f32 denormal result on GFX8) fail the same way on main on this card.
  • Sonic Origins (PPSA05324), with feat(libSceJson2): implement sce::Json::Object::empty #2004 and local workarounds for its earlier stops (see Sonic Origins Plus (PPSA05324) on Linux #2021): its depth/stencil clear draws have no pixel program and never write SPI_SHADER_PGM_LO_PS. Before, they stopped at the precheck above. With this change they reach the null pixel program variant, prepared shader artifact is missing for the requested static ABI ... stage=5 wave=64, which fix(agc): prepare the null pixel program at draw when its variant was not prepared #1902 covers.
  • tools/check_conventions.py --base origin/main 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 (Claude Code)

🤖 Generated with Claude Code

PixelProgramSkipped only treated SPI_SHADER_PGM_LO/HI_PS written as 0 as
a draw without a pixel program, while the draw decoder already reads an
unwritten address as 0 and binds the null pixel program for it. A
depth/stencil-only draw whose pixel program address was never written
was instead rejected by the precheck with "depth/stencil-only draws
without a pixel shader are not implemented".

An unwritten address is now unset in PixelProgramSkipped too, so such a
draw goes through the null pixel program like one with the address
written as 0, and one that writes color is rejected as before.

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

@MarcZX10 MarcZX10 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.

Reviewed the full diff and the draw precheck/null pixel program flow. Treating unwritten LO/HI registers as zero matches the decoder behavior, the precheck no longer intercepts valid depth/stencil-only draws, and the fixture now declares its real pixel program. The added tests cover color rejection and depth-only acceptance. Linux, Windows, changes, conventions, and report checks pass for this head.

@popcoder565

Copy link
Copy Markdown
Contributor

Native Windows run, since no Windows results were posted. Setup: Windows 10 (19045), RTX 3060 Laptop (NVIDIA 616.92), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. Head 5c291a55, merged onto main d70b899 in one build with 33 other AGC/shader PRs that had no Windows run.

No title was run.

🤖 Addressed by Claude Code

@tv7

tv7 commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Tested on Windows with Marvel's Wolverine (PPSA03671).

Setup: Windows 11 Pro (10.0.26200), RTX 3070, GCC 15.2.0 UCRT (WinLibs), Release. This PR (5c291a5) merged onto main 54f28f2 with other open PRs the title needs to get this far (#1836, #1893, #1709, #1837, #1940), plus a local change that lets sceKernelSignalSema accept a count of 0 (the title calls it that way).

Without this PR: the first depth-only draw aborts with AGC graphics: depth/stencil-only draws without a pixel shader are not implemented.

With this PR: that draw passes. The next stop is the DB_RENDER_CONTROL depth clear covered by #2219.

Limits: one title, one run each way. Nothing is presented yet at that point, so I can't check that these draws render correctly.

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the diff, built and ran the libSceAgcDriver ctest scope (273/273, agc_driver_graphics and agc_driver_prepared_graphics pass). With the source changes reverted agc_driver_graphics fails, so the new checks pin the fix. Consistent with the decoder's existing reading of an unwritten address as 0; colour-writing draws are still rejected. Also confirmed on Windows by @popcoder565 and @tv7; merging.

@adriadam10
adriadam10 merged commit 9b67cbb into boykopovar:main Oct 10, 2026
6 checks passed
SleglJan pushed a commit to SleglJan/AnyPS5 that referenced this pull request Oct 10, 2026
…n-pixel-program

fix(agc): read an unwritten pixel program address as unset
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants