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.19k stars 2.17k forks source link

Final Fantasy I icons incorrectly clipped/positioned #12257

Open bearoso opened 5 years ago

bearoso commented 5 years ago

What happens?

In some menus, the icons representing an item type are clipped off at the top. Example: ULUS10251_00000

Look at the icons next to the item names, particularly the Staff, Rapier, and Hammer. The top row of pixels for each is clipped off.

This menu can be accessed by starting a new game, entering the town, then entering the weapon shop and talking to the character inside. This is not the only location it occurs, but the easiest to access. It also occurs in the "Equipment" menu and Item and Magic menus in battle.

What should happen?

Using software rendering fixes the problem: ULUS10251_00001

Note that the icons are positioned one pixel lower relative to the text, which prevents the top from being clipped. Maybe a rounding issue?

What hardware, operating system, and PPSSPP version? On desktop, GPU matters for graphical issues.

RX580 Linux, OpenGL/Vulkan (all 3 ICDs), hardware mode only. As far back as I could test from PPSSPP 1.4 to latest git.

LunaMoo commented 5 years ago

Increasing render res very commonly will cause slight missplacement in graphics since the PSP games are not ment to render above 1x PSP display res, so just try that and change to x1 render resolution.

bearoso commented 5 years ago

Yes, this is at 1x PSP resolution. All compatibility options were tested.

unknownbrackets commented 5 years ago

Here's how it should look on a real PSP (matches your screenshot): ULUS10251_ff1_offset_icons

Here's what I get in OpenGL (other backends look the same): ULUS10251_ff1_offset_icons_opengl

The colors are not perfect, but generally they look the same.

This is 2x render resolution at 1x window size: ULUS10251_ff1_offset_icons_2x

And event 2x at 2x window size, which you appear to at least be using 2x window size: ULUS10251_ff1_offset_icons_2xw

I can't reproduce this at all on a US version of the game. To me, it looks like you're either forcing bilinear filtering (not letting the game decide with auto), using 2x render resolution, using texture scaling (2x or higher), or maybe using 1x render res with 2x window size and linear screen scaling.

Software rendering is also correct.

-[Unknown]

bearoso commented 5 years ago

No, I've messed with all the settings to make sure nothing was causing it. Even started with a clean config. 1xPSP, Auto texture filtering for PSP API. Toggled all compatibility options to no avail. Even tried booting up Windows and the same problem. Downloaded a new ROM off the internet and did a checksum to make sure it was different from. That ROM exhibited the same problem.

Software rendering fixes it. Also, turning off buffered rendering for some reason mostly fixes it, but it's still clipping a bit like in your 2xPSP resolution shot: ULUS10251_00000

I thought that it might be high-dpi related, but was able to disprove that. Might be the video card or drivers doing it. I really don't want to have to dig out a NVIDIA card to test with.

hrydgard commented 5 years ago

The game probably draws the symbol offset by a fractional pixel and accidentally relies on a quirk in PSP's GPU's sampler hardware, where it's just slightly offset, and when rendering 1:1 with point sampling it happens to roll over to the next pixel.

Can probably be fixed in hardware rendering too by applying a tiny offset when sampling textures, costing a bit of extra overhead for every pixel. Not something that has top priority, since the game plays just fine even with this visual imperfection visible.

bearoso commented 5 years ago

I'm kind of curious now why I'm getting it and unknown isn't. It looks like my instance is using a 2x framebuffer even though it's set to 1x, because the top row of the icons is half the height of the other pixels, and that would otherwise be impossible. I've ruled out the driver by using llvmpipe.

bearoso commented 5 years ago

I've looked at the frame analysis, and in the instances where the icon is drawn incorrectly, it's sampling from the 256x16 texture with integer U coordinates and half-pixel offset V coordinates.

It's a 12x12 icon, so for the Rapier it's 0.0, 0.5 to 12.0, 12.5. With nearest sampling, it incorrectly rounds that up and ends up sampling 0.0, 1.0 to 12.0, 13.0. The text beside it is drawn with both 0.5 offset U and V coordinates (0.5, 0.5 to 12.5, 12.5), and seems like it might have some heuristic in PPSSPP that causes it to round down correctly to integers. In the locations where the icon is drawn correctly in the game, like the "Item" menu, the game uses integer coordinates (0.0, 0.0, to 12.0, 12.0).

So it looks like 0.5 rounding policy is the problem.

edit For the text, the debugger says it uses signed 16-bit positions, but for the icon, it says floating point positions. The game is specifying 0.5x0.5 pixel offsets for the text, but PPSSPP opts to use integral coordinates. The icon is 0.0x0.5 offset, but it doesn't.

unknownbrackets commented 5 years ago

I know the PSP rounds at 0.625 in some cases, but iirc it rounds at 0.5 for texture filtering. That said, I don't remember if it consistently rounds down or up at 0.5 - it might round to even. Maybe even NVIDIA rounds to even, since I don't see this bug on NVIDIA.

It does seem to be wrong on Adreno, though.

The icons are drawn in through-mode, which might possibly behave differently than transform-mode with rounding too. That said, both the text and icons use float texcoords (that's what U and V are) and through-mode, so it ought to round the same way. Maybe there's just space above the font so it isn't noticeable.

-[Unknown]

bearoso commented 5 years ago

The icons are drawn in through-mode, which might possibly behave differently than transform-mode with rounding too.

I was referring to this: float

It's the positions, not the texcoords, but nothing else in the frame but the icons uses float positions, they all show s16 instead: s16

The texcoords are the problem, but could the position format be influencing rounding somehow?

hrydgard commented 5 years ago

Different GPUs do this rounding in different ways - it's right on the edge so your results will be different. To reliably simulate what the PSP does on other GPUs we have to apply a slight, slight offset. The offset we need to apply might even be GPU-dependent. So this is not entirely trivial.

ghost commented 2 years ago

I cannot reproduce this, can you try the latest git build? https://buildbot.orphis.net/ppsspp/index.php?m=fulllist

bearoso commented 2 years ago

Nope, not fixed. Read above--nvidia cards have the same rounding as PSP. It's a problem with other GPUs.

unknownbrackets commented 1 year ago

Just for reference, 454/792 is where the first icon is drawn in this frame dump: #12257_ULUS10251_ff1_offset_icons.zip

It's using nearest filtering + throughmode, with X/Y/U at even pixels and V at 0.5. The PSP's nearest filtering seems to round nearest down to the nearest texel, so even 0.99 would round to 0. Most likely, Adreno is rounding 0.5 to 1 here.

-[Unknown]

unknownbrackets commented 1 year ago

Actually, strange observation: there's presumably more to it. I had written a test at some point comparing WRAP/CLAMP with 0.5 offsets, and looked at it again. A simple (0,0) - (1,1) rectangle with UV (0, 0.5) - (1, 1.5) in throughmode should actually round up (WRAP/CLAMP doesn't change this.) This is because it samples at pixel centers, so the nearest round down is from that center, which would be exactly even.

But the rendering of this frame dump obviously rounds 0.5 down. So it's probably more complicated than that simple rule.

I haven't tried more hardware tests (just looking at existing results), but some differences between the two draws:

Ordered in maybe the likelihood it could matter. Just noting this for any future accuracy testing.

-[Unknown]