This depends. By default I believe only your iGPU will be used. But maybe it isn’t and that’s why playback isn’t working?
Anyway, let’s take a step back and look at what you have and might want. There are multiple things GPUs can be used for:
- Rendering intensive graphical workfloads, such as video games
- Accelerating certain types of computation
- Rendering your desktop
- Accelerating media playback
Your dGPU is good at the first two, and your iGPU is good at the last two, while using less energy (good for your battery life and/or environment) and being more stable (since the drivers are baked into the kernel). For this reason, the ideal setup is to use your iGPU for rendering your desktop and watching videos, and using your dGPU for rendering games and doing various compute things (e.g. blender and “AI workloads”, as most of those have algorithms that can be accelerated well using GPUs).
That said, you can choose to make either GPU do any of those things. My recommendation is to make your iGPU do most stuff, and only turn on your dGPU for games or compute, but since media acceleration isn’t working on your iGPU maybe you can try the nvidia alternative.
How do you make this work? Well, that also depends. Your hardware is positively ancient, and since nvidia has always had proprietary drivers (it has improved a bit lately, but that doesn’t affect GPUs from 2011), it’s quite possible that using the proprietary driver with your nvidia GPU simply will not work with modern kernels. nouveau is however also notorious for not being very good, both in terms of performance and battery use, since it doesn’t implement power scaling correctly, so using the nvidia GPU at all may simply not be worth it.
You’re also using wayland. Wayland fully supports multi-GPU management, but the specific implementation depends on your compositor. Plasma has some special default logic to choose a suitable GPU for rendering your desktop, but this logic can be quirky; it may well make a weird choice with some hardware. I don’t use Plasma, so I don’t know how to ask it for its default choice.
So, there are a couple of different setups to try. Firstly, you’ll need to figure out which nvidia driver version actually supports your graphics card. From your neofetch output I can’t tell which GPU you actually have; it’s either the 470 or the 390 driver, but who knows. There might be a hardware sticker somewhere telling you the actual name.
Additionally, you’ll need to figure out the bus IDs of both of your GPUs. See the offload option for instructions on how to get the ID, then look for those IDs in /dri/by-path/pci and note down the path for your nvidia and intel GPUs.
From there, we can go and start filling in the options for using your GPUs. Since we’re going to be mucking with what makes your computer show anything at all, remember that you can switch to an old generation if you hold space during boot, just in case stuff breaks.
I’d recommend doing this in a separate file, so create a new file called /etc/nixos/graphics.nix, and import it in /etc/nixos/configuration.nix (and make sure to remove any former graphics configuration from configuration.nix):
# configuration.nix
{ pkgs, lib, ... }: {
imports = [
./graphics.nix
];
# Rest of your configuration here
}
Let’s first try if the nvidia GPU works at all, and try to render the desktop with it:
# graphics.nix
{ config, ... }: let
# Put your real IDs here; these should not be the same in practice
gpuBusId = {
intelBusId = "PCI:0:2:0";
nvidiaBusId = "PCI:1:0:0";
};
gpuPaths = let
pciPath =
xorgBusId:
let
components = lib.drop 1 (lib.splitString ":" xorgBusId);
toHex = i: lib.toLower (lib.toHexString (lib.toInt i));
domain = "0000"; # Apparently the domain is always set to 0000
bus = lib.fixedWidthString 2 "0" (toHex (builtins.elemAt components 0));
device = lib.fixedWidthString 2 "0" (toHex (builtins.elemAt components 1));
function = toHex (builtins.elemAt components 2);
in
"dri/by-path/pci-${domain}:${bus}:${device}.${function}-card";
in {
intel = pciPath gpuBusId.intelBusId;
nvidia = pciPath gpuBusId.nvidiaBusId;
};
in {
services.xserver.videoDrivers = [ "nvidia" ];
hardware = {
nvidia = {
# Depending on which GPU you actually have
package = config.boot.kernelPackages.nvidiaPackages.legacy_470;
# package = config.boot.kernelPackages.nvidiaPackages.legacy_390;
videoAcceleration = false;
};
graphics = {
enable = true;
extraPackages = [
pkgs.intel-vaapi-driver
];
};
};
# Note that this is using `.variables` not `.sessionVariables` now;
# Double check that this is still set correctly when you start your terminal
environment.variables = {
LIBVA_DRIVER_NAME = "i965";
KWIN_DRM_DEVICES = gpuPaths.nvidia;
};
}
If you build this config (use nixos-rebuild boot and reboot, not nixos-rebuild switch) and reboot, and everything continues to work, congratulations, you can use your nvidia GPU!
If not, well, that’s not surprising, I’ve seen many people try to revive old nvidia GPUs and fail.
If it does work, we can go a step further and try to use the iGPU as the desktop driver, and only offload intense rendering to the dGPU. How you do that depends on the driver version. If you have a GPU that is supported by the 470 driver, you can use prime offload. For that, we configure the system like so:
# graphics.nix
{ config, ... }: let
# Put your real IDs here; these should not be the same in practice
gpuBusId = {
intelBusId = "PCI:0:2:0";
nvidiaBusId = "PCI:1:0:0";
};
gpuPaths = let
pciPath =
xorgBusId:
let
components = lib.drop 1 (lib.splitString ":" xorgBusId);
toHex = i: lib.toLower (lib.toHexString (lib.toInt i));
domain = "0000"; # Apparently the domain is always set to 0000
bus = lib.fixedWidthString 2 "0" (toHex (builtins.elemAt components 0));
device = lib.fixedWidthString 2 "0" (toHex (builtins.elemAt components 1));
function = toHex (builtins.elemAt components 2);
in
"dri/by-path/pci-${domain}:${bus}:${device}.${function}-card";
in {
intel = pciPath gpuBusId.intelBusId;
nvidia = pciPath gpuBusId.nvidiaBusId;
};
in {
services.xserver.videoDrivers = [ "nvidia" ];
hardware = {
nvidia = {
package = config.boot.kernelPackages.nvidiaPackages.legacy_470;
videoAcceleration = false;
prime = {
inherit (gpuBusId) intelBusId nvidiaBusId;
offload = {
enable = true;
enableOffloadCommand = true;
};
};
};
graphics = {
enable = true;
extraPackages = [
pkgs.intel-vaapi-driver
];
};
};
environment.variables = {
LIBVA_DRIVER_NAME = "i965";
KWIN_DRM_DEVICES = "${gpuPaths.intel}:${gpuPaths.nvidia}";
};
}
Again, rebuild and reboot, see if your computer still works. If you get to your desktop, you will now be rendering using the intel GPU; to test that the nvidia GPU is still working, you will have to use the offload command to explicitly make something start with nvidia.
Say, for example, your web browser:
$ nvidia-offload firefox
You can then use the nvidia-smi command to confirm that firefox is in fact rendering on your GPU.
If this works, congratulations! We can further dig into the details of media acceleration once you get here. There are also other things you will likely want to configure, such as “finegrained” power management and KMS - these are enabled by default on newer drivers, but not on these old drivers. They may even be required to get wayland to run, so I’m not holding my breath for the first attempt being successful.
If your GPU only supports the 390 driver, well, I have to admit I don’t really know how to do that. I don’t have the hardware to test this scenario. The nvidia docs might help: Chapter 17. Using the NVIDIA Driver with Optimus Laptops
… given the length of this post, and that we’re not even halfway to a fully featured setup, you may realize that using nvidia on Linux is a FREAKING MESS. Good luck!