Skip to main content

Proton - Adding Complexity

Now that we’ve had a look at the basic Wine installation (with a Fedora focus) in the last post we can start to look at Valve’s Proton, what it is, why it’s important, and what makes it different to Wine.

We will also touch on the tertiary projects, Wine-GE and Proton-GE, in this post. As well as exploring the history of Steam on Linux.

Contents

Steam Play

Origins

Starting back in 2010, as mentioned in this blog post from Valve, Steam Play was originally a way for you to play the games you already owned on Windows, on macOS (OS X as was) and Linux (when the Linux client was officially released in 2013.) This was great for games that supported all three platforms, notably Team Fortress 2 and other Valve titles1, but its shortcoming was that games had to actually support those three platforms to enable installation on those operating systems. It wasn’t so much a ‘mechanism to play games’ as a transparent way to ensure that those games which already supported your platform, could be easily installed through Steam.

Steam Machines

Fast forward to 2013 and Steam Machines are announced by Valve, as their in-home console solution to gaming on your TV. They’re effectively a spin of Debian Linux called SteamOS (later to be repurposed for the Steam Deck, though it would be based on Arch instead) on top of some fairly beefy hardware (for the time.) The original FAQ for the SteamOS install from back then gives some interesting insights on the supported form of the OS. They even explicitly answer the question “Can I run Microsoft Windows games and applications on SteamOS” with a blanket “No (but you can stream them,)” which is a nice example of being honest, but likely didn’t help the overall appeal of the Steam Machines.

At the time, I was quite excited but quietly concerned by this news, because while I did actually enjoy the classic Big Picture experience (since replaced with the Deck UI) it was obvious from the start that the majority of people’s libraries being unplayable out of the box would be a real concern. They even touted, for a while, The Witcher 3 as being a launch title, though the marketing around this slowly disappeared, and The Witcher 3 never got an official Linux build (despite the first and second games having Wine-wrapped releases).

Ultimately, the Steam Machines didn’t work out, and the SteamOS based on Debian was doomed, this README.txt remains in the apt repo:

SteamOS version 1 ‘alchemist’ and version 2 ‘brewmaster’ have been discontinued. No further updates are planned.

The SteamOS ‘clockwerk’ prototype has also been discontinued and will not be released.

SteamOS version 3 ‘holo’, as used on the Steam Deck, is a separate codebase based on Arch Linux packages and does not use this apt repository.

Steam Controller

Of particular note, and interesting at least to me, was the release of the Steam Controller to compliment the Steam Machines. I still have and use mine frequently, and can honestly say that having experienced a great many controllers in my life2, it really does rank quite highly.

There are probably a few reasons why it didn’t grab the mass market, but I generally boil it down to the lack of a second analogue stick, at a time when they were typical (and still are) on controllers; as well as the “weird” concept of dual trackpads in place of a D-pad and the second stick. I could wax lyrical about the brilliance and customisability of those original controllers, and maybe one day I will…

You can still see a lot of the design legacy of the Steam Controller in the Steam Deck today.

Steam Play Reborn

2018 rolled around and, being in more recent memory, many people likely remember the blog post above, and the announcement from Valve that they had been working away in the background to ‘reboot’ Steam Play as a name for the Proton compatibility layer, which was Wine with extra bits, used to play Windows games on Linux. See the previous post about Wine for how this is fundamentally possible.

Many people at the time, myself included, wondered why Valve had opted to promote Linux gaming in this fashion, and potentially put a lot of effort into a user base who typically might run Linux, but also had a Windows partition that they would boot into for gaming (some people definitely still do this.) Even so, it was welcome news.

Valve even went out of their way to contribute to upstream Wine, and commissioned Collabora to further develop the areas they needed to improve in, to make the process of gaming on Linux seamlessish.

Steam Play, or Proton as it’s now better known3, had been reborn anew, and it was awesome!

At the time of release, only a few games were “officially” supported by Valve, but the initial set soon exploded with others as people tried their entire back catalogue of Valve titles with the new tool, and found that a good portion of those games worked. Some didn’t, and others required “hacks” in the form of additional DLLs installed using winetricks (and later protontricks).

