mpv-player / mpv

🎥 Command line video player
https://mpv.io
Other
28.82k stars 2.93k forks source link

Cannot render GIF files on Vulkan or D3D11 API with certain shaders #8102

Closed Rabcor closed 4 years ago

Rabcor commented 4 years ago

Important Information

Provide following Information:

Reproduction steps

Install Anime4K Shaders and enable Anime4K_Deblur_DoG.glsl and/or Anime4K_DarkLines_HQ.glsl Configure gpu-api to vulkan or d3d11 Play an animated gif (absolutely any animated gif) (Only tested on windows)

Expected behavior

Plays & renders the gif

Actual behavior

Plays but does not render the gif

Note: OpenGL renders the gif, but it doesn't use the shaders correctly.

Log file

https://pastebin.com/vGE0JDwZ

Notes

I'm not sure whether this is a problem with the shader itself or a problem with the shadersc (as suggested by Akemi); Furthermore I'm not sure how big of an issue the fact that OpenGL is not loading the shader is (this was something I discovered after initially posting the issue)

Akemi commented 4 years ago

try with --no-config like the issue template asked for. my bet it's because of one of the shaders you use.

[edit] otherwise, maybe that gif for testing might be helpful.

Rabcor commented 4 years ago

try with --no-config like the issue template asked for. my bet it's because of one of the shaders you use.

[edit] otherwise, maybe that gif for testing might be helpful.

I already did that with no-config to confirm the gifs rendered properly with no-config. Also there was no specific gif, the problem applied to absolutely all gifs, you can pull any animated gif off the internet for testing it.

Then I troubleshot it further by disabling/re-enabling options until I found out removing the gpu-api/context settings/switching to opengl solved the issue.

But since you did mention it I decided to double check, and indeed you were right, disabling the shaders also solved the issue on both vulkan and d3d11;

Still it is strange that the problem only occurs when shaders + vulkan/d3d11 are enabled but goes away when using opengl.

I actually had another issue as well which was that if I played a downscaled 4K video the performance went completely to shit (but upscaling even the tiniest of videos to 1080p works completely fine), which also went away under the exact same conditions (e.g. disable shaders or use opengl api)

There shouldn't be any such differences in the shader behavior between the APIs right? is opengl maybe just ignoring the shaders? or are vulkan and d3d11 not processing the shaders as well as opengl?

Edit: I narrowed it down to 2 specific shaders: Anime4K_Deblur_DoG.glsl & Anime4K_DarkLines_HQ.glsl

If either of those two is enabled, gifs will not play.

The one causing the issue with downscaled 4K files was Anime4K_ThinLines_HQ.glsl

But again, if I use opengl API, all said issues go away... that's strange.

Rabcor commented 4 years ago

I did some further testing and found that the reason the issue did not persist on opengl API is because the opengl API is not actually processing/applying the shaders correctly.

Wondering if that is a shader issue, or an mpv issue?

Akemi commented 4 years ago

Still it is strange that the problem only occurs when shaders + vulkan/d3d11 are enabled but goes away when using opengl.

no that is not strange at all. the shaders are written in GLSL (GL Shader Language) and need to be converted to the appropriate format if not used on an opengl backend, Vulkan > SRIRV, D3D11 > HLSL(?). the conversion of those shaders are done via shadersc and/or some SPRIV Tool. that's either done directly (d3d11) or libplacebo (vulkan).

since both d3d11 and vulkan are affected it's most likely not a libplacebo only problem and rather a shadersc one(?), or the those shaders are somewhat broken.

anyway it's most likely an upstream problem and should be reported there.

Rabcor commented 4 years ago

@Akemi So it might not be strange if Vulkan and D3D11 are having problems processing the GLSL shaders; but isn't it strange that OpenGL is ignoring the shaders entirely while the shaders are actually working on Vulkan and D3D11?

(BTW it seems that problems with image file rendering (e.g. GIFs and PNGs, but I also noticed something on JPEG too while testing earlier) are a known issue for the Anime4k shaders)

Akemi commented 4 years ago

where does the "shaders are actually working on Vulkan and D3D11" come from? you said they don't work, eg you don't get the expected output?

if you get an output on opengl but no processing (no shaders applied) and no output on vulkan and d3d11, that can be totally possible. in all cases the shader don't work properly and the not working part manifests differently on all outputs.

sry, but your infos are all over the place.

Rabcor commented 4 years ago

