hrydgard / ppsspp

A PSP emulator for Android, Windows, Mac and Linux, written in C++. Want to contribute? Join us on Discord at https://discord.gg/5NJB6dD or just send pull requests / issues. For discussion use the forums at forums.ppsspp.org.
https://www.ppsspp.org
Other
11.03k stars 2.15k forks source link

FFT0 problematic effect in Emina scenes #6349

Open LunaMoo opened 10 years ago

LunaMoo commented 10 years ago

Basically looks like that: npjh50443_00040 See her legs? Yup they're under the effect, even through it should be applied before she is drawn, and that's because the effect "sticks" to the screen" on the top of everything, which can be easily seen by moving or zooming camera: npjh50443_00041

Entering ppsspp menu or changing resolution can refresh/center the effect back to look like on the first screenshot. Disabling simulate block transfer makes it never refresh the effect so it stucks on the glitch which it was showing before disabling that option.

Here's a screenshot from GE debugger during the glitch: problematic effect

In the log during that scene it shows:

00:51:007 user_main I[SCEGE]: GLES\Framebuffer.cpp:963 Creating FBO for 00000000 : 480 x 272 x 3 00:51:010 user_main I[G3D]: GLES\TextureScaler.cpp:545 TextureScaler: early exit -- empty/flat texture 00:51:046 user_main I[SCEGE]: GLES\Framebuffer.cpp:963 Creating FBO for 00154000 : 256 x 136 x 3 00:51:046 user_main W[SCEGE]: GLES\Framebuffer.cpp:998 FBO reusing depthbuffer, 00154000/00110000 and 00000000/00110000 00:51:051 user_main I[SCEGE]: GLES\Framebuffer.cpp:807 Resizing FBO for 00000000 : 512 x 272 x 3 00:51:081 user_main I[SCEGE]: GLES\Framebuffer.cpp:963 Creating FBO for 04156000 : 256 x 272 x 3 00:51:081 user_main W[SCEGE]: GLES\Framebuffer.cpp:998 FBO reusing depthbuffer, 04156000/00110000 and 00000000/00110000 00:51:122 user_main I[SCEGE]: GLES\Framebuffer.cpp:963 Creating FBO for 00088000 : 480 x 272 x 3 00:51:122 user_main W[SCEGE]: GLES\Framebuffer.cpp:998 FBO reusing depthbuffer, 00088000/00110000 and 00000000/00110000 00:51:147 user_main I[SCEGE]: GLES\Framebuffer.cpp:807 Resizing FBO for 00088000 : 512 x 272 x 3 00:51:230 idle0 I[SCEGE]: GLES\Framebuffer.cpp:1991 Decimating FBO for 00154000 (256 x 136 x 3), age 6

~tested on v0.9.8-1241-gfafd371

Edit: Ooops, have to edit this a bit, what I saw as correct effect is actually caused accidently by auto frameskip I had on, and the glitched one has correct colors, I just forgot that I'm using shaders >.< ~ done.

unknownbrackets commented 10 years ago

What does it draw to 4154? That's only 32 pixels from 4156.

Maybe it's doing some evil offset clear.

-[Unknown]

LunaMoo commented 10 years ago

Here's from other scene(log shows exactly same thing)

0x04154000: 4154 ^already has the effect, I moved camera so it looks like a ghost copy of the background and that ghost copy seems to be made by 0x04176000, however the first 0x04154000 comes right after and makes it somewhat stronger. Without moving the camera the glitch is visible only by being drawn over character, there's no offset if that's what you mean.

Maybe those are 2 separate problems. One that the effect isn't refreshed every frame, the second one that it's ending on top of everything else including character, which is incorrect.

and here is 0x04154000 second time since it's used 2 times: 4154-2 ^it looks same as above except has an extra layer of color and character.

unknownbrackets commented 10 years ago

Well, maybe it's copying and we're not detecting it... can you try setting a memory breakpoint in the disassembly (click stop, then breakpoint) at 0x04154000 with size 0x2000? Then trigger the scene and see if it trips the breakpoint. If it does, it's somewhere writing to the buffer (might be a caught block transfer, or mips code writing directly.)

I'm a bit unclear about yuor comments of ghosting / simulate block transfers. My expectation is that there will be more graphical glitches if you disable simulate block transfers. It's default on for a reason.

But anyway, what about 04156000? What's drawn there?

-[Unknown]

