Merge remote-tracking branch 'origin/main' into pr-fix-129

This commit is contained in:
lucannez64 committed 2026-10-25 19:28:43 +01:00
commit 82bc150d30
10 files changed
+135 -18

No files matched your search

+9
View File
@@ -164,3 +164,12 @@ keeps no identity of its own, so it reports the same values as IOKit, including
override saved by this tool. A field the guest does not provide is left out.
`python3 -m unittest tests.test_system_profiler` checks the output with stub
commands.
`SPDisplaysDataType` reads the host DRM cards. With `DARLING_METAL_MAC_GPU_NAME`
set (the launcher default), an AMD or NVIDIA host card is reported as the
`MacBookPro16,1` discrete GPU: `AMD Radeon Pro 5500M`, vendor `0x1002`, device
`0x7340`, bus PCIe and VRAM from `DARLING_METAL_VRAM_MB` (4096 by default; a
value that is not a positive decimal keeps the default). An Intel card is
reported as `Intel UHD Graphics 630` on bus Built-In with shared memory, as
`MTLDevice.name` does. This keeps the display report consistent with Metal;
without the variable the host card is reported as-is.
+1 -1
View File
@@ -196,7 +196,7 @@ The hand-off experiments (`metal-present-dispatch-wait`, `metal-deferred-blit` a
| `/tmp/metal-skip-cpu-devices` | software Vulkan devices (lavapipe) are skipped while a hardware device exists |
| `/tmp/metal-gpu` | diagnostic: selects the Vulkan device used for Metal by index or case-insensitive name substring instead of the loader's first device. The OpenGL context that presents does not follow it; see [hybrid laptops](TROUBLESHOOTING.md#hybrid-graphics-laptops-amdintel-igpu--nvidia). `METAL_INDIUM_GPU` is the environment equivalent; the file wins |
| `/tmp/metal-all-devices` | a `VkDevice` is created for every supported Vulkan device, as before 2026-10-16. Without it only the selected device gets one; on a machine with lavapipe installed this also drops lavapipe's idle rasterizer threads |
| `/tmp/metal-no-drawable-vram` | drawables of a layer with `framebufferOnly` off (League sets it off) go back to host-visible system RAM, as before 2026-10-16. Without the file they are allocated in GPU memory like `framebufferOnly` drawables; nothing maps drawable memory from the CPU. On the RX 6600 this gave about 20 FPS more in a practice-tool fight and the same FPS when idle, not yet measured in an ARAM. `/tmp/metal-device.log` shows `drawable-vram=on` and `storage=vram` |
| `/tmp/metal-no-drawable-vram` | drawables of a layer with `framebufferOnly` off (League sets it off) go back to host-visible system RAM, as before 2026-10-16. Without the file they are allocated in GPU memory like `framebufferOnly` drawables; nothing maps drawable memory from the CPU. On the RX 6600 this gave about 20 FPS more in a practice-tool fight and the same FPS when idle, not yet measured in an ARAM. `/tmp/metal-device.log` (with `DARLING_METAL_DEVICE_LOG=1`) shows `drawable-vram=on` and `storage=vram` |
| `/tmp/metal-no-lazy-wakeup` | every completion registration signals the event loop's wake-up semaphore from the CPU again, as before 2026-10-18. The handshake is per device. Without the file a registration signals only while the poller has announced a blocking wait (a spinning poller re-reads the registrations on its next pass, and its spin ends when one arrives). On the NVIDIA proprietary driver each `vkSignalSemaphore` is an RM control ioctl that waits on a driver-wide lock, about 0.3 ms each and ~25 per League frame, and it was the largest kernel cost of the submit worker. Re-read every 256 registrations; the wait log counts `wakeupSignalled` and `wakeupSkipped` |
| `/tmp/metal-submit-batch-us` | the submit batch window in microseconds (500–100000, default 500); re-read every 256 checks, so it can be changed during a match. A presenting commit and every CPU wait still flush the batch at once. On the NVIDIA proprietary driver every `vkQueueSubmit2` is an RM control ioctl that waits on a driver-wide lock (about 0.4 ms each in a League match); with the default window a frame took about 8.5 submits, with `5000` about 2.5 (RTX 4090: 89 → 113 FPS, same match) |
| `/tmp/metal-submit-batch-max` | command buffers per batch (1–256, default 16), re-read like the window; `64` lets one batch hold a whole frame |
+34 -1
View File
@@ -558,7 +558,7 @@ The guest file `/tmp/metal-gpu` (a device index or part of its name, for example
### Check which GPU rendered
Each process that uses Metal appends to guest `/tmp/metal-device.log` (host `~/.darling/private/tmp/metal-device.log`): every Vulkan device the loader reported, the selected one and why, and the renderer of the presenting OpenGL context with both device UUIDs:
With `DARLING_METAL_DEVICE_LOG=1` in the launcher environment, each process that uses Metal appends to guest `/tmp/metal-device.log` (host `~/.darling/private/tmp/metal-device.log`): every Vulkan device the loader reported, the selected one and why, and the renderer of the presenting OpenGL context with both device UUIDs. The log is off by default because the guest can read it and it names the host GPU:
```
[MetalDevice] pid=… physical name="NVIDIA GeForce RTX 3060 Laptop GPU" type=discrete vendorID=0x10de … supported=yes
@@ -767,3 +767,36 @@ install the QuartzCore and OpenGL changes. Until updated, disable in-game
VSync to use the game's frame cap, as the issue reporter confirmed. Physical
scanout timing still depends on the driver and desktop compositor; the fix
has standalone regression coverage but needs an in-game timing retest.
## Installer aborts on `/proc/<pid>/fdinfo`
[Issue #38](https://github.com/lucannez64/darling-lol/issues/38) reports an
uncaught `ghc::filesystem::filesystem_error` with `Permission denied` on
`/proc/<pid>/fdinfo`. `ghc::filesystem` is a C++ filesystem library, not evidence
that the Riot installer is written in Haskell.
An independent guest/native Vulkan probe reproduced this exact exception with
MangoHud 0.8.4 enabled on 2026-10-18. MangoHud's `GPU_fdinfo::find_fd()` builds
`/proc/<getpid()>/fdinfo` and uses a throwing directory iterator. Inside Darling,
the native library's PID is in the guest PID namespace while its native `/proc`
view can still refer to host processes: the probe's native PID 35 resolved to an
inaccessible host process. The same probe completed Vulkan instance, device and
swapchain creation with MangoHud disabled. This does not establish the cause of
every installer abort; confirmation from the original reporter remains pending.
The normal launcher now unsets `MANGOHUD` and exports `DISABLE_MANGOHUD=1` before
runtime helpers start, including first-time installation. This disables inherited
implicit MangoHud activation for the launched session without changing the host
configuration. Do not wrap the launcher in `mangohud` or explicitly force its
Vulkan layer. Updating these launcher scripts needs no Darling rebuild. For an
older checkout, use:
```sh
env -u MANGOHUD DISABLE_MANGOHUD=1 ./scripts/installer.sh euw
```
Do not run the installer as root or change `/proc` permissions. If it still
fails, include the exception and whether a host overlay was enabled; redact
account tokens from logs.
Upstream source: [MangoHud 0.8.4 fdinfo scan](https://github.com/flightlessmango/MangoHud/blob/v0.8.4/src/gpu_fdinfo.cpp#L9).
+7 -3
View File
@@ -10116,12 +10116,13 @@ diff --git a/QuartzCore/CAMetalDrawable.mm b/QuartzCore/CAMetalDrawable.mm
index d6f86b31..687f05d5 100644
--- a/QuartzCore/CAMetalDrawable.mm
+++ b/QuartzCore/CAMetalDrawable.mm
@@ -31,6 +31,13 @@
@@ -31,6 +31,14 @@
#include <OpenGL/glext.h>
#include <indium/indium.private.hpp>
+#include <atomic>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <mutex>
+#include <string>
@@ -10130,7 +10131,7 @@ index d6f86b31..687f05d5 100644
namespace DynamicVK = Indium::DynamicVK;
static void reportGLErrors(void) {
@@ -50,8 +57,111 @@ static void reportGLErrors(void) {
@@ -50,8 +57,114 @@
namespace Indium::DynamicVK {
static DynamicFunction<PFN_vkGetSemaphoreFdKHR> vkGetSemaphoreFdKHR("vkGetSemaphoreFdKHR");
static DynamicFunction<PFN_vkGetMemoryFdKHR> vkGetMemoryFdKHR("vkGetMemoryFdKHR");
@@ -10154,8 +10155,11 @@ index d6f86b31..687f05d5 100644
+ }
+}
+
+// Same line format as Indium's device log.
+// Same line format as Indium's device log; off unless DARLING_METAL_DEVICE_LOG is
+// set, so the guest-readable file does not name the host GPU by default.
+static void appendDeviceLog(const std::string& line) {
+ const char* enabled = getenv("DARLING_METAL_DEVICE_LOG");
+ if (!enabled || !*enabled || (enabled[0] == '0' && !enabled[1])) return;
+ if (FILE* log = fopen("/tmp/metal-device.log", "a")) {
+ fprintf(log, "[MetalDevice] pid=%d %s\n", getpid(), line.c_str());
+ fclose(log);
+5 -2
View File
@@ -2919,7 +2919,7 @@ index 322e186..f712c7a 100644
#include <indium/instance.private.hpp>
#include <indium/command-queue.private.hpp>
#include <indium/render-pipeline.private.hpp>
@@ -12,39 +17,207 @@
@@ -12,39 +17,210 @@
#include <iridium/iridium.hpp>
@@ -2946,8 +2946,11 @@ index 322e186..f712c7a 100644
+ // device list is built, plus one when the presenting OpenGL context first
+ // imports a Vulkan drawable. It exists so a user can tell us which GPU
+ // actually rendered a match, which the game's own logs and FPS numbers do not
+ // show.
+ // show. Off by default: the guest can read this file, so enabling it names the
+ // host GPU to anything running in the prefix. Set DARLING_METAL_DEVICE_LOG=1.
+ void appendDeviceLog(const std::string& line) {
+ const char* enabled = getenv("DARLING_METAL_DEVICE_LOG");
+ if (!enabled || !*enabled || (enabled[0] == '0' && !enabled[1])) return;
+ if (FILE* log = fopen("/tmp/metal-device.log", "a")) {
+ fprintf(log, "[MetalDevice] pid=%d %s\n", getpid(), line.c_str());
+ fclose(log);
+15 -3
View File
@@ -23,10 +23,12 @@ REQUIRED = {
'__NV_PRIME_RENDER_OFFLOAD': '1', '__EGL_VENDOR_LIBRARY_FILENAMES': '/usr/share/glvnd/egl_vendor.d/10_nvidia.json',
'VK_ICD_FILENAMES': '/usr/share/vulkan/icd.d/nvidia_icd.json', 'LIBGL_ALWAYS_SOFTWARE': '0',
'LD_PRELOAD': 'libgamemodeauto.so.0', 'LD_LIBRARY_PATH': '/run/opengl-driver/lib',
'HOME': '/home/u', 'USER': 'u', 'PATH': '/usr/bin:/bin', 'LANG': 'en_US.UTF-8', 'TERM': 'xterm',
'HOME': '/home/u', 'USER': 'u', 'PATH': '/usr/bin:/bin', 'LANG': 'en_US.UTF-8',
'DPREFIX': '/home/u/.darling', 'RCLOL_REFRESH_HZ': '144', 'DYLD_LIBRARY_PATH': '/Users/u/RuntimeLibraries',
}
SESSION = {
'TERM': 'xterm', 'STARSHIP_SESSION_KEY': 'host-prompt', 'AWS_PROFILE': 'host-profile',
'GIT_CONFIG_GLOBAL': '/home/u/.gitconfig', 'EDITOR': '/bin/host-editor',
'WAYLAND_DISPLAY': 'wayland-0', 'XDG_CURRENT_DESKTOP': 'GNOME', 'XDG_SESSION_TYPE': 'wayland',
'XDG_SESSION_ID': '2', 'XDG_SEAT': 'seat0', 'DESKTOP_SESSION': 'gnome', 'GDMSESSION': 'gnome',
'GDM_LANG': 'en_US.UTF-8', 'SESSION_MANAGER': 'local/host:@/tmp/.ICE-unix/1', 'GNOME_SETUP_DISPLAY': ':1',
@@ -45,7 +47,13 @@ class FilterTests(unittest.TestCase):
environ = {**REQUIRED, **SESSION, 'SHELL': '/bin/fish'}
removed = exec_guest.filter_host_environment(environ)
self.assertEqual(set(removed), set(SESSION))
self.assertEqual(environ, {**REQUIRED, 'SHELL': '/bin/zsh'})
self.assertEqual(environ, {**REQUIRED, 'SHELL': '/bin/zsh', 'PATH': '/usr/bin:/bin:/usr/sbin:/sbin'})
def test_explicit_keep_preserves_host_path_and_terminal(self):
environ = {'PATH': '/custom/bin', 'TERM': 'xterm',
'RCLOL_KEEP_HOST_ENV': 'PATH TERM', 'RCLOL_FILTER_HOST_ENV': '1'}
self.assertEqual(exec_guest.filter_host_environment(environ), [])
self.assertEqual(environ, {'PATH': '/custom/bin', 'TERM': 'xterm', 'SHELL': '/bin/zsh'})
def test_keep_list(self):
environ = {'WAYLAND_DISPLAY': 'wayland-0', 'SSH_AUTH_SOCK': '/s', 'SHELL': '/bin/fish',
@@ -53,6 +61,7 @@ class FilterTests(unittest.TestCase):
self.assertEqual(exec_guest.filter_host_environment(environ), ['SSH_AUTH_SOCK'])
self.assertEqual(environ['WAYLAND_DISPLAY'], 'wayland-0')
self.assertEqual(environ['SHELL'], '/bin/fish')
self.assertNotIn('RCLOL_KEEP_HOST_ENV', environ)
class ExecTests(unittest.TestCase):
@@ -82,8 +91,11 @@ class ExecTests(unittest.TestCase):
self.assertEqual(child['fds'], [0, 1, 2])
self.assertFalse(set(SESSION) & set(child['env']))
for name, value in REQUIRED.items():
self.assertEqual(child['env'].get(name), value, name)
expected = '/usr/bin:/bin:/usr/sbin:/sbin' if name == 'PATH' else value
self.assertEqual(child['env'].get(name), expected, name)
self.assertEqual(child['env']['SHELL'], '/bin/zsh')
self.assertNotIn('RCLOL_FILTER_HOST_ENV', child['env'])
self.assertNotIn('RCLOL_KEEP_HOST_ENV', child['env'])
if __name__ == '__main__':
+27 -6
View File
@@ -35,7 +35,11 @@ pci_name() { # vendor device (hex without 0x) -> "Vendor Model"
done
}
displays() { # one line per GPU: vendor|device|vram MB or empty|name
displays() { # one line per GPU: vendor|device|vram MB or empty|name|bus
# Same switch as the Metal device name: a Mac profile presents the MacBookPro16,1
# discrete GPU instead of the host card, so system_profiler and Metal agree.
mac_spoof=0
case "${DARLING_METAL_MAC_GPU_NAME:-}" in '') ;; 0) ;; *) mac_spoof=1;; esac
for card in "$host"/sys/class/drm/card[0-9] "$host"/sys/class/drm/card[0-9][0-9]; do
[ -r "$card/device/vendor" ] || continue
vendor=$(sed 's/^0x//' "$card/device/vendor"); device=$(sed 's/^0x//' "$card/device/device")
@@ -44,7 +48,23 @@ displays() { # one line per GPU: vendor|device|vram MB or empty|name
vram=$(awk '{ printf "%d", $1 / 1048576 }' "$card/device/mem_info_vram_total")
fi
name=$(pci_name "$vendor" "$device"); [ -n "$name" ] || name="Display"
echo "$vendor|$device|$vram|$name"
bus=builtin
if [ "$mac_spoof" = 1 ]; then
case "$vendor" in
1002|10de) vendor=1002; device=7340; name='AMD Radeon Pro 5500M'
vram=${DARLING_METAL_VRAM_MB:-4096}
case "$vram" in ''|*[!0-9]*) vram=4096;; esac
# Keep the numeric test overflow-safe: a long digit string must
# fall back before the shell compares it.
if [ "${#vram}" -gt 7 ] || [ "$vram" -eq 0 ] || [ "$vram" -gt 1048576 ]; then
vram=4096
fi
bus=pcie;;
8086) vendor=8086; device=3e9b; name='Intel UHD Graphics 630'
vram=; bus=builtin;;
esac
fi
echo "$vendor|$device|$vram|$name|$bus"
done
}
@@ -144,11 +164,11 @@ if [ "$xml" = 1 ]; then
SPHardwareDataType) hardware | overview_xml hardware_overview;;
SPSoftwareDataType) software | overview_xml os_overview;;
SPDisplaysDataType)
displays | while IFS='|' read -r vendor device vram name; do
displays | while IFS='|' read -r vendor device vram name bus; do
name=$(printf '%s' "$name" | escape)
echo ' <dict>'
echo " <key>_name</key><string>$name</string>"
echo ' <key>spdisplays_bus</key><string>spdisplays_builtin</string>'
echo " <key>spdisplays_bus</key><string>spdisplays_$bus</string>"
echo " <key>spdisplays_device-id</key><string>0x$device</string>"
echo " <key>spdisplays_vendor</key><string>${name%% *} (0x$vendor)</string>"
[ -z "$vram" ] || echo " <key>spdisplays_vram</key><string>$vram MB</string>"
@@ -190,8 +210,9 @@ for type in $types; do
SPSoftwareDataType) software | overview_text Software 'System Software Overview';;
SPDisplaysDataType)
printf 'Graphics/Displays:\n\n'
displays | while IFS='|' read -r vendor device vram name; do
printf ' %s:\n\n Chipset Model: %s\n Type: GPU\n Bus: Built-In\n' "$name" "$name"
displays | while IFS='|' read -r vendor device vram name bus; do
[ "$bus" = pcie ] && bus_text=PCIe || bus_text='Built-In'
printf ' %s:\n\n Chipset Model: %s\n Type: GPU\n Bus: %s\n' "$name" "$name" "$bus_text"
[ -z "$vram" ] || printf ' VRAM (Total): %s MB\n' "$vram"
printf ' Vendor: %s (0x%s)\n Device ID: 0x%s\n\n' "${name%% *}" "$vendor" "$device"
done;;
+14
View File
@@ -16,6 +16,12 @@ SESSION_PREFIXES = (
'XDG_SESSION_', 'XDG_SEAT', 'XDG_VTNR', 'XDG_CURRENT_DESKTOP', 'XDG_MENU_PREFIX',
'GNOME_', 'KDE_', 'GDM', 'SSH_', 'SYSTEMD_', 'MEMORY_PRESSURE_', 'QT_', 'GTK_', 'GDK_',
'GIO_', 'GSETTINGS_', 'GJS_', 'FLATPAK_', 'SNAP_', 'KONSOLE_', 'TERM_PROGRAM', 'BASH_FUNC_',
# Host shell, prompt and developer-tool metadata. None of it exists on a Mac and
# several entries name Linux paths, so the guest must not inherit them.
'STARSHIP_', 'ILLOGICAL_IMPULSE_', 'INIR_', 'PNPM_', 'YARN_', 'npm_config_', 'PIP_',
'CARGO_', 'GIT_', 'LESS_TERMCAP_', '_P9K_', 'VSSCRIPT_', 'ORCA_', 'CLAUDE', 'TF_',
'CUDA_', 'COMPOSER_', 'DEBIAN_', 'FZF_', 'BAT_', 'MYSQL_', 'AWS_', 'LESS',
'CLOUDSDK_', 'GH_', 'GLAB_', 'HOMEBREW_', 'ELECTRON_', 'DELTA_', 'HIST', 'GPG_',
)
SESSION_NAMES = {
'WAYLAND_DISPLAY', 'DESKTOP_SESSION', 'DESKTOP_STARTUP_ID', 'SESSION_MANAGER',
@@ -23,6 +29,9 @@ SESSION_NAMES = {
'LISTEN_FDS', 'LISTEN_PID', 'LISTEN_FDNAMES', 'COLORTERM', 'VTE_VERSION', 'WINDOWID',
'WINDOWPATH', 'CHROME_DESKTOP', 'NO_AT_BRIDGE', 'MOTD_SHOWN', 'SNAP', 'APPIMAGE', 'APPDIR',
'OWD', 'VIRTUAL_ENV', 'DEBUGINFOD_URLS', 'LS_COLORS', 'COLORFGBG', 'OLDPWD', 'SHLVL',
'AGENT', 'NO_COLOR', 'TERM', 'VISUAL', 'PROMPT_COMMAND', 'HISTFILE', 'HISTSIZE',
'SAVEHIST', 'HISTORY_IGNORE', 'PYTHONUNBUFFERED', 'LINES', 'COLUMNS', '_',
'CI', 'EDITOR', 'PAGER', 'GIT_PAGER', 'SYSTEMD_PAGER', 'MANPAGER',
}
GUEST_SHELL = '/bin/zsh'
@@ -40,6 +49,11 @@ def filter_host_environment(environ):
# The host login shell (for example /bin/fish) does not exist in the guest.
if 'SHELL' not in keep:
environ['SHELL'] = GUEST_SHELL
# A host PATH names Linux directories; the guest always has the Mac layout.
if 'PATH' not in keep:
environ['PATH'] = '/usr/bin:/bin:/usr/sbin:/sbin'
environ.pop('RCLOL_KEEP_HOST_ENV', None)
environ.pop('RCLOL_FILTER_HOST_ENV', None)
return removed
+9 -1
View File
@@ -38,6 +38,7 @@ if record["command"] == "darling":
record["flags"] = {{key: os.environ.get(key) for key in
("RCLOL_APP_ARG3", "RCLOL_APP_ARG3_SLOT", "RCLOL_UX_ARG2", "RCLOL_UX_ARG2_SLOT", "RCLOL_UX_ARG1", "RCLOL_APP_ARGS", "RCLOL_APP_ARG2", "DYLD_INSERT_LIBRARIES", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH", "DARLING_XSHM_LIBRARY",
"WAYLAND_DISPLAY", "XAUTHORITY", "DRI_PRIME", "MESA_NO_ERROR", "__GL_THREADED_OPTIMIZATIONS", "SHELL")}}
record["hud"] = {{key: os.environ.get(key) for key in ("MANGOHUD", "DISABLE_MANGOHUD")}}
with open({str(log)!r}, "a") as output:
output.write(json.dumps(record) + "\\n")
'''
@@ -59,6 +60,8 @@ with open({str(log)!r}, "a") as output:
env["DYLD_INSERT_LIBRARIES"] = "/Users/offline-check/zzlogdir.dylib:/tmp/inherited.dylib"
env["RCLOL_APP_ARGS"] = "--inherited-shim-argument"
env["RCLOL_APP_ARG2"] = "--inherited-shim-argument-2"
env["MANGOHUD"] = "1"
env.pop("DISABLE_MANGOHUD", None)
env["RCLOL_NATIVE_VPX"] = "1"
env["RCLOL_LEAGUE_UX_TUNING"] = "1"
# Inherited legacy settings must not re-enable inspection or unlimited frames.
@@ -90,6 +93,8 @@ with open({str(log)!r}, "a") as output:
], "unexpected automatic helper"
launches = [r for r in records if r["command"] == "darling"]
assert len(launches) == 1, "unexpected launch count"
for record in records:
assert record["hud"] == {"MANGOHUD": None, "DISABLE_MANGOHUD": "1"}, "MangoHud survived before a runtime helper"
launch = launches[0]
assert launch["fds"] == [0, 1, 2], f"inherited descriptors reached the guest: {launch['fds']}"
assert all(launch["flags"][key] is None for key in (
@@ -106,17 +111,20 @@ with open({str(log)!r}, "a") as output:
assert "--log-dir=/Users/offline-check/Library/Logs/Riot Games/Riot Client" in launch["args"], "absolute log directory lost"
# An inherited injection must also be absent for first-time installation.
env["RIOT_LAUNCHER_HOST"] = str(folder / "Install Riot.app/Contents/MacOS/RiotClientServices")
env["DISABLE_MANGOHUD"] = "0" # Inherited settings cannot override launcher policy.
subprocess.run(["sh", str(launcher)], env=env, check=True, capture_output=True, text=True)
install = json.loads(log.read_text().splitlines()[-1])
assert install["args"][0] == env["RIOT_LAUNCHER_HOST"]
assert "--skip-to-install" in install["args"]
assert not any(arg.startswith("--app-root=") for arg in install["args"])
assert install["flags"]["DYLD_INSERT_LIBRARIES"] is None
assert install["hud"] == {"MANGOHUD": None, "DISABLE_MANGOHUD": "1"}
env.pop("RIOT_LAUNCHER_HOST")
env.pop("DYLD_INSERT_LIBRARIES")
subprocess.run(["sh", str(launcher)], env=env, check=True, capture_output=True, text=True)
clean = json.loads(log.read_text().splitlines()[-1])
assert clean["flags"]["DYLD_INSERT_LIBRARIES"] is None
assert clean["hud"] == {"MANGOHUD": None, "DISABLE_MANGOHUD": "1"}
# The opt-in host environment filter drops session metadata but never the launcher's GPU tuning.
env.update({"RCLOL_FILTER_HOST_ENV": "1", "WAYLAND_DISPLAY": "wayland-0", "XAUTHORITY": "/tmp/xauth",
"DRI_PRIME": "1", "SHELL": "/bin/fish"})
@@ -127,7 +135,7 @@ with open({str(log)!r}, "a") as output:
assert filtered["WAYLAND_DISPLAY"] is None and filtered["SHELL"] == "/bin/zsh", "host session metadata survived"
assert (filtered["XAUTHORITY"], filtered["DRI_PRIME"]) == ("/tmp/xauth", "1"), "X11/GPU selection lost"
assert (filtered["MESA_NO_ERROR"], filtered["__GL_THREADED_OPTIMIZATIONS"]) == ("1", "0"), "launcher GPU tuning lost"
print("LAUNCHER_OFFLINE pass=1 installed=PASS installer=PASS inherited_injection=absent runtime=preserved inherited_fds=closed host_env_filter=PASS")
print("LAUNCHER_OFFLINE pass=1 installed=PASS installer=PASS inherited_injection=absent runtime=preserved inherited_fds=closed host_env_filter=PASS mangohud=disabled")
if __name__ == "__main__":
+14 -1
View File
@@ -2,6 +2,11 @@
# Launch Riot Client using the Darling runtime, without library injection.
# Darling supplies Xlib Display pointers to EGL, so select X11 explicitly.
set -eu
# Native MangoHud uses the guest PID against the host /proc view and can abort
# in GPU_fdinfo::find_fd (issue #38). Disable inherited implicit activation
# before any helper can start Darling, including first-time installation.
unset MANGOHUD
export DISABLE_MANGOHUD=1
# Native guest crashes created large system core files and exhausted this disk.
# Address-only diagnostics suffice; bound this runner and its new namespace.
if [ "${RCLOL_CORE_DUMPS:-0}" != 1 ]; then
@@ -44,11 +49,19 @@ unset RCLOL_UX_ARG2 RCLOL_UX_ARG2_SLOT
# Explicit 0 or an empty value selects the CPU fallback for diagnostics.
# DARLING_METAL_MAC_GPU_NAME reports the MacBookPro16,1 GPU of the host vendor (AMD or Intel) as
# MTLDevice.name, matching the model IOKit reports; memory figures stay the host's.
# VRAM clamp: honor an explicit DARLING_METAL_VRAM_MB, otherwise pin 4096 MB so the
# 5500M identity does not leak the host card's heap size.
export DARLING_METAL_VRAM_MB="${DARLING_METAL_VRAM_MB:-4096}"
for option in RCLOL_GPU_DIRECT_PRESENT RCLOL_GPU_DIRECT_ASYNC RCLOL_GPU_DIRECT_VSYNC DARLING_CA_PRESENT_AT_COMMIT DARLING_CA_SKIP_LOCAL_IOSURFACE_RENDER RCLOL_FORWARD_MOUSE_MOVED RCLOL_MOUSE_CONFINEMENT DARLING_METAL_MAC_GPU_NAME; do
eval 'value=${'"$option"'-1}'
case "$value" in 0|'') unset "$option";; *) export "$option=$value";; esac
done
prefix=$prefix_dir
# Resolve the loader before the environment filter replaces PATH with the Mac layout.
darling_bin=$(command -v darling) || {
echo 'darling loader not found in PATH' >&2
exit 1
}
# RIOT_GUEST_HOME is host-side; DYLD paths must be relative to the guest root.
case "$guest_home" in
"$prefix"/*) guest_path=/${guest_home#"$prefix"/} ;;
@@ -166,6 +179,6 @@ exec python3 "$runner_dir/exec-guest.py" env -u ELECTRON_RUN_AS_NODE -u DYLD_INS
DYLD_LIBRARY_PATH="${DYLD_LIBRARY_PATH:-$guest_path/RuntimeLibraries}" \
DYLD_FRAMEWORK_PATH="${DYLD_FRAMEWORK_PATH:-$guest_path/RuntimeFrameworks}" \
DARLING_XSHM_LIBRARY="${DARLING_XSHM_LIBRARY:-$guest_path/libDarlingXShm.dylib}" \
darling "$A" --region="${RCLOL_REGION:-EUW}" --locale="${RCLOL_LOCALE:-en_GB}" \
"$darling_bin" "$A" --region="${RCLOL_REGION:-EUW}" --locale="${RCLOL_LOCALE:-en_GB}" \
"$@" \
--log-dir="$guest_path/Library/Logs/Riot Games/Riot Client"