Valve even added a mechanism for developers to see which platform a game had been ‘wishlisted’ for, meaning Linux gamers could report their desire for a game to support Proton in the client. In reality, I’m not sure how much this was and is used.

Soon after the announcement, it became obvious that the best place to look for game compatibility was the GitHub Issue Tracker which was used by Valve and users to discuss problems with specific games4.

ProtonDB

ProtonDB soon appeared (October 2018~) which was and still is, the premier place to look at game compatibility on your Linux system, and your Steam Deck. Some of the information is occasionally hit-and-miss, sometimes outdated, but it’s generally a good place to get a baseline understanding of how your game might work, or what to do to make it work.

DXVK

DXVK wasn’t written with Steam in mind originally, and was reportedly simply started as a hobby project to get DirectX 10 games working in Wine, it was later sponsored by Valve and bundled into Proton directly, to support many more games than a vanilla Wine installation can out of the box.

Why not Wine?

Wine and Proton have different goals, Proton’s main aim is gaming, and therefore includes a lot of aftermarket fixes and hacks (more so in the community spins) which simply wouldn’t be acceptable to the upstream Wine Project.

Wine aims to implement Windows functions correctly even if that includes some undocumented behaviour here and there, as long as it’s ‘what Windows does’ then it’s generally fine. Wine is there to act as the solid base for other projects to build their specific use-cases on, and to be a general “all rounder” which still works great for its own needs5.

Proton is not unique in this regard, even CodeWeavers, who provide CrossOver to run Windows applications on Mac and Linux in a pleasing, paid-for, supported way, include “hacks” and fixes to make some applications work, which never make it back to upstream Wine (though they also contribute to upstream Wine too!) because their goal is to produce a product which gets a thing done, even if that thing gets done in a way which isn’t technically correct, which as we all know, is the best kind of correct.

Valve had started something with Proton, and while people were initially confused as to why this effort was going into Linux (and notably not macOS too, as macOS support was removed early in development) nobody was complaining!

Steam Deck

In 2021, July, the wider world became aware of the Steam Deck, Valve’s second adventure into the console market, and notably running a new version of their SteamOS, Holo, which was Arch based and utilised Proton to run Windows games. This time, Valve had addressed the biggest failing of their Steam Machines, the lack of games, by making the entirety of the back catalogue of Steam (theoretically) playable on a handheld console.

The trackpads, pioneered in the Steam Controller, made a triumphant return, and the Deck had two analogue sticks, two! To date, it’s reportedly sold over a million units, though Valve remains tight lipped on the actual numbers, and gamers everywhere are playing games on Linux, some of them without even realising it!

Suddenly that earlier effort Valve had put into diversifying their target installation base made more sense, if this had been in the works for some time, then it stood to reason that those developments of Proton (nee. Steam Play-ish) were the bedrock for what would become their new handheld. They were looking to the future, and keeping their options open.

Proton

We are, proverbially, where we are. The Steam Deck is a success (at the moment) and Proton makes it possible to play more games on Linux than has ever been conceivable before. Linux gamers everywhere no longer have to rely on Sauerbraten6 for their shooter fix, and even games that have anti-cheat work! Well… if the developer toggled the appropriate options, and if it didn’t break occasionally for no apparent reason7… shout out to areweanticheatyet for trying to track this.

But what actually happens when you run a game through Proton? How has it changed from the earlier releases to now? What makes Proton-GE so interesting and why do some people use it over the bundled versions?

Let’s investigate!

Versioning

There have been several bugfix and minor adjustment releases made to each of the major version releases (the first digit) so the current version that it’s possible to install is actually 3.7-8. Valve uses the major and minor versions of the Wine release that Proton is rebased against, when releasing a new version:

  • Proton 4.11-1 - Rebased to Wine 4.11
  • Proton 4.11-4 - DXVK, D9VK, FAudio updates, some small fixes.
  • Proton 5.0-1 - Rebased to Wine 5.0
  • Proton 5.0-10 - Update to Steamworks SDK, configurable log directory, etc.
  • Proton 8.0-1 - Rebased to Wine 8.0

You get the idea.

If you want to, you could pull in the assets of an older release and load them into the client manually, but this is usually not required as breaking changes aren’t common8.