i30817 commented 10 years ago

I saw other artifacts on the a older radeon mobile. One had a yellow transparent 'cover' over most of the screen (2/6 of it was free on the right side) and another had a 'moving overlay' over it (the flower scene). It actually looked a bit like the Dante's inferno bug report here (the older closed one, not the new fire one).

LunaMoo commented 10 years ago

Well I'm not sure if I'm making it clear what the problem looks like, basically I enter the scene(I do have simulate block transfer on) it looks ok except that the effect covers character model that's the only wrong thing about it as you can see on the first screenshot, until I try to move the camera.

Once I do move the camera around however, the copy of the effect, which is basically a transparent copy of background moves with the camera without refreshing itself and so creates that extra ghosting that you can see on the second screenshot. It does refresh to a new frame if I enter/exit ppsspp menu or change resolution or even texture scalling - I guess this causes the FBO decimating/refreshing.

I set the breakpoint as you asked and it printed out: 53:35:732 user_main N[MM]: Debugger\Breakpoints.cpp:41 CHK Read1114112 at 04154000 ((04154000)), PC=08b9ffd4 (gu_update_stall) breakpoint

unknownbrackets commented 10 years ago

Hmm, that would be a block transfer read. If you keep going does it do more?

-[Unknown]

LunaMoo commented 10 years ago

Yup, it does it for every frame/spams the log with that breakpoint. Edit: it reads it 2 times per frame, just as it shows that texture 2 times in ge debugger.

solarmystic commented 10 years ago

Here's a very short video demonstration of the issue for those who're wondering what it looks like in motion:-

https://www.mediafire.com/?mdq8s8dr4ymx7ti

unknownbrackets commented 9 years ago

Does this still happen? And also does it happen in Direct3D 9?

-[Unknown]

LunaMoo commented 9 years ago

Still happens, the issue looks/behaves exactly same in D3D9.

LunaMoo commented 9 years ago

Just something I missed testing this earlier.

No clue if that tells anything new about the problem, but after setting a read memory breakpoint in disassembly on this texture as above(the screenshot where it stops in gu_update_stall), continuing to press "Go", or better - closing disassembly(without removing breakpoint) and holding F8 makes the scene update correctly and look as it should, even when moving the camera.

Does breakpoint do anything special in here which would update that texture when otherwise it's never being updated? Texture cache related maybe?

unknownbrackets commented 9 years ago

Well, it would cause it to rebind and reset some parameters, maybe? At least, stepping in the GE debugger "fixed" render-to-self textures, so it might be the same sort of thing.

If you go into the GE debugger, click step prim, and then hold down the enter key, does that also make it work correctly? It will be slower, though, but that would ensure it's not some weird affect of having a breakpoint.

-[Unknown]

LunaMoo commented 9 years ago

Step prim doesn't help, so weird effect it is?

unknownbrackets commented 9 years ago

I'm trying to think what might happen with a breakpoint that doesn't happen with the GE debugger. I think it would re-apply the GE state. I don't think it would flush anything...

The reapplying part, in GPU/GLES/TransformPipeline.cpp, here:

void TransformDrawEngine::DoFlush() {

After that, add:

ReapplyGfxState();

Does that make any difference (except being probably much slower)?

-[Unknown]

LunaMoo commented 9 years ago

I understood correctly to add ReapplyGfxState(); directly under: void TransformDrawEngine::DoFlush() { ? Because it's not really slower like that, but there is no actual graphics, just black screen with some artifacts.

unknownbrackets commented 9 years ago

Hmm. Maybe that is a bad place, then. What about adding it after this in GPU/GPUCommon.cpp:

u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<PspGeListArgs> args, bool head) {

Same thing:

ReapplyGfxState();

-[Unknown]

LunaMoo commented 9 years ago

No change from this, no noticeable speed decrease either, if that should kill performance maybe wrong place again?

unknownbrackets commented 9 years ago

No, that place should not really affect perf much. Hm.

A breakpoint might make it abort during a block transfer and resume the list later. So maybe it's flushing related. In GLES_GPU.cpp:

        if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) {
            transformDraw_.Flush();
        }

Change this to:

        transformDraw_.Flush();

This will flush constantly, and should definitely hurt perf (although maybe it might still run full speed on a powerful desktop.) Does this make it any better?

-[Unknown]

LunaMoo commented 9 years ago

No change from that either. Also weird I didn't get a slowdown from this, not sure if the scene isn't just very simple since my pc is anything but powerfull.

LunaMoo commented 7 years ago

Cool, seems to work fine in DX11 :) whatever doesn't get refreshed or cleared in ogl apparently is in the new backend:3. Funny that DX9 is broken just as OGL.

