perf(qt): one repaint pulse for the whole shell (GPU 95% -> 25%)
Qt Quick has no partial redraws: any dirty item presents the WHOLE window, and on the owner's hybrid laptop each full-window present costs ~1.2% GPU flat (KWin composite + dGPU scanout; area-independent, while the app's own render is 0.08 ms/frame). The bill was presents/s, and the shell ran unsynchronised ~30 Hz clocks plus two leaks: - QbzShell.pulseMs: ONE Rust-driven 33 ms edge that every continuous animator ticks on (knob QBZ_PULSE_MS). VizSettle now stashes on publish and applies on the pulse (its 16 ms interpolation timer is gone); AmbientField and ImmersiveAtmosphere ride the same edge. - VizSettle writes NOTHING while not live: the always-mounted but invisible immersive panels were dirtying 28 bar rects per FFT publish (named via QT_LOGGING_RULES=qt.quick.dirty=true). - AmbientField renders inline again: ShaderEffectSource scheduleUpdate() double-presents (minimal repro fbo_repro.qml in the investigation folder). - Background mode 2 (ImmersiveAtmosphere) composites its four drifting layers + base + dim + scrim in ONE opaque ShaderEffect (atmosphere.frag, baked by build.rs); numeric parity vs the Image stack verified (atmo-shader-parity-check.py, delta 0.0). The four-Image stack stays as the software/failure fallback. Measured on the owner's machine: 93-97% -> 25-26% GPU, ~34 W -> 12-13 W, ~33 presents/s in both background modes. Full story: qbz-nix-docs/qt-frontend/2026-08-11-scenegraph-batches/GPU-COST-INVESTIGATION.md km
This commit is contained in:
9 files changed
+814
-259
No files matched your search
@@ -17,9 +17,9 @@
|
||||
// the fill is the SAME vertical topColor->bottomColor gradient plus the 1px
|
||||
// radius the delegates had (rounded-rect SDF with a 1px AA edge, including
|
||||
// Rectangle's clamp of r to half the short side). Heights are pushed in ONE
|
||||
// JS pass per VizSettle re-evaluation — the push hooks the exact same
|
||||
// JS pass per VizSettle application — the push hooks the exact same
|
||||
// from/to/progress triplet the delegates' at(i) bindings used to capture —
|
||||
// so a 16 ms tick dirties ONE node instead of 28-48. No Canvas anywhere:
|
||||
// so a shell-pulse edge dirties ONE node instead of 28-48. No Canvas anywhere:
|
||||
// Canvas is CPU raster and is banned on this path.
|
||||
//
|
||||
// THE SHADER IS A .qsb, NOT AN INLINE STRING. Qt 6's ShaderEffect takes the
|
||||
@@ -104,7 +104,9 @@ Rectangle {
|
||||
visible: band.shown
|
||||
radius: theme.radiusMd
|
||||
color: "#59000000"
|
||||
clip: true
|
||||
// No clip: the shader arm is anchors.fill, and the fallback bars take
|
||||
// settle.at(i) hard-clamped to 0..1 (VizSettle.qml:86-91) against a
|
||||
// hardcoded 42px band, so nothing can poke out.
|
||||
|
||||
// Album-derived gradient, reusing the ambient triad (ambient_qt.rs) instead
|
||||
// of a second album-color pipeline — the Slint dock reads
|
||||
|
||||
Reference in new issue
Block a user