The rule was derived from two data points and generalised into a negation:
owner's Vulkan + mirror=false -> upside-down (Vulkan needs the mirror)
Xvfb Mesa GL + mirror=true -> upside-down (GL does not)
"mirror on everything EXCEPT OpenGL" fits both, and it was wrong about the one
API nobody had run. On the Mac mini M2 the Line Bed comes out upside-down, so
Metal wants mirror=false like OpenGL rather than =true like Vulkan — the
generalisation reached a third platform on the strength of a shape it had never
been tested against.
Kept as a NEGATION with Metal excluded rather than rewritten as "Vulkan ||
D3D". Naming the APIs that DO mirror would silently stop mirroring on any enum
this file failed to list: an unknown member is `undefined` in QML and compares
false, so a typo or a future backend would degrade to "no mirror" with no error.
This way only Metal's behaviour changes and every other backend keeps exactly
what it was verified with.
All four RHI scenes carry the line, because the convention belongs to the
graphics API and not to the scene — a per-scene split would be the surprising
result, not the expected one. Only LineBed made it observable: it is the one
directional scene, so a flip reads instantly, where Plasma and TunnelFlow are
near-radial and hide it. RIBBON IS THE ONE TO CHECK NEXT — it is a spectrogram
with a time axis, so if the convention really is per-API it should have been
flipped too, and if it now looks flipped the rule is per-scene after all.
The three sibling headers said "mirror on Vulkan/Metal/D3D" and were corrected
in place; they had become comments that contradict their own code.
Built and smoked on Linux (gate green). The observation this fixes is the
owner's, on the Mac.
cc
Port the immersive GPU scenes: Plasma, Tunnel, Aurora, Ambient, Spectral
Ribbon and Line Bed as QQuickRhiItems/ShaderEffects under a pulse-driven
ShaderSceneLayer, plus the Qt-only Tunnel Flow (Tauri Canvas2D port) fed
by the Viz16 stream. Scene rows live in the header view menu (no Off row);
g cycles the ring. A fresh immersive open defaults to Split > Lyrics
(owner ruling).
OpenGL link fix (owner smoke: Tunnel black with "uniform _22 declared as
type buf and type buf"): every ShaderEffect fragment with its own uniform
layout now ships a paired vertex stage declaring the identical block —
the shared spectrum.vert only ever linked under Vulkan.
RHI hardening: render pass descriptors on the ping-pong targets (the
Tunnel Flow segfault / Plasma dead window), mirrorVertically tied to the
backend (!== OpenGL), ribbon sub-uploads carry setSourceSize.
km