Edit: Hmm after taking a closer look colors are slightly different, so maybe it just lacks one of the filters, still better than non buffered which removes all filters and makes it dark.

hrydgard commented 7 years ago

Hm, then I would expect this to break again once D3D11 is fully implemented :)

LunaMoo commented 7 years ago

Well at worst cwcheat solution will do. As far as I see if I remove blurry layer from all cutscenes those special Emina cutscenes keep both color and it's additional CRT(kind of) filter just fine in OGL.

_C0 Remove blur from cutscenes
_L 0xE0010006 0x0032D0B8
_L 0x2032D0B8 0x00002021
_C0 Remove blur from cutscenes [Disable]
_L 0x2032D0B8 0x34040006

The subjective downside is all properly working cutscenes get's crispy sharp backgrounds.

unknownbrackets commented 4 years ago

Is this now happening the same way on all backends? Or does it still "work" on D3D 11?

-[Unknown]

LunaMoo commented 4 years ago

It's same on all backends now. Broken bloom layer which sticks to whatever it started at.

Two dumps from same scene, one how it launches so the bloom layer is aligned and doesn't immediately appear broken, and second one where camera is moved and the effect keeps a layer mirroring the past. DUMP.zip

LunaMoo commented 2 years ago

Retested with v1.13.1-347-g6cc8ca517, only Open GL seems to be broken now and even that is less broken than it was in the past, only has some glitchy has a working part in the upper left corner. In GEdump it seems all broken even under working backends, but I guess that's just how it is. ;o NPJH50443_0001.zip

Edit: actually looking at it side by side, ogl left top corner is the small part that works, not being glitched. ^_^ NPJH50443_00003 NPJH50443_00004

unknownbrackets commented 2 years ago

The GE frame dump seems to have weird interlacing in software and hardware.