@Akemi The shader was always working with Vulkan and D3D11 (didn't thoroughly check on the latter though).

I discovered the issue with GIFs and after messing with my options files I mistakenly thought that the problem was with the GPU-API since setting it to OpenGL seemed to solve the issue.

But upon further analysis, the only reason setting the gpu-api to opengl seemed to solve the issue was because OpenGL was not applying the shader in the first place for unknown reasons. (I just checked the logs to see, and it appears to be loading the shader just fine, there were no error messages, yet when watching the video the shader is clearly not applied on opengl)

Vulkan and D3D11 are loading the shader correctly, and probably exactly because they are doing so I was experiencing the issues with GIF files; issues with loading GIFs and PNGs have been reported on the Anime4K github page so it is a known issue for this shader.

As I'm mostly an end-user, I don't know if the problem lies with the shader itself, how the shader is processed, or if perhaps the fact that opengl fails to load the shader is a bigger issue which was discovered by accident while troubleshooting this problem, but it would probably deserve it's own issue.

qmega commented 4 years ago

Perhaps the shader can only handle YUV input? Videos would be that but GIF/PNG would be RGB. Your log has a bunch of:

    vo/gpu: Variable LUMA not found in RPN expression!

Does --vf-append=format=yuv444p or --vf-append=format=yuv420p help by any chance? I'm actually not sure if that would work, even if I'm right about the problem, but it's worth a try. If that is the problem, there's probably a better way to fix it, too.

Akemi commented 4 years ago

would have been my guess too.

though since the initial issue is an issue with the shader itself i will close this one. it might be a good idea to link the issue on the other issue tracker here as reference.

for the other issue, opengl not loading the shader properly, you should open a separate issue here with a log with minimal reproduction settings.

Rabcor commented 4 years ago

Perhaps the shader can only handle YUV input? Videos would be that but GIF/PNG would be RGB. Your log has a bunch of:

    vo/gpu: Variable LUMA not found in RPN expression!

Does --vf-append=format=yuv444p or --vf-append=format=yuv420p help by any chance? I'm actually not sure if that would work, even if I'm right about the problem, but it's worth a try. If that is the problem, there's probably a better way to fix it, too.

Actually yes, this solves the issue. Why would this not be the best way to solve it though? At a glance it seems like the perfect solution since it allows me to use the shaders with gifs?

Akemi commented 4 years ago

because you don't want to convert the format in all cases. especially if you don't need it. conversion is also not lossless. rgb to yuv420p will for example kill image information, since the resulting two chroma planes only have half the resolution.

[edit] also this conversion is done on the CPU and not on the GPU.

qmega commented 4 years ago

I'm just not very well versed in this so I'm not sure if you'd be losing precision somewhere by doing that way. I think it would be more efficient and possibly result in better quality to do that conversion as part of the shader pipeline, but I don't know how to do that.

You almost certainly don't want to do conversion on videos that already work with the shader, so at least use a conditional profile or something to only apply it to image files.

Rabcor commented 4 years ago

because you don't want to convert the format in all cases. especially if you don't need it. conversion is also not lossless. rgb to yuv420p will for example kill image information, since the resulting two chroma planes only have half the resolution.

[edit] also this conversion is done on the CPU and not on the GPU.

I see, thanks. What if I just use yuv444? is it still as lossy? and also I don't think it's so bad that the conversion is done on the CPU considering we're talking GIFs and not actual video files.

I'm just not very well versed in this so I'm not sure if you'd be losing precision somewhere by doing that way. I think it would be more efficient and possibly result in better quality to do that conversion as part of the shader pipeline, but I don't know how to do that.

You almost certainly don't want to do conversion on videos that already work with the shader, so at least use a conditional profile or something to only apply it to image files.

[extension.gif]
vf-append=format=yuv444p                                    #Fix compatibility for Anime4K shaders.
[extension.png]
profile=extension.gif                                       #Fix compatibility for Anime4K shaders.

This is what I'm currently doing (thanks for your suggestion btw, before I would just disable the shaders for these formats, even if some color data might get damaged in translation, it's still a good tradeoff in the end since most gifs are quite low-res, so what I lose in color I get returned in fidelity in the end)

Akemi commented 4 years ago

yuv444p would be the best equivalent for an RBG format (at least for 8 bit), since all planes will have the full resolution. though since there is still a conversion done from rgb (red, green, blue channel) to yuv (luma, chroma, chroma plane), you will still lose some information. it's sadly not completely lossless. there is also other things like chroma placement, dithering, etc.

another thing is, you will do an unnecessary conversion. RBG (image) > YUV (ffmpeg CPU) > RGB (renderer GPU), instead of RBG (image) > RGB (renderer GPU), which is also not completely lossless.

there can also be the case of 16bit pngs where you want at least yuv444p10 (or better a 16 bit format), otherwise you will lose 50% of your colour information.

the CPU might bottleneck with the conversion, since the GPU can do this a lot faster. just imaging png with a high resolution in a slide show.

Rabcor commented 4 years ago

@Akemi yuv444p10 it is then.

Is there any way to do the conversion on the GPU instead? Or is that not implemented as is?

ghost commented 4 years ago

I'm going to stop this. Don't use that shitty shader if it breaks for you; stop suggesting bad workarounds that will probably only be copied by others, and which will cause problems in all eternity by being endlessly copy & pasted and cargo-culted.

Akemi commented 4 years ago

i don't think there is a ways to do colour conversion as a shader, since you can't change the format of the output and we don't have a ways to signal that format change in any way(?). also i would say RGB to YUV is a not a trivial conversion.

what should be done is a proper fix in the shader, so it can operate on arbitrary formats.

haasn commented 4 years ago

I haven't thought this through 100% but I think inserting a pass that hooks RGB and saves LUMA should work (by allowing later passes to bind/reference LUMA). Feel free to pass this suggestion to the Anime4K author.

I agree that using vf_format to hack around the issue is a terrible idea (except for debugging)

On Sat, 19 Sep 2020 12:11:45 -0700, der richter notifications@github.com wrote:

i don't think there is a ways to do colour conversion as a shader, since you can't change the format of the output and we don't have a ways to signal that format change in any way(?). also i would say RGB to YUV is a not a trivial conversion.

what should be done is a proper fix in the shader, so it can operate on arbitrary formats.

-- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/mpv-player/mpv/issues/8102#issuecomment-695345945Non-text part: text/html