IW4L_PIPELINED_RENDERING=1 panicked on the first frame on macOS ("can only
access NSView on the main thread" in raw-window-metal), which is why the
default is off there. Bevy's create_surfaces takes a NonSendMarker so that
the multi-threaded executor hands it back to the main thread, but the render
app's Render schedule runs on a single-threaded executor. With pipelining on
that schedule runs on the render thread, so create_surfaces built the
CAMetalLayer there and touched the NSView off the main thread.
With pipelining on, macOS now also runs create_surfaces in the render app's
ExtractSchedule, after extract_cameras and so after the windows are
extracted. Extraction runs on the main thread, so the surface is created and
configured there. The Render schedule's instance then finds it configured
and skips, or after a resize reconfigures it, which only sets CAMetalLayer
properties and is allowed off the main thread.
The macOS default stays off, so nothing changes unless
IW4L_PIPELINED_RENDERING=1 is set. docs/BUILD.md now says how to turn it on
instead of pointing at the plugins.rs explanation this removes.
Measured on an Apple M3 (mp_terminal, 9 bots, uncapped present, bench
recorder), pipelining off -> on: 87 -> 105 fps average, frame p50 10.8 ->
8.3 ms, p99 19.4 -> 18.4 ms, worst frames about the same (36 -> 34 ms),
main/render overlap 5.4 ms per frame, presented state one frame older.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2.1 KiB
Build dependencies
Rust stable via rustup (rust-toolchain.toml pins it), plus a C toolchain
and the Bevy system libs. IW4L enables both x11 and wayland
(Cargo.toml), so the Wayland headers stay required. Gamepad input and
rumble (bevy_gilrs) link libudev, so the udev headers (systemd-devel /
libudev-dev) are required too.
# Fedora
sudo dnf install gcc-c++ pkgconf-pkg-config libX11-devel alsa-lib-devel systemd-devel wayland-devel libxkbcommon-devel
# Debian / Ubuntu
sudo apt install g++ pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
# Arch / Manjaro
sudo pacman -S gcc pkgconf libx11 alsa-lib systemd wayland libxkbcommon libxcursor libxrandr libxi
Upstream list (other distros, GPU Vulkan drivers): Bevy
linux_dependencies.md.
What is not needed for a native Linux build: clang / llvm / lld /
glibc-static — plain gcc-c++ links it. llvm (the llvm-lib tool) is
only required for the Windows cross build:
sudo dnf install llvm # Fedora: provides llvm-lib
make setup-windows # rustup target + cargo-xwin, once
macOS needs only the Xcode command line tools (xcode-select --install)
and rustup: winit, wgpu (Metal), CoreAudio and gilrs link system frameworks,
and the x11 / wayland features compile to nothing. Menu and
make map mp_boneyard run on Apple silicon (M2 Max, Metal). Pipelined
rendering is off by default there; IW4L_PIPELINED_RENDERING=1 turns it on.
Game data: the Windows depot of a Steam copy, steamcmd +@sSteamCmdForcePlatformType windows +force_install_dir ~/Games/MW2 +login <user> +app_update 10190 +quit, then IW4L_GAMES=~/Games.
Then follow README.md (Build and run): copy .env.example, set
IW4L_GAMES, make map mp_boneyard. Portable Windows is
WINDOWS.md.
Match metadata uses the Git commit count as its numeric build number. Release
builders can set IW4L_BUILD_NUMBER; source archives need this variable. The
package version remains the textual build version.