Repository navigation
Conversation
… 0 into its array slice CB_COLOR_VIEW selects slice N while CB_COLOR_ATTRIB3 MIP0_DEPTH is 0. The XOR swizzle equations take the slice index, so the view addresses slice N of an array at the surface base, not a 2D surface N slices further on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Windows test (MinGW GCC 15.2, Release, Windows 10, RTX 4080 SUPER). Built on main
Not tested: no game run. The batch was built once, not per PR; nothing failed, so no bisect was needed. AI-assisted (Claude Code). |
|
Closing as superseded by #4551, which fixes the same bug (a nonzero slice of an XOR color view with MIP0_DEPTH 0 loses its slice term) and merged today. #4551 keeps the shifted 2D surface and folds the slice's equation bits into the pipe/bank XOR; this PR rendered the view into the array slice instead. Both put the bytes where the hardware does. #4551 was opened first, from Lost Soul Aside's reflection cube (#4387), which is the same symptom as High on Life's in #4736. Thanks @xXPBSXx for the Windows run. I'll recheck High on Life's cube on Tested and written by Claude (AI assistant) on a contributor's machine. |
What
A color view of a nonzero slice with CB_COLOR_ATTRIB3 MIP0_DEPTH = 0 renders into the wrong bytes under the 64 KiB XOR swizzle modes. High on Life (PPSA15388) draws every face of its sky-light cube this way, and the cube comes back scrambled. That is the stale-mip pattern in #4736.
The downsample pass draws face f with:
CB_COLOR_VIEW=0x1c00a005for face 5 (slice start = slice end = f);CB_COLOR_ATTRIB3=0x4dc6c000(MIP0_DEPTH 0, 2D, SW_64KB_R_X).Cause:
DecodeColorBufferkeeps the array slice only when MIP0_DEPTH is nonzero. With MIP0_DEPTH 0 it addsslice × slice sizeto the address and renders a standalone 2D surface there, so the slice term of the swizzle is lost. In the R_X equations inTextureSwizzleEquations.hpp(from addrlib's GFX10 non-RB+ pattern tables), at 8 bytes per element, byte-address bits 8–11 are XORed with slice bits 3–0. Slice 0 is unaffected. For slices 1–5 the bytes land in permuted 256-byte blocks, and the cube texture that later reads slice f sees them in the wrong order. The pass also downsamples into mip tails, which share a 64 KiB block, so the permutation mixes mips there.Fix: a nonzero slice of an XOR color view with MIP0_DEPTH 0 becomes slice
sliceof an array ofmax(slice, last slice) + 1layers at the surface base. That is the path MIP0_DEPTH ≠ 0 already takes. Linear and non-XOR views are unchanged.The source is the slice term in the existing addrlib-derived equations. This has not been measured on hardware: I have no capture showing the CB applies the slice term when MIP0_DEPTH is 0. The game's own use is the evidence. It draws face f this way and samples the six faces as a cube, so the slice term must apply.
Tested
Linux, GCC 16, Release, RTX 4090 (NVIDIA 615.78).
agc_driver_array_layer_targetgains a case that draws into slice 1 with MIP0_DEPTH 0 and reads slice 1 back through a 4-layer array texture. It checks the result both while pending and after a re-upload from guest memory.Full
agc_suite on this branch: 464 of 464 pass (agc_driver_stencil_ref_exportskipped on this device).tools/check_conventions.py --base origin/mainpasses.High on Life (PPSA15388), on a local stack:
main3377986aplus feat(agc): render layered draws into 3D color targets #1077, feat(agc): depth planes sampled as 2D arrays, cubes and integer views #425, fix(agc): bind a buffer descriptor past the range limit by its committed bytes, or empty #3202 and this change. The before values come from earlier runs on the same stack without it.The scene is still dark, because indirect light is missing (see AGC: a cube's packed-tail mips rendered per face are not seen by the cube's sampled view; the reflection capture filters a clear value (High on Life PPSA15388, black lighting) #4736). Direct light now renders correctly.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code