Early Proton - and why it’s a bit broken

The earliest Proton release that it is possible to install through the Steam client, is version 3.7. This is the version released to support DOOM (2016), Battlefront 2 (the superior 2005 version) and a handful of other titles.

I own Into the Breach, which is one of the games that was announced as being compatible with Proton 3.7, so let’s give that a whirl on my Fedora 38 installation with 3.7 now and see what breaks.

Note: When “Steam Play” was first rejigged into its current form, titles that Valve “whitelisted” as working with “Steam Play” would show with a little indication that the game was running “via Steam Play” without you having to manually select a Proton version. At some point in the client’s history this feature was dropped, and now you have to either default select Proton for everything (as a lot of gamers do) or manually select a version for each title (as I do.) It was basically replaced by the “Verified on Deck” program.

Into the Breach actually has a Linux build as of 2020 anyway, so this test is a bit moot… but we’ll set the Proton version in the game’s properties to 3.7-8 and try a launch.

Note: steam is run from the command line to get some output to the terminal when interacting with the Steam client, this requires that Steam be closed first.

If we ignore the usual Steam warnings and errors (gameoverlayrenderer.so, etc.) our game appears to start, and then… crashes… we hit an “Unrecognised Exception” and can’t go any further.

wine: Call from 0x7b43c45c to unimplemented function lsteamclient.dll.Steam_ReleaseThreadLocalMemory, aborting

Wait… I thought this was a supported title?

Well, it is, or rather was, but the problem with this setup is that the early versions of Proton were simply a bundle of Wine files, custom Proton files, and a Wine binary (and wineserver) to get games running. They still relied on the host operating system for some scant elements, and didn’t compartmentalise as much as they could.

Valve also only targeted Ubuntu as the base Operating System, so if you happened to run Arch, Fedora, or the plethora of other options, you were basically on your own when it came to support (outside of best efforts).

Running Outside of Steam

What’s actually run, when we click ‘Play’ in the Steam client on Into the Breach is something like the following, by Steam itself:

~/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=590380 -- \
  ~/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- \
  '~/.local/share/Steam/steamapps/common/Proton 3.7'/proton waitforexitandrun \
  '~/.local/share/Steam/steamapps/common/Into the Breach/Breach.exe'

reaper is presumably used to clean up threads without a parent (reap them) it was introduced to the Steam Linux client some time in 2021.

steam-launch-wrapper seems to be exactly that, a wrapper for Steam to launch games correctly on Linux.

proton here is a Python script, which we can poke through, we can determine that it:

  • Immediately states that it’s there to wrap wine with the correct environment
  • Upgrades from one Proton prefix to another if required
  • Checks for a compat data path (see below)
  • Checks for user-supplied environment variables such as PROTON_USE_WINED3D11
  • A bunch of VR stuff for working with VR
  • Applies any custom DLL overrides
  • Checks if the game is 32 or 64 bit
  • Runs Wine
  • etc.

Breaking the run command (literally %command% in Steam) down, and attempting to run it outside of Steam, gives us the following:

Proton: No compat data path?

This is because Steam, and Proton, set several environment variables which are required for execution of games, some of these should be familiar to you (like WINEPREFIX) and others will be non-obvious.

Variable Discovery - environ method

We can discover a list by leaving the process executing (the game running, even while crashed) and grabbing the environment list:

$ cat /proc/$(pidof Breach.exe)/environ | tr '\0' '\n' 

Immediately we can see some familiar variables, there’s some bundled overrides to use the “native” versions of dxgi and d3d11. We’ve got a Wine prefix (C drive) per game. Specific DLL paths are being included. Steam is being told where its compatdata for the game in question actually lives.

This method gives you everything though, and includes variables which aren’t needed for game execution.

Variable Discovery - run method

In an easier fashion, we can also get a list of the environment variables that a game expects to have available, to enable it to run, as well as supporting libraries. If we set our launch command to PROTON_DUMP_DEBUG_COMMANDS=1 %command% in Steam, a run file in the /tmp directory is created, which sets the required environment variables, prior to trying to execute the game. It’ll appear as /tmp/proton_<youruser>/run by default.

