libretro / slang-shaders

239 stars 92 forks source link

several shaders show artifacts in glcore #103

Closed LazyBumHorse closed 5 years ago

LazyBumHorse commented 5 years ago

I'm actually not sure if this is a shader problem or a RetroArch video driver (i.e. Slang shader translation) problem, but here's what's happening:

Using the glcore video driver, xbr-mlv4-multipass shows artifacts: glcore xbr-mlv4-multipass glslp It's fine in Vulkan: vulkan xbr-mlv4-multipass glslp Here's glcore again: glcore xbr-mlv4-multipass slangp And here's the GLSL version in gl for another comparison: gl xbr-mlv4-multipass glslp

I'm using a GTX 1060 6GB.

This may be related to #70 as well, though Vulkan is innocent this time.

hizzlekizzle commented 5 years ago

Looks like a glslang issue. Other reflections seem to be okay.

LazyBumHorse commented 5 years ago

Now that I know what to look for, I found several shaders that seem to be affected by this as well:

Can we break it down what they have in common? Maybe there's already an issue in the glslang's issue tracker.

hizzlekizzle commented 5 years ago

I'm not getting any issues with xbr-mlv4-multipass, scalefx or hqx, but I am getting rough edges on xbr-lv3-multipass. Using glcore with mesa driver on a Haswell integrated GPU.

LazyBumHorse commented 5 years ago

Do you mean this when you say rough edges in xbr-lv3-multipass? xbr-lv3-multipass slangp Noticeable at the font the most, I don't seem to get issues with the single pass xbr-lv3 version: xbr-lv3 slangp

And are you sure you don't have any issues with the other examples? They aren't very pronounced for me but in direct screenshot comparison to glsl it becomes very obvious something is wrong, e.g. at first glance hq2x looks okay until you notice the 'ghosting' of the font and then the fact it doesn't smooth the pixels at all: hq2x slangp vs glsl hq2x glsl

scalefx is also very very subtle, here's another (upscaled) comparison, slang in glcore vs glsl in gl: scalefx slangp Notice e.g. the darker lines between the gray bricks besides the king. vs glsl: scalefx glsl

I want to try debugging it myself, but I don't even know how Slang or glslang you mentioned work nor what reflections precisely are.

hizzlekizzle commented 5 years ago

Here's what lv3-multipass looks like for me: Screenshot from 2019-05-26 20-24-43 hq4x looks okay here: Screenshot from 2019-05-26 20-26-35 The way slang works is it gets converted to SPIR-V, which then gets "reflected" back to whatever driver's native code via glslang. So, there are several places where inconsistency can sneak in, whether it's the normal endpoint driver issues we always have to deal with when shaders are involved, but also issues with glslang's reflection (rare, but it can happen).

LazyBumHorse commented 5 years ago

I think I found the issue! It was my graphics driver settings all along. I forced 16x anisotropic filtering in all programs, which surprisingly messes up the shaders in glcore. Now all the named shaders behave like they should.

Well, almost. aa-shader-4.0 and xbr-lv4-multipass still show some line artifacts. aa-shader-4.0 shows a rough line every 32 pixels (at least in the bottom half): aa-shader-4 0 xbr-lv4-multipass has seemingly a single rough line going through the bottom characters: xbr-lv4-multipass

LazyBumHorse commented 5 years ago

I found the xbr-lv4-multipass issue so weird so I did some more testing. It appears to really be only one singular line artifact and it does appear in Snes9x glcore and vulkan (didn't know you could use vulkan with it, but apparently you can). I also couldn't replicate the issue in cores for other systems and I believe that is because of differing vertical resolutions. In higan you can set different internal resolutions and only if the vertical resolution is 224 (like in Snes9x), the single rough line appears. Maybe some kind of precision error? Rounding error? Off-by-one error? Compared to glsl, the 'slicing' appears to be different, you see what I mean when you switch between the images: slang glsl: glsl I should have activated integer scale... gl aa 4x glcore aa 4x Interestingly the artifact disappears when integer scaling, the horizontal 'slicing' still seems to be different though, which is weird - different rounding?

So a workaround would be to set the scaling of the last pass to a clean 4x or 5x instead of 'Don't care'.


The aa-shader-4.0 issue appears in glcore and vulkan and also seems to be dependent on the vertical resolution. 224 and 240 have issues, but 448 and 480 appear fine. Some other cores/resolution I tested appeared fine as well.

I thought this had something to do with the use of scale_type(...) = "viewport" and nearest neighbor scaling because 224 and 240 don't divide 1080 (and maybe the issue is just slightly hidden with 448 and 480), but using integer scale or setting scale_type to source and scale to 4x, the lines are still there.

Looking closer: glcore aa 4 glsl: gl aa 4 This looks like an off-by-one error, all lines appear to shift down by 1 in Slang, except for every 32th (in 1080p) or 28th (with integer scaling, 896'p') line.

hizzlekizzle commented 5 years ago

yeah, rounding errors like that are very common. I usually deal with them by multiplying the texcoord calculation in the vertex by something like 1.0001 but I believe the issue is also GPU-dependent, so sometimes 1.0001 does it, other times I have to go up to 1.0004 or somesuch.

LazyBumHorse commented 5 years ago

Hm... that sucks. I guess you just can't expect pixel perfect output in every case, but I didn't think it would be that bad.

What's just so weird to me is that the code for the aa-shader-4.0 slang and glsl shaders are actually identical, except glsl is using precision qualifiers for OpenGL ES, which I'm not using, so...

Oh well, the original problem has been solved, xbr-lv4-multipass has a workaround and aa-shader-4.0 seems to only break in that particular resolution on my particular system in this particular universe, so the topic can be closed.

hizzlekizzle commented 5 years ago

I spotted another common culprit for rounding errors in aa-shader-4.0: floor(). Adding a small offset to it appears to have cleaned it up quite a bit! https://github.com/libretro/slang-shaders/commit/79c95a5036af4a38138dc8f924445a168eee4e54

LazyBumHorse commented 5 years ago

That works very well! The difference image is almost completely black. Only around the very top, there's still one line artifact, probably because the effect of the multiplication is too low at that point.

glcore How it should look like: gl