ares-emulator / ares

ares is a cross-platform, open source, multi-system emulator, focusing on accuracy and preservation.
https://ares-emu.net
Other
864 stars 105 forks source link

Inconsistent upscaling causes issues with shaders #541

Open MorsGames opened 2 years ago

MorsGames commented 2 years ago

I was trying out the quark-shaders with Ares v127, but many of the shaders were giving weird results with some of the cores (noticed with SNES, Genesis, and N64).

Well, it turns out that different cores output the image with different upscaling levels, and it's never really consistent. Some seem to only upscale the image on the horizontal axis (I think? I'm not entirely sure), some do it in both, and some don't do any upscaling at all.

I think this was done because some of these consoles have different output modes, but in that case wouldn't it make more sense to change the output resolution based on the mode, or at the very least sending the image to the shader before any upscaling is done? This would make many of the currently broken shaders start working correctly.

It's possible to work around this issue by downscaling the image within the shader manifest file, but the real issue is that the internal upscale amount is different in each core, and as far as I can tell there's no way to set different shaders per core. Not to mention that this workaround would also break all the different resolution modes, like Sonic 2's multiplayer mode and SNES's fake transparency.

Screwtapello commented 2 years ago

This behaviour was inherited from higan's high-accuracy GPU emulation. I don't think ares uses high-accuracy emulation by default, but it can, and perhaps that behaviour is kept for consistency?

I think this was done because some of these consoles have different output modes, but in that case wouldn't it make more sense to change the output resolution based on the mode, or at the very least sending the image to the shader before any upscaling is done?

The issue is that the output mode can change during a frame. For example, you can make a Genesis game where the top half of each frame is 256px wide, while the bottom half is 320px wide. There's various ways you might represent that in a way that shaders could make sense of it, but the overall simplest implementation was just to make the overall output width 1280px, since the shader is just going to rescale the result anyway. Genesis pixels drawn in 256px mode become 5 output pixels, while Genesis pixels drawn in 320px mode become 4 output pixels.

MorsGames commented 2 years ago

The issue is that the output mode can change during a frame.

Oh that makes sense, I hadn't considered that possibility.

In that case it would probably be most ideal to change the resolution to 1280px whenever both modes are used on the same frame instead. I think it would be worth it because as it is right now it's not possible to use the NTSC shader (as well as some of the CRT ones I'd imagine) on all cores without making core specific changes.

For comparison here's how the NTSC shader looks with default resolution settings. image Not much different than how it would look without a shader.

And here's how it should ideally look, after downscaling the horizontal resolution to 25%, and vertical resolution to 50%. image

I guess another solution would be to allow setting different shaders per core but there doesn't seem to be any other core dependent setting like that so I can see that going against the nature of the project.

Gryzor1363 commented 1 year ago

I can confirm this issue is persisting as of latest version 130.1. Seems to be especially and quasi-exclusively impacting CRT shaders of the "quark" pack, with the notable exception of CRT-Geom and CRT Simple, following the same pattern as described above : uneven/incorrect scaling of shader texture with scanlines, resulting in vertical and/or horizontal blocking that grossly distorts the intended effect in fullscreen.

Noteworthy is that every single of the impacted shaders seem to scale correctly in windowed mode, with scaling + aspect correction, adaptive sizing and auto-centering options enabled.

I have attached the Super Mario Bros in its original NES edition as an example, since its dominantly bright and light-green tones are a good benchmark to whatever can be wrong in shading in general. Shader used in that particular sample was CRT-Royale.

Supr Mario Bros - NES - Windowed Supr Mario Bros - NES - Fullscreen

As a side note, on every SNES game I have tested so far (about a dozen of them), some of the shaders such as CRT-Royale render in a nearly unwatchable, anomalous, strongly flickering interlacing even in windowed mode.

Not fully apparent in a still, I thought useful to attach the fullscreen distorsion that behave in a quite similar way to the NES games. Shader used in the fullscreen image : CRT-Lottes-Multipass.

