Killing Floor 2 performance under Proton

June 19, 2019 - Reading time: 7 minutes

Recently everything received updates and since then I struggle to have good performance on Killing Floor 2 under Proton. I can't find what changed and what made the game run bad, but the good old day of high frame rate is gone. I did a few tests first to check if it was a game issue amplified by Proton or if it was just an issue on my Linux install.

I copied over my Linux KF 2 install to my Windows library, and booted on Windows. Performance was excellent, with the game maxed out.

I then copied my config folder from Windows to Linux, to start on the same base of settings, and to collect data to compare performance with various things I'll try later. First weird thing I noticed is that with these game config files, the game had same or even better performance (I had High to Low settings after trying to solve the performance issue).. which is weird as you would think the higher the quality the lower the performance, but I already noticed this exact behavior on Rising Storm 2: Vietnam.

I ran the Basic Training every time in my subsequent tests for consistency, and ran at same spots and took FPS average in these areas.

I added a config file for GameMode at /etc/gamemode.ini and enabled the gamemoded user service (checking service status can help debugging) in order to force some global setting for when I'll use it:

[general]
; The reaper thread will check every 5 seconds for exited clients and for config file changes
reaper_freq=5

; The desired governor is used when entering GameMode instead of "performance"
desiredgov=performance
; The default governer is used when leaving GameMode instead of restoring the original value
defaultgov=powersave

; GameMode can change the scheduler policy to SCHED_ISO on kernels which support it (currently
; not supported by upstream kernels). Can be set to "auto", "on" or "off". "auto" will enable
; with 4 or more CPU cores. "on" will always enable. Defaults to "off".
softrealtime=on

; GameMode can renice game processes. You can put any value between 0 and 20 here, the value
; will be negated and applied as a nice value (0 means no change). Defaults to 0.
renice=5

; By default, GameMode adjusts the iopriority of clients to BE/0, you can put any value
; between 0 and 7 here (with 0 being highest priority), or one of the special values
; "off" (to disable) or "reset" (to restore Linux default behavior based on CPU priority),
; currently, only the best-effort class is supported thus you cannot set it here
ioprio=0

; Sets whether gamemode will inhibit the screensaver when active
; Defaults to 1
inhibit_screensaver=1

[gpu]
; Here Be Dragons!
; Warning: Use these settings at your own risk
; Any damage to hardware incurred due to this feature is your responsibility and yours alone
; It is also highly recommended you try these settings out first manually to find the sweet spots

; Setting this to the keyphrase "accept-responsibility" will allow gamemode to apply GPU optimisations such as overclocks
;apply_gpu_optimisations=0

; The DRM device number on the system (usually 0), ie. the number in /sys/class/drm/card0/
;gpu_device=0

; Nvidia specific settings
; Requires the coolbits extension activated in nvidia-xconfig
; This corresponds to the desired GPUPowerMizerMode
; "Adaptive"=0 "Prefer Maximum Performance"=1 and "Auto"=2
; See NV_CTRL_GPU_POWER_MIZER_MODE and friends in https://github.com/NVIDIA/nvidia-settings/blob/master/src/libXNVCtrl/NVCtrl.h
;nv_powermizer_mode=1

; These will modify the core and mem clocks of the highest perf state in the Nvidia PowerMizer
; They are measured as Mhz offsets from the baseline, 0 will reset values to default, -1 or unset will not modify values
;nv_core_clock_mhz_offset=0
;nv_mem_clock_mhz_offset=0

; AMD specific settings
; Requires a relatively up to date AMDGPU kernel module
; See: https://dri.freedesktop.org/docs/drm/gpu/amdgpu.html#gpu-power-thermal-controls-and-monitoring
; It is also highly recommended you use lm-sensors (or other available tools) to verify card temperatures
; This corresponds to power_dpm_force_performance_level, "manual" is not supported for now
;amd_performance_level=high

[supervisor]
; This section controls the new gamemode functions gamemode_request_start_for and gamemode_request_end_for
; The whilelist and blacklist control which supervisor programs are allowed to make the above requests
;supervisor_whitelist=
;supervisor_blacklist=

; In case you want to allow a supervisor to take full control of gamemode, this option can be set
; This will only allow gamemode clients to be registered by using the above functions by a supervisor client
;require_supervisor=0

[custom]
; Custom scripts (executed using the shell) when gamemode starts and ends
start=notify-send -i preferences-desktop-gaming -t 8000 "GameMode started" && nvidia-settings -a '[gpu:0]/GPUPowerMizerMode=1'
end=notify-send -i preferences-desktop-gaming -t 8000 "GameMode ended" && nvidia-settings -a '[gpu:0]/GPUPowerMizerMode=0'

I didn't enable some of the high end setting like GPU overclocking.

May need some more configuration/tweaks for gamemode to properly apply everything like renice and ioprio.. to be checked and confirmed later. Message from the future, reinstalling properly GameMode from AUR fixed the issue (see also comments on the AUR package). Running gamemoded -t made sure every tests passed which wasn't the case before.

I benchmarked performance first with Nvidia settings set to Force (+Full) Composition Pipeline and tried without it completely by saving settings and rebooting. Performance wasn't even worst with it fully forced and there was less/no tearing at all in game. Problem wasn't this for sure.

I compared performance with the PROTON_NO_ESYNC option and the test was just obvious. I could reach near 200FPS when looking directly at a wall, and run around in the map at 100+ FPS when I couldn't play the day before. I didn't need this before but fore sure it now makes a difference.

There might have been an other issue though the day before when I couldn't play at all, the performance today isn't as bad as the day before even if performance aren't good, also I didn't have an inventory in game so that could also be part of my bad performance with the game struggling to connect to the steam backend and infinitely looping in errors.. just a guess but not impossible as I had inventory during my tests when it was working good.

Here is my current startup command line for KF2 to force the PROTON_NO_ESYNC setting and start the game with GameMode to enable system wide optimization as well as game CPU and IO prioritization.

PROTON_NO_ESYNC=1 gamemoderun %command%

At least this issue made me realize that despite what I thought, the PROTON_NO_ESYNC setting wasn't worthless.

Other things to do to improve performance (maybe):