Skip to content

fix(agc): render a color view of several array slices into its first slice - #3633

Merged
oneandonlydean merged 2 commits into
boykopovar:mainfrom
tv7:fix/color-view-array-slice-range
Oct 13, 2026
Merged

oneandonlydean merged 2 commits into
boykopovar:mainfrom
tv7:fix/color-view-array-slice-range

Conversation

@tv7

@tv7 tv7 commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

What

DecodeColorBuffer rejected every CB_COLOR_VIEW whose SLICE_MAX is past SLICE_START ("color views of several array slices are unsupported"). The layer a primitive lands in is SLICE_START plus its render target index, which is 0 when the draw does not export one. So for a 2D array target, such a view renders into SLICE_START, the same as a one-slice view of that slice. This accepts it that way.

Still rejected:

  • the same view when PA_CL_VS_OUT_CNTL enables the render target index export (bit 18): layered draws are not routed (existing comment above LayerExports), and sending them all to the first slice would be wrong;
  • views of several 3D slices (feat(agc): render layered draws into 3D color targets #1077 implements layered draws into 3D targets);
  • a SLICE_MAX below SLICE_START, or past the last array slice.

Marvel's Wolverine (PPSA03671) binds 2D array color targets through views of several slices, without the render target index export. On main its first presentation stops on this check.

Tested

Windows 11, RTX 3070, GCC 15.2.0 UCRT, Release, on main a11c8f7f7.

Checklist

  • Based on current main; no other open PR implements the same functions (feat(agc): render layered draws into 3D color targets #1077 touches the same check for 3D targets only)
  • 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
  • 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

@blawesom

Copy link
Copy Markdown
Contributor

Independent pre-review on Linux (full CI runs only happen on manual trigger, so recording one): CachyOS, kernel 7.2.9, GCC 16.2.1, Ninja, Release, BUILD_TESTING=ON.

  • Builds; tools/check_conventions.py --base origin/main passes.
  • Full suite: 832/832 passed (all tests including the Vulkan suites on AMD RX 9070 XT / RADV).

@tv7

tv7 commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

Note on overlap: #3524 (XairRrR) touches the same lines in DecodeColorBuffer. The two are complementary, not duplicates. #3524 addresses a one-slice view of a 2D array through the array's swizzle, and this PR accepts a view whose SLICE_MAX is past SLICE_START (rendered into SLICE_START). They conflict textually on the beyond the array surface line. If both land, the check should test lastSlice and keep #3524's arraySlice = SLICE_START.

AI-assisted: yes (Claude Code)

@oneandonlydean

Copy link
Copy Markdown
Collaborator

A view of several slices on a target with no array slices is now accepted. In DecodeColorBuffer the lastSlice bound is only checked inside else if ((attrib3 & 0x1fffu) != 0), and the test row that covered this case (0x31b = 1u << 13u on the plain target) was changed to a reversed view. Please check lastSlice for every non-3D target and keep that row, expecting beyond the array surface.

@Pacuka

Pacuka commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Data point from Minecraft (PPSA17221), Linux / RX 6650 XT (RADV), on main d592d54e1 + #4215 #4218 #454: without this PR the title aborts about 2.5 minutes in, from the presenter, with AGC graphics: color views of several array slices are unsupported. With it, the title keeps running: menu, world load and rendering of the world. #1077 conflicts with current main in 13 files, so this was the change I could apply. It merged cleanly.

@tv7

tv7 commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 7215ff3: a target with no array slices now requires the view to cover one slice, so a view of several slices on it throws beyond the array surface. One-slice views on such a target (the existing "move the target by one slice" case) still work. The 0x31b = 1u << 13u row on the plain target is back, expecting beyond the array surface, next to the reversed-view row. Also rebased on main 2a5eca1. Windows/MinGW: 973/973.

Thanks @Pacuka for the Minecraft data point.

tv7 and others added 2 commits October 12, 2026 23:32
…slice

A CB_COLOR_VIEW whose SLICE_MAX is past SLICE_START was rejected. Without
a render target index export every primitive goes to SLICE_START, so the
target is that slice, as for a one-slice view. Layered draws into such a
view, and views of several 3D slices, still throw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lices renders into its only slice

Marvel's Wolverine draws into a 256x256 mipmapped 2D target
(CB_COLOR_ATTRIB3 0x4dc6c000, no array slices) through CB_COLOR_VIEW
0x4046000: slices 0 to 35 at mip 1. The view's last slice is not bounded
by the surface on that path, so the draw renders into slice 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tv7
tv7 force-pushed the fix/color-view-array-slice-range branch from 7215ff3 to 257ff1e Compare October 12, 2026 20:39
@tv7

tv7 commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean I need to take back part of 7215ff3. Running Marvel's Wolverine (PPSA03671) on main 3e0e01f35 showed a title that uses exactly the case it refused. It draws into a 256x256 mipmapped 2D target with no array slices (CB_COLOR_ATTRIB3=0x4dc6c000, CB_COLOR_ATTRIB2=0x503fc0ff) through CB_COLOR_VIEW=0x4046000: slices 0 to 35 at mip 1. With the plain-target bound it stops at the color view slice is beyond the array surface in the presenter, within the first minute. Without the bound it renders into slice 0 and continues.

So the branch (rebased on 44ab0c39e) now leaves a view's last slice unbounded on a target with no array slices. That target has only one slice to render into. Instead of the beyond the array surface row, there is a test with Wolverine's shape: a view of slices 0 to 35 on the plain target decodes to the same address, size and slice range as a one-slice view. Array targets keep the bound, 3D targets still refuse several slices, and a reversed view still throws. Windows/MinGW: 1006/1006.

@github-actions

github-actions Bot commented Oct 13, 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
#3763 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp L1011, L1023-1024, L1026-1030
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp L1345

@oneandonlydean oneandonlydean self-assigned this Oct 13, 2026
@oneandonlydean
oneandonlydean merged commit fe8d3eb into boykopovar:main Oct 13, 2026
8 checks passed
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.

4 participants