mirror of
				https://github.com/PancakeTAS/lsfg-vk.git
				synced 2025-10-30 07:01:10 +00:00 
			
		
		
		
	Compare commits
	
		
			13 commits
		
	
	
		
			72492c3cd0
			...
			9c9a16afee
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9c9a16afee | ||
|   | 0a6455a381 | ||
|   | 60baec1e26 | ||
|   | e09d590f2d | ||
|   | 7ddf1bdbde | ||
|   | f5b55c7f83 | ||
|   | 938fe930b0 | ||
|   | 62ce71e4d4 | ||
|   | 26e4dc5827 | ||
|   | ec59c072b5 | ||
|   | b899324b8c | ||
|   | bee751e16b | ||
|   | 4c4452c9e5 | 
					 8 changed files with 101 additions and 40 deletions
				
			
		
							
								
								
									
										47
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										47
									
								
								README.md
									
										
									
									
									
								
							|  | @ -1,23 +1,46 @@ | |||
| # lsfg-vk | ||||
| Lossless Scaling is a Windows-exclusive app with the goal of bringing frame generation (among other features) to every single game or app. | ||||
| 
 | ||||
| lsfg-vk brings this frame generation to Linux users by acting as a Vulkan layer inbetween your game and your graphics card. | ||||
| Lossless Scaling is a Windows-exclusive app bringing frame generation (among other features) to every single game or app. | ||||
| 
 | ||||
| ## Installation | ||||
| **lsfg-vk** brings this frame generation to Linux users by acting as a Vulkan layer inbetween your game and your graphics card. | ||||
| 
 | ||||
