Addendum v2.1 — GPU-Agnostic & Flatpak Survival Guide
(Extends the “Universal Stability Blueprint” for all platforms and all game versions)
TL;DR — “I have 3 minutes, what do I copy?”
Table
| You have… |
Runner |
Esync |
Fsync |
D3D Extras |
DXVK VRAM Cap |
Quick note |
|
Tsardoms / Fall of Constantinople (M2TWEOP) |
GE-Proton8-26 |
ON |
OFF |
OFF |
YES |
Esync mandatory for M2TWEOP hooks |
|
DaC / DCI:LA (no M2TWEOP, heavy) |
GE-Proton8-26 |
OFF |
env |
ON |
NO |
Fsync via WINEFSYNC=1, D3D Extras fixes artifacts |
|
Third Age 3.2 / GoT / TATW 6.2 (light) |
GE-Proton10-34+ |
OFF |
env |
ON |
NO |
Native Fsync, DXVK_ASYNC=1 accepted |
| NVIDIA proprietary |
any |
ON |
OFF |
ON |
optional |
__GL_THREADED_OPTIMIZATIONS=0 is CRITICAL |
| Intel iGPU / Arc |
any |
OFF |
env |
ON |
YES |
Shared VRAM = DXVK cap mandatory |
| AMD RADV |
any |
see above |
see above |
see above |
see above |
Baseline of the original guide |
Golden Rule (all mods, all GPUs):
-
WINE_LARGE_ADDRESS_AWARE=1
-
LC_ALL=C
-
SteamAppId=21690 + SteamGameId=21690 (even for retail/GOG versions — see Section 6)
-
Quit to Desktop — never reload a save from the in-game menu.
Section 1 — WHY Esync vs Fsync? When to choose which?
I’ve seen confusion in the thread: “Why does Tsardoms want Esync ON, DaC wants Fsync, and TATW doesn’t care?” The answer isn’t arbitrary — it depends on three factors: M2TWEOP, Proton/GE version, and GPU vendor.
1.1 What do they actually do?
-
Esync (Eventfd Sync): Wine/Proton emulates Windows synchronization objects using Linux eventfd. Available on any kernel. Higher overhead with hundreds of threads, but maximum compatibility with external DLL hooks.
-
Fsync (Futex Waitv): Uses futex_waitv (kernel 5.16+). Much lower overhead, smoother frames, but stricter with user-space hooks.
1.2 Decision matrix
Table
| Factor |
Esync ON |
Fsync (env) |
|
Mod uses M2TWEOP (Tsardoms, FoC) |
MANDATORY
|
Risk of deadlock on M2TWEOP DLL injection with GE-Proton8-26 |
|
Mod without M2TWEOP (DaC, DCI, TATW) |
Works, but stutters |
RECOMMENDED — smoother frames |
|
NVIDIA proprietary old (<driver 535) |
Safer |
Kernel may lack futex_waitv support |
| Kernel < 5.16 |
Only option |
Incompatible |
| AMD RADV / Intel |
works |
Optimal
|
1.3 Why Fsync via WINEFSYNC=1 and NOT the UI toggle?
The Lutris UI toggle only works if the runner was compiled with the Fsync patch and exposes it correctly via registry. GE-Proton8-26 and 10-34 have inconsistent behavior with the UI toggle — sometimes it ignores it, sometimes it conflicts with Esync. The WINEFSYNC=1 environment variable forces the Fsync path regardless of UI, and PROTON_NO_ESYNC=1 disables the other. This is the empirically tested “bulletproof” method.
How to apply in Lutris:
-
Esync ON: UI toggle “Enable Esync” = ON. Do NOT add WINEFSYNC.
-
Fsync ON: UI toggle “Enable Esync” = OFF, UI toggle “Enable Fsync” = OFF. Add env var: WINEFSYNC=1.
-
NEVER both simultaneously.
Section 2 — GPU Vendor-Specific Cheatsheet
The original guide was validated on AMD RADV (ACO). Here are the adaptations for NVIDIA and Intel.
2.1 NVIDIA (Proprietary / Closed-Source Driver)
NVIDIA has the best Vulkan driver for modern games, but for 32-bit legacy it has pitfalls:
Mandatory environment variables for NVIDIA:
plain
__GL_THREADED_OPTIMIZATIONS=0 # CRITICAL: For 32-bit executables,
# threaded opts cause race conditions
# and crash at loading screen.
__GL_SHADER_DISK_CACHE=1 # Persistent shader cache
__GL_SHADER_DISK_CACHE_SKIP_CLEANUP=1 # Don't wipe cache on exit
__GL_SYNC_TO_VBLANK=0 # Force Vsync OFF at driver level
DXVK note on NVIDIA: The NVIDIA driver manages VRAM aggressively. If you have 8GB VRAM or less, keep DXVK_CONFIG with dxvk.vramBudget (see Heavy profiles). If you have 12GB+, you can remove the cap.
Fsync on NVIDIA: Fsync requires support in the NVIDIA kernel module. It was added in drivers 535.x+. If your driver is older, Fsync will not work at all — the game will launch, but synchronization will fall back to the classic (slow) path. Stick to Esync.
Useful one-time nvidia-settings:
bash
nvidia-settings -a '[gpu:0]/GPUPowerMizerMode=1' # Permanent Performance Mode
2.2 Intel (iGPU Iris Xe / Arc A-series / UHD)
Intel uses the ANV driver (open-source). DXVK performance on Intel iGPU is surprisingly good for M2TW, but requires attention to shared memory.
Environment variables for Intel:
plain
ANV_QUEUE_THREAD=1 # Dedicated thread for queue submission
MESA_SHADER_CACHE_MAX_SIZE=1GB # Generous cache for shader compilation
INTEL_DEBUG=noccs # Disable color compression,
# prevents corruption on certain SKUs
Shared VRAM = mandatory DXVK_CONFIG: On Intel iGPU, “VRAM” is system RAM. Without dxvk.vramBudget, DXVK can request more than Linux can allocate, triggering OOM. Always keep dxvk.vramBudget=2048 and dxvk.maxChunkSize=64 on Intel iGPU.
Fsync on Intel: Works natively, no restrictions. You can use Fsync on all non-M2TWEOP mods.
2.3 AMD RADV (The guide’s baseline)
The original profiles remain valid. One addition:
plain
RADV_DEBUG=nocompute # Only for Fall of Constantinople 2.0
# (compute shaders crash on AMD iGPU)
RADV_PERFTEST=aco # Fast shader compiler (default on newer kernels,
# but explicit = safe)
Section 3 — Using Lutris from Flatpak? Survival Guide
Many install Lutris from Flathub (flatpak install flathub org.lutris.Lutris). It works, but the sandbox blocks some commands from the guide.
3.1 What does NOT work in Flatpak (and the fix)
Table
| Command / Setting |
Why it fails |
Fix |
sudo sysctl vm.swappiness=10 |
Flatpak has no kernel access |
Run in a separate terminal on the host before gaming |
gsettings set org.gnome.mutter check-alive-timeout 0 |
gsettings inside sandbox only modifies the sandbox |
Run on host: gsettings set org.gnome.mutter check-alive-timeout 0
|
flatpak run --command=gsettings org.lutris.Lutris ... |
Does not affect host GNOME |
Don’t use — it’s useless |
Access to /mnt/Jocuri_SSD
|
Flatpak only sees ~/ and ~/.var/ by default |
Add explicit permission (see below) |
cpupower frequency-set |
Lacks CAP_SYS_ADMIN capability |
Run on host with sudo
|
zRAM (zram-config) |
System service — works regardless |
Install on host, not in Flatpak |
3.2 How to grant Flatpak permissions for your game drive
If your games are on /mnt/Jocuri_SSD (or any external path):
bash
flatpak override --user --filesystem=/mnt/Jocuri_SSD org.lutris.Lutris
If you use Flatseal (GUI for Flatpak permissions):
-
Open Flatseal → select Lutris
-
Under “Filesystem” → add /mnt/Jocuri_SSD or ~/Games (as applicable)
-
Enable “Device=all” (for direct GPU access)
3.3 Recommended workflow for Flatpak
Step 1 — Terminal on host (before session):
bash
# Mutter fix (one-time, persists permanently)
gsettings set org.gnome.mutter check-alive-timeout 0
# Temporary RAM optimizations
sudo sysctl vm.swappiness=10
sudo sysctl vm.vfs_cache_pressure=50
# Governor performance (optional)
sudo cpupower frequency-set -g performance
Step 2 — Open Lutris (Flatpak) and launch the game.
Step 3 — Terminal on host (after session):
bash
sudo sysctl vm.swappiness=60
sudo sysctl vm.vfs_cache_pressure=100
sudo cpupower frequency-set -g ondemand
Alternative: Save a pre-game.sh and post-game.sh script on your desktop and run them manually. Flatpak cannot automate this from inside.
3.4 Wineprefix in Flatpak
Flatpak Lutris creates prefixes in ~/.var/app/org.lutris.Lutris/data/lutris/runners/wine/. This path works correctly — no changes needed. Just make sure the actual game files (.exe, mod folders) are on a path with Flatpak permission.
Section 4 — Game Version: Retail, GOG, Steam, or Standalone?
The guide uses SteamAppId=21690 and WINEDLLOVERRIDES=steam_api=n,b. This works for all versions, not just Steam.
4.1 Why?
-
SteamAppId=21690 tricks the Proton layer into thinking “I already know what game this is” — avoiding launcher checks that crash non-Steam versions.
-
WINEDLLOVERRIDES=steam_api=n,b (no-op + builtin) forces Wine to ignore the Steam API DLL. If your game doesn’t have steam_api.dll (e.g., GOG, retail CD), Wine “simulates” it without errors. If it has a fake one, it prevents the crash.
4.2 Table per source
Table
| Game source |
SteamAppId |
WINEDLLOVERRIDES |
Additional note |
| Original Steam |
21690 |
steam_api=n,b |
Works out-of-the-box |
| GOG release |
21690 |
steam_api=n,b |
GOG has no Steam API, override is harmless |
| Retail CD/DVD |
21690 |
steam_api=n,b |
Make sure you have official patch 1.5 |
| Standalone / Digital re-release |
21690 |
steam_api=n,b |
Symlink kingdoms.exe needed if mod looks for medieval2.exe
|
It doesn’t matter where you got the game — the variables stay identical. Do not change SteamAppId and do not remove WINEDLLOVERRIDES.
Section 5 — “One-Shot” Setup Script (Bash)
For those who want to automate without copying 15 variables manually into the GUI:
bash
#!/bin/bash
# m2tw_flatpak_bootstrap.sh
# Run on HOST (not inside Flatpak) before the session
echo "=== M2TW Linux Bootstrap ==="
# 1. Mutter fix (permanent)
echo "[1/5] Disabling 'not responding' popup..."
gsettings set org.gnome.mutter check-alive-timeout 0
# 2. Temporary sysctl
echo "[2/5] Optimizing kernel RAM/cache..."
sudo sysctl vm.swappiness=10
sudo sysctl vm.vfs_cache_pressure=50
# 3. Governor (optional)
echo "[3/5] CPU Performance mode..."
sudo cpupower frequency-set -g performance 2>/dev/null || echo " (cpupower unavailable, skip)"
# 4. Check Flatpak permissions
echo "[4/5] Checking Flatpak permissions..."
if flatpak info org.lutris.Lutris &>/dev/null; then
echo " Lutris Flatpak detected. Make sure you ran:"
echo " flatpak override --user --filesystem=/mnt/Jocuri_SSD org.lutris.Lutris"
fi
# 5. Symlink kingdoms.exe (if medieval2.exe exists)
M2TW_PATH="/mnt/Jocuri_SSD/jocuri instalate/Medieval II - Total War"
if [ -f "$M2TW_PATH/medieval2.exe" ] && [ ! -L "$M2TW_PATH/kingdoms.exe" ]; then
echo "[5/5] Creating symlink kingdoms.exe..."
ln -sf "$M2TW_PATH/medieval2.exe" "$M2TW_PATH/kingdoms.exe"
else
echo "[5/5] Symlink kingdoms.exe exists or path invalid — skip."
fi
echo ""
echo "✅ System ready. Now open Lutris and launch the game."
echo "⚠️ AFTER you finish, run: ./m2tw_cleanup.sh"
Cleanup script (after session):
bash
#!/bin/bash
# m2tw_cleanup.sh
echo "Restoring system parameters..."
sudo sysctl vm.swappiness=60
sudo sysctl vm.vfs_cache_pressure=100
sudo cpupower frequency-set -g ondemand 2>/dev/null || true
echo "✅ Done."
Section 6 — Quick Diagnostic: “How do I read my own crash?”
Not all crashes are “Out of Memory”. Here’s how to identify the cause before posting.
6.1 Where the logs are
-
Wine/Proton: ~/.local/share/lutris/runners/wine/[prefix]/drive_c/users/[user]/Temp/
-
Mod-specific: .../mods/[Mod]/logs/ (e.g., tsardoms.log.txt)
-
DXVK: ~/.local/share/lutris/runners/wine/[prefix]/drive_c/users/[user]/Local Settings/Application Data/
6.2 Key messages and what they mean
Table
| Message in log / terminal |
Meaning |
Fix |
VK_ERROR_MEMORY_MAP_FAILED |
Insufficient or fragmented VRAM/RAM |
Add dxvk.maxChunkSize=64;dxvk.vramBudget=2048
|
R6025 - pure virtual function call |
Thread desync (GPU ahead of CPU) |
d3d9.maxFrameLatency=1 + DXVK_FRAME_RATE=60
|
Out of Memory (without VK error) |
LAA missing or 4GB patch ignored |
WINE_LARGE_ADDRESS_AWARE=1 |
Garrison for Draw.settlementName loop |
Garrison Manager deadlock post-battle |
Strict frame-pacing (see Tsardoms profile) |
steam_api.dll not found / crash at startup |
Proton checking for Steam |
SteamAppId=21690 + WINEDLLOVERRIDES=steam_api=n,b
|
Oh no... (M2TWEOP) |
Lua/script parser error |
Fix campaign_script.txt (see post #12) |
| Crash on “Apply Changes” video |
Native fullscreen on Wine |
windowed=1 + borderless_window=1 in CFG |
6.3 MangoHud for live diagnostic
Add to env vars:
plain
MANGOHUD=1
MANGOHUD_CONFIG=ram,vram,frametime,graphs,cpu_stats,gpu_stats
Displays in real-time: RAM, VRAM, frametime. If VRAM hits the limit before the crash, you know for sure it’s memory.
Section 7 — OpenGL Fallback (Plan B)
If DXVK crashes inexplicably (especially on old Intel or problematic NVIDIA drivers), Medieval II has a native OpenGL renderer accessible via WineD3D.
How to switch to OpenGL (WineD3D):
-
In Lutris → Runner Options → Disable DXVK (uncheck)
-
Add env var: WINEDLLOVERRIDES="d3d9=w"
-
w = WineD3D (OpenGL implementation of DirectX 9)
- Expect lower FPS (20-30% below DXVK), but maximum stability.
When to use:
-
Crash on every loading screen on Intel HD 5500/620
-
Purple/green visual artifacts on NVIDIA with beta drivers
-
“Black screen” after intro on certain configurations
Final Checklist before first launch
Copy this to a text file and check off:
-
[ ] Game is on an ext4 partition (not NTFS)
-
[ ] Each mod has its own Wine prefix
-
[ ] ln -sf medieval2.exe kingdoms.exe exists in the game folder
-
[ ] medieval2.preference.cfg is read-only (chmod 444)
-
[ ] log level = * error in CFG (not trace)
-
[ ] windowed = 1, borderless_window = 1, vsync = 0 in CFG
-
[ ] Correct environment variables for your mod (see TL;DR table)
-
[ ] If using Flatpak: --filesystem permission is active
-
[ ] If using NVIDIA: __GL_THREADED_OPTIMIZATIONS=0 is set
-
[ ] If using Intel iGPU: dxvk.vramBudget=2048 is present
-
[ ] Quit to Desktop after every session — never “Load Game” from menu
This addendum completes the “Universal Stability Blueprint” (post #12) and the community v2.0 guide. Tested on AMD RADV, NVIDIA 535+, and Intel Iris Xe. For questions, mention your GPU and Lutris version (native/Flatpak).