Skip to content

Commit 0cbeee3

Browse files
committed
examples/10-graphics: the offscreen example runs on all three platforms
macOS and Windows built it and did not run it, which is the shape the cross-platform work exists to remove: the half of a lane written for a host is the half that host never exercises. A build asserts that the shader compiler this platform publishes works and that the Vulkan half links. It cannot assert that the loader hands the program a device, and on macOS that is the interesting half. The example now declares a device for those two platforms as well -- `xim:moltenvk` under `cfg(macos)`, `xim:mesa-lavapipe` under `cfg(windows)` -- rather than leaving CI to install one. The omission was invisible while the example was never run, because a program that does not run never asks the loader for a device, and declaring it here is what makes the example complete for anyone who checks it out rather than only for the runner that had an extra command. The two CI steps therefore install nothing. They locate the ICD the build already provisioned and set `VK_DRIVER_FILES`, so a manifest that failed to name the driver fails the step. An `xlings install` in the step would have made it pass either way. macOS and Windows assert different things, and the difference is the point. lavapipe is a software rasteriser producing the same pixels by construction, so the image cannot distinguish it and the device name is what does. MoltenVK is the host's own GPU through Metal, so its name differs by runner; what distinguishes reaching a device there is that a centre pixel was reported at all, which a portability driver the loader declined to show would not produce. This closes the dependency between the two halves of the portability change: the package without the enumeration finds no device, and the enumeration without the package has nothing to find.
1 parent 235449a commit 0cbeee3

3 files changed

Lines changed: 110 additions & 0 deletions

File tree

.github/workflows/ci-macos.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,54 @@ jobs:
361361
done
362362
echo "ok: both shader stages compiled and the Vulkan half linked"
363363
364+
# AND NOW IT RUNS, WHICH IS A DIFFERENT CLAIM FROM THE ONE ABOVE.
365+
#
366+
# A build asserts that the shader compiler this platform publishes works
367+
# and that the Vulkan half links. It cannot assert that the loader hands
368+
# this program a device, and on macOS that is the interesting half:
369+
# MoltenVK is a PORTABILITY driver, which the loader does not give to
370+
# `vkEnumeratePhysicalDevices` unless the instance asked for portability
371+
# enumeration. A program written against native drivers therefore finds no
372+
# device here and reports it as "this machine has no GPU".
373+
#
374+
# This step is what turns that into a red build rather than a plausible
375+
# message. It depends on the portability enumeration in this PR: without
376+
# it the run reaches zero devices even though everything installed
377+
# correctly.
378+
#
379+
# `VK_DRIVER_FILES` rather than an ICD search directory: the package is in
380+
# the xlings store, not in `/usr/local/share/vulkan/icd.d`, and naming the
381+
# file is the one form that does not depend on where the loader looks.
382+
- name: "Graphics: the offscreen example RUNS on MoltenVK"
383+
shell: bash
384+
run: |
385+
set -e
386+
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
387+
# NOT installed from here. The example declares `xim:moltenvk` under
388+
# `cfg(macos)`, so the build above already provisioned it, and looking
389+
# for the ICD without installing anything is what asserts that the
390+
# declaration works. An `xlings install` here would make this step
391+
# pass whether the manifest named the driver or not.
392+
icd=$(find "${MCPP_HOME:-$HOME/.mcpp}/registry/data/xpkgs/xim-x-moltenvk" \
393+
"$HOME/.xlings/data/xpkgs/xim-x-moltenvk" \
394+
-name 'MoltenVK_icd.json' -print -quit 2>/dev/null || true)
395+
[ -n "$icd" ] || { echo "no MoltenVK ICD in either store"; exit 1; }
396+
echo "ICD: $icd"
397+
cd "$GITHUB_WORKSPACE/examples/10-graphics/offscreen"
398+
out=$(VK_DRIVER_FILES="$icd" "/tmp/mcpp-fresh" run 2>&1) || { echo "$out"; exit 1; }
399+
echo "$out"
400+
# The program asserts the corners and the centre itself and exits
401+
# non-zero on either. What CI adds is that the run reached a DEVICE:
402+
# a portability driver that the loader declined to show would leave
403+
# the program reporting no device, which is the failure this step
404+
# exists for. The name is not compared to a fixed string because it is
405+
# the host's GPU and differs by runner; that it is non-empty and the
406+
# centre pixel is opaque is what distinguishes reaching a device from
407+
# not.
408+
echo "$out" | grep -qE 'centre pixel: \([0-9]+, [0-9]+, [0-9]+, 255\)' \
409+
|| { echo "no centre pixel was reported: the run reached no device"; exit 1; }
410+
echo "ok: MoltenVK enumerated and the image was rendered on it"
411+
364412
# Integration: the mcpp built from THIS PR's source (the self-host binary,
365413
# $MCPP = /tmp/mcpp-fresh) builds & runs a real external C++ project —
366414
# xlings (openxlings/xlings ships its own mcpp.toml).

.github/workflows/ci-windows.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,45 @@ jobs:
456456
done
457457
echo "ok: both shader stages compiled and the Vulkan half linked"
458458
459+
# AND NOW IT RUNS. `xim:mesa-lavapipe` publishes a Windows build, so this
460+
# host has a software device and the claim can be the same one Linux
461+
# makes: the program reached a device and rendered the image, not merely
462+
# that it compiled.
463+
#
464+
# The device name IS compared here, unlike on macOS. lavapipe is a
465+
# software rasteriser that produces the same pixels by construction, so
466+
# the image cannot distinguish it from any other implementation and the
467+
# name is what does.
468+
#
469+
# `VK_DRIVER_FILES` rather than an ICD search directory: the package is in
470+
# the xlings store rather than in the registry the Windows loader reads,
471+
# and naming the file is the one form that does not depend on that.
472+
- name: "Graphics: the offscreen example RUNS on lavapipe"
473+
shell: bash
474+
run: |
475+
set -e
476+
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
477+
# NOT installed from here, for the reason the macOS job records: the
478+
# example declares `xim:mesa-lavapipe` under `cfg(windows)`, so
479+
# finding the ICD without installing anything is what asserts the
480+
# declaration works.
481+
icd=$(find "${MCPP_HOME:-$HOME/.mcpp}/registry/data/xpkgs/xim-x-mesa-lavapipe" \
482+
"$HOME/.xlings/data/xpkgs/xim-x-mesa-lavapipe" \
483+
-name '*.json' -path '*icd.d*' -print -quit 2>/dev/null || true)
484+
[ -n "$icd" ] || { echo "no lavapipe ICD in either store"; exit 1; }
485+
echo "ICD: $icd"
486+
cd "$GITHUB_WORKSPACE/examples/10-graphics/offscreen"
487+
# `$MCPP_SELF`, which is what the build step above used. `/tmp/mcpp-fresh.exe`
488+
# is a copy a LATER step makes, so naming it here would look right and
489+
# fail with a missing file.
490+
out=$(VK_DRIVER_FILES="$icd" "$MCPP_SELF" run 2>&1) || { echo "$out"; exit 1; }
491+
echo "$out"
492+
echo "$out" | grep -q 'llvmpipe' \
493+
|| { echo "the run did not reach the lavapipe device"; exit 1; }
494+
echo "$out" | grep -qE 'centre pixel: \([0-9]+, [0-9]+, [0-9]+, 255\)' \
495+
|| { echo "no centre pixel was reported"; exit 1; }
496+
echo "ok: lavapipe enumerated and the image was rendered on it"
497+
459498
- name: "Toolchain: LLVM — build mcpp (self-host)"
460499
shell: bash
461500
run: |

examples/10-graphics/offscreen/mcpp.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,29 @@ vulkan-runtime = "2026.09.07"
4444
[target.'cfg(linux)'.xlings.workspace]
4545
"xim:mesa-lavapipe" = "26.2.1"
4646

47+
# THE OTHER TWO PLATFORMS GET A DEVICE TOO, AND FOR THE SAME REASON.
48+
#
49+
# These were absent while the example was built but not run on macOS and
50+
# Windows, which made the omission invisible: a program that never runs never
51+
# asks the loader for a device. Declaring the driver here rather than installing
52+
# it from a CI step is what makes the EXAMPLE complete -- anyone who checks it
53+
# out gets a machine that can run it, not only the runner that had an extra
54+
# command.
55+
#
56+
# macOS has no native Vulkan. MoltenVK is an implementation on top of Metal, and
57+
# the specification calls that a portability driver: the loader does not hand it
58+
# to `vkEnumeratePhysicalDevices` unless the instance asked for portability
59+
# enumeration, which `src/vulkan/render.cpp` now does. The two halves are one
60+
# change -- the package without the enumeration finds no device, and the
61+
# enumeration without the package has nothing to find.
62+
[target.'cfg(macos)'.xlings.workspace]
63+
"xim:moltenvk" = "1.4.2"
64+
65+
# Windows takes the same software rasteriser Linux does; upstream publishes a
66+
# separate build of it, one minor behind the Linux one.
67+
[target.'cfg(windows)'.xlings.workspace]
68+
"xim:mesa-lavapipe" = "26.2.0"
69+
4770
[build]
4871
accel = "vulkan1.2"
4972
sources = [

0 commit comments

Comments
 (0)