diff --git a/README.md b/README.md index f1dc805..fba34ce 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,70 @@ # lsfg-vk-flake -WIP! Nix flake to build the library for using Lossless Scaling's frame generation on Linux +Nix flake for using [Lossless Scaling's frame generation on Linux](https://github.com/PancakeTAS/lsfg-vk) -current state: builds and seems to be functional +>[!IMPORTANT] +> You need to have Lossless Scaling installed on Steam! +> In case it is not installed on the default Steam drive, you may want to consider setting the correct path in the lsfg-vk config. -## manual install -1. build the library with ``nix build`` -2. copy library and vulkan layer config to your ~/.local: ``cp -r result/* ~/.local/`` (check contents of result first!) -3. have lossless scaling installed on Steam or manually reference the DLL file using LSFG_DLL_PATH +## Installation +### System-wide (NixOS module) +This approach will install an implicit layer to ``/etc/vulkan/implicit_layer.d/`` -example usage command: ``LD_PRELOAD=~/.local/lib/liblsfg-vk.so LSFG_DLL_PATH=/Lossless.dll ENABLE_LSFG=1 vkcube`` +Add this to your flake inputs, output function and modules list: +```nix +inputs = { + ... + lsfg-vk-flake.url = "github:pabloaul/lsfg-vk-flake/main"; + lsfg-vk-flake.inputs.nixpkgs.follows = "nixpkgs"; +} + +outputs = {nixpkgs, lsfg-vk-flake, ...}: { + + nixosConfigurations.hostname = nixpkgs.lib.nixosSystem { + ... + modules = [ + ... + lsfg-vk-flake.nixosModules.default + ]; + }; +} +``` + +And then enable this in your system config: +```nix +services.lsfg-vk = { + enable = true; + ui.enable = true; # installs gui for configuring lsfg-vk +}; +``` + +### User install (manual) +1. Build the library: + ```bash + nix build + ``` +2. Create the following path in case it does not exist: + ```bash + mkdir -p $HOME/.local/share/vulkan/implicit_layer.d + ``` +3. Symlink the build results to your $HOME/.local/ + ```bash + cp -ifrsv "$(readlink -f ./result)"/* $HOME/.local/ + ``` + +## Usage +Run a Vulkan application with the environment variable ``ENABLE_LSFG=1`` set. + +Example: +```bash +ENABLE_LSFG=1 vkcube +``` + +To confirm that it is working, look for output like this in the terminal: lsfg-vk(...): ... + +You can also enable it per game on Steam by adding this to the launch options: +``` +ENABLE_LSFG=1 %COMMAND% +``` + +>[!NOTE] +> If the environment variable is set but the program doesn't show any lsfg-vk output, you may need to add the application to your lsfg-vk configuration file at `~/.config/lsfg-vk/config.toml`. Read more about it in the [Wiki](https://github.com/PancakeTAS/lsfg-vk/wiki/Configuring-lsfg-vk) \ No newline at end of file diff --git a/default.nix b/default.nix deleted file mode 100644 index a810806..0000000 --- a/default.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ lib -, fetchFromGitHub -, cmake -, ninja -, vulkan-headers -, vulkan-loader -, llvmPackages -, spirv-headers -}: let - -in llvmPackages.stdenv.mkDerivation { - pname = "lsfg-vk"; - version = "unstable-2025-07-13-f998647"; - - src = fetchFromGitHub { - owner = "PancakeTAS"; - repo = "lsfg-vk"; - rev = "f998647d74051467e39de9de2df2ff9a5996db5f"; - hash = "sha256-X708aKFz3wqSVYsMvCKsY7kqi+2LTewnoOMrXFPVEPY="; - fetchSubmodules = true; - }; - - cmakeFlags = [ - "-DCMAKE_BUILD_TYPE=Release" - ]; - - nativeBuildInputs = [ - # clang-tools needs to come before clang so it can locate Vulkan headers correctly - llvmPackages.clang-tools - llvmPackages.clang - llvmPackages.libllvm # needed for release builds - cmake - ninja - ]; - - buildInputs = [ - vulkan-headers - vulkan-loader - spirv-headers - ]; - - meta = with lib; { - homepage = "https://github.com/PancakeTAS/lsfg-vk/"; - license = licenses.mit; - platforms = platforms.linux; - }; -} diff --git a/flake.lock b/flake.lock index a63de06..83fcd4c 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1751792365, - "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", + "lastModified": 1756266583, + "narHash": "sha256-cr748nSmpfvnhqSXPiCfUPxRz2FJnvf/RjJGvFfaCsM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", + "rev": "8a6d5427d99ec71c64f0b93d45778c889005d9c2", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 7e14bb7..99e7737 100644 --- a/flake.nix +++ b/flake.nix @@ -1,10 +1,17 @@ { inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - outputs = { nixpkgs, ... }: let - system = "x86_64-linux"; - pkgs = import nixpkgs { inherit system; }; - in { - packages.${system}.default = pkgs.callPackage ./default.nix {}; + outputs = { nixpkgs, ... }: + let + forAllSystems = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ]; + in + { + packages = forAllSystems (system: { + default = nixpkgs.legacyPackages.${system}.callPackage ./lsfg-vk.nix { }; + lsfg-vk = nixpkgs.legacyPackages.${system}.callPackage ./lsfg-vk.nix { }; + lsfg-vk-ui = nixpkgs.legacyPackages.${system}.callPackage ./lsfg-vk-ui.nix { }; + }); + + nixosModules.default = import ./module.nix; }; } diff --git a/lsfg-vk-ui.nix b/lsfg-vk-ui.nix new file mode 100644 index 0000000..700eb7a --- /dev/null +++ b/lsfg-vk-ui.nix @@ -0,0 +1,54 @@ +{ + lib, + fetchFromGitHub, + rustPlatform, + pkg-config, + glib, + pango, + gdk-pixbuf, + gtk4, + libadwaita, +}: + +rustPlatform.buildRustPackage rec { + pname = "lsfg-vk-ui"; + version = "1.0.0"; + + src = fetchFromGitHub { + owner = "PancakeTAS"; + repo = "lsfg-vk"; + tag = "v${version}"; + hash = "sha256-nIyVOil/gHC+5a+sH3vMlcqVhixjJaGWqXbyoh2Nqyw="; + }; + + cargoHash = "sha256-hIQRS/egIDU5Vu/1KWHtpt4S26h+9GadVr+lBAG2LDg="; + + sourceRoot = "source/ui"; + + nativeBuildInputs = [ + pkg-config + glib + ]; + + buildInputs = [ + pango + gdk-pixbuf + gtk4 + libadwaita + ]; + + postInstall = '' + install -Dm444 $src/ui/rsc/gay.pancake.lsfg-vk-ui.desktop $out/share/applications/gay.pancake.lsfg-vk-ui.desktop + install -Dm444 $src/ui/rsc/icon.png $out/share/icons/hicolor/256x256/apps/gay.pancake.lsfg-vk-ui.png + ''; + + meta = { + description = "Graphical configuration interface for lsfg-vk"; + homepage = "https://github.com/PancakeTAS/lsfg-vk/"; + changelog = "https://github.com/PancakeTAS/lsfg-vk/releases/tag/${src.tag}"; + license = lib.licenses.mit; + platforms = lib.platforms.linux; + maintainers = with lib.maintainers; [ pabloaul ]; + mainProgram = "lsfg-vk-ui"; + }; +} \ No newline at end of file diff --git a/lsfg-vk.nix b/lsfg-vk.nix new file mode 100644 index 0000000..63e494c --- /dev/null +++ b/lsfg-vk.nix @@ -0,0 +1,44 @@ +{ + lib, + fetchFromGitHub, + cmake, + vulkan-headers, + llvmPackages, +}: + +llvmPackages.stdenv.mkDerivation rec { + pname = "lsfg-vk"; + version = "1.0.0"; + + src = fetchFromGitHub { + owner = "PancakeTAS"; + repo = "lsfg-vk"; + tag = "v${version}"; + hash = "sha256-hWpuPH7mKbeMaLaRUwtlkNLy4lOnJEe+yd54L7y2kV0="; + fetchSubmodules = true; + }; + + postPatch = '' + substituteInPlace VkLayer_LS_frame_generation.json \ + --replace-fail "liblsfg-vk.so" "$out/lib/liblsfg-vk.so" + ''; + + nativeBuildInputs = [ + llvmPackages.clang-tools + llvmPackages.libllvm + cmake + ]; + + buildInputs = [ + vulkan-headers + ]; + + meta = { + description = "Vulkan layer for frame generation (Requires owning Lossless Scaling)"; + homepage = "https://github.com/PancakeTAS/lsfg-vk/"; + changelog = "https://github.com/PancakeTAS/lsfg-vk/releases/tag/${src.tag}"; + license = lib.licenses.mit; + platforms = lib.platforms.linux; + maintainers = with lib.maintainers; [ pabloaul ]; + }; +} \ No newline at end of file diff --git a/module.nix b/module.nix new file mode 100644 index 0000000..f2fcaa6 --- /dev/null +++ b/module.nix @@ -0,0 +1,69 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.lsfg-vk; + lsfg-vk = pkgs.callPackage ./lsfg-vk.nix { }; + lsfg-vk-ui = pkgs.callPackage ./lsfg-vk-ui.nix { }; +in +{ + options = { + services.lsfg-vk = { + enable = lib.mkEnableOption "Lossless Scaling Frame Generation Vulkan layer"; + + ui.enable = lib.mkEnableOption "Enables a GUI for configuring lsfg-vk"; + + package = lib.mkOption { + type = lib.types.package; + description = "The lsfg-vk package to use"; + default = lsfg-vk; + }; + + losslessDLLFile = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + example = "/home/user/games/Lossless Scaling/Lossless.dll"; + description = '' + Sets the LSFG_DLL_PATH environment variable. + Required if Lossless Scaling isn't installed in a standard location + ''; + }; + + configFile = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + example = "/home/user/.config/lsfg-vk/conf.toml"; + description = '' + Sets the LSFG_CONFIG environment variable. + Required if the lsfg-vk configuration file isn't stored at the standard location + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable ( + lib.mkMerge [ + { + environment.systemPackages = [ cfg.package ]; + + # Installs the Vulkan implicit layer system-wide + environment.etc."vulkan/implicit_layer.d/VkLayer_LS_frame_generation.json".source = + "${cfg.package}/share/vulkan/implicit_layer.d/VkLayer_LS_frame_generation.json"; + } + (lib.mkIf cfg.ui.enable { + environment.systemPackages = [ lsfg-vk-ui ]; + }) + (lib.mkIf (cfg.losslessDLLFile != null) { + environment.sessionVariables.LSFG_DLL_PATH = + lib.warn "losslessDLLFile is deprecated and will only be used by lsfg-vk if LSFG_LEGACY is set." + cfg.losslessDLLFile; + }) + (lib.mkIf (cfg.configFile != null) { + environment.sessionVariables.LSFG_CONFIG = cfg.configFile; + }) + ] + ); +}