Drakulix / nvscreencopy

A userspace utility to mirror outputs on wayland to nvidia gpus
MIT License
7 stars 0 forks source link

nvscreencopy

Although the situation has improved with the 470 driver on linux, nvidia gpus and wayland compositors on linux still remain in a poor state.

Especially if you are not using the larger compositors included in desktop-environments like GNOME or KDE.

A rather popular choice of a framework for smaller compositors has been wlroots, which is not supporting proprietary drivers, and especially not the nvidia driver due to the only api supported being the rather uncommon eglstream api.

Users of nvidia-gpus on desktop machines can instead rely on the wlroots-eglstream fork of @danvd.

Laptop users however often struggle as this port does not include support for multi-gpu setups, like commonly found in optimus laptops.

While you can run normal wlroots on the internal gpu be limiting the drm-devices used using the WLR_DRM_DEVICES environment variable (and special cmd arguments like the famous --my-next-gpu-wont-be-nvidia flag for sway), you cannot fully utilize your nvidia gpu this way.

You can use the gpu for rendering through e.g. primus_vk (even without relying on X11) and you can of course use it's cuda capabilities, but notably you cannot utilize external monitors, if your machine does not provide any ports, that are hooked up to your internal gpu.

An alternative for this use-case is using the nouveau driver, which is supported by wlroots-based compositors, but then you loose the performance and cuda capabilities of your card. Forcing you to switch drivers for either of these use-cases.

nvscreencopy aims to fix this by allowing you to clone outputs on your internal gpu to your nvidia gpu. On compositors supporting headless outputs (notable sway through its create_output ipc command), this even allows you to extend your workspace.

How does this work

nvscreencopy is basically primus_vk but backwards.

  1. It receives an output image through the export-dmabuf protocol.
  2. (tries to import the dmabuf into the nvidia driver, but even with 470 this still fails)
  3. falls back to doing a cpu copy, by
    1. reading out the image into main memory
    2. uploading the image to the nvidia gpu
  4. rendering the image via the eglstream protocol

Because nvscreencopy is the only process requesting kms capabilities of the nvidia gpu this works without any additional permission.

How do I use this

Make sure the nvidia driver is loaded with modeset support: sudo modprobe nvidia-drm modeset=1 (To set this up automatically refer to your distributions documentation.)

$ ./nvscreencopy --help

nvscreencopy 0.1
Drakulix <nvscreencopy@drakulix.de>
Implements screen mirroring to nvidia gpus using the wayland export-dmabuf protocol

USAGE:
    nvscreencopy [OPTIONS] [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -c, --connector <NAME>    Connector to clone onto. By default takes the first connected one it finds
    -m, --mode <MODE>         Sets the outputs mode, by default it mirrors the mode of the source. Use this if they are
                              incompatible, the result will be streched. Format "WIDTHxHEIGHT"
    -s, --source <SRC>        Sets the monitor to copy from, checks by comparing the monitor make to contain the given
                              value. Default is "headless".

SUBCOMMANDS:
    help               Prints this message or the help of the given subcommand(s)
    list-connectors    lists available sources
    list-sources       lists available sources

How do I build this

nvscreencopy is written in Rust and uses smithay - which is a compositor framework on its own - to facilitate the copy.

That means for building you need rustc installed.

You will also need development packages of the following libraries for building:

Then run cargo build --release in this directory.

Known limitations

Can this also be used to proxy applications?

I have issues / this does not run very well