We can see that the following needs to be set, in order that a game be executed correctly:

  • cd into the game’s common directory
  • PATH which includes the Proton /bin and Steam Runtime /bins
  • TERM
  • WINEDLLPATH that includes the 3.7 bundled path in this case
  • LD_LIBRARY_PATH which again, includes the 3.7 .so files, and Steam Runtime library paths
  • WINEPREFIX for our compatdata directory (C drive)
  • WINEESYNC setting
  • SteamGameId ID
  • SteamAppId ID (the same as above)
  • WINEDLLOVERRIDES for the game, set by Steam
  • STEAM_COMPAT_CLIENT_INSTALL_PATH which points to the Steam client install path… unsurprisingly…

In this way, the game gets the required Steam library files, the bundled Wine files, and the execution environment correct. We still get errors when trying to run the game, but crucially it should launch in the same way as it would do through Steam, simply by executing this file. Because of this we can add to the run script with additional options (like +loaddll) and try to debug as we would any other Wine program.

Note: While this can also be used to run games outside of Steam, a lot of games depend on a running Steam client for some of their functionality, such as multiplayer, and some games might refuse to start at all without Steam also running.

Some of the Problems

Some quirks with these old versions of Proton might include:

  • Games have updated, and the version of Wine that Proton is based on might not support a new function.
  • The old Proton version might fail to run on a more recent OS, as the Wine components themselves struggle with shared libraries which cannot be bundled with the Steam client (uncommon).
  • Games have updated to use a new Steam function (as appears to be the case here) and the older, bundled Proton .dll doesn’t support the new function.

How can we resolve these issues?

Proton, Steam Linux Runtime, Bubblewrap, and Pressure Vessel

Starting with Proton 5.13 Valve aimed to solve some of the problems with their Proton builds by making use of a parallel technology they’d contracted Collabora to produce, called Pressure Vessel.

Proton was rebuilt utilising Pressure Vessel to make use of a container runtime which includes newer library versions than those bundled with Steam (though not necessarily newer than your host OS.) This gives Proton a more predictable environment in which to execute, cutting out some dependencies on the host operating system, which might not be Ubuntu or SteamOS (1,2, or 3).

Steam Linux Runtime - Scout, Soldier, Sniper, and beyond

Simon McVittie did an excellent talk on the “Linux namespace” support that was added to Steam, in the form of the Steam Linux Runtime update.

Prior to this addition of “container support” the Steam Linux Runtime existed as far back as 2013, and was/is a way for Valve to ensure that Linux native games have access to the appropriate libraries required to run, across many Linux systems. The first, non-containerised, version bundled with Steam was codenamed ‘Scout’ after the TF2 character.

The first version of SLR had some problems, mostly that it still needed to work with your “core” host libraries, and that developers could still do things like build their applications against libraries on their own system and forget to ship them.

In the updated version, pressure-vessel Steam itself still used the Scout runtime, but a child process bubblewrap, makes a container. This container originally had a “very strict” Scout environment. If your game is built against the Scout environment (or later, the Sniper runtime,) this should then work fine.

pressure-vessel does some “mad hacks” to make some dependent systems work inside the container, such as ensuring your host system’s graphics drivers are available inside the container.

The Soldier runtime (Steam Runtime 2) is the one used for Proton 5.13 or later.

So…

  • Native Linux games compiled against a strict Scout environment probably still run without any additional configuration. They’re just using Steam’s local Scout environment (assuming those bundled libraries still work against your host’s) and don’t need bubblewrap to make them a pressure-vessel.
  • Native Linux games not compiled against the strict Scout environment can be selected to use “Steam Linux Runtime” from the Steam client, or ‘made to’ at release, which starts a Soldier container, which then sets the Scout LD_LIBRARY_PATH runtime from inside the Soldier container.
  • Native Linux games can’t require or be built against Soldier directly.
  • Native Linux games can require the newer-than-Soldier runtime (3) codenamed Sniper.
  • Non-native games configured to start with Proton <= 5.0 will run wine using the Steam Scout environment, and your host system’s files where appropriate.
  • Non-native games configured to start with Proton >= 5.13 will start wine inside a Soldier (or newer) pressure-vessel container, using the Soldier runtime.

