Skip to content

fix(agc): accept ANCILLARY without PS_ITER_SAMPLE for a one-sample depth target without MSAA_ENABLE - #9988

Open
frankea wants to merge 5 commits into
boykopovar:mainfrom
frankea:fix/one-sample-ancillary-unsampled
Open

frankea wants to merge 5 commits into
boykopovar:mainfrom
frankea:fix/one-sample-ancillary-unsampled

Conversation

@frankea

@frankea frankea commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What

A one-sample depth target under a multisampled rasterizer with PA_SC_MODE_CNTL_0.MSAA_ENABLE clear is drawn as a one-sample draw at the pixel center (debt entry "A one-sample target under a multisampled rasterizer without MSAA_ENABLE"). A pixel program that reads the ANCILLARY input threw on this path: a one-sample depth target under a multisampled rasterizer without MSAA_ENABLE is unsupported for points or lines and with alpha-to-coverage, a sample index or coverage input, ....

  • ANCILLARY now throws on this path only with PA_SC_MODE_CNTL_1.PS_ITER_SAMPLE. SAMPLE_COVERAGE still throws, and so does everything else the rule refuses. The message now says "a sample index input under PS_ITER_SAMPLE, a coverage input".
  • The one-sample color rule (one-sample color targets and no depth target) is not changed here. fix(agc): draw a PS_ITER_SAMPLE program once per pixel into a one-sample color target #8121, now in main, changed its PS_ITER_SAMPLE handling; this branch merges it.
  • The debt entry says ANCILLARY throws with a one-sample depth target only under PS_ITER_SAMPLE, and why the rest is accepted.

GPU semantics, with sources:

  • The ancillary word holds the primitive class at bits 0-1, the sample index at bits 8-11 and the render target index at bits 16-28. The sources are in the shader debt entry "Packed pixel ancillary word": Mesa's ac_nir_lower_intrinsics_to_args.c, LLPC, and the RDNA 3 and GCN register guides.
  • In a pixel program the guest does not iterate per sample, the recompiler already reads the sample index as 0, "the iterated sample number of a pixel the hardware does not iterate". That entry marks it as inferred, not measured. Sample 0 at the pixel center is also the sample this path keeps: the one-sample draw tests and writes the depth there. The primitive class and the render target index don't depend on the sample.
  • With PS_ITER_SAMPLE, fix(agc): draw a PS_ITER_SAMPLE program once per pixel into a one-sample depth target #7729 draws the program once per pixel on this path, but the console runs one invocation per sample, and each would read its own sample index. That case still throws.

Why: Gran Turismo 7 (PPSA01317) draws three draws of its main pass this way while loading the World Map. They have pixel programs 0x12804bd400, 0x1280441a00 and 0x1280393e00, SPI_PS_INPUT_ENA and SPI_PS_INPUT_ADDR 0x2b01 (PERSP_SAMPLE, POS_X_FLOAT, POS_Y_FLOAT, POS_W_FLOAT, ANCILLARY), PA_SC_MODE_CNTL_1 0, DB_SHADER_CONTROL 0x60 and DB_EQAA 0x00050000. The one-sample depth target is under a 4x PA_SC_AA_CONFIG.

Tested

