Skip to content
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]: support GPUs without Vulkan #62

Open
I60R opened this issue Nov 21, 2022 · 8 comments
Open

[Feature request]: support GPUs without Vulkan #62

I60R opened this issue Nov 21, 2022 · 8 comments

Comments

@I60R
Copy link

I60R commented Nov 21, 2022

I have an older laptop with Nvidia Quadro 3000m GPU that has no Vulkan support under Linux.

When I try to spawn wluma it prints:

[2022-11-21T17:14:32Z INFO  wluma] Continue adjusting brightness and wluma will learn your preference over time.
thread 'predictor-LVDS-1' panicked at 'Unable to initialize Vulkan: ERROR_INITIALIZATION_FAILED', src/frame/capturer/wlroots.rs:86:44
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Would you consider adding OpenGL capturer?

@maximbaz
Copy link
Owner

I have no objections to add support for OpenGL, in fact the earlier version of wluma was written using OpenGL in C (you can find the code here, just before I made the switch, and play around). I found it extremely difficult to work with, that's why I moved to Vulkan.

I'll honestly say that most probably won't do this myself, but if you (or anyone else for that matter) try the earlier version, and it works for you or you can get it to work, and you feel like porting that code to rust (it was somewhat randomly working for me, from what I remember), then please submit a PR, and I would be very happy to assist along the way, with concepts and explanations, as well as with code review, and of course with getting it all merged.

Terminology-wise, I'd probably call that "processor" instead of "capturer" (for me it's wlroots that captures the frame, and Vulkan processes the image to find the lightness value), so we can make a folder with vulkan.rs and opengl.rs, and add it to config.toml.

Let me know what you think!

@I60R
Copy link
Author

I60R commented Nov 21, 2022

Thank you for fast response and for considering this.

I'm trying to compile the oldest version of project you've specified with

meson setup builddir
cd builddir
meson compile

it gives errors:

[1/2] Compiling C object wlsun.p/src_main.c.o
FAILED: wlsun.p/src_main.c.o 
cc -Iwlsun.p -I. -I.. -I/usr/include/libdrm -I/usr/include/pixman-1 -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -std=c11 -O0 -g -Wno-unused -DWLR_USE_UNSTABLE -DENABLE_DMABUF -MD -MQ wlsun.p/s
rc_main.c.o -MF wlsun.p/src_main.c.o.d -o wlsun.p/src_main.c.o -c ../src/main.c
../src/main.c:49:20: error: field ‘egl’ has incomplete type
   49 |     struct wlr_egl egl;
      |                    ^~~
../src/main.c: In function ‘frame_ready’:
../src/main.c:90:10: error: ‘struct wlr_dmabuf_attributes’ has no member named ‘flags’
   90 |         .flags = ctx->next_frame->flags,
      |          ^~~~~
../src/main.c:91:21: warning: initialized field overwritten [-Woverride-init]
   91 |         .modifier = ctx->next_frame->format_modifier,
      |                     ^~~
../src/main.c:91:21: note: (near initialization for ‘attribs.modifier’)
../src/main.c:99:5: error: unknown type name ‘EGLImageKHR’
   99 |     EGLImageKHR img = wlr_egl_create_image_from_dmabuf(&ctx->egl, &attribs);
      |     ^~~~~~~~~~~
../src/main.c:99:23: warning: implicit declaration of function ‘wlr_egl_create_image_from_dmabuf’ [-Wimplicit-function-declaration]
   99 |     EGLImageKHR img = wlr_egl_create_image_from_dmabuf(&ctx->egl, &attribs);
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.c:107:54: warning: passing argument 2 of ‘ctx->glEGLImageTargetTexture2DOES’ makes pointer from integer without a cast [-Wint-conversion]
  107 |     ctx->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img);
      |                                                      ^~~
      |                                                      |
      |                                                      int
