Compare commits
No commits in common. "main" and "v1.0.6" have entirely different histories.
2
.github/release-nest-v3
vendored
2
.github/release-nest-v3
vendored
@ -1 +1 @@
|
||||
1
|
||||
2
|
||||
|
145
README.md
145
README.md
@ -1,145 +0,0 @@
|
||||
# falcond - Advanced Linux Gaming Performance Daemon
|
||||
|
||||
falcond is a powerful system daemon designed to automatically optimize your Linux gaming experience. It intelligently manages system resources and performance settings on a per-game basis, eliminating the need to manually configure settings for each game.
|
||||
|
||||
## Features
|
||||
|
||||
- **Automatic Game Detection**: Automatically detects running games and applies optimized settings
|
||||
- **Per-Game Profiles**: Customizable profiles for different games
|
||||
- **Performance Mode**: Enables system-wide performance optimizations when gaming
|
||||
- **3D vcache Management**: Smart management of AMD 3D vcache settings
|
||||
- **SCX Scheduler Integration**: Dynamically pick a scheduler that is best for the specific game
|
||||
- **Proton Compatibility**: Full support for Steam Proton games, with a global profile for excellent game coverage
|
||||
- **Low Overhead**: Minimal system resource usage
|
||||
- **Different Device Modes**: Profiles for desktops, handhelds, HTPC etc
|
||||
|
||||
## Installation
|
||||
|
||||
falcond is available on PikaOS via the falcond package or via the Pika Gameutils Metapackage. For other distributions, please check your package manager or build from source.
|
||||
|
||||
## Configuration
|
||||
|
||||
The configuration file is located at `/etc/falcond/config.conf`. Here's an example configuration, it will be generated automatically on first run:
|
||||
|
||||
```
|
||||
enable_performance_mode = true
|
||||
scx_sched = none
|
||||
scx_sched_props = default
|
||||
vcache_mode = none
|
||||
profile_mode = none
|
||||
```
|
||||
|
||||
This is global configuration and all options other than profile_mode override individual game profiles.
|
||||
|
||||
There is also a list of proton/wine system processes in `/usr/share/falcond/system.conf`. This list can be updated if for example a crash handler is intercepting your profile and needs to be ignored.
|
||||
|
||||
### Configuration Options
|
||||
|
||||
- `enable_performance_mode`: Enable/disable performance mode (default: true)
|
||||
- `scx_sched`: SCX scheduler (options: none, bpfland, lavd, rusty, flash)
|
||||
- `scx_sched_props`: SCX scheduler mode (options: default, gaming, power, latency, server)
|
||||
- `vcache_mode`: VCache management mode (options: none, cache, freq)
|
||||
- `profile_mode`: What type of device is in use, none means desktop (options: none, handheld, htpc)
|
||||
|
||||
## Profile Modes
|
||||
Falcond now supports different profile modes for different device types:
|
||||
- Default (none): Uses profiles from `/usr/share/falcond/profiles`
|
||||
- Handheld: Uses profiles from `/usr/share/falcond/profiles/handheld`
|
||||
- HTPC: Uses profiles from `/usr/share/falcond/profiles/htpc`
|
||||
|
||||
To set a profile mode, add this to your config file:
|
||||
```
|
||||
profile_mode = "handheld" # or "htpc" or "none"
|
||||
```
|
||||
|
||||
## Game Profiles
|
||||
|
||||
Game profiles are stored in `/usr/share/falcond/profiles/` and define specific optimizations for individual games. You can contribute new profiles via PR at:
|
||||
[Falcond Profiles Repository](https://github.com/PikaOS-Linux/falcond-profiles)
|
||||
|
||||
Example profile:
|
||||
```
|
||||
name = "game.exe"
|
||||
performance_mode = true
|
||||
scx_sched = bpfland
|
||||
scx_sched_props = gaming
|
||||
vcache_mode = cache
|
||||
```
|
||||
|
||||
### Available Options
|
||||
|
||||
- `name`: The exe name (examples: cs2, PathOfExileSteam.exe)
|
||||
- `performance_mode`: Enable/disable performance mode (default: true)
|
||||
- `scx_sched`: SCX scheduler (options: none, bpfland, lavd, rusty, flash)
|
||||
- `scx_sched_props`: SCX scheduler mode (options: none, gaming, power, latency, server)
|
||||
- `vcache_mode`: VCache management mode (options: none, cache, freq)
|
||||
|
||||
## Service Management
|
||||
|
||||
To restart the daemon:
|
||||
```bash
|
||||
sudo systemctl restart falcond
|
||||
```
|
||||
|
||||
To check the status:
|
||||
```
|
||||
sudo systemctl status falcond
|
||||
```
|
||||
|
||||
## Source Code
|
||||
|
||||
The source code for falcond can be found at:
|
||||
[Falcond Source Repository](https://git.pika-os.com/general-packages/falcond)
|
||||
|
||||
## Important Notes
|
||||
|
||||
⚠️ **Compatibility Warning** ⚠️ falcond should not be used alongside Feral GameMode or Falcon GameMode as they may conflict with each other. falcond provides similar functionality with additional features and optimizations.
|
||||
|
||||
## Why falcond?
|
||||
|
||||
Traditional gaming on Linux often requires manual optimization for each game - tweaking CPU governors, scheduling priorities, and cache settings. falcond automates this entire process by:
|
||||
|
||||
1. Automatically detecting when games are running
|
||||
2. Applying optimized settings based on pre-configured profiles
|
||||
3. Reverting settings when games are closed
|
||||
4. Providing a centralized way to manage gaming performance
|
||||
5. Easy switching of options for different device types
|
||||
|
||||
This means you can focus on gaming while falcond handles all the technical optimizations in the background!
|
||||
|
||||
## License
|
||||
|
||||
falcond is released under the [MIT License](http://git.pika-os.com/general-packages/falcond/raw/branch/main/LICENSE).
|
||||
|
||||
## Contributing
|
||||
|
||||
Please fork the [PikaOS-Linux/falcond](https://github.com/PikaOS-Linux/falcond) repository and submit a pull request.
|
||||
|
||||
## Build Dependencies
|
||||
|
||||
zig 0.14.0+
|
||||
|
||||
## Building from Source
|
||||
|
||||
```
|
||||
git clone https://git.pika-os.com/general-packages/falcond.git
|
||||
cd falcond
|
||||
cd falcond
|
||||
zig build -Doptimize=ReleaseFast
|
||||
```
|
||||
|
||||
## Runtime Dependencies
|
||||
|
||||
These should be feature detected by falcond so if not present that specific feature will not be used.
|
||||
|
||||
power-profiles-daemon or tuned + tuned-ppd
|
||||
scx-sched
|
||||
Linux kernel patched with AMD 3D vcache support
|
||||
|
||||
## Packaging
|
||||
|
||||
falcond should be placed in /usr/bin/falcond and run via a service file. There is an example systemd service file in ./falcond/debian/falcond.service
|
||||
|
||||
falcond needs profiles to be useful, these should be placed in /usr/share/falcond/profiles alongside the system.conf in /usr/share/falcond/system.conf. Upto date profiles can be found in the [PikaOS-Linux/falcond-profiles](https://github.com/PikaOS-Linux/falcond-profiles) repository. We currently pull the latest profiles from there on building of this package but you could also package seperately and depend on that package.
|
||||
|
||||
There is a config file in /etc/falcond/config.conf which is generated automatically on first run. You could also package that if you need different default settings.
|
@ -1,15 +1,3 @@
|
||||
falcond (1.0.8-101pika2) pika; urgency=low
|
||||
|
||||
* Fix scx scheduler mode selection order
|
||||
|
||||
-- ferreo <ferreo@pika-os.com> Sun, 12 Jan 2025 13:48:00 +0300
|
||||
|
||||
falcond (1.0.7-101pika2) pika; urgency=low
|
||||
|
||||
* Don't load profiles in subfolders
|
||||
|
||||
-- ferreo <ferreo@pika-os.com> Sun, 12 Jan 2025 13:48:00 +0300
|
||||
|
||||
falcond (1.0.6-101pika1) pika; urgency=low
|
||||
|
||||
* Add handheld and htpc profiles, split system processes config to live in the profiles repo for easier updates
|
||||
|
@ -75,11 +75,7 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
||||
allocator = alloc;
|
||||
std.log.info("Initializing scheduler state", .{});
|
||||
|
||||
const sched_list = getSupportedSchedulers(alloc) catch |err| {
|
||||
std.log.warn("Failed to get supported schedulers: {}, scx_loader may not be available", .{err});
|
||||
supported_schedulers = &[_]ScxScheduler{};
|
||||
return;
|
||||
};
|
||||
const sched_list = try getSupportedSchedulers(alloc);
|
||||
defer alloc.free(sched_list);
|
||||
|
||||
std.log.info("Supported schedulers:", .{});
|
||||
@ -106,8 +102,8 @@ const SCX_IFACE = "org.scx.Loader";
|
||||
fn modeToInt(mode: ScxSchedModes) u32 {
|
||||
return switch (mode) {
|
||||
.default => 0,
|
||||
.gaming => 1,
|
||||
.power => 2,
|
||||
.power => 1,
|
||||
.gaming => 2,
|
||||
.latency => 3,
|
||||
.server => 4,
|
||||
};
|
||||
@ -116,8 +112,8 @@ fn modeToInt(mode: ScxSchedModes) u32 {
|
||||
fn intToMode(value: u32) ScxError!ScxSchedModes {
|
||||
return switch (value) {
|
||||
0 => .default,
|
||||
1 => .gaming,
|
||||
2 => .power,
|
||||
1 => .power,
|
||||
2 => .gaming,
|
||||
3 => .latency,
|
||||
4 => .server,
|
||||
else => error.InvalidValue,
|
||||
@ -127,38 +123,23 @@ fn intToMode(value: u32) ScxError!ScxSchedModes {
|
||||
pub fn getCurrentScheduler(alloc: std.mem.Allocator) !?ScxScheduler {
|
||||
var dbus_conn = dbus.DBus.init(alloc, SCX_NAME, SCX_PATH, SCX_IFACE);
|
||||
|
||||
const current = dbus_conn.getProperty("CurrentScheduler") catch |err| {
|
||||
std.log.warn("Failed to get current scheduler: {}", .{err});
|
||||
return .none;
|
||||
};
|
||||
const current = try dbus_conn.getProperty("CurrentScheduler");
|
||||
defer alloc.free(current);
|
||||
|
||||
if (current.len == 0) return .none;
|
||||
return ScxScheduler.fromString(current) catch |err| {
|
||||
std.log.warn("Invalid scheduler value: {}", .{err});
|
||||
return .none;
|
||||
};
|
||||
if (current.len == 0) return null;
|
||||
return try ScxScheduler.fromString(current);
|
||||
}
|
||||
|
||||
pub fn getCurrentMode(alloc: std.mem.Allocator) !ScxSchedModes {
|
||||
var dbus_conn = dbus.DBus.init(alloc, SCX_NAME, SCX_PATH, SCX_IFACE);
|
||||
|
||||
const mode_str = dbus_conn.getProperty("SchedulerMode") catch |err| {
|
||||
std.log.warn("Failed to get scheduler mode: {}", .{err});
|
||||
return .default;
|
||||
};
|
||||
const mode_str = try dbus_conn.getProperty("SchedulerMode");
|
||||
defer alloc.free(mode_str);
|
||||
|
||||
if (mode_str.len == 0) return .default;
|
||||
|
||||
const mode = std.fmt.parseInt(u32, mode_str, 10) catch |err| {
|
||||
std.log.warn("Invalid scheduler mode value: {}", .{err});
|
||||
return .default;
|
||||
};
|
||||
return intToMode(mode) catch |err| {
|
||||
std.log.warn("Invalid mode value: {}", .{err});
|
||||
return .default;
|
||||
};
|
||||
const mode = try std.fmt.parseInt(u32, mode_str, 10);
|
||||
return intToMode(mode);
|
||||
}
|
||||
|
||||
pub fn getSupportedSchedulers(alloc: std.mem.Allocator) ![]ScxScheduler {
|
||||
@ -266,21 +247,23 @@ fn runSystemCtl(alloc: std.mem.Allocator, command: []const u8, service: []const
|
||||
.allocator = alloc,
|
||||
.argv = &argv,
|
||||
.max_output_bytes = max_output_size,
|
||||
}) catch {
|
||||
}) catch |err| {
|
||||
std.log.warn("Failed to run systemctl {s} {s}: {}", .{ command, service, err });
|
||||
return;
|
||||
};
|
||||
defer alloc.free(result.stderr);
|
||||
defer alloc.free(result.stdout);
|
||||
|
||||
if (result.term.Exited != 0) {
|
||||
std.log.warn("systemctl failed: {s}", .{result.stderr});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deactivateScheduler(alloc: std.mem.Allocator) ScxError!void {
|
||||
runSystemCtl(alloc, "start", "ananicy-cpp");
|
||||
var dbus_conn = dbus.DBus.init(alloc, SCX_NAME, SCX_PATH, SCX_IFACE);
|
||||
try dbus_conn.callMethod("StopScheduler", &[_][]const u8{});
|
||||
runSystemCtl(alloc, "start", "ananicy-cpp");
|
||||
}
|
||||
|
||||
pub fn restorePreviousState(alloc: std.mem.Allocator) void {
|
||||
|
@ -30,10 +30,12 @@ pub fn loadConfDir(comptime T: type, allocator: std.mem.Allocator, dir_path: []c
|
||||
var dir = try std.fs.openDirAbsolute(dir_path, .{ .iterate = true });
|
||||
defer dir.close();
|
||||
|
||||
var iter = dir.iterate();
|
||||
while (try iter.next()) |entry| {
|
||||
if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".conf")) {
|
||||
const path = try std.fs.path.join(allocator, &.{ dir_path, entry.name });
|
||||
var walker = try dir.walk(allocator);
|
||||
defer walker.deinit();
|
||||
|
||||
while (try walker.next()) |entry| {
|
||||
if (entry.kind == .file and std.mem.endsWith(u8, entry.path, ".conf")) {
|
||||
const path = try std.fs.path.join(allocator, &.{ dir_path, entry.path });
|
||||
defer allocator.free(path);
|
||||
|
||||
const file = try std.fs.openFileAbsolute(path, .{});
|
||||
|
@ -288,7 +288,7 @@ pub fn Parser(comptime T: type) type {
|
||||
}
|
||||
},
|
||||
.pointer => |ptr_info| {
|
||||
if (ptr_info.size != .many) return error.InvalidSyntax;
|
||||
if (ptr_info.size != .Slice) return error.InvalidSyntax;
|
||||
switch (ptr_info.child) {
|
||||
u8 => {
|
||||
@field(result, field.name) = try self.parseString();
|
||||
|
Loading…
x
Reference in New Issue
Block a user