Windows 11 (build 26200), NVIDIA GeForce RTX 4090 (driver 616.92), MinGW GCC Release build with BUILD_TESTING=ON, all on one machine.

  • New CPU cases in agc_driver_graphics, with and without a one-sample color target. A one-sample depth draw whose running pixel program reads ANCILLARY without PS_ITER_SAMPLE decodes as a one-sample draw, and the draw precheck accepts it. So does GT7's input set, 0x2b01. SAMPLE_COVERAGE still throws, and ANCILLARY with PS_ITER_SAMPLE still throws (an existing case).
  • Focused set: the 62 ctest entries of 18 targets. These are agc_driver_graphics_tests and the MSAA, CMASK, FMASK and journal tests: alpha_to_coverage, cached_image_multisample_guard, cmask_fast_clear, color565_target, fmask_image_reads, image_msaa_address_on_plane, msaa_enable_single_sample, multisample_fill_host_only, multisample_readback, multisample_retirement, multisampled_pass_order, native_multisample_depth, pipeline_journal, pixel_sample_coverage, sample_mask_multisample, sample_multisample_target, staged_clear_sampled_read.
  • This PR (90d0242 on main 2e0c925): 62/62 passed, each test run three times (ctest --repeat until-fail:3).
  • main control: main 2e0c925 with only this PR's tests/Graphics.cpp. agc_driver_graphics fails on the new case with main's refusal.
  • Validation layer: VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (Vulkan SDK 1.4.363.0), ANYPS5_NO_SHADER_CACHE=1 and ANYPS5_REQUIRE_VULKAN=1 with ctest -V, on main 2e0c925 (62/62) and on this PR (62/62). Neither log has was not found but was requested by env var VK_INSTANCE_LAYERS, and neither has a VUID- line. Both have the same three Undefined-Value-ShaderOutputNotConsumed-DynamicRendering warnings, from main's agc_driver_alpha_to_coverage.
  • Not run on Linux. tools/check_conventions.py --base origin/main reports no errors; its one warning is the length of the existing debt entry this PR edits.
  • Per @oneandonlydean's review (36b5996), agc_driver_graphics no longer checks that unimplemented one-sample depth states throw: the depthRefused message and its expectFailure calls are gone (SAMPLE_COVERAGE, ANCILLARY under PS_ITER_SAMPLE, a sample-mask export, alpha-to-coverage, points and lines, and four DB_EQAA settings). The positive ANCILLARY and 0x2b01 decode checks, the PS_ITER_SAMPLE and INTERPOLATE_COMP_Z checks and the sample-count mismatch check stay.
  • After merging main 379b1dc (fc29c5a, fix(agc): accept DB_EQAA INTERPOLATE_COMP_Z for a one-sample depth target without MSAA_ENABLE #9721's conflicting line kept with this PR's) and then main 9c85790 (head 5c19aa5; fix(agc): draw a PS_ITER_SAMPLE program once per pixel into a one-sample color target #8121 changed the same debt sentence, and both changes are kept), RTX 4090: the 65 ctest entries of the focused set's 18 targets pass 65/65 on both heads, three times each, and 65/65 under the validation layer with no VUID- line; the only messages are main's three Undefined-Value-ShaderOutputNotConsumed-DynamicRendering warnings from agc_driver_alpha_to_coverage. main 9c85790 passes the union of the sets tested tonight, 109/109, under the same layer settings with no VUID- line.

Checklist

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 8424 docs/dev/debt/libSceAgcDriver.md L39-40
PR 9450 docs/dev/debt/libSceAgcDriver.md L40
PR 10515 docs/dev/debt/libSceAgcDriver.md L39-40

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 1191 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 2434 docs/dev/debt/libSceAgcDriver.md
PR 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5441 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5925 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6186 docs/dev/debt/libSceAgcDriver.md
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
PR 6194 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6300 docs/dev/debt/libSceAgcDriver.md
PR 6412 docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6977 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7410 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7449 docs/dev/debt/libSceAgcDriver.md
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7618 docs/dev/debt/libSceAgcDriver.md
PR 7642 docs/dev/debt/libSceAgcDriver.md
PR 7844 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7910 docs/dev/debt/libSceAgcDriver.md
PR 8014 docs/dev/debt/libSceAgcDriver.md
PR 8223 docs/dev/debt/libSceAgcDriver.md
PR 8246 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8319 docs/dev/debt/libSceAgcDriver.md
PR 8365 docs/dev/debt/libSceAgcDriver.md
PR 8542 docs/dev/debt/libSceAgcDriver.md
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 9348 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9356 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9393 docs/dev/debt/libSceAgcDriver.md
PR 9431 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9432 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9508 docs/dev/debt/libSceAgcDriver.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9672 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9673 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9674 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9675 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9676 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9748 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9842 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9891 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9892 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9893 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9895 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9897 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9898 docs/dev/debt/libSceAgcDriver.md
PR 9904 docs/dev/debt/libSceAgcDriver.md
PR 9905 docs/dev/debt/libSceAgcDriver.md
PR 9906 docs/dev/debt/libSceAgcDriver.md
PR 10193 docs/dev/debt/libSceAgcDriver.md
PR 10348 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10420 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md

@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 exact head 90d0242 against current main. The code narrows the exception to the one-sample depth path: ANCILLARY is accepted only when PS_ITER_SAMPLE is clear; sample coverage and per-sample ancillary remain rejected. The tests cover the no-depth/color variants and GT7's reported input mask, while retaining negative controls. The debt note marks the inferred sample-0 behavior as unmeasured on console.

The PR explicitly records the same-line integration order with #9721, which is still open; the touched code is separate in purpose and the PR is mergeable. I reran the convention check against current main, the test-script registration check available at this exact head (171 scripts), and git diff --check; all pass. I could not execute the Vulkan/guest test suite locally because this workspace has no configured AnyPS5 build or GPU test runtime. The author reports 62/62 focused tests repeated three times on Windows with validation enabled, and a negative control that fails on the old behavior. Hosted policy checks pass and product build jobs are skipped.

No blocking issue found in the reviewed diff.

@BKlaasWerkman

Copy link
Copy Markdown

Windows run on two more GPUs, one of them not NVIDIA. Head ea2b648 was merged into main 15e71db (clean merge) and compared with that main on the same machine.

Setup: Windows 11 Pro 10.0.26300, WinLibs GCC 15.2.0 r7, Release. Environment: VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (1.4.363), ANYPS5_REQUIRE_VULKAN=1 and ANYPS5_NO_SHADER_CACHE=1. The run covers the 1,250 tests that tools/select_tests.py selects for this diff.

GPU this PR main
NVIDIA GeForce RTX 3060 Ti (617.42) 1243 passed, 4 skipped, 3 failed the same
Intel Arc Graphics (Meteor Lake, 101.9150) 1222 passed, 26 skipped, 2 failed the same
  • No test changes result, and on both GPUs the validation messages are the same as main's.
  • agc_driver_graphics, which has the new cases, passes on both GPUs.
  • The failures also occur on main:
    • On NVIDIA, agc_driver_sample_order and its two variants fail.
    • On Intel, agc_storage_write_back and agc_driver_multisample_retirement fail.

AI-assisted: yes (Claude Code)

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

Copy link
Copy Markdown
Collaborator

@frankea Please remove the depthRefused expectations at Graphics.cpp:911 and the expectFailure calls at lines 921, 929, 933, 936, 940 and 945 that require unimplemented one-sample/MSAA rendering states to throw, including the reintroduced SAMPLE_COVERAGE case. Keep the positive ANCILLARY/0x2b01 decode checks and real argument validation. Implementing the remaining rendering paths should not break these tests.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
…ary-unsampled

# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
#	core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
#	docs/dev/debt/libSceAgcDriver.md
…ary-unsampled

# Conflicts:
#	docs/dev/debt/libSceAgcDriver.md
@frankea

frankea commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean Done in 36b5996: the depthRefused message and every expectFailure that required an unimplemented one-sample depth state to throw are gone, the reintroduced SAMPLE_COVERAGE case included. The positive ANCILLARY and 0x2b01 decode checks stay, as do the PS_ITER_SAMPLE and INTERPOLATE_COMP_Z ones and the sample-count mismatch check.

The branch also merges main twice: 379b1dc for #9721 (mine, same Require), then 9c85790 for #8121, which changed the same debt sentence. Both changes are kept in that sentence. The head is 5c19aa5. RTX 4090: the 65 ctest entries of the focused set pass 65/65, three times each, and 65/65 under the validation layer with no VUID- line.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 24, 2026

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

unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants