NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.39k stars 14.34k forks source link

Mesa-git #165636

Closed Ashe closed 2 years ago

Ashe commented 2 years ago

Project description I'd really like a package that mimics mesa-git from the AUR. It'd be nice if there was a package that was linked to the main branch of mesa.

Perhaps this is better suited for a flake, but I can't work that out myself :cry:. With gaming getting more popular and improvements/fixes always coming to bleeding edge first, it's a shame that there's no easy way to opt for bleeding-edge drivers too.

Metadata

jansol commented 2 years ago

Such a package would not work very well with the concept of nix(pkgs): nix always verifies the hash of sources it downloads for a build, meaning that in order to track a git branch the package would have to get updated every couple of hours, passing reviews and rebuilding dependent packages.

If you don't mind rebuilding half of your system locally (including but not limited to your web browser and your desktop environment as they depend on mesa directly), you can override the src attribute of the mesa package in an overlay or by getting a local checkout of nixpkgs, changing the mesa package there and telling nix to rebuild your system using the local checkout instead of the usual channel: sudo nixos-rebuild -I nixpkgs=/path/to/checkout boot.

And of course tracking main is not enough, the really spicy stuff is always in the merge requests... :wink: For those you can use fetchpatch to get the combined merge request patchset ("download as e-mail patches" in gitlab) straight into the patches list of the package.

Artturin commented 2 years ago

This shouldn't be in-tree instead it should be a flake with a github action that updates it

Ashe commented 2 years ago

Thank you for your quick reply and I apologise for the unreasonable request!

It sounds like there is in theory a way of doing it, but it also sounds like you've identified some real headaches. I wouldn't mind building the drivers, but building web browsers sounds extremely tedious and resource intensive.

I guess I didn't realise what I was asking for - I thought it was a case of just switching the source to master and building that, rather than it to be stable. Aside from building regularly (I'm okay doing that locally), I didn't think there'd be anything troublesome other than the occasional compiler bug in master.

It is a shame that the reasons nixos is so great to use is also one of the barriers to getting master as quickly as possible. It's not a massive loss, but I imagine these kinds of requests will be more and more common as people switch over from distros like arch and realise they are no longer as up to date as they used to be.

Thanks for the great reply! Perhaps this should be closed for the reasons you've stated.

Artturin commented 2 years ago

For autoupdating flakes / overlays see the following

https://github.com/colemickens/flake-firefox-nightly which is a flakes wrapper for https://github.com/mozilla/nixpkgs-mozilla/blob/master/firefox-overlay.nix

https://github.com/nix-community/nixpkgs-wayland

Artturin commented 2 years ago

Also see reviewing mesa changes here https://nixos.wiki/wiki/Nixpkgs/Reviewing_changes#Packages

jansol commented 2 years ago

I thought it was a case of just switching the source to master and building that

Well, essentially it is exactly that.

Just that because nix package builds are meant to be reproducible they necessarily ripply through the entire dependency chain, you'll have to rebuild all the dependent packages that you have installed, too. Depending on your set of installed packages and your system specs that can be a matter of 15 minutes or one of 3+ hours.