Looking into that to start (maybe it's related), things seem to go bad right after 85/592. To that point, 0x04000000 was rendered at 8888. Here it's copied to 0x04154000, also at 8888 but half size. So far so good. Now we block transfer, 0x04154000 to 0x04176000... which the dump currently replaces with a RAM copy.

This doesn't look to be at the right stride - seems like 512 instead of 256. It makes me think the framebuf download screwed up when the dump was created. Anyway, stubbing that out we get to the next problem...

At 570/592, it copies a pretty-good looking (in software renderer) screen to 0x04156000 stretched to 256x256. That takes us to 574/592, which uses that copy... but the copy is overwritten by Framebuf for 0x04088000 of size 512x512 which overlaps 0x04156000 . This looks highly suspect. Maybe we're detecting this as an offset texture in that framebuf. But for now, just ignoring the memcpy in Framebuf.

That gives something that looks good in software, so let's check OpenGL... and it looks pretty good there too: OpenGL image

It might be the dump doesn't reproduce this issue. If you enable "Auto Flush Pending" in the GE debugger, and check around 84-90 and 570-580, does the artifact get introduced near any of those?

-[Unknown]

LunaMoo commented 2 years ago

The artifact get's introduced closer to the end, I see 570 as max and the difference in rendered effect starts close before it. I noticed a really weird thing through, if I press "step frame" then "resume", the whole effect becomes a bit lighter(and stays like that in-game), it add's soo pressing a few times step frame and resume ends up in much lighter screen ;o NPJH50443_00004 NPJH50443_00005 only the small rectangle keeps looking the same and that's the part that renders correctly, since other backends are fine for whole screen this doesn't affect them.

LunaMoo commented 2 years ago

Actually about effect showing difference with "Auto Flush Pending" I was confused, it actually shows around 80 range. Edit: or maybe I'm still confused as at that stage it only starts to render character on the bed if I got step by step, however with that setting if I use use step count and go to 80 the problem is already there. >.< Don't understand what's the difference between going through each step and step count to step 80.

unknownbrackets commented 2 years ago

The difference between stepping using "step prim" and jumping directly to 80 using "step count" is that "Auto Flush Pending". It only automatically flushes pending draws when the debugger is woken up, so if you step prim each time, it'll flush each time - but step count will only flush the once, at 80.

If there's a difference between what shows up if you step one by one and if you step count, that means a likely state dirtying/caching bug.

-[Unknown]

LunaMoo commented 2 years ago

Don't have time before the weekend to test more, but when I tried the latest update v1.13.1-633-g437d6d30a, the issue reappeared in all backends how it was in the past - frozen effect of first frame covering whole screen, and even got worse - blinking now ;o

Only had time to bisect using buildbot which left a somewhat large range:

LunaMoo commented 2 years ago

The flickering stopped in latest version so I didn't bother bisecting, as for the effect not refreshing I got pretty bad results:

There are only 'skip'ped commits left to test.
The first bad commit could be any of:
3c5ec25f61c8448181986c9da766a9fc2e1bbe51
1ccfd7986af168738d9961d5f1cd8cd40efdd700
afb90f6b049213d582680f2fc18ff6c69d88f149
6aecbef11f6849949ee16aff19e802e872cc06ff
eeb784b41701f31693f52892d6554b837cd4b897
9a82a7d6594cabe4704a2ce7bb1b5c7c1c411dba
dfccdc6367b3ba1ad7eac27b7e04683a82d6d1c4
39690a95bef8c065f1e93e24b180c4e9a7a19753
cd0a31a3cd69652af25ee4f3a3a1fdd396f80771
693fd0870f3c57398db7c54025c2121750b810bc
We cannot bisect more!

The skipped commits all crashed and the last one of them which ran ~ v1.13.1-556-g693fd0870 was already bad.

Basically: v1.13.1-547-g9f4a84945 runs well in all backends through OGL only has effect in the upper left of the screen, the effect refreshes every frame and looks nice. NPJH50443_00007

v1.13.1-556-g693fd0870 is the first build that runs and is broken the same way as it was broken in ancient times, the effect does render, but keeps using the first frame that loads, in some way it's worse at I recall it was updating when going to pause menu or changing settings, now it just keeps that glitched first frame forever, ogl problem is unchanged aka renders the broken effect only in top left which makes it appear somewhat better from other backends as the rest of the screen does not render the effect at all and while darker, doesn't get glitched. NPJH50443_00006

hrydgard commented 2 years ago

Except for the OGL corner thing, this is probably yet another issue where there are multiple overlapping framebuffers somehow, and we pick the wrong one for texturing for whatever reason. Should be a matter of tweaking the MatchFramebuffer heuristics...

Are there any interesting warn logs with "Multiple candidates" or something showing up?

LunaMoo commented 2 years ago

Didn't even know there's a new warning for those in the log:)

00:16:587 user_main    W[FRAMEBUF]: Common\FramebufferManagerCommon.cpp:1 Creating 8888 FBO at 04156000/256 256x272 (force=1)
00:16:587 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:1638 Memcpy fbo upload 04556000 -> 04156000 (size: 44000)
00:28:537 user_main    W[FRAMEBUF]: Common\FramebufferManagerCommon.cpp:1 Creating 8888 FBO at 04154000/256 256x136 (force=1)
00:28:537 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:1780 Didn't find a destination candidate for 04176000/256/4 0,0 256x136
00:28:537 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:2052 Inter-buffer block transfer 256x136 4bpp from 04154000 (x:0 y:0 stride:256 8888) -> 04176000 (x:0 y:0 stride:256 8888)
00:28:538 user_main    W[FRAMEBUF]: Common\FramebufferManagerCommon.cpp:1 Resizing 8888 FBO at 04000000/512 from 480x272 to 512x272 (force=0)
00:28:571 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:2052 Inter-buffer block transfer 256x136 4bpp from 04154000 (x:0 y:0 stride:256 8888) -> 04176000 (x:0 y:0 stride:256 8888)
00:28:571 user_main    W[FRAMEBUF]: Common\FramebufferManagerCommon.cpp:1 Resizing 8888 FBO at 04088000/512 from 480x272 to 512x272 (force=0)
00:28:604 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:2052 Inter-buffer block transfer 256x136 4bpp from 04154000 (x:0 y:0 stride:256 8888) -> 04176000 (x:0 y:0 stride:256 8888)
00:28:638 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:2052 Inter-buffer block transfer 256x136 4bpp from 04154000 (x:0 y:0 stride:256 8888) -> 04176000 (x:0 y:0 stride:256 8888)
00:28:671 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:2052 Inter-buffer block transfer 256x136 4bpp from 04154000 (x:0 y:0 stride:256 8888) -> 04176000 (x:0 y:0 stride:256 8888)
00:30:441 user_main    W[FRAMEBUF]: Common\FramebufferManagerCommon.cpp:1 Creating 8888 FBO at 04156000/256 256x272 (force=1)
00:30:453 user_main    W[G3D]: Common\TextureCacheCommon.cpp:1003 Matching from framebuffer at 04154000 +0x8
00:30:453 user_main    W[G3D]: Common\TextureCacheCommon.cpp:652 GetFramebufferCandidates: Multiple (2) candidate framebuffers. texaddr: 04156000 offset: 0 (256x256 stride 256, 8888):
[COLOR seq:10058 C:04154000/256(8888) Z:04110000/512 X:0 Y:8 reint: false]
[COLOR seq:10063 C:04156000/256(8888) Z:04110000/512 X:0 Y:0 reint: false]

