feat(qt): immersive shader scenes — RHI items, scene menu, GL link pairing

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
This commit is contained in:
vicrodh committed 2026-08-16 08:22:57 -06:00
1 parent 8bd02e35d3
commit e6c058c2f2
74 files changed
+6036 -111

No files matched your search

+10 -4
View File
@@ -288,6 +288,12 @@ ApplicationWindow {
// atmosphere_url to this singleton on every track change — a missing
// boot line would drop those publishes silently (see above).
QbzImmersive.boot()
// Shader scenes (2026-08-15 immersive-completion contract, block A1).
// Booted right after QbzImmersive: its open funnel resets the scene
// through this singleton's hop, and the viz drain publishes the audio
// pack here on every tick while immersive is open — a missing boot
// line makes both silent no-ops (TRACK-RULES, singleton boot order).
QbzShaderScene.boot()
// Immersive Suggestions (the same contract, block B4 §4.5) — booted
// WITH its bridge: every publish the suggestions loader makes rides
// this hop, so a missing line is the forever-"{}" silent no-op the
@@ -646,10 +652,10 @@ ApplicationWindow {
// false, clear the maximized latch in the FullScreen branch too. Qt
// collapses both into one enum, so the maximized latch is cleared ONLY
// by an explicit return to Windowed — never by entering fullscreen.
// Nothing in QBZ's chrome sets FullScreen (both toggles go
// Maximized <-> Windowed, shell/HeaderBar.qml:76,830); it arrives from
// the WM keybind, and quitting from there must not un-maximize the
// next launch of either frontend.
// FullScreen arrives from the WM keybind OR from the immersive
// chrome (immersive/ImmersiveHeader.qml fs toggle — the first
// FullScreen write in this frontend, 2026-08-02 §5.2); quitting from
// there must not un-maximize the next launch of either frontend.
if (vis === Window.Maximized) {
window.maximizedLatch = true
window.fullScreenLatch = false