Yep, it’s confusing.

Half Life Native

By way of example, this is what loading a simple, native install of Half Life looks like, with no additional configuration:

"/~/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=70 -- \
  /~/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- \
  '/~/.local/share/Steam/steamapps/common/Half-Life/hl.sh' -steam"

Note that it just starts the hl.sh script, when we inspect the process, we see that it’s including the standard Linux runtime environment (bundled with the client) and isn’t doing anything with containers.

Half Life Native - SRL Selected

Conversely, running is with “Steam Linux Runtime” selected from properties, forces the Soldier container to be started and the Scout runtime inside that container to be used:

"/~/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=70 -- \
  /~/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- \
  '/~/.local/share/Steam/steamapps/common/SteamLinuxRuntime_soldier'/_v2-entry-point
  --verb=waitforexitandrun -- \
  '/~/.local/share/Steam/steamapps/common/SteamLinuxRuntime'/scout-on-soldier-entry-point-v2
  --  \'/~/.local/share/Steam/steamapps/common/Half-Life/hl.sh' -steam"

The _soldier entrypoint shell script, complete with a warning about it being a ‘prototype’, sets up our Soldier container environment. Then the scout-on-soldier command is run inside the Soldier container to utilise the bundled Scout libraries (Steam Runtime Environment.)

Half Life Proton - 5.0-10

Choosing a Proton release that didn’t make use of the Soldier container (Pressure Vessel) results in the following start command:

"/~/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=70 -- \
  /~/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- \
  '/~/.local/share/Steam/steamapps/common/Proton 5.0'/proton waitforexitandrun \
  '/~/.local/share/Steam/steamapps/common/Half-Life/hl.exe' -steam"

So simply runs Proton and Wine as we already know.

Half Life Proton - 5.13-6

And finally, using Proton which uses a Pressure Vessel container:

"/~/.local/share/Steam/ubuntu12_32/reaper SteamLaunch AppId=70 -- \
  /~/.local/share/Steam/ubuntu12_32/steam-launch-wrapper -- \
  '/~/.local/share/Steam/steamapps/common/SteamLinuxRuntime_soldier'/_v2-entry-point
  --verb=waitforexitandrun -- \
  '/~/.local/share/Steam/steamapps/common/Proton 5.13'/proton \
  waitforexitandrun '/~/.local/share/Steam/steamapps/common/Half-Life/hl.exe' -steam"

This starts our Soldier container, critically not using the Scout Runtime, but the newer Soldier one instead, and runs Proton.

Phew…

Why Proton and Pressure Vessel?

You might be asking why one might build Proton using the Soldier Steam Runtime Environment, but it’s a fairly obvious answer I’m afraid. It’s a known environment, and Valve can be sure that the Proton execution is happening in a way that’s 99% consistent between installations9.

Proton-GE and Wine-GE

It would be remiss of me to not mention the Glorious Eggroll builds of Proton and Wine, which are extremely popular amongst gamers who want those extra elements of polish which Valve can’t, or choose not to, add to their official Proton builds.

Proton-GE is a version provided by the eponymous Glorious Eggroll which adds additional workarounds and fixes for specific games which Valve, for one reason or another, haven’t included. One example are additional media foundation patches to make some video playback work, Valve supposedly cannot include these sorts of fixes for “legal reasons” which is understandable.

Proton-GE can be a good choice for games which might be fixed with haemorrhaging
edge patches from upstream Wine, that Valve hasn’t incorporated yet, or which require specific protontricks fixes and configuration which Valve hasn’t (yet) put into place, but which the community can easily contribute.

There is a big warning on the homepage of Proton-GE stating that Proton is not to be used outside of Steam, we should now have a good idea of why this is, because Steam provides the Runtime which Proton runs within. Indeed, running GE-Proton7-54 as the compatibility tool for our Half Life install, shows that this still runs in the Soldier container.

For running outside of Steam, GE has also provided Wine-GE which specifically caters to those people who want the haemorrhaging edge Wine fixes, and other fixes (like Media Foundation).

Wine-GE is generally best used in conjunction with a manager, such as Lutris, Bottles, Heroic, and the like. These programs usually unpack the custom Wine installations into their own ‘runner’ directories, and then calls these when directed to against specific games. Wine-GE can be a good choice for games provided by GOG, Blizzard, and if you really hate yourself, Epic.

Helper tools exist to make managing these custom installations easier, like ProtonUp.

Steam Flatpak

If you’re using a distribution or a version of your favourite Linux flavour which chooses to use Flatpaks instead of traditional packaging methods, you might find yourself installing the unofficial Flatpak version of Steam.

This can be a good choice, but you should be aware of some caveats.

Proton, Proton-GE, gamescope, and a few other “add-ons” can be installed alongside your Steam Flatpak, and this used to be the preferred way to install these components. You can also install them as you would traditionally, using the Steam Client.

Pressure Vessel is supported in Steam Flatpak, though this didn’t used to be the case, see here for detailed information.

Preferring Proton Over Native

Why might you use Proton, even if a game supports Linux?

This is a perfectly valid question, and one that I should probably answer now that I’ve been gaming on Linux for a great many years.

In truth, I usually just play whichever version works. In a perfect world I would love for developers to support Linux, or at least support a default runtime like the Freedesktop Flatpak one, or the Valve Sniper Runtime (3) release, but the honest truth is that there’s not a big enough Linux user-base to usually do this.

That might change with the Steam Deck, and we’re already seeing some advancements, but generally developers are still choosing to target Windows, and are then “checking” that it works on Linux (or the Steam Deck,) through Proton. As a selfish and entitled gamer nerd, the fact it works under any runtime is good enough.

I also install the Windows versions of games to get around problems sometimes, historically Linux releases have usually been fine but have occasionally lagged behind their Window’s counterparts for DLC releases, bugfixes, and the like. This is not a blanket statement, some publishers are better than others, but coupled into this is my next point.

A lot of games don’t support cross-play, or it breaks easily. Running the Windows version of Civilization 6, and Crusader Kings 3, means that I can play with my Windows heathen friends without worrying about desyncs and compatibility issues.

So yes, there are still reasons to choose a non-native build of a game, over a Linux one, I have 13 Linux native games installed in Steam at present, and 42 Proton ones, read into that what you will.

Looking to the Future

Here are some closing thoughts on Proton, and what I would like to see in the future.

Firstly, Proton and Valve’s commitment to gaming on Linux has propelled us much further than we’ve ever been before. I’ve said it before and I’ll say it again, we’ve got a lot to be thankful for to one company (and those companies they hire) even if their interests are (understandably) economical.

That said, I would love to still see improvements around anti-cheat. I considered talking about the Proton EasyAntiCheat Runtime in this post, but it’s a big topic and this post is long enough as it is, so I’m going to leave it for another day.

I would like to hope that other companies could also follow Valve’s approach. And support Linux by way of Wine, or perhaps other systems, before considering a release. This could be as simple as paying CodeWeavers to consult on your build and ensure it works before release, and would win a good degree of good grace with the Linux and Steam Deck communities for low, low consultancy fees.

Thank you for reading.

References

https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/blob/main/docs/container-runtime.md
https://archive.fosdem.org/2020/schedule/event/containers_steam/
https://gitlab.steamos.cloud/steamrt
https://steamcommunity.com/app/221410/discussions/0/1638675549018366706/
https://steamcommunity.com/games/221410/announcements/detail/1696055855739350561
https://github.com/flatpak/flatpak/issues/3797


  1. Speaking as the proud owner of both the Earbuds and a Tux doll in TF2. ↩︎

  2. I own a Philips CD-i “TV-style” controller! ↩︎

  3. One has to wonder why they decided to re-use the existing Steam Play namespace for this. ↩︎

  4. I spent a particularly long amount of time keeping my eye on the issue for Beyond Good & Evil↩︎

  5. I run Wine to use Scrivener on my system, I wouldn’t dream of using Proton for such a use-case. ↩︎

  6. But I still love it. ↩︎

  7. Looking at you, Vermintide 2. ↩︎

  8. Not common, but they still happen… ↩︎

  9. There are still other things in the wonderfully varied Linux landscape which can cause issues, such as the filesystem that’s in use. Some games just won’t run on XFS systems. ↩︎