On the upside it all happens automatically so if you have a less fancy PC you can kick off the rebuild and go to sleep (or work/school if you don't need that PC for those) and assuming the builds all pass it'll be ready when you get back.

jansol commented 2 years ago

That said, graphics drivers are a bit messy and there already is a layer of indirection there that packages don't know about, i.e. /run/opengl-driver/ and the libglvnd and libvulkan1 ICD loaders that are responsible for choosing the actual driver that is used at runtime. I wonder how feasible it would be to manipulate the list of available ICDs while making it seem to other packages like nothing changed?

ReplayCoding commented 2 years ago

You can set the undocumented NixOS options hardware.opengl.package and package32 to the drivers output of the mesa derivation which will make applications load custom drivers. The dependency on mesa that applications have is just a loader for these drivers.

  hardware.opengl = {
    enable = true;
    package = pkgs.mesa-custom.drivers;
    package32 = pkgs.pkgsi686Linux.mesa-custom.drivers;
  };
jansol commented 2 years ago

For individual applications you can also use the __EGL_VENDOR_LIBRARY_FILENAMES and VK_ICD_FILENAMES environment variables for GL and Vulkan applications respectively. I'm not sure if that works with the steam bubblewrap sandbox though.

The way this solution works is do the nixpkgs checkout thing and instead of building your whole system from it, just build mesa: nix-build /path/to/checkout -A mesa.drivers and then launch your application with VK_ICD_FILENAMES=./result-drivers/share/vulkan/icd.d/radeon_icd.x86_64.json or __EGL_VENDOR_LIBRARY_FILENAMES=./result-drivers/share/glvnd/egl_vendor.d/50_mesa.json depending on whether it uses OpenGL or Vulkan (adjust paths depending on exact driver)

natto1784 commented 2 years ago

This is what I did for the vulkan layers specifically

  hardware = {
    opengl =
      let
        fn = oa: {
          nativeBuildInputs = oa.nativeBuildInputs ++ [ pkgs.glslang ];
          mesonFlags = oa.mesonFlags ++ [ "-Dvulkan-layers=device-select,overlay" ];
          patches = oa.patches ++ [ ./mesa-vulkan-layer-nvidia.patch ];
          postInstall = oa.postInstall + ''
              mv $out/lib/libVkLayer* $drivers/lib
              layer=VkLayer_MESA_device_select
              substituteInPlace $drivers/share/vulkan/implicit_layer.d/''${layer}.json \
                --replace "lib''${layer}" "$drivers/lib/lib''${layer}"
              layer=VkLayer_MESA_overlay
              substituteInPlace $drivers/share/vulkan/explicit_layer.d/''${layer}.json \
                --replace "lib''${layer}" "$drivers/lib/lib''${layer}"
            '';
        };
      in
      with pkgs; {
        driSupport32Bit = true;
        enable = true;
        package = (mesa.overrideAttrs fn).drivers;
        package32 = (pkgsi686Linux.mesa.overrideAttrs fn).drivers;
      };

The mesa-vulkan-layer-nvidia.patch isn't required usually, but my Nvidia drivers seem to be interfering with the vulkan priority order and I can't figure out how (probably an Nvidia proprietary vulkan layer), so I just use a patch where only a single (desired) device is passed to vulkan. Here is the patch in case someone wants it.

diff --color -u -r b/src/vulkan/device-select-layer/device_select_layer.c a/src/vulkan/device-select-layer/device_select_layer.c
--- b/src/vulkan/device-select-layer/device_select_layer.c  2022-03-22 11:18:04.309569433 +0530
+++ a/src/vulkan/device-select-layer/device_select_layer.c  2022-03-22 11:18:17.944644235 +0530
@@ -454,12 +454,8 @@
       exit(0);
    } else {
       unsigned selected_index = get_default_device(info, selection, physical_device_count, physical_devices);
-      selected_physical_device_count = physical_device_count;
+      selected_physical_device_count = 1;
       selected_physical_devices[0] = physical_devices[selected_index];
-      for (unsigned i = 0; i < physical_device_count - 1; ++i) {
-         unsigned  this_idx = i < selected_index ? i : i + 1;
-         selected_physical_devices[i + 1] = physical_devices[this_idx];
-      }
    }

    if (selected_physical_device_count == 0) {
Ashe commented 2 years ago

So this morning I cracked building mesa from source. I retrieve mesa-git from an input to my flake setup, and then I have this in configuration.nix:

    nixpkgs.config.packageOverrides = pkgs: {
      mesa = ((pkgs.mesa.override {
        driDrivers = [];
      }).overrideAttrs (attrs: {
        name = "mesa-git";
        src = mesa-git;
      }));
    };

As people theorised though, this results in trying to recompile things like my web browser. For the record I'm fine with compiling mesa drivers, that took 4 minutes. What I don't want to do is recompile entire programs (especially browsers). Whether I can find a way of simply replacing drivers in-place or not will dictate whether I continue this attempt or whether I just go back to the drivers in unstable.

I've tried to understand what has been discussed overnight but am I wrong in thinking that I'd need to VK_ICD_FILENAMES for every program? Or is this something I could just write in my config and all programs will see it?

Ashe commented 2 years ago

You can set the undocumented NixOS options hardware.opengl.package and package32 to the drivers output of the mesa derivation which will make applications load custom drivers. The dependency on mesa that applications have is just a loader for these drivers.

  hardware.opengl = {
    enable = true;
    package = pkgs.mesa-custom.drivers;
    package32 = pkgs.pkgsi686Linux.mesa-custom.drivers;
  };

Does this approach involve actually overriding mesa in packageOverrides / an overlay? Or are you suggesting we build mesa-git separately and simply point hardware.opengl.package / package32 to it?

I made a gist for my work-in-progress configuration, not quite sure which parts need to change in order to try and avoid building the web browser etc: https://gist.github.com/Ashe/c5b479ff9ddb491125cdcb7deb5036cc

jansol commented 2 years ago

VK_ICD_FILENAMES would have to be defined for every program you want to run with the newer driver, yes. You could set it in your .profile or environment.variables, but there can be situations where something indiscriminately clears its environment.

The hardware.opengl.package{, 32} solution involves either overriding the mesa package or defining a completely custom package in an overlay. The override can be done "in place" as shown in this comment so that is probably the "simplest" option here.

Ashe commented 2 years ago

The override can be done "in place" as shown in this comment so that is probably the "simplest" option here.

I tried this and updated my gist to show how I had a go at it. It compiled the drivers, but it still tried to recompile things like webkitgtk which I assume is my for my browser.

Some questions / notes:

Thank you for helping me so far, and I hope anyone else searching for the infamous mesa-git on nixos finds this thread useful.

Ashe commented 2 years ago

I finally got it working! This was what I ended up with:

{ pkgs, mesa-git, ... }:

{
  # Enable AMD GPU
  hardware.opengl =
  let 
    attrs = oa: {
      name = "mesa-git";
      src = mesa-git;
      nativeBuildInputs = oa.nativeBuildInputs ++ [ pkgs.glslang ];
      mesonFlags = oa.mesonFlags ++ [ "-Dvulkan-layers=device-select,overlay" ];
      postInstall = oa.postInstall + ''
        mv $out/lib/libVkLayer* $drivers/lib
        layer=VkLayer_MESA_device_select
        substituteInPlace $drivers/share/vulkan/implicit_layer.d/''${layer}.json \
          --replace "lib''${layer}" "$drivers/lib/lib''${layer}"
        layer=VkLayer_MESA_overlay
        substituteInPlace $drivers/share/vulkan/explicit_layer.d/''${layer}.json \
          --replace "lib''${layer}" "$drivers/lib/lib''${layer}"
      '';
    }; 
    ovrd = _: {
      driDrivers = [];
    };
  in with pkgs; {
    enable = true;
    driSupport = true;
    driSupport32Bit = true;
    package = ((mesa.override ovrd).overrideAttrs attrs).drivers;
    package32 = ((pkgsi686Linux.mesa.override ovrd).overrideAttrs attrs).drivers;
    extraPackages = with pkgs; [
      amdvlk
    ];
    extraPackages32 = with pkgs; [
      driversi686Linux.amdvlk
    ];
  };

  # Force RADV drivers
  environment.variables.AMD_VULKAN_ICD = "RADV";
}

Thank you everyone!

jansol commented 2 years ago

This thread should probably be distilled into a page on https://nixos.wiki

natto1784 commented 2 years ago

https://nixos.wiki/wiki/Mesa

SuperSamus commented 1 year ago

Overlays are now the only option: #223729.

beh-10257 commented 8 months ago

do you all have a working version now also what is mesa-git that is imported here { pkgs, mesa-git, ... }:

jansol commented 8 months ago

@beh-10257 nixpkgs now has mesa 24.0.2 and it is working perfectly fine for me. That mesa-git is a custom modification.

If you really, really have to build mesa from git, I suggest you clone nixpkgs locally, change the exact commit & hash there and rebuild your system from that. (note that this will cause a lot of rebuilds of other packages)

beh-10257 commented 8 months ago

@jansol I don't understand how is rebuilding my entire system suggested anyway I am trying to get into mesa development and well I am trying to test a merge request today https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28096 and well the developer is waiting for my response and I don't think my laptop has the power to rebuild everything

sidenote if mesa causes a lot of rebuilds what if I want to patch glibc is rebuilding everything really a solution I understand that nix is always about reproducibility but that will stop the developers of these core pkgs from ever giving a try to nix

SuperSamus commented 8 months ago

For mesa specifically, there's a Flake for using mesa-git without rebuilding anything else: https://github.com/chaotic-cx/nyx. It is very hacky though (note that there are two methods).

Still, I don't think that mesa has that many dependants? Like, if you make a test environment that has only the minimum required to test your thing (e.g. by using as compositor something like Gamescope or Sway), there shouldn't be many rebuilds.

beh-10257 commented 8 months ago

I can't use that since I already tried and overlaying it doesn't work since they are using mesa-mirror instad of actual mesa gitlab https://github.com/chaotic-cx/mesa-mirror I am trying to use this solution now and well its not working so far image

jansol commented 8 months ago

Still, I don't think that mesa has that many dependants? Like, if you make a test environment that has only the minimum required to test your thing

Ah, yea in that case it'll probably be fine. IIRC the biggest rebuild I normally run into is Plasma (and by dependency, Qt).