00:30:453 user_main    W[G3D]: Common\TextureCacheCommon.cpp:652 GetFramebufferCandidates: Multiple (2) candidate framebuffers. texaddr: 04156000 offset: 0 (256x256 stride 256, 8888):
[COLOR seq:10058 C:04154000/256(8888) Z:04110000/512 X:0 Y:8 reint: false]
[COLOR seq:10065 C:04156000/256(8888) Z:04110000/512 X:0 Y:0 reint: false]

00:30:453 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:1771 Multiple framebuffer candidates for 04176000/256/4 0,0 256x136 (dest = 1):
 - 04176000/1024/8888 seq:10059  0,0 256x136
 - 04156000/1024/8888 seq:10065  0,128 256x136

00:30:453 user_main    W[G3D]: Common\TextureCacheCommon.cpp:980 Ignoring possible texturing from framebuffer at 04156000 +0x128 / 256x272
00:30:471 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:1771 Multiple framebuffer candidates for 04176000/256/4 0,0 256x136 (dest = 1):
 - 04176000/1024/8888 seq:10059  0,0 256x136
 - 04156000/1024/8888 seq:10068  0,128 256x136

00:30:472 user_main    W[G3D]: Common\TextureCacheCommon.cpp:652 GetFramebufferCandidates: Multiple (2) candidate framebuffers. texaddr: 04156000 offset: 0 (256x256 stride 256, 8888):
[COLOR seq:10075 C:04154000/256(8888) Z:04110000/512 X:0 Y:8 reint: false]
[COLOR seq:10080 C:04156000/256(8888) Z:04110000/512 X:0 Y:0 reint: false]

00:30:472 user_main    W[G3D]: Common\TextureCacheCommon.cpp:652 GetFramebufferCandidates: Multiple (2) candidate framebuffers. texaddr: 04156000 offset: 0 (256x256 stride 256, 8888):
[COLOR seq:10075 C:04154000/256(8888) Z:04110000/512 X:0 Y:8 reint: false]
[COLOR seq:10082 C:04156000/256(8888) Z:04110000/512 X:0 Y:0 reint: false]

00:30:472 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:1771 Multiple framebuffer candidates for 04176000/256/4 0,0 256x136 (dest = 1):
 - 04176000/1024/8888 seq:10059  0,0 256x136
 - 04156000/1024/8888 seq:10082  0,128 256x136

00:30:507 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:1771 Multiple framebuffer candidates for 04176000/256/4 0,0 256x136 (dest = 1):
 - 04176000/1024/8888 seq:10059  0,0 256x136
 - 04156000/1024/8888 seq:10085  0,128 256x136

00:30:507 user_main    W[G3D]: Common\TextureCacheCommon.cpp:652 GetFramebufferCandidates: Multiple (2) candidate framebuffers. texaddr: 04156000 offset: 0 (256x256 stride 256, 8888):
[COLOR seq:10092 C:04154000/256(8888) Z:04110000/512 X:0 Y:8 reint: false]
[COLOR seq:10097 C:04156000/256(8888) Z:04110000/512 X:0 Y:0 reint: false]

00:30:507 user_main    W[G3D]: Common\FramebufferManagerCommon.cpp:1771 Multiple framebuffer candidates for 04176000/256/4 0,0 256x136 (dest = 1):
 - 04176000/1024/8888 seq:10059  0,0 256x136
 - 04156000/1024/8888 seq:10099  0,128 256x136