Upgrade to Wine 11.5 devel with EGL support and fix GPU rendering#334
Upgrade to Wine 11.5 devel with EGL support and fix GPU rendering#334pdelagrave wants to merge 1 commit intonetbrain:masterfrom
Conversation
…NVIDIA Wine 11 switches from GLX to EGL as the default OpenGL backend, and requires several fixes to render correctly with an NVIDIA GPU under Docker. **Dockerfile** - Bump Wine to 11.5~trixie-1 devel (EGL default since 10.17, Wayland since 9.9) - Add libegl1:i386, libgl1:i386, libvulkan1:i386 for 32-bit EGL/GL/Vulkan parity - Register NVIDIA as a GLVND EGL vendor by baking 10_nvidia.json into the image so the EGL dispatcher loads libEGL_nvidia.so.0 when injected by the NVIDIA container runtime (harmless when NVIDIA is absent — GLVND skips missing libs) **entrypoint.sh** - Fix ownership check depth: maxdepth 0 → maxdepth 1 so root-owned .wine (created by mkdir -p before privilege drop) is detected and chowned - Fix gosu supplementary groups: gosu user:user skips initgroups() and drops all supplementary groups including the DRI render group; use gosu user instead - Register DRI render group by GID before privilege drop using getent group to avoid silent conflict with Mesa's pre-existing render:990 group **update_zwift.sh** - Skip WebView2 install: both bootstrapper and standalone require the MicrosoftEdgeUpdate COM service which Wine cannot activate; SilentLaunch bypasses the launcher UI so WebView2 is not needed at runtime **zwift.sh** - Add --ipc=host alongside the X11 socket mount so Mesa can attach to X11 shared memory (required for DRI2/DRI3 screen initialization) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| && mkdir -p /usr/share/glvnd/egl_vendor.d \ | ||
| && printf '{"file_format_version":"1.0.0","ICD":{"library_path":"libEGL_nvidia.so.0"}}\n' \ | ||
| > /usr/share/glvnd/egl_vendor.d/10_nvidia.json |
There was a problem hiding this comment.
Why did you need to add the 10_nvidia.json file? It already exists in the container for me (tried with both docker and podman), I'm guessing this is something the nvidia container toolkit does.
user@glenn-main-pc:/$ ls /usr/share/glvnd/egl_vendor.d/
10_nvidia.json 50_mesa.json
user@glenn-main-pc:/$ cat /usr/share/glvnd/egl_vendor.d/10_nvidia.json
{
"file_format_version" : "1.0.0",
"ICD" : {
"library_path" : "libEGL_nvidia.so.0"
}
}There was a problem hiding this comment.
I tried with both docker and podman and I still have the same issues as I have in my own fork glennvl#14 if I don't add --ipc=host.
eglgears_x11 still says MESA: error: Failed to attach to x11 shm even with --ipc=host.
docker
- With docker zwift launches with software rendering if I add
--ipc=hostto the zwift and build scripts. - Adding the container user to the render group does not make a difference.
libEGL warning: egl: failed to create dri2 screen
libEGL warning: failed to open /dev/dri/card1: Permission denied
podman
With podman zwift launches with software rendering if I add --ipc=host to the zwift and build scripts.
libEGL warning: egl: failed to create dri2 screen
| # Add DRI render group to user so gosu preserves GPU access. | ||
| # gosu sets supplementary groups from /etc/group, not from Docker's --group-add, | ||
| # so we must register the DRI device's GID in the container before dropping privileges. | ||
| # Note: do not use groupadd -f (silently no-ops if group name exists with different GID). | ||
| if [[ -d /dev/dri ]]; then | ||
| dri_gid="$(stat -c '%g' /dev/dri/renderD128 2>/dev/null || stat -c '%g' /dev/dri/card0 2>/dev/null || true)" | ||
| if [[ -n ${dri_gid} ]]; then | ||
| if ! getent group "${dri_gid}" > /dev/null 2>&1; then | ||
| groupadd -g "${dri_gid}" dri_render 2>/dev/null || true | ||
| fi | ||
| dri_group="$(getent group "${dri_gid}" | cut -d: -f1)" | ||
| if [[ -n ${dri_group} ]]; then | ||
| usermod -aG "${dri_group}" user 2>/dev/null || true | ||
| msgbox info "Added user to ${dri_group} group (gid=${dri_gid}) for DRI access" | ||
| fi | ||
| fi | ||
| fi |
There was a problem hiding this comment.
What issue is this trying to fix? Graphics card access already worked?
It does not change anything for me for egl
libEGL warning: egl: failed to create dri2 screen
libEGL warning: egl: failed to create dri2 screen
libEGL warning: egl: failed to create dri2 screen
libEGL warning: egl: failed to create dri2 screen
libEGL warning: failed to open /dev/dri/card1: Permission denied
On my machine (fedora 43), the card and render devices belong to a different group:
$ ls -al /dev/dri
total 0
drwxr-xr-x. 3 root root 100 23 mrt 09:23 .
drwxr-xr-x. 21 root root 4960 23 mrt 09:23 ..
drwxr-xr-x. 2 root root 100 23 mrt 09:23 by-path
crw-rw----+ 1 root video 226, 1 23 mrt 09:23 card1
crw-rw-rw-. 1 root render 226, 128 23 mrt 09:23 renderD128And the card is /dev/dri/card1, so we shouldn't assume it's card0?
There was a problem hiding this comment.
With docker, if I add the user to the group from /dev/dri/card1 and launch with gosu user instead of gosu user:user, the permission denied warning goes away. But the other warning remains and it still uses software rendering instead of hardware rendering.
| # WebView2 install skipped: both bootstrapper and standalone require the | ||
| # MicrosoftEdgeUpdate COM service which Wine cannot activate. SilentLaunch | ||
| # bypasses the launcher UI so WebView2 is not needed at runtime. |
There was a problem hiding this comment.
This appears to be a specific issue with wine 11.5. It still worked with wine 11.3. But if we don't need webview2, we might indeed as well remove it.
| libegl1:i386 \ | ||
| libgl1 \ | ||
| libgl1:i386 \ | ||
| libvulkan1 \ | ||
| libvulkan1:i386 \ |
There was a problem hiding this comment.
Why did you add the 32-bit libraries? They're not needed?
Summary
Wine 11 switches from GLX to EGL as the default OpenGL backend. This PR upgrades the image to Wine 11.5 devel and fixes several issues required to get hardware GPU rendering working correctly under Docker.
Dockerfile
11.5~trixie-1devel (EGL default since 10.17, Wayland native since 9.9)libegl1:i386,libgl1:i386,libvulkan1:i386for 32-bit EGL/GL/Vulkan parity with 64-bit10_nvidia.jsoninto the image to register NVIDIA as a GLVND EGL vendor — the NVIDIA container runtime injectslibEGL_nvidia.so.0but not the vendor registration file, causing the EGL dispatcher to fall back to Mesa and then software rendering (llvmpipe). Harmless when NVIDIA is absent — GLVND silently skips vendors whose library is not found.entrypoint.sh
maxdepth 0→maxdepth 1):mkdir -p $ZWIFT_HOMEruns as root before privilege drop and creates.wineowned by root. The previousmaxdepth 0check on/home/userpassed (it is owned by user) while missing the root-owned.winesubdirectory, causing Wine to refuse to start with "wine: '/home/user/.wine' is not owned by you".gosu user:userskipsinitgroups()and drops all supplementary groups including the DRI render group. Changed togosu userso all groups from/etc/groupare loaded.getent groupto find or create the group by GID, avoiding silent conflict with Mesa's pre-existingrendergroup (GID 990).update_zwift.sh
MicrosoftEdgeUpdateCOM service ({cecddd22-2e72-4832-9606-a9b0e5e344b2}), which Wine cannot activate (out-of-process COM server for a Windows service).SilentLaunchbypasses the launcher UI entirely so WebView2 is not needed at runtime.zwift.sh
--ipc=hostalongside the X11 socket mount so Mesa can attach to X11 shared memory, which is required for DRI2/DRI3 screen initialization.Test plan
OpenGL 4.6.0 NVIDIA 570.211.01on GTX 1070)WINE_EXPERIMENTAL_WAYLAND=1)🤖 Generated with Claude Code