| lsfg-vk has been prebuilt to run on a variety of Linux distributions: | ||||
| - Click [here](https://github.com/PancakeTAS/lsfg-vk/releases) to download lsfg-vk for your distribution | ||||
| - Follow [this guide](https://github.com/PancakeTAS/lsfg-vk/wiki/Installation-Guide) if you need any more help. | ||||
| ## Getting Started | ||||
| 
 | ||||
| Once installed, open up the lsfg-vk Configuration Window from your application menu or by typing `lsfg-vk-ui` into the console. | ||||
| For comprehensive instructions on setting up, configuring, and using **lsfg-vk**, please refer to the [Wiki](https://github.com/PancakeTAS/lsfg-vk/wiki). | ||||
| 
 | ||||
| Please see the [Wiki](https://github.com/PancakeTAS/lsfg-vk/wiki) for more information and join the [Discord](https://discord.gg/losslessscaling) for help (needs Steam verification). | ||||
| ### Installation | ||||
| 
 | ||||
| **lsfg-vk** is available as pre-built packages for various Linux distributions. | ||||
| 
 | ||||
| 1. Visit the [Releases page](https://github.com/PancakeTAS/lsfg-vk/releases) to download the package for your Linux distribution. | ||||
| 2. Follow the step-by-step instructions in the [Installation Guide](https://github.com/PancakeTAS/lsfg-vk/wiki/Installation-Guide) for your specific distro. | ||||
| 
 | ||||
| ### Configuration and Usage | ||||
| 
 | ||||
| After installation, you can open the graphical configuration editor **lsfg-vk-ui** from your application menu or by typing `lsfg-vk-ui` in your console. | ||||
| 
 | ||||
| * For detailed instructions on setting up your preferences, visit the [Configuring lsfg-vk](https://github.com/PancakeTAS/lsfg-vk/wiki/Configuring-lsfg%E2%80%90vk) page. | ||||
| * Learn how to use **lsfg-vk**'s integrated benchmark on the [Using lsfg-vk's integrated benchmark](https://github.com/PancakeTAS/lsfg-vk/wiki/Using-lsfg%E2%80%90vk's-integrated-benchmark) page. | ||||
| 
 | ||||
| ## Building from Source | ||||
| 
 | ||||
| If you prefer to build **lsfg-vk** yourself for development, debugging, or to use the latest and greatest features, a detailed build guide is available in the [Build Guide](https://github.com/PancakeTAS/lsfg-vk/wiki/Building-from-source) page. | ||||
| 
 | ||||
| ## Support and Troubleshooting | ||||
| 
 | ||||
| If you encounter any issues or need assistance, please consult the following resources: | ||||
| 
 | ||||
| * **Quirks:** Before reporting any issues refer to the [Quirks](https://github.com/PancakeTAS/lsfg-vk/wiki/Quirks) page. | ||||
| * **How to Ask for Help:** When creating a report, refer to the [How to ask for help](https://github.com/PancakeTAS/lsfg-vk/wiki/How-to-ask-for-help) page. | ||||
| * **Discord:** Join the [Lossless Scaling Discord server](https://discord.gg/losslessscaling) for help (Steam verification required). | ||||
| 
 | ||||
| ## Credits | ||||
| 
 | ||||
| Most of the project has still only been written by me, PancakeTAS, but I couldn't have done it without the help of these people: | ||||
| - [0xNULLderef](https://github.com/0xNULLderef): Teaching me how to reverse engineer software. | ||||
| - [Caliel666](https://github.com/Caliel666): Writing the initial draft of the user interface. | ||||
| - [Samueru-sama](https://github.com/Samueru-sama): Helping with various things XDG as well as app images and testing. | ||||
| - Other contributors: Thank you for your contribution! | ||||
| 
 | ||||
| * **0xNULLderef:** Teaching me how to reverse engineer software. | ||||
| * **Caliel666:** Writing the initial draft of the user interface. | ||||
| * **Samueru-sama:** Helping with various things XDG as well as app images and testing. | ||||
| * Other contributors: Thank you for your contributions! | ||||
| 
 | ||||
| I'd also like to thank every single person sponsoring this project. Thanks to you I'll be able to invest more time into this and hopefully bring some cool new features to everyone. | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ multiplier = 4 | |||
| performance_mode = false | ||||
| 
 | ||||
| [[game]] # override Genshin Impact | ||||
| exe = "Genshin" | ||||
| exe = "GenshinImpact.exe" | ||||
| 
 | ||||
| multiplier = 3 | ||||
| )"; | ||||
|  |  | |||
|  | @ -29,6 +29,11 @@ namespace { | |||
| 
 | ||||
| Configuration Config::activeConf{}; | ||||
| 
 | ||||
| extern "C" __attribute__((visibility("default"))) | ||||
| void lsfg_get_active_conf(Configuration *cfg) { | ||||
|     *cfg = Config::activeConf; | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
|     /// Turn a string into a VkPresentModeKHR enum value.
 | ||||
|     VkPresentModeKHR into_present(const std::string& mode) { | ||||
|  |  | |||
|  | @ -51,7 +51,7 @@ LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain, | |||
|         LSFG_3_1::finalize(); | ||||
| 
 | ||||
|         // print config
 | ||||
|         std::cerr << "lsfg-vk: Reloaded configuration for " << name.second << ":\n"; | ||||
|         std::cerr << "lsfg-vk: Reloaded configuration for " << name.first << ":\n"; | ||||
|         if (!conf.dll.empty()) std::cerr << "  Using DLL from: " << conf.dll << '\n'; | ||||
|         if (conf.no_fp16) std::cerr << "  FP16 Acceleration: Force-disabled\n"; | ||||
|         std::cerr << "  Multiplier: " << conf.multiplier << '\n'; | ||||
|  |  | |||
							
								
								
									
										23
									
								
								src/main.cpp
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								src/main.cpp
									
										
									
									
									
								
							|  | @ -3,10 +3,7 @@ | |||
| #include "utils/benchmark.hpp" | ||||
| #include "utils/utils.hpp" | ||||
| 
 | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include <exception> | ||||
| #include <fstream> | ||||
| #include <stdexcept> | ||||
| #include <iostream> | ||||
| #include <cstdint> | ||||
|  | @ -34,7 +31,7 @@ namespace { | |||
|         try { | ||||
|             Config::activeConf = Config::getConfig(name); | ||||
|         } catch (const std::exception& e) { | ||||
|             std::cerr << "lsfg-vk: The configuration for " << name.second << " is invalid, IGNORING:\n"; | ||||
|             std::cerr << "lsfg-vk: The configuration for " << name.first << " is invalid, IGNORING:\n"; | ||||
|             std::cerr << e.what() << '\n'; | ||||
|             return; // default configuration will unload
 | ||||
|         } | ||||
|  | @ -45,7 +42,7 @@ namespace { | |||
|             return; // default configuration will unload
 | ||||
| 
 | ||||
|         // print config
 | ||||
|         std::cerr << "lsfg-vk: Loaded configuration for " << name.second << ":\n"; | ||||
|         std::cerr << "lsfg-vk: Loaded configuration for " << name.first << ":\n"; | ||||
|         if (!conf.dll.empty()) std::cerr << "  Using DLL from: " << conf.dll << '\n'; | ||||
|         if (conf.no_fp16) std::cerr << "  FP16 Acceleration: Force-disabled\n"; | ||||
|         std::cerr << "  Multiplier: " << conf.multiplier << '\n'; | ||||
|  | @ -57,22 +54,6 @@ namespace { | |||
|         // remove mesa var in favor of config
 | ||||
|         unsetenv("MESA_VK_WSI_PRESENT_MODE"); // NOLINT
 | ||||
| 
 | ||||
|         // write latest file
 | ||||
|         try { | ||||
|             std::ofstream latest("/tmp/lsfg-vk_last", std::ios::trunc); | ||||
|             if (!latest.is_open()) | ||||
|                 throw std::runtime_error("Failed to open /tmp/lsfg-vk_last for writing"); | ||||
|             latest << "exe: " << name.first << '\n'; | ||||
|             latest << "comm: " << name.second << '\n'; | ||||
|             latest << "pid: " << getpid() << '\n'; | ||||
|             if (!latest.good()) | ||||
|                 throw std::runtime_error("Failed to write to /tmp/lsfg-vk_last"); | ||||
|         } catch (const std::exception& e) { | ||||
|             std::cerr << "lsfg-vk: An error occurred while trying to write the latest file, exiting:\n"; | ||||
|             std::cerr << "- " << e.what() << '\n'; | ||||
|             exit(EXIT_FAILURE); | ||||
|         } | ||||
| 
 | ||||
|         // load shaders
 | ||||
|         try { | ||||
|             Extract::extractShaders(); | ||||
|  |  | |||
|  | @ -209,20 +209,25 @@ void Utils::resetLimitN(const std::string& id) noexcept { | |||
| } | ||||
| 
 | ||||
| std::pair<std::string, std::string> Utils::getProcessName() { | ||||
|     // check override first
 | ||||
|     const char* process_name = std::getenv("LSFG_PROCESS"); | ||||
|     if (process_name && *process_name != '\0') | ||||
|         return { process_name, process_name }; | ||||
| 
 | ||||
|     // then check benchmark flag
 | ||||
|     const char* benchmark_flag = std::getenv("LSFG_BENCHMARK"); | ||||
|     if (benchmark_flag) | ||||
|         return { "benchmark", "benchmark" }; | ||||
|     std::array<char, 4096> exe{}; | ||||
| 
 | ||||
|     // find executed binary
 | ||||
|     const ssize_t exe_len = readlink("/proc/self/exe", exe.data(), exe.size() - 1); | ||||
|     if (exe_len <= 0) | ||||
|         return { "Unknown Process", "unknown" }; | ||||
|     exe.at(static_cast<size_t>(exe_len)) = '\0'; | ||||
|     std::string exe_str(exe.data()); | ||||
| 
 | ||||
|     // find command name as well
 | ||||
|     std::ifstream comm_file("/proc/self/comm"); | ||||
|     if (!comm_file.is_open()) | ||||
|         return { std::string(exe.data()), "unknown" }; | ||||
|  | @ -233,7 +238,37 @@ std::pair<std::string, std::string> Utils::getProcessName() { | |||
|     if (comm_str.back() == '\n') | ||||
|         comm_str.pop_back(); | ||||
| 
 | ||||
|     return{ std::string(exe.data()), comm_str }; | ||||
|     // replace binary with exe for wine apps
 | ||||
|     if (exe_str.find("wine") != std::string::npos | ||||
|         || exe_str.find("proton") != std::string::npos) { | ||||
| 
 | ||||
|         std::ifstream proc_maps("/proc/self/maps"); | ||||
|         if (!proc_maps.is_open()) | ||||
|             return{ exe_str, comm_str }; | ||||
| 
 | ||||
|         std::string line; | ||||
|         while (std::getline(proc_maps, line)) { | ||||
|             if (!line.ends_with(".exe")) | ||||
|                 continue; | ||||
| 
 | ||||
|             size_t pos = line.find_first_of('/'); | ||||
|             if (pos == std::string::npos) { | ||||
|                 pos = line.find_last_of(' '); | ||||
|                 if (pos == std::string::npos) | ||||
|                     continue; | ||||
|                 pos += 1; // skip space
 | ||||
|             } | ||||
| 
 | ||||
|             const std::string exe_name = line.substr(pos); | ||||
|             if (exe_name.empty()) | ||||
|                 continue; | ||||
| 
 | ||||
|             exe_str = exe_name; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return{ exe_str, comm_str }; | ||||
| } | ||||
| 
 | ||||
| std::string Utils::getConfigFile() { | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ pub fn default_config() -> TomlConfig { | |||
|                 experimental_present_mode: PresentMode::Vsync, | ||||
|             }, | ||||
|             TomlGame { | ||||
|                 exe: String::from("Genshin"), | ||||
|                 exe: String::from("GenshinImpact.exe"), | ||||
|                 multiplier: Multiplier::from(3), | ||||
|                 flow_scale: FlowScale::from(1.0), | ||||
|                 performance_mode: false, | ||||
|  |  | |||
|  | @ -18,11 +18,28 @@ pub fn find_vulkan_processes() -> ProcResult<Vec<(String, String)>> { | |||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         // find executed binary
 | ||||
|         let mut exe = prc.exe()?.to_string_lossy().to_string(); | ||||
| 
 | ||||
|         // replace binary with exe for wine apps
 | ||||
|         if exe.contains("wine") || exe.contains("proton") { | ||||
|             let result = maps.iter() | ||||
|                 .filter_map(|map| map.filename()) | ||||
|                 .map(|filename| filename.to_string_lossy().to_string()) | ||||
|                 .find(|filename| filename.ends_with(".exe")); | ||||
| 
 | ||||
|             if let Some(exe_name) = result { | ||||
|                 exe = exe_name; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // split off last part of the path
 | ||||
|         exe = exe.split('/').last().unwrap_or(&exe).to_string(); | ||||
| 
 | ||||
|         // format process information
 | ||||
|         let pid = prc.pid(); | ||||
|         let name = prc.stat()?.comm; | ||||
|         let process_info = format!("PID {}: {}", pid, name); | ||||
|         processes.push((process_info, name)); | ||||
|         let process_info = format!("PID {}: {}", pid, exe); | ||||
|         processes.push((process_info, exe)); | ||||
|     } | ||||
| 
 | ||||
|     Ok(processes) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue