From f6760471c8bb2c9004b4b0b79973187778cf2741 Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Fri, 4 Sep 2026 12:11:05 +0300 Subject: [PATCH 1/4] Build a Mesa llvmpipe with the gl_PrimitiveID fix for Ubuntu 26.04 Resolute ships Mesa 26.0.8, which mis-reads gl_PrimitiveID in a fragment shader that also has user varyings and no geometry shader (mesa#15660), so MeshInspector picks garbage faces and crashes. The fix landed on Mesa main on 2026-07-22, seven days after the 26.2 branch point, and was never nominated for stable: it is in one branch and zero tags, so no release and no PPA carries it - kisak-mesa/resolute is 26.1.7 and still affected. llvmpipe only, against Resolute's own llvm-21-dev (the same LLVM 21.1.8 its stock llvmpipe links), built in an ubuntu:26.04 container so glibc, libdrm, libglvnd and X11 match the image that will consume it. The smoke test refuses a build that still reports the distro's Mesa version. --- .github/workflows/build-mesa-llvmpipe.yml | 118 ++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/build-mesa-llvmpipe.yml diff --git a/.github/workflows/build-mesa-llvmpipe.yml b/.github/workflows/build-mesa-llvmpipe.yml new file mode 100644 index 0000000..4f0cfbf --- /dev/null +++ b/.github/workflows/build-mesa-llvmpipe.yml @@ -0,0 +1,118 @@ +name: Build Mesa llvmpipe for Ubuntu 26.04 + +# Ubuntu 26.04 ships Mesa 26.0.8, which mis-reads gl_PrimitiveID in a fragment shader that +# also has user varyings and no geometry shader (mesa#15660): MeshInspector picks garbage +# faces and crashes. The fix, mesa!42967, landed on Mesa main seven days after the 26.2 +# branch point, so no Mesa release carries it - hence this build. +# +# llvmpipe only, against Resolute's own llvm-21-dev (the same LLVM 21.1.8 its stock llvmpipe +# uses), built in an ubuntu:26.04 container so glibc, libdrm, libglvnd and X11 all match the +# image that consumes it. Retire this once a Mesa >= 26.3 reaches the archive or kisak-mesa. + +on: + push: + # not on main: merging must not restart the builds; run from the Actions tab instead + branches-ignore: [ main ] + paths: [ '.github/workflows/build-mesa-llvmpipe.yml' ] + workflow_dispatch: + inputs: + mesa_ref: + description: Mesa commit to build + default: 77251a488e9157ed450b3ff93a3d97390625d5b9 + type: string + extra_meson: + description: Extra meson setup arguments + default: '' + type: string + +concurrency: + group: build-mesa-llvmpipe-${{ github.ref }} + cancel-in-progress: false + +env: + # mesa!42967 "llvmpipe: emit FS input vertex attributes in driver location order" + MESA_REF: ${{ inputs.mesa_ref || '77251a488e9157ed450b3ff93a3d97390625d5b9' }} + PREFIX: /opt/mesa-llvmpipe + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - arch: x64 + os: ubuntu-latest + - arch: arm64 + os: ubuntu-24.04-arm + runs-on: ${{ matrix.os }} + container: + image: ubuntu:26.04 + timeout-minutes: 90 + steps: + - name: Install build dependencies + run: | + set -eux + export DEBIAN_FRONTEND=noninteractive + apt-get update -qqy + apt-get install -qqy --no-install-recommends ca-certificates git curl xz-utils pkg-config build-essential meson ninja-build bison flex python3-mako python3-yaml python3-setuptools llvm-21-dev libclang-cpp21-dev libdrm-dev libexpat1-dev zlib1g-dev libzstd-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxdamage-dev libxshmfence-dev libxxf86vm-dev libxrandr-dev libxcb-dri3-dev libxcb-present-dev libxcb-sync-dev libxcb-glx0-dev libxcb-shm0-dev libxcb-randr0-dev + meson --version + llvm-config-21 --version + + - name: Fetch the Mesa sources + run: | + set -eux + mkdir -p /tmp/mesa && cd /tmp/mesa + git init -q + git remote add origin https://gitlab.freedesktop.org/mesa/mesa.git + git fetch -q --depth 1 origin "$MESA_REF" + git checkout -q FETCH_HEAD + git log -1 --format='%H %s' + # mesa!42967's head commit; its own subject is the nir change that carries the fix + test "$( git rev-parse HEAD )" = "$MESA_REF" + + - name: Configure + run: | + set -eux + cd /tmp/mesa + meson setup build --prefix "$PREFIX" --buildtype release -Dgallium-drivers=llvmpipe -Dvulkan-drivers= -Dplatforms=x11 -Dglx=dri -Degl=enabled -Dgbm=enabled -Dglvnd=true -Dllvm=enabled -Dshared-llvm=enabled -Dtools= -Dvideo-codecs= ${{ inputs.extra_meson }} + meson configure build | sed -n '1,60p' + + - name: Build and install + run: | + set -eux + cd /tmp/mesa + ninja -C build + ninja -C build install + find "$PREFIX" -name '*.so*' -exec ls -l {} + | sort -k5 -rn | head -20 + du -sh "$PREFIX" + + - name: Smoke test the stack + run: | + set -eux + export DEBIAN_FRONTEND=noninteractive + apt-get install -qqy --no-install-recommends mesa-utils xvfb + # the stock renderer, for the log + xvfb-run -a glxinfo -B | grep -E 'OpenGL (vendor|renderer|version)' || true + # ours: libglvnd stays the distro's, the vendor libs and the DRI module are ours + export LD_LIBRARY_PATH="$PREFIX/lib/$(uname -m)-linux-gnu:$PREFIX/lib" + export LIBGL_DRIVERS_PATH="$PREFIX/lib/$(uname -m)-linux-gnu/dri:$PREFIX/lib/dri" + export __GLX_VENDOR_LIBRARY_NAME=mesa LIBGL_ALWAYS_SOFTWARE=1 + xvfb-run -a glxinfo -B | grep -E 'OpenGL (vendor|renderer|version)' + # must NOT be the distro's stock Mesa any more + if xvfb-run -a glxinfo -B | grep -q "Mesa 26.0."; then echo "still the distro Mesa" >&2; exit 1; fi + + - name: Package + run: | + set -eux + ASSET="mesa-llvmpipe-ubuntu26-$(uname -m).tar.gz" + tar -C /opt -czf "/tmp/$ASSET" "$(basename "$PREFIX")" + # sidecar names the tarball itself, so `sha256sum -c` works next to it + cd /tmp && sha256sum "$ASSET" | tee "$ASSET.sha256" + ls -l "/tmp/$ASSET" + + - name: Upload + uses: actions/upload-artifact@v7 + with: + name: mesa-llvmpipe-ubuntu26-${{ matrix.arch }} + path: /tmp/mesa-llvmpipe-ubuntu26-* + if-no-files-found: error From e96bc2420bb11b0af18142e68b5bfb5c40272b5d Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Fri, 4 Sep 2026 12:14:18 +0300 Subject: [PATCH 2/4] meson needs libglvnd-dev for -Dglvnd=true --- .github/workflows/build-mesa-llvmpipe.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-mesa-llvmpipe.yml b/.github/workflows/build-mesa-llvmpipe.yml index 4f0cfbf..1163eec 100644 --- a/.github/workflows/build-mesa-llvmpipe.yml +++ b/.github/workflows/build-mesa-llvmpipe.yml @@ -54,7 +54,7 @@ jobs: set -eux export DEBIAN_FRONTEND=noninteractive apt-get update -qqy - apt-get install -qqy --no-install-recommends ca-certificates git curl xz-utils pkg-config build-essential meson ninja-build bison flex python3-mako python3-yaml python3-setuptools llvm-21-dev libclang-cpp21-dev libdrm-dev libexpat1-dev zlib1g-dev libzstd-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxdamage-dev libxshmfence-dev libxxf86vm-dev libxrandr-dev libxcb-dri3-dev libxcb-present-dev libxcb-sync-dev libxcb-glx0-dev libxcb-shm0-dev libxcb-randr0-dev + apt-get install -qqy --no-install-recommends ca-certificates git curl xz-utils pkg-config build-essential meson ninja-build bison flex python3-mako python3-yaml python3-setuptools llvm-21-dev libclang-cpp21-dev libglvnd-dev libdrm-dev libudev-dev libexpat1-dev zlib1g-dev libzstd-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxdamage-dev libxshmfence-dev libxxf86vm-dev libxrandr-dev libxcb-dri3-dev libxcb-present-dev libxcb-sync-dev libxcb-glx0-dev libxcb-shm0-dev libxcb-randr0-dev meson --version llvm-config-21 --version From 48b11fa6e18910ad38133626abf6d59280a550fa Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Fri, 4 Sep 2026 12:24:38 +0300 Subject: [PATCH 3/4] Document the Mesa llvmpipe asset and name it after the Mesa commit --- .github/workflows/build-mesa-llvmpipe.yml | 4 +- README.md | 57 +++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-mesa-llvmpipe.yml b/.github/workflows/build-mesa-llvmpipe.yml index 1163eec..2288496 100644 --- a/.github/workflows/build-mesa-llvmpipe.yml +++ b/.github/workflows/build-mesa-llvmpipe.yml @@ -104,7 +104,7 @@ jobs: - name: Package run: | set -eux - ASSET="mesa-llvmpipe-ubuntu26-$(uname -m).tar.gz" + ASSET="mesa-llvmpipe-$( echo "$MESA_REF" | cut -c1-7 )-ubuntu26-$(uname -m).tar.gz" tar -C /opt -czf "/tmp/$ASSET" "$(basename "$PREFIX")" # sidecar names the tarball itself, so `sha256sum -c` works next to it cd /tmp && sha256sum "$ASSET" | tee "$ASSET.sha256" @@ -114,5 +114,5 @@ jobs: uses: actions/upload-artifact@v7 with: name: mesa-llvmpipe-ubuntu26-${{ matrix.arch }} - path: /tmp/mesa-llvmpipe-ubuntu26-* + path: /tmp/mesa-llvmpipe-*-ubuntu26-* if-no-files-found: error diff --git a/README.md b/README.md index 5176a46..b6b2e8b 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,52 @@ against the Homebrew `lld` each machine had: Ordinary dylib links of 0.1-0.4 s show no difference at all; the gain is in ThinLTO codegen, which is what the profile covers. +## Mesa 26.3.0-devel llvmpipe (Ubuntu 26.04) — `mesa-llvmpipe-77251a4-ubuntu26` + +Ubuntu 26.04 ships Mesa 26.0.8, which mis-reads `gl_PrimitiveID` in a fragment +shader that also has user varyings and no geometry shader +([mesa#15660](https://gitlab.freedesktop.org/mesa/mesa/-/issues/15660)). +MeshInspector's picker is exactly that combination, so it picks garbage faces and +crashes. The fix +([mesa!42967](https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/42967), +head `77251a488e9157ed450b3ff93a3d97390625d5b9`) reached Mesa `main` seven days +after the 26.2 branch point and was never nominated for stable — it is in one +branch and zero tags, so no Mesa release and no PPA has it, `kisak-mesa` for +resolute included. Hence this build. + +llvmpipe only, no Vulkan, no video codecs, no tools: 25 MB installed, ~6 MB +compressed. Built in an `ubuntu:26.04` container against Resolute's own +`llvm-21-dev` (1:21.1.8, the same LLVM its stock llvmpipe links), so glibc, +libdrm, libglvnd and X11 match the image that consumes it. Takes 6 min on x64 and +3 min on arm64. + +libglvnd stays the distro's; this supplies the vendor libraries and the DRI +module, selected per process by three env vars: + + TOOLCHAIN=mesa-llvmpipe-77251a4-ubuntu26 + curl -fsSL "https://github.com/MeshInspector/toolchains/releases/download/${TOOLCHAIN}/${TOOLCHAIN}-$(uname -m).tar.gz" | tar -C /opt -xz + + export LD_LIBRARY_PATH="/opt/mesa-llvmpipe/lib/$(uname -m)-linux-gnu:/opt/mesa-llvmpipe/lib" + export LIBGL_DRIVERS_PATH="/opt/mesa-llvmpipe/lib/$(uname -m)-linux-gnu/dri:/opt/mesa-llvmpipe/lib/dri" + export __GLX_VENDOR_LIBRARY_NAME=mesa LIBGL_ALWAYS_SOFTWARE=1 + +Check that it took effect — the version must not say 26.0: + + glxinfo -B | grep 'OpenGL version' + # OpenGL version string: 4.6 (Compatibility Profile) Mesa 26.3.0-devel (git-77251a488e) + +sha256 of the tarballs: + + ee0783eb22ef1badf021353ab82b5cbb3cda36645cc00c8ceeba3b689b91138f mesa-llvmpipe-77251a4-ubuntu26-x86_64.tar.gz + 92c78c2c12de9dfc32c6b14b4504703580b4fdbc682b5ddb3bd2ca5afbfb0deb mesa-llvmpipe-77251a4-ubuntu26-aarch64.tar.gz + +Each has a `.sha256` sidecar naming the tarball itself, so `sha256sum -c` next to +it just works. + +**Retire this** once a Mesa >= 26.3 reaches the Ubuntu archive or kisak-mesa. The +commit is in the tag deliberately: an image pinned by content checksum must not +silently acquire a different driver. + ## Who consumes these - `docker/rockylinux8-vcpkgDockerfile` in our Linux images fetches the Linux @@ -261,6 +307,10 @@ ThinLTO codegen, which is what the profile covers. by the workflow below, so MeshInspector builds link with it without downloading anything per job. +- The Ubuntu 26.04 CI images will fetch the Mesa llvmpipe tarball into `/opt` and + set the three env vars above, so headless GL in those containers renders with a + driver that has the `gl_PrimitiveID` fix. + ## Rebuilding The Linux recipe is a two-job chain per arch, in a `rockylinux:8` container: @@ -290,6 +340,13 @@ and re-runnable by hand: after a machine is reimaged or its keg is rebuilt, since either wipes the keg's `bin`. +Mesa is a single job per arch in +[`.github/workflows/build-mesa-llvmpipe.yml`](.github/workflows/build-mesa-llvmpipe.yml), +triggered by pushing to its file on any branch but `main`, with the Mesa commit as +a dispatch input. It smoke-tests the result through `glxinfo` under xvfb and fails +if the reported version is still the distro's, so a build that does not take +effect cannot be published. 6 min x64, 3 min arm64. + The macOS kegs are built on the self-hosted macOS runners by `brew install --build-bottle` from a local tap, then packed straight out of the Cellar. The [`Validate llvm-pgo keg`](.github/workflows/validate-llvm-pgo.yml) From 4b1160bd5ca64dbc15030811dda264efef1b7970 Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Fri, 4 Sep 2026 14:51:37 +0300 Subject: [PATCH 4/4] Drop the debug prints from the Mesa build --- .github/workflows/build-mesa-llvmpipe.yml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-mesa-llvmpipe.yml b/.github/workflows/build-mesa-llvmpipe.yml index 2288496..ada9812 100644 --- a/.github/workflows/build-mesa-llvmpipe.yml +++ b/.github/workflows/build-mesa-llvmpipe.yml @@ -55,8 +55,6 @@ jobs: export DEBIAN_FRONTEND=noninteractive apt-get update -qqy apt-get install -qqy --no-install-recommends ca-certificates git curl xz-utils pkg-config build-essential meson ninja-build bison flex python3-mako python3-yaml python3-setuptools llvm-21-dev libclang-cpp21-dev libglvnd-dev libdrm-dev libudev-dev libexpat1-dev zlib1g-dev libzstd-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxdamage-dev libxshmfence-dev libxxf86vm-dev libxrandr-dev libxcb-dri3-dev libxcb-present-dev libxcb-sync-dev libxcb-glx0-dev libxcb-shm0-dev libxcb-randr0-dev - meson --version - llvm-config-21 --version - name: Fetch the Mesa sources run: | @@ -75,7 +73,6 @@ jobs: set -eux cd /tmp/mesa meson setup build --prefix "$PREFIX" --buildtype release -Dgallium-drivers=llvmpipe -Dvulkan-drivers= -Dplatforms=x11 -Dglx=dri -Degl=enabled -Dgbm=enabled -Dglvnd=true -Dllvm=enabled -Dshared-llvm=enabled -Dtools= -Dvideo-codecs= ${{ inputs.extra_meson }} - meson configure build | sed -n '1,60p' - name: Build and install run: | @@ -83,23 +80,18 @@ jobs: cd /tmp/mesa ninja -C build ninja -C build install - find "$PREFIX" -name '*.so*' -exec ls -l {} + | sort -k5 -rn | head -20 - du -sh "$PREFIX" - name: Smoke test the stack run: | set -eux export DEBIAN_FRONTEND=noninteractive apt-get install -qqy --no-install-recommends mesa-utils xvfb - # the stock renderer, for the log - xvfb-run -a glxinfo -B | grep -E 'OpenGL (vendor|renderer|version)' || true # ours: libglvnd stays the distro's, the vendor libs and the DRI module are ours export LD_LIBRARY_PATH="$PREFIX/lib/$(uname -m)-linux-gnu:$PREFIX/lib" export LIBGL_DRIVERS_PATH="$PREFIX/lib/$(uname -m)-linux-gnu/dri:$PREFIX/lib/dri" export __GLX_VENDOR_LIBRARY_NAME=mesa LIBGL_ALWAYS_SOFTWARE=1 - xvfb-run -a glxinfo -B | grep -E 'OpenGL (vendor|renderer|version)' - # must NOT be the distro's stock Mesa any more - if xvfb-run -a glxinfo -B | grep -q "Mesa 26.0."; then echo "still the distro Mesa" >&2; exit 1; fi + GL="$( xvfb-run -a glxinfo -B | grep 'OpenGL version' )" + case "$GL" in *'Mesa 26.0.'*) echo "the fix is not in this build: $GL" >&2 ; exit 1 ;; esac - name: Package run: | @@ -107,8 +99,7 @@ jobs: ASSET="mesa-llvmpipe-$( echo "$MESA_REF" | cut -c1-7 )-ubuntu26-$(uname -m).tar.gz" tar -C /opt -czf "/tmp/$ASSET" "$(basename "$PREFIX")" # sidecar names the tarball itself, so `sha256sum -c` works next to it - cd /tmp && sha256sum "$ASSET" | tee "$ASSET.sha256" - ls -l "/tmp/$ASSET" + cd /tmp && sha256sum "$ASSET" > "$ASSET.sha256" - name: Upload uses: actions/upload-artifact@v7