../src/main.c:107:54: note: expected ‘GLeglImageOES’ {aka ‘void *’} but argument is of type ‘int’
../src/main.c: In function ‘init’:
../src/main.c:305:10: warning: implicit declaration of function ‘wlr_egl_init’; did you mean ‘wl_signal_init’? [-Wimplicit-function-declaration]
  305 |     if (!wlr_egl_init(&ctx->egl, EGL_PLATFORM_WAYLAND_EXT, ctx->display, NULL, WL_SHM_FORMAT_ARGB8888)) {
      |          ^~~~~~~~~~~~
      |          wl_signal_init
../src/main.c:305:34: error: ‘EGL_PLATFORM_WAYLAND_EXT’ undeclared (first use in this function)
  305 |     if (!wlr_egl_init(&ctx->egl, EGL_PLATFORM_WAYLAND_EXT, ctx->display, NULL, WL_SHM_FORMAT_ARGB8888)) {
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~
../src/main.c:305:34: note: each undeclared identifier is reported only once for each function it appears in
../src/main.c:315:52: warning: implicit declaration of function ‘eglGetProcAddress’ [-Wimplicit-function-declaration]
  315 |     *(void **)&ctx->glEGLImageTargetTexture2DOES = eglGetProcAddress("glEGLImageTargetTexture2DOES");
      |                                                    ^~~~~~~~~~~~~~~~~
../src/main.c:315:50: warning: assignment to ‘void *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
  315 |     *(void **)&ctx->glEGLImageTargetTexture2DOES = eglGetProcAddress("glEGLImageTargetTexture2DOES");
      |                                                  ^
ninja: build stopped: subcommand failed.

Am I doing something wrong, or the problem isn't on my side?


Regarding making a PR: that would be difficult task for me since I can barely read C code as well as have zero experience in graphic programming. Most likely I'll waste a lot of your time while achieving nothing. Sorry

@maximbaz
Copy link
Owner

../src/main.c:99:5: error: unknown type name ‘EGLImageKHR’

This one looks most severe in your case, from my limited understanding there are various extensions over OpenGL, and the code that I wrote back then relies on this one. Based on Dependencies section, you might be either missing EGL 1.2 or EGL client API, such as OpenGL ES or OpenVG...? It's probably possible to use some other API to achieve that same functionality, but I don't know how 😞

../src/main.c:90:10: error: ‘struct wlr_dmabuf_attributes’ has no member named ‘flags’

This is because wlroots 0.15 removed the flags attribute, because the code was written before that version, some migration is needed to the latest wlroots. The entire flags is just to be removed, as far as I understand the changelog.

../src/main.c:305:34: error: ‘EGL_PLATFORM_WAYLAND_EXT’ undeclared (first use in this function)

Hmm looks like another extension.

This all is a bit weird, as I thought because of these dependencies, your compilation step shouldn't even start, if meson will conclude that you are missing one of them (and maybe you can install some package and fix it)...

As you can probably sense I also have a very limited understanding of graphic programming and C 😅 But let's keep the issue open, maybe someone else would help us out here 😁

@I60R
Copy link
Author

I60R commented Nov 22, 2022

What's certain I have neither wlr-export-dmabuf-unstable-v1-client-protocol.h nor wlr-export-dmabuf-unstable-v1-client-protocol.xml installed on my system. I've tried wayland-protocols and wayland-protocols-git packages and none provides it. Maybe I should install it somehow and it will catch the rest?

@maximbaz
Copy link
Owner

That one is getting magically created out of protocols/ folder, see the protocols/meson.build. Also, if you rename the file name in #include in src/main.c, you'd get a completely different error, saying that the file cannot be included.

I just tried to fix the issues, but unfortunately it seems wlroots API is quite different nowadays. Not only .flags field is gone (that one is easy, just delete line 90), wlr_egl_init function was replaced with wlr_egl_create as some point (and even this one is now gone, I think), same for wlr_egl_create_image_from_dmabuf. I don't think I would be able to dig deeper into it, but if you want to proceed, I think the best place to get ideas / inspirations from would be https://gitlab.freedesktop.org/wlroots/wlroots/-/tree/master/examples, just trying to find good snippets of code that do the same thing as this project was doing back then...

@I60R
Copy link
Author

I60R commented Nov 24, 2022

So, I've added opengl.rs with a lot of todo!() alongside with vulkan.rs, created config option for it and made it all to compile. Have no idea how to proceed further, since OpenGL is really complicated and I have no idea what Vulkan code does as well as what original C code does 😄

I see that you imported the same wlr-export-dmabuf-unstable-v1-client-protocol in Rust code, and from my understanding it returns reference to frame which somehow should be imported by OpenGL. But no more than that.

Anyway, here's the fork with some routine work done (if someone want's to push this further).

@9SMTM6
Copy link

9SMTM6 commented May 30, 2023

I might be entirely missing the picture here, and it would probably be a big dependency, but have you considered wgpu?

Other than that name and some other things might suggest, wgpu can also be used entirely without browsers. Relevant for this project, it supports a few different backends, namely OpenGL ES (and also Metal for macOS), and it probably handles all the dependencies for you.

It compiles SPIR-V (which you probably compile to from vulcan shader code) or WGSL (not finalized shader language) to something any of these backends can use using gfx-rs/naga.

And AFAIK the WebGPU Interface, and how its set up, is mostly based on the way Vulcan does things.

Mind you, I never got into much experimenting, my experience is largely limited to OpenCL.

@maximbaz
Copy link
Owner

maximbaz commented Jun 2, 2023

This is a very interesting finding, thanks for sharing! I've never heard about it before.

If it can be used for the purposes of this project and give us few different backends out of the box, I don't mind it being a big dependency.

I don't think I'll have a chance to experiment with it in the near future, but if you or anyone else wants to give it a go, please do so, and post some updates here in this thread!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants