refactor(cleanup): add docs to main repository

This commit is contained in:
PancakeTAS 2025-12-25 03:49:18 +01:00
parent f3019dd714
commit 2a13914b55
6 changed files with 370 additions and 12 deletions

View file

@ -6,9 +6,11 @@
>[!CAUTION]
>You are reading the README for the upcoming version 2.0 of lsfg-vk. For the stable version 1.x, [please read here](https://github.com/PancakeTAS/lsfg-vk/tree/ff1a0f72a7d6d08b84d58b7b4dc5f05c9f904f98)
More information, as well as how to build from source, can be found on the [wiki](https://pancake.gay/lsfg-vk/).
## Installation
>[!INFO]
> If you are on a Steam Deck or similar handheld, consider using the [Decky plugin for lsfg-vk](https://github.com/xXJSONDeruloXx/decky-lsfg-vk). This is an easy way to install and configure lsfg-vk on the Steam Deck.
> Please keep in mind that it is not officially supported and support questions should be directed to the plugin's repository & discord.
1. Before proceeding, please make sure you have [Lossless Scaling](https://store.steampowered.com/app/993090/Lossless_Scaling/) downloaded on Steam.
2. Head to the [GitHub Releases](https://github.com/PancakeTAS/lsfg-vk/releases) and download the file named "lsfg-vk-2.0.0-x86_64.tar.xz".
3. Open a terminal in the folder where you downloaded the file and run the following:
@ -24,7 +26,7 @@ sudo pacman -S qt6-declarative qt6-base # On Arch-based systems
sudo dnf install qt6-qtdeclarative qt6-qtbase # On Fedora
```
5. (Optional) If you wish to use lsfg-vk within Flatpak applications, see the [Flatpak Setup Guide](https://pancake.gay/lsfg-vk/#/flatpak).
5. (Optional) If you wish to use lsfg-vk within Flatpak applications, see the [Flatpak Guide](docs/Flatpak-Guide.md).
## Usage
In order to start using lsfg-vk, you will need to configure it. This can either be done using the GUI application, or manually.
@ -36,7 +38,7 @@ Start 'lsfg-vk Configuration Window' from your application launcher, or run `~/.
- Should Lossless Scaling be installed in a non-standard location, you can specify the path here.
- Select a profile and configure the "Profile Settings" section to your liking.
- When editing the "Active In" list, you can add a game using its executable name (e.g. `Game.exe`, `mpv`).
- Please see the [wiki](https://pancake.gay/lsfg-vk/#/configure) for detailed information on each setting.
- Please see the [documentation](docs/Configuration.md) for detailed information on each setting.
- Once you are done configuring, simply starting a game that matches one of the profiles will automatically apply the settings.
### Manual Configuration
@ -44,7 +46,7 @@ The default configuration is located in `~/.config/lsfg-vk/conf.toml`. It will b
- In the `[global]` section, you can change where Lossless Scaling is installed, as well as other global settings.
- Each profile is defined in its own `[[profile]]` section.
- The `active_in` array/string defines which applications the profile is active in. You can add applications using their executable name (e.g. `Game.exe`, `mpv`).
- Please see the [wiki](https://pancake.gay/lsfg-vk/#/configure) for detailed information on each setting.
- Please see the [documentation](docs/Configuration.md) for detailed information on each setting.
- Once you are done configuring, simply starting a game that matches one of the profiles will automatically apply the settings.
You can validate the configuration using `lsfg-vk-cli`:
@ -52,12 +54,6 @@ You can validate the configuration using `lsfg-vk-cli`:
~/.local/bin/lsfg-vk-cli validate
```
### Environment Variables
Certain environment variables can be used to modify the behavior of lsfg-vk:
- `LSFGVK_CONFIG`: Specify a custom path to the configuration file.
- `LSFGVK_PROFILE`: Choose a specific profile to use by name, overriding the automatic selection.
- `LSFGVK_ENV`: Configure the profile based on environment variables. Please see the [wiki](https://pancake.gay/lsfg-vk/#/configure) for more information.
### Benchmarking Mode
You can run a frame generation benchmark using `lsfg-vk-cli`:
```bash
@ -67,4 +63,4 @@ You can run a frame generation benchmark using `lsfg-vk-cli`:
By default, the benchmark will run for 10 seconds. Add `-h` to see all available benchmarking options.
## Support and Troubleshooting
If you encounter any issues or have questions regarding lsfg-vk, read through the [Troubleshooting](https://pancake.gay/lsfg-vk/#/troubleshooting) page on the wiki or join the [Discord server](https://discord.gg/losslessscaling) for assistance.
If you encounter any issues or have questions regarding lsfg-vk, read through the [Troubleshooting](docs/Troubleshooting.md) documentation page or join the [Discord server](https://discord.gg/losslessscaling) for assistance.

View file

@ -0,0 +1,99 @@
# Building lsfg-vk from Source
This guide provides step-by-step instructions on how to build the lsfg-vk project from source code.
>[!IMPORTANT]
>If you are planning on compiling lsfg-vk on a Steam Deck, you need to disable the read-only protection and reinstall certain system packages first:
> ```bash
> sudo steamos-readonly disable
> sudo pacman-key --init
> sudo pacman-key --populate
> sudo pacman -Syy
> sudo pacman -S linux-headers linux-api-headers glibc
### Prerequisites
Before you begin, ensure you have the required packages installed on your system.
You will need the following dependencies:
- Typical build tools, such as `git`, `curl`, etc.
- A C++ compiler that supports C++20 or later
- CMake (version 3.10 or higher)
- Ninja build system (other build systems may work, but Ninja is recommended)
- Vulkan SDK
- Qt6 and Qt6Quick (only needed when building lsfg-vk-ui)
The list of required packages may vary depending on your operating system. Below are the installation commands for some common Linux distributions.
```bash
# On Debian/Ubuntu, use:
sudo apt-get install -y \
git curl \
llvm clang clang-tools clang-tidy \
cmake ninja-build pkg-config \
libvulkan-dev \
mesa-common-dev \
qt6-base-dev qt6-base-dev-tools \
qt6-tools-dev qt6-tools-dev-tools \
qt6-declarative-dev qt6-declarative-dev-tools
# On Arch Linux, use:
sudo pacman -S --needed \
git curl \
llvm clang \
cmake ninja \
vulkan-headers vulkan-icd-loader \
qt6-base qt6-declarative
```
### Building & Installing lsfg-vk
1. **Clone the Repository**
Clone the lsfg-vk repository from GitHub:
```bash
git clone https://github.com/PancakeTAS/lsfg-vk.git
cd lsfg-vk
```
Optionally, you can checkout a specific release tag:
```bash
git checkout tags/vX.Y.Z
```
2. **Configure the build with CMake**
The recommended way to configure lsfg-vk is this:
```bash
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_CXX_COMPILER=clang++ \
-DLSFGVK_BUILD_UI=On \
-DLSFGVK_INSTALL_XDG_FILES=On
```
However, lsfg-vk provides several CMake options to customize the build process:
- `CMAKE_BUILD_TYPE`: Set to `Release` for optimized builds or `Debug` for debugging builds.
- `CMAKE_INSTALL_PREFIX`: Specify the installation directory (default is `/usr/local`).
- `LSFGVK_BUILD_VK_LAYER`: Set to `On` to build the Vulkan layer (default is `On`).
- `LSFGVK_BUILD_UI`: Set to `On` to build the user interface (default is `Off`).
- `LSFGVK_BUILD_CLI`: Set to `On` to build the command-line interface (default is `On`).
- `LSFGVK_INSTALL_DEVELOP`: Set to `On` to install development files like headers and libraries (default is `Off`).
- `LSFGVK_INSTALL_XDG_FILES`: Set to `On` to install XDG desktop files and icons (default is `Off`).
- `LSFGVK_LAYER_LIBRARY_PATH`: Override the path to the Vulkan layer library (by default, Vulkan will search the systems library path).
Please keep in mind that installing to non-system paths will require `LSFGVK_LAYER_LIBRARY_PATH` to be set accordingly (e.g. `../../../lib/liblsfg-vk-layer.so`).
3. **Build the Project**
Build the project using Ninja:
```bash
cmake --build build
```
4. **Install the Project**
Install the built files to the specified installation prefix:
```bash
sudo cmake --install build
```
Keep track of the installed files, in order to uninstall them later if needed.

54
docs/Configuration.md Normal file
View file

@ -0,0 +1,54 @@
# Configuration Options
Configuring lsfg-vk is done either through **lsfg-vk-ui** (graphical interface) or by manually editing the configuration file located at `~/.config/lsfg-vk/conf.toml`.
Regardless of the method you choose, the concept of profiles remains the same.
- **Profiles**: Profiles allow you to create different sets of configurations for different applications or use cases. A profile can automatically be selected through the "active_in" property.
- **Profile Settings**: Settings related to a profile are stored under the "Profile Settings" or `[[profile]]` section.
- **Global Settings**: Any settings in the "Global Settings" or `[global]` section apply to all profiles.
### All Configuration Options
Below is a list of all available **global** configuration options:
- **Path to Lossless Scaling / `dll`**: By default, lsfg-vk will search certain directories for Lossless Scaling. If you have Lossless Scaling installed in a custom location, you can specify the full path to the "Lossless.dll" file inside of Lossless Scaling here.
- **Allow half-precision / `allow_fp16`**: If enabled, this will allow lsfg-vk to take advantage of half-precision shader operations if supported by the GPU. This has a giant performance uplift on AMD GPUs, but does not affect NVIDIA GPUs (GTX 1000-series or older cards will actually see a big performance **decrease**). This option **does not** influence quality. (Default: `true`)
Next is a list of all available **profile** configuration options:
- **Profile Name / `name`**: The name of the profile, displayed in **lsfg-vk-ui**. Additionally, this is used when selecting a profile through the `LSFGVK_PROFILE` environment variable.
- **Active In / `active_in`**: A list of 1) linux binary names, such as `mpv`, 2) windows executables, such as `GenshinImpact.exe` and 3) process names, such as `GameThread`. It is also possible to specify the last part of a path (e.g. `Ghostrunner2/Binaries/Win64/Ghostrunner2-Win64-Shipping.exe`). When a process matching one of these rules is detected, this profile will be activated.
- **Multiplier / `multiplier`**: The frame generation multiplier. A value of 3 means that for every frame rendered by the application, lsfg-vk will generate 2 additional frames. (Default: `2`)
- **Flow Scale / `flow_scale`**: The resolution scale at which the motion vectors are calculated. A lower value means better performance, but worse quality. (Default: `1.0`)
- **Performance Mode / `performance_mode`**: When enabled, a significantly lighter frame generation model is used. This has a minor quality impact, but greatly improves performance.
(Default: `false`)
- **Pacing Mode / `pacing`**: This option is explained in greater detail below. Supported values are **None / `none`**.
- **GPU / `gpu`**: The GPU to use for frame generation. This MUST be the **same GPU** as the one being used by the application. **Dual GPU is NOT supported**. You can identify a GPU through its name (e.g. `NVIDIA GeForce RTX 3080`), uppercase-only ID (e.g. `0x10DE:0x2C02`) or PCI bus ID (e.g. `3:0.0`). If not specified, the primary GPU will be used, which may lead to issues.
The "Multiplier", "Flow Scale" and "Performance Mode" options can be **hot-reloaded**, meaning that changes to these options will take effect immediately without needing to restart the application. Options such as "Pacing Mode" or removal of the profile require a swapchain recreation, which usually means resizing or restarting the application. Any other change requires an application restart.
### Pacing Modes
**Pacing modes** determine how lsfg-vk synchronizes frame generation with the application's frame rate.
Traditionally, lsfg-vk did not have frame pacing and would present frames to the screen as soon as they are generated. This approach is flawed, because frames are generated and presented much quicker than your screen refreshes, causing frames to be skipped. This effect is countered by force-enabling V-Sync, as the compositor will then wait for the next screen update, before presenting the next frame.
Enabling V-Sync is not a "get-out-of-jail-free" card, because it introduces input latency. Additionally, not every compositor (such as gamescope) respects the V-Sync setting, leading to the same issues as before. As a result of this, additional pacing modes have been introduced to properly handle frame pacing.
Here are all available pacing modes:
- `none`: Traditional lsfg-vk behavior. Forces V-Sync. Might require workarounds on some compositors.
- *... there are no other pacing modes yet ...*
### Environment Variables
The following environment variables affect lsfg-vk:
- `DISABLE_LSFGVK`: If set, lsfg-vk will be completely disabled.
- `LSFGVK_CONFIG`: Path to the configuration file.
- `LSFGVK_PROFILE`: Name of the profile to use. If set, this will override automatic profile detection.
If you do not wish to use a configuration file, you can also set configuration options through environment variables. To do this, set `LSFGVK_ENV=1` and then any of the following variables:
- `LSFGVK_DLL_PATH`: Path to Lossless Scaling DLL.
- `LSFGVK_NO_FP16`: If set to `1`, half-precision will be disabled.
- `LSFGVK_MULTIPLIER`: Frame generation multiplier.
- `LSFGVK_FLOW_SCALE`: Flow scale value.
- `LSFGVK_PERFORMANCE_MODE`: If set to `1`, performance mode will be enabled.
- `LSFGVK_PACING`: Pacing mode to use.
- `LSFGVK_GPU`: GPU to use for frame generation.

63
docs/Flatpak-Guide.md Normal file
View file

@ -0,0 +1,63 @@
# Flatpak Guide
If you want to use **lsfg-vk** with Flatpak applications, you must install the Vulkan layer for Flatpak. You can also optionally install the graphical configuration editor **lsfg-vk-ui** as a Flatpak application.
## Installation
You can install lsfg-vk for Flatpak through three different methods.
### Through Flathub
The main lsfg-vk layer is available on Flathub and can be installed with the following commands (you can omit the `--user` in a system installation):
```bash
flatpak install --user org.freedesktop.Platform.VulkanLayer.lsfgvk//24.08
flatpak install --user org.freedesktop.Platform.VulkanLayer.lsfgvk//25.08
```
If you require an older runtime (23.08), you must install it manually as shown in the next section. Similarly, if you want to install the graphical configuration editor **lsfg-vk-ui**, you must also install it manually.
### Through GitHub Releases
Head over to the [GitHub Releases](https://github.com/PancakeTAS/lsfg-vk/releases) page and download the Flatpak files for the Vulkan layer and/or the graphical configuration editor.
It can be installed with the following commands (you can omit the `--user` in a system installation):
```bash
tar -xf lsfg-vk-2.0.0-flatpaks-x86_64.tar.xz
flatpak --user install ./org.freedesktop.Platform.VulkanLayer.lsfg-vk-23.08.flatpak
flatpak --user install ./org.freedesktop.Platform.VulkanLayer.lsfg-vk-24.08.flatpak
flatpak --user install ./org.freedesktop.Platform.VulkanLayer.lsfg-vk-25.08.flatpak
flatpak --user install ./gay.pancake.lsfg-vk-ui.flatpak
```
You can then run the graphical configuration editor with:
```bash
flatpak run gay.pancake.lsfg_vk_ui
```
### Through Custom Build
If you want to build lsfg-vk yourself, install `flatpak-builder` and run the following commands:
```bash
git clone --depth=1 https://github.com/PancakeTAS/lsfg-vk.git
# optional: git checkout <desired-version>
cd lsfg-vk
flatpak-builder --force-clean --user --install-deps-from=flathub --install flatpak-build \
dist/flatpak/lsfg-vk-ui/gay.pancake.lsfg-vk-ui.yml
flatpak-builder --force-clean --user --install-deps-from=flathub --install flatpak-build \
dist/flatpak/lsfg-vk-layer/org.freedesktop.Platform.VulkanLayer.lsfgvk_23.08.yml
flatpak-builder --force-clean --user --install-deps-from=flathub --install flatpak-build \
dist/flatpak/lsfg-vk-layer/org.freedesktop.Platform.VulkanLayer.lsfgvk_24.08.yml
flatpak-builder --force-clean --user --install-deps-from=flathub --install flatpak-build \
dist/flatpak/lsfg-vk-layer/org.freedesktop.Platform.VulkanLayer.lsfgvk_25.08.yml
```
## Configuration
Before using lsfg-vk with Flatpak applications, you need to give them access to the configuration directory, as well as Lossless Scaling.
```bash
export appid= # e.g. io.mpv.Mpv
mkdir -p ~/.config/lsfg-vk
flatpak override --user --filesystem=/home/$USER/.config/lsfg-vk:rw $appid
flatpak override --user --filesystem=/home/$USER/local/share/Steam/steamapps/common:ro $appid
flatpak override --user --env=LSFGVK_CONFIG=/home/$USER/.config/lsfg-vk/conf.toml $appid
```

101
docs/Journey.md Normal file
View file

@ -0,0 +1,101 @@
# The Journey of lsfg-vk
Welcome to the journey of lsfg-vk, this is where I, the developer, PancakeTAS, share interesting stories about the development process and the challenges faced along the way.
---
## Porting LSFG to native Vulkan (Jul 6, 2025)
This document details the process of getting LSFG to work in a native Vulkan environment. It is not a guide. It is not a tutorial for doing this yourself. It simply describes the psychological torture I went through to make this project work
### Figuring out how LSFG works
The first thing I did was open Lossless Scaling in dnSpy, which quickly revealed that all the magic was in Lossless.dll file.\
Then I opened up Lossless.dll in IDA... and quickly found out that this is a D3D11 program.
I closed dnSpy and IDA. What this teaches you is that throwing IDA at something is not always the right move.
### Getting D3D11 to run on Linux
_"The first step to translating D3D11 to Vulkan, is to not translate D3D11 to Vulkan. Instead, it is to translate D3D11 to D3D11, and then to Vulkan."_ - Me (after not sleeping for 2 days)
It's true!
When you're trying to translate something that utilizes the GPU, it often comes in multiple parts:\
The **shaders** that run on the actual GPU and the **pipeline** used to coordinate the shaders
Like I said, I didn't translate D3D11 to Vulkan just yet. Instead I used what the Steam Deck, Proton, and native Linux titles from Valve use: DXVK.
DXVK is a project that pretends to be D3D11 and provides just enough methods to run most if not all Windows games written in D3D8 through D3D11 on Linux. It can also be used natively without proton/wine! And that's what I did.
#### Step 1: The shaders
The first step to translating everything to D3D11 was to get the shaders to work.
Vulkan uses SPIR-V and D3D11 uses DXBC. Thankfully DXVK can translate the shaders just fine.
I wrote a hook for Lossless Scaling that intercepted all D3D11 calls and dumped the shader files to my computer. Then I took those shader files and copied them over to Linux. I wrote a really small D3D11 app that loaded one shader, loaded a texture that I dumped into it, and dumped the outputs. Voila, WinMerge tells me the files are identical!
I did this to a few other shaders until I moved on to actually translating the pipeline.
#### Step 2: The pipeline
Translating the shader pipeline is the fun part of all of this. Attaching RenderDoc to LS on Windows is near impossible because it isn't a game by itself. Current RenderDoc simply does not detect anything and older versions crash immediately. NVIDIA Nsight Graphics also crashed when taking a capture.
The solution is a mix of IDA to get the dispatch math, self written C++ programs to dump the D3D11 commands, and a heck ton of WinMerge to compare my shader pipeline with the original.
Step by step I rewrote the shader pipeline in D3D11, just like Valve did with Portal 2, until I was done.
This process took a huuuge amount of time and there were many barricades in the way like when stuff just wouldn't work for no reason.
### Translating D3D11 to Vulkan
Having a working pipeline on Linux now means I can attach RenderDoc and get the exact Vulkan calls in a neatly organized manner.
This was my first time writing something in Vulkan, so I had to do quite a bit of research on Vulkan and read quite a bit of it. Originally my plan was to keep the DXVK pipeline and simply use Vulkan to hook the game. This plan was cut short however, because D3D11 does not have any synchronization primitives and Vulkan exclusively works with synchronization primitives. Since that didn't work, I had to translate the entire pipeline to Vulkan.
This process was fairly smooth and I did it in 27 hours. Twenty seven.. consecutive.. hours.. with no sleep.
_"Sometimes, no sleep is all you ne-"_ Okay I'm gonna stop with these stupid quotes, lol.
And there we have it, the Vulkan pipeline is completed. What follows is a bit of PE parsing to extract shaders from the exe at runtime, so that not everyone using the project needs to go through my painful process. And also a statically linked subset of DXVK is now used to translate the shaders without actually using DXVK.
### Credits
Huge thanks to [0xNULLderef](https://github.com/0xNULLderef) who sat through this with me. They were the first to suggest native DXVK and taught me how to use IDA and RenderDoc. This project would not have worked without them!
This document details the process of injecting frames into a Vulkan app. It describes the mechanism currently in use in lsfg-vk. This is not a guide, nor a tutorial. This is a technical document explaining what I did and how it works.
---
## Injecting into a Vulkan app (Jul 6, 2025)
This document details the process of injecting frames into a Vulkan app. It describes the mechanism currently in use in lsfg-vk. This is not a guide, nor a tutorial. This is a technical document explaining what I did and how it works.
### Injecting into a Vulkan app
There's plenty of ways to hook into a Vulkan app. At first this project used an `LD_PRELOAD` approach, where `dlopen`, `dlsym` and `dlclose` were hooked and replaced the Vulkan loader with it's own modded version.
Towards completion of the process I realized there was a better way to do this and seeing how it would fix a lot of issues I decided to implement it.
Enter: Vulkan layers.
When you link against Vulkan, statically or dynamically it does not matter, you're not linking against the actual library, but a loader. This Vulkan loader provides you with two functions called `vkDeviceGetProcAddr` and `vkInstanceGetProcAddr`. Calling these functions returns function pointers for each function requested.
This approach allows the Vulkan loader to return function pointers not to the actual driver, but an intermediate function. These intermediary functions are called layers and Vulkan stacks as many as you want ontop of each other.
lsfg-vk uses an implicit layer, which means it is implicitly enabled simply by existing in one of the many Vulkan layer folders, or by having an environment variable set. In our case, it loads when `ENABLE_LSFG` is set to 1.
### Hooking various functions
Each layer has its own `vkIntanceGetProcAddr` (and corresponding device-level) function. By default this function simply calls the _next_ layer's `vkInstanceGetProcAddr` function. If you wish to actually override a method, you simply store the next layer's function pointer and return your own method, which then eventually calls the next layer.
In order for us to inject frames into Vulkan apps, we need to add a few extensions to the Vulkan instance and each Vulkan device, as well as monitor created swapchains. We override `vkCreate{Instance,Device,SwapchainKHR}` as well as `vkDestroy{Instance,Device,SwapchainKHR}` and modify the creation info to add our own extensions, or in the case of the swapchain, add `TRANSFER_SRC` and `TRANSFER_DST` to the imageUsage flags (so that we can copy the to and from swapchain images).
### Grabbing and inserting frames into the app
This is where stuff gets interesting. First we hook `vkQueuePresentKHR`, which is the function used for presenting an image to the screen. Then we create a command buffer for copying the swapchain image in the parameters to some other image we created. That command buffer now takes the waitSemaphores from the present call and outputs its own semaphore, which is used in the original present call itself. Just like that, we've successfully grabbed a swapchain image. (I say "just like that", but this is several hundreds if not thousands of lines of code).
Inserting frames is where stuff gets interesting. If you just want to insert a frame, acquire an image from the swapchain using `vkAcquireNextImageKHR`, write or copy something to it, and call `vkQueuePresentKHR` a second time. The problem is synchronization.
### Synchronizing frame insertions
You don't know when the frame grab starts, because the waitSemaphores passed to you are GPU-only, you can not access them.
You don't know when your inserted frames are done rendering either, because that is also signaled by a semaphore on the GPU.
All of the code within `vkQueuePresentKHR` runs _immediately_, and you simply hook up one semaphore to another so that the GPU knows what to do. The GPU cant do math and go like "okay last frame took so long, so let's insert our frame once it's done rendering, plus an average time of 5 ms".
There is only two solutions to this problem. Solution one is to create a second thread and do a CPU-wait for rendering to finish, then sleep on the CPU for as long as you need to and insert the frame without a semaphore. The problem is that VkQueues are not thread safe and access needs to be synchronized on the CPU. This means you'll now be adding a mutex to each and every call using VkQueue, _and_ VkSwapchainKHR, _and_ the command buffer, etc.
The other solution is simply turning on the FIFO present mode. This mode queues up calls to vkQueuePresentKHR in order and takes a submitted frame each VBlank. This mode is more commonly known as V-Sync, but it's not exactly that. This solution only works because the amount of swapchain images is limited. Usually between 3 or 8 images can be prepared and presented (this does technically mean, that there may be up to 8 frames of latency if you do not handle this correctly.). Either way, changing the present mode is done in the swapchain creation, so we both switch to the FIFO present mode, as well as increase the amount of frames rendered by one plus the intermediate images. (Adding 1 here, because we're also delaying the rendering of one real frame).
### Integrating the frame generation
Integrating the frame generation into this is not really the target of this document, but I'll mention it anyways.
Frame generation runs in a separate Vulkan device, this is required because we need Vulkan 1.3 for DXVK's Shaders to run. We use the shared memory and shared semaphore extensions to get a file descriptor to image memory on the hook side and pass it to the frame gen side. Then we have two different VkImages on two devices which can both read and write to the same underlying memory.
From here it's a simple double buffering logic and sharing semaphores to synchronize completion and requests.
And there we have it, that's the entire application explained basically.

45
docs/Troubleshooting.md Normal file
View file

@ -0,0 +1,45 @@
# Troubleshooting
This page documents common issues, known incompatibilities and contains a guide to help you create a helpful bug report.
Before reporting a bug, please read through the following sections to see if your issue is already addressed.
### Basic Troubleshooting Steps
If lsfg-vk does not seem to be doing *anything*:
- Ensure the game you are trying to run is using Vulkan (not OpenGL).
- Ensure you are running a 64-bit game (try `PROTON_USE_WOW64=1`, but if it doesn't work then you're out of luck).
- Install `vulkan-tools` and run `vulkaninfo | grep -i VK_LAYER_LSFGVK_frame_generation`.
- If there is no output revisit the installation steps.
- Launch the game with the environment variable `VK_LOADER_DEBUG=layer` set.
- Look for lines mentioning `VK_LAYER_LSFGVK_frame_generation` inbetween `<Loader>` and `<Device>`.
- If you can't find any, try again using `LSFGVK_ENV=1`.
- If it still doesn't show up, you may be running in flatpak.
- If it does show up, then the `active_in` property of your profile is likely misconfigured. Reconfigure it, then try again without `LSFGVK_ENV=1`.
- Check for warnings/errors from lsfg-vk in the terminal/log output. These will often give clues as to what is going wrong.
- If there are no errors/warnings and you have gone through all above steps, then move onto the next section.
If lsfg-vk is loaded, but frame generation is not working:
- (When using `pacing_mode = none`): Disable VRR.
- (When using `pacing_mode = none`): Explicitly enable V-Sync in your game settings.
- (When using `pacing_mode = none` on Gamescope/SteamDeck): Set `ENABLE_GAMESCOPE_WSI=0`.
- (When using `pacing_mode = none` on Wayland): Disable tearing control & direct passthrough in your compositor
- (When using `pacing_mode = none` on Wayland): Try running in windowed mode.
- Disable in-game upscaling options (e.g. DLSS, FSR, etc).
- Disable other Vulkan layers (e.g. VkBasalt, MangoHud)
Should none of the above help, please proceed to the bug reporting section.
### Performance Overlays
If you are using performance overlays like Steam's built-in overlay, there is a good chance that they will not show the correct framerate.
This is a known limitation of Vulkan layers and without directly working with the overlay developers, there is little that can be done to fix this.
### Opening a Bug Report
When opening a bug report, please include the following information to help us diagnose and fix the issue:
- A detailed description of the issue you are experiencing.
- What system you are running on (OS, GPU, drivers, etc).
- The game you are trying to run (and through what platform, e.g. Steam Proton, native Linux, etc).
- The relevant section of your lsfg-vk configuration file.
Ideally, also include a log file with the environment variables `VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation` and `VK_LOADER_DEBUG=all` set. You might need to install the Vulkan validation layers package for your distribution to do this.
If you're running the game through Steam, the log file is located at `~/.steam/steam/logs/console-linux.txt`. Please clear it before launching the game to ensure it only contains relevant information.