Supr Metroid - SNES - Fullscreen

Screwtapello commented 1 year ago

Noteworthy is that every single of the impacted shaders seem to scale correctly in windowed mode, with scaling + aspect correction, adaptive sizing and auto-centering options enabled.

If a shader ever renders "correctly" for a given core, that's a different issue.

As a side note, on every SNES game I have tested so far (about a dozen of them), some of the shaders such as CRT-Royale render in a nearly unwatchable, anomalous, strongly flickering interlacing even in windowed mode.

That sounds more like this issue, yes.

Gryzor1363 commented 1 year ago

Noteworthy is that every single of the impacted shaders seem to scale correctly in windowed mode, with scaling + aspect correction, adaptive sizing and auto-centering options enabled.

If a shader ever renders "correctly" for a given core, that's a different issue.

My bad, actually that remark was meant as a way to provide you with additional information pointing to what situations made the shaders mostly "right" versus all of those where they are almost always broken, and not exclusively stick to what does simply not work in relation to them. Indeed several use cases produced different results and not a "100% broken feature". Context, so to speak. Nonetheless, I stand corrected on the posting rules, thank you.

As a side note, on every SNES game I have tested so far (about a dozen of them), some of the shaders such as CRT-Royale render in a nearly unwatchable, anomalous, strongly flickering interlacing even in windowed mode.

That sounds more like this issue, yes.

Noted. Then I would emphasize on the fact that this would be the one and only case I have been able to reproduce with a CRT-category shader also failing in windowed, as much as it does in fullscreen, to the point that I considered it an exception to the phenomenon I was describing.

And thanks for your quick reply, @Screwtapello

MorsGames commented 1 year ago

I can confirm this issue is persisting as of latest version 130.1. Seems to be especially and quasi-exclusively impacting CRT shaders of the "quark" pack, with the notable exception of CRT-Geom and CRT Simple, following the same pattern as described above : uneven/incorrect scaling of shader texture with scanlines, resulting in vertical and/or horizontal blocking that grossly distorts the intended effect in fullscreen.

Yeah I feel like this is a slightly different issue than what I described in my original post.

My complaint was that the internal image buffer was upscaled before being passed to the shader, in ways that was not consistent between cores at all, which impacted the usefulness of the whole shaders feature significantly. The issue is given the "bug" label but it's more like a weird quirk of the emulator, and if the emulator is in fullscreen or windowed should be unrelated to it.

The issue you're describing sounds like the final framebuffer (the one after the shader is applied) getting upscaled incorrectly which is an entirely different problem, unless I'm misunderstanding what you're describing.

Gryzor1363 commented 1 year ago

Thanks for the clarification to both of you. Indeed my post didn't entirely belong to that thread considering we aren't even discussing the same processing phase/pass and only the resulting visual behavior i.e. distorsion/broken effect seem similar in some ways. I simply cobbled "shader" and "issues" together and thought I would contribute, as far as my (very narrow) technical understanding of shaders and their application goes. My final question would be : Where should I move my own observations, assuming of course that they aren't already covered by another ticket ?

Thx

Screwtapello commented 1 year ago

I don't think they're covered by another ticket yet. Please create one, with the screenshots and description you added to this issue - that's a good example and description of the problem you're having.

Gryzor1363 commented 1 year ago

No problem, glad I could bring up something useful. Done.

aduffey commented 3 months ago

Is there any possibility that the vertical scaling could be decoupled from the horizontal scaling?

Some CRT shaders will look the same regardless of how many times horizontal pixels are duplicated, but if vertical pixels are duplicated they will either look double-scanned (i.e. 2 scanlines per logical vertical pixel) or they will assume the input is interlaced and will output a flickering mess. I don't think there's really any way around that from the point of view of the shader developer. Currently none of the CRT shaders I've tried (v137, librashader) look right on SFC/SNES or MD/Genesis.

If vertical pixel doubling can be avoided, and higher line counts only used for interlaced content, more shaders will be usable.