[BUG]: Xenosaga Episode III misdetected shuffle (?)
Describe the Bug
Game has broken graphics likely due to a misdetected shuffle.
Reproduction Steps
Download and run the following GS dumps.
https://drive.google.com/file/d/1sIxDkpGZez8aYr90Xb7WbrYDEH9zKDBw/view?usp=drive_link https://drive.google.com/file/d/11aFdKyfy2wmYTOkTiCgdTNyypj1_XRII/view?usp=drive_link
Expected Behavior
Game no broke.
PCSX2 Revision
v2.5.229
Operating System
Windows 10 (64bit)
If Linux - Specify Distro
No response
CPU
Ryzen 5 5600X
GPU
RTX 2070 Super
GS Settings
No response
Emulation Settings
No response
GS Window Screenshots
No response
Logs & Dumps
No response
Haven't fully determined the issue but it appears that a C16 target @0x1800 is drawn in frame 403 (draws 115822 - 115826) and is read back as a C16 source in frame 405 (draw 116619). For some reason, it is corrupted somewhere in between. It appears to be a regular (non-shuffle) draw for a post-processing blur effect.
I thought I fixed that, yeah it's not a shuffle, it's just being misdetected as one then screwed up.
Hmm, when I stepped through it, I didn't see the possible_shuffle flag set in GSTextureCache::LookupSource(), though it's possible that it's triggered in a different place.
idk, you'll have to trace through (it might be the end of the source lookup, where it tries to be smart), but it's probbaly being converted to 32bit, or told it is. But you should be able to to find the draw where the PSM gets updated to CT32 and see why :)
Notes for future reference (with respect to the large dump above). Occurs around frames 403-405:
- A C16 target at 0x1800 is created for a post-processing effect to scale down the main RT. However, there is already a C32 target at 0x1800. Instead of nuking the old C32, it is resized making the new C16 targer larger than it needs to be (should be around 512 x 224 but ends up 512 x 512).
- A few draws later, the C16 target at 0x1800 is used as a source for the post-processing effect.
- A few draws later, a new RT is draw at 0x1C00. Since this overlaps the larger-than-needed C16 source at 0x1800, the C16 source gets nuked.
- A few hundred draws later, another RT is drawn at 0x1C00. This time it triggers a path in GSTextureCache::LookupTarget() that signals that the C16 target at 0x1800 is part of a double buffer, so the C16 target also gets nuked. This is also in part because the C16 target is too large.
- A few hundred draws later, we attempt to use the (nonexistent) C16 target at 0x1800 for a similar post-processing effect. Since there is no longer a target or source at 0x1800 we load garbage from memory and get the bugged visuals above.
Proposed solution: Improve the heuristics in step 1 so that we appropriately nuke the old C32 target instead of resizing it. Resizing the target is useless anyway it is being converted to a different format with incompatible swizzle, and is not being used for a shuffle.