-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature request: look-up table support in user shaders #4586
Comments
I have an unmerged branch sitting on my computer that allows user shaders to load custom textures, but it's annoying for a couple of reasons so I haven't merged it. Maybe I could get your comments about the API? For reference, the patch looks like this: haasn@484a011 The API design I was considering looks something like this:
In order, that's This would be much easier on the mpv side of things than actually trying to parse the texture/float data literally. Would you consider this API acceptable? Maybe I could introduce a hybrid between your syntax and my syntax, where the Also, I'm concerned about user shaders trying to replace the shader kernel because that doesn't “work” properly - the main shader still runs, and the user shader can't take into account options like sigmoid upscaling or cropping/offset issues. What I might do instead is introduce a new shader primitive next to |
Really glad to know that there is a working solution now. A few comments:
|
The only code that gets run per-frame for user shaders is in
I'd rather do the other way. I actually like the
I actually think it owuld be more elegant to have them as part of the same file, to make it more self-contained. Unfortunately, the inability to easily load these weights is a big selling point that gets lost. Hmm.. what if we use something like base64 to store the raw weights file as plaintext inside the shader body? That way you can include newlines and such, and mpv is freed from the burden of having to parse a few thousand floats. (We get base64 for “free” from libavutil) |
I see. A few additional configuration settings for texture that could matter potentially
|
This approach also looks good to me, especially considering that decimal representation of float-point number won't save much space either. |
To be honest even the thought of extending the user shader API is annoying. Maybe we should revolutionize the API and switch to loading something like a That's also ugly though, especially the “bridge” that would have to be built between vo_opengl and lua. (Where would this even go? a VOCTRL?) |
Yes, it do feels to be annoying. But if I understand correctly, after adding LUT support, within the rendering workflow current
There is just the technical side. I also feel that migrating all existing user shader (even though not much) to Anyway, I do hope there is an elegant solution to this situation. Embedding weights might be weird, but could resolve some real problem, and have some performance benefits (smaller GLSL shader size, LUT resists on GPU). |
Hmm no, even this would be insufficient. It seems like ideally, what would have to happen is that |
@bjin @wm4 How about this design?
This way we would unify user scripts with user shaders, both just being lua files you plop into As an annoying side detail, the “size expressions” would probably still have to be in some form in which |
As an aside, this registered |
This is kind of thing I want to avoid. I could image porting python code into lua gonna be a nightmare for me. If it have to be done in this way, I will definitely choose to generate lua code (which "returns" shader file) from python directly.
I'm actually not sure what's the gain for this move. If it's just about extending customized DSL, we could probably use another structure format like JSON. User shaders are, after all, just a bunch of metadata and strings. If it's about dynamically generating shader with lua, and providing flexibility like reading and uploading LUT texture, it seems to be a little bit overkill for me. |
Hmm good point re: just loading JSON, I guess mpv already has reusable functions for this somewhere. Unfortunately that's somewhat annoying since it means having to escape the shader body. YAML would probably be better, but wm4 would kill me for suggesting it. I just thought that making them more dynamic would possibly solve a number of different requirements, like dynamically loading-unloading individual shaders via keybind or property (currently not really possible unless you plan on parsing the But oh well, if you think it's overkill then maybe it is. I guess I'll probably stick with the status quo of having this horrible (What do you think, @wm4?) |
This change requires commits from an unmerged branch of mpv[1]. The API is most likely going to change[2]. So some temporary hack is used, `/tmp/ravu.bin` will be written for example. `--target=native` is still insanely slow for some reason I don't understand, probably due to my shader compiler failed to perform certain optimization (float vs. half-float?). So default target is changed to `luma` for now. [1]: https:/haasn/mpv/tree/gl_user_tex [2]: mpv-player/mpv#4586
@haasn I adopted the API provided by your |
In the absence of any sort of radical lua-based reformation, I would be leaning towards that as well. In addition to allowing How much does the texture upload help performance? What I found for FSRCNN is that hard-coding the weights in the shader was actually faster for fixed convolutions, even though the weight required a position-based array lookup, so I expect this to be the case for e.g. NNEDI3 as well. |
Yes, this is the case for nnedi3 as well. We used to have two approach to upload nnedi3 weights, via uniform buffer, or hard-coded in code. The hard coding approach is much faster as I tested. I guess this is always true if all weights are going to be used for rendering single pixel, and in specified order. RAISR, however, is not neural network based. Only a small portion of the weights are going to be used. So using a texture to look up weights is much faster than hard-coding all weights, about 8 times faster as I tested. |
Parsing the texture data as raw strings makes the textures the most portable and self-contained. I decided to reuse the internal saved_tex mechanism to avoid having to bloat up `pass_hook` more, and make the texture binding mechanism consistent for users, even though the result of doing this is slightly quirky. because now we will also generate the _size etc. uniforms even though they don't really make sense. This also requires me to add a new PLANE_ type so I just have _something_ to set for the type, because none of RGB etc. really make sense. May revisit this in the future. As an aside, by request of @wm4, I've added hex decoding code to bstr.c and made stream_memory.c use it. As a result of this, stream_memory.c's hex:// protocol now silently ignores invalid characters. (But this change is backwards compatible) Closes mpv-player#4586.
Parsing the texture data as raw strings makes the textures the most portable and self-contained. As an aside, by request of @wm4, I've added hex decoding code to bstr.c and made stream_memory.c use it. As a result of this, stream_memory.c's hex:// protocol now silently ignores invalid characters. (But this change is backwards compatible) Closes mpv-player#4586.
Parsing the texture data as raw strings makes the textures the most portable and self-contained. As an aside, by request of @wm4, I've added hex decoding code to bstr.c and made stream_memory.c use it. As a result of this, stream_memory.c's hex:// protocol now silently ignores invalid characters. (But this change is backwards compatible) Closes mpv-player#4586.
Parsing the texture data as raw strings makes the textures the most portable and self-contained. As an aside, by request of @wm4, I've added hex decoding code to bstr.c and made stream_memory.c use it. As a result of this, stream_memory.c's hex:// protocol now silently ignores invalid characters. (But this change is backwards compatible) Closes mpv-player#4586.
Parsing the texture data as raw strings makes the textures the most portable and self-contained. As an aside, by request of @wm4, I've added hex decoding code to bstr.c and made stream_memory.c use it. As a result of this, stream_memory.c's hex:// protocol now silently ignores invalid characters. (But this change is backwards compatible) Closes mpv-player#4586.
Parsing the texture data as raw strings makes the textures the most portable and self-contained. As an aside, by request of @wm4, I've added hex decoding code to bstr.c and made stream_memory.c use it. As a result of this, stream_memory.c's hex:// protocol now silently ignores invalid characters. (But this change is backwards compatible) Closes mpv-player#4586.
Parsing the texture data as raw strings makes the textures the most portable and self-contained. In order to facilitate different types of shaders, the parse_user_shader interaction has been changed to instead have it loop through blocks and call the passed functions for each valid block parsed. This is more modular and also cleaner, with better code separation. Closes mpv-player#4586.
Parsing the texture data as raw strings makes the textures the most portable and self-contained. In order to facilitate different types of shaders, the parse_user_shader interaction has been changed to instead have it loop through blocks and call the passed functions for each valid block parsed. This is more modular and also cleaner, with better code separation. Closes mpv-player#4586.
Look-up table is an essential technique used to speed up some core part of mpv's
opengl
backend, including most scaler based on convolution kernel (polar or not), dithering and 3dlut based color management.But currently, there is no direct support of look-up table in user shaders (either via texture or uniform buffer). This makes a large part of LUT-based algorithm/filter infeasible to be implemented as user shader. This includes any reasonable main scaler that I can think of (all are convolution based), some prescaler with large amount of weights, and customized dithering algorithm.
It would be a great help if it's possible to define and upload static texture in user shader:
BIND
.bilinear
andnearest
sampling. Again, there is actual use case for both.My proposal
We can extend the definition of single block in user shaders to define a constant texture.
Texture will be named
LUT_weights
, and hooks are able to useBIND LUT_weights
to access it.Values like
t00.r
are floating numbers in decimal representation (like "0.01" or "1e-3"). There areh
lines in the body, each withw
texel separated by semicolon. Within each texel, components are separated by comma.It's tempting to allow binary representation of single-precision float, or even exact integer. But
--opengl-fbo-format
is not controlled by user shader, and a safe fall back is generic float number, the value that will later be retrieved.This feature is kind of critical to the performance of a new prescaler I'm currently trying to implement (theoretically it should be comparable to built-in EWA scalers but currently it's far slower than nnedi3). But besides it, I also feel it's necessary since otherwise I can't even port built-in scalers into user shader and make some customization.
I post the proposal here since I feel it's not necessary the only approach. I don't have input from other user shader authors, and also haven't been following the
opengl
backend for a while.The text was updated successfully, but these errors were encountered: