https://rosenzweig.io/blog/aaa-gaming-on-m1.html
AAA gaming on Asahi Linux
10 Oct 2024
Gaming on Linux on M1 is here! We're thrilled to release our Asahi
game playing toolkit, which integrates our Vulkan 1.3 drivers with
x86 emulation and Windows compatibility. Plus a bonus: conformant
OpenCL 3.0.
Asahi Linux now ships the only conformant OpenGL(r), OpenCL(tm), and
Vulkan(r) drivers for this hardware. As for gaming... while today's
release is an alpha, Control runs well!
Control
Installation
First, install Fedora Asahi Remix. Once installed, get the latest
drivers with dnf upgrade --refresh && reboot. Then just dnf install
steam and play. While all M1/M2-series systems work, most games
require 16GB of memory due to emulation overhead.
The stack
Games are typically x86 Windows binaries rendering with DirectX,
while our target is Arm Linux with Vulkan. We need to handle each
difference:
* FEX emulates x86 on Arm.
* Wine translates Windows to Linux.
* DXVK and vkd3d-proton translate DirectX to Vulkan.
There's one curveball: page size. Operating systems allocate memory
in fixed size "pages". If an application expects smaller pages than
the system uses, they will break due to insufficient alignment of
allocations. That's a problem: x86 expects 4K pages but Apple systems
use 16K pages.
While Linux can't mix page sizes between processes, it can virtualize
another Arm Linux kernel with a different page size. So we run games
inside a tiny virtual machine using muvm, passing through devices
like the GPU and game controllers. The hardware is happy because the
system is 16K, the game is happy because the virtual machine is 4K,
and you're happy because you can play Fallout 4.
Fallout 4
Vulkan
The final piece is an adult-level Vulkan driver, since translating
DirectX requires Vulkan 1.3 with many extensions. Back in April, I
wrote Honeykrisp, the only Vulkan 1.3 driver for Apple hardware. I've
since added DXVK support. Let's look at some new features.
Tessellation
Tessellation enables games like The Witcher 3 to generate geometry.
The M1 has hardware tessellation, but it is too limited for DirectX,
Vulkan, or OpenGL. We must instead tessellate with arcane compute
shaders, as detailed in today's talk at XDC2024.
The Witcher 3
Geometry shaders
Geometry shaders are an older, cruder method to generate geometry.
Like tessellation, the M1 lacks geometry shader hardware so we
emulate with compute. Is that fast? No, but geometry shaders are slow
even on desktop GPUs. They don't need to be fast - just fast enough
for games like Ghostrunner.
Ghostrunner
Enhanced robustness
"Robustness" permits an application's shaders to access buffers
out-of-bounds without crashing the hardware. In OpenGL and Vulkan,
out-of-bounds loads may return arbitrary elements, and out-of-bounds
stores may corrupt the buffer. Our OpenGL driver exploits this
definition for efficient robustness on the M1.
Some games require stronger guarantees. In DirectX, out-of-bounds
loads return zero, and out-of-bounds stores are ignored. DXVK
therefore requires VK_EXT_robustness2, a Vulkan extension
strengthening robustness.
Like before, we implement robustness with compare-and-select
instructions. A naive implementation would compare a loaded index
with the buffer size and select a zero result if out-of-bounds.
However, our GPU loads are vector while arithmetic is scalar. Even if
we disabled page faults, we would need up to four compare-and-selects
per load.
load R, buffer, index * 16
ulesel R[0], index, size, R[0], 0
ulesel R[1], index, size, R[1], 0
ulesel R[2], index, size, R[2], 0
ulesel R[3], index, size, R[3], 0
There's a trick: reserve 64 gigabytes of zeroes using virtual memory
voodoo. Since every 32-bit index multiplied by 16 fits in 64
gigabytes, any index into this region loads zeroes. For out-of-bounds
loads, we simply replace the buffer address with the reserved address
while preserving the index. Replacing a 64-bit address costs just two
32-bit compare-and-selects.
ulesel buffer.lo, index, size, buffer.lo, RESERVED.lo
ulesel buffer.hi, index, size, buffer.hi, RESERVED.hi
load R, buffer, index * 16
Two instructions, not four.
Next steps
Sparse texturing is next for Honeykrisp, which will unlock more DX12
games. The alpha already runs DX12 games that don't require sparse,
like Cyberpunk 2077.
Cyberpunk 2077
While many games are playable, newer AAA titles don't hit 60fps yet.
Correctness comes first. Performance improves next. Indie games like
Hollow Knight do run full speed.
Hollow Knight
Beyond gaming, we're adding general purpose x86 emulation based on
this stack. For more information, see the FAQ.
Today's alpha is a taste of what's to come. Not the final form, but
enough to enjoy Portal 2 while we work towards "1.0".
Portal 2
Acknowledgements
This work has been years in the making with major contributions from...
* Alyssa Rosenzweig
* Asahi Lina
* chaos_princess
* Davide Cavalca
* Dougall Johnson
* Ella Stanforth
* Faith Ekstrand
* Janne Grunau
* Karol Herbst
* marcan
* Mary Guillemard
* Neal Gompa
* Sergio Lopez
* TellowKrinkle
* Teoh Han Hui
* Rob Clark
* Ryan Houdek
... Plus hundreds of developers whose work we build upon, spanning the
Linux, Mesa, Wine, and FEX projects. Today's release is thanks to the
magic of open source.
We hope you enjoy the magic.
Happy gaming.
Back to home