Performance: surfaces, the candle ring and the equalizer curve as shaders, the pill's bars as quads; tools/perf.sh
A playing pill cost the iGPU about 2.9 ms and the CPU 3.7 ms a frame, 60 frames a second: two vello passes over the whole island window for the surface's shadow and gradients (vello keeps no gradient between frames) and one for the bars. Now 0.4 ms GPU and 1.2 ms CPU. The open card went from 5.2 to 2.6 ms GPU and 6.2 to 3.4 ms CPU a frame. surface.wgsl draws every design's shadow, fill and inner gradient in one pass, with vello's own blurred-rectangle formula
This commit is contained in:
@@ -132,7 +132,13 @@ The config window edits the same file: Settings at the foot of the control centr
|
||||
|
||||
### Glass
|
||||
|
||||
`appearance.surface.design` picks what the island, the pills, the tray menu, the control centre and its popups are made of: `solid` (the wallpaper's gradient with an accent glow), `frosted` (a thin tint, a hairline white rim, a sheen along the top, a soft shadow) or `liquid` (clear glass, denser toward the bottom right, a light-catching edge, the accent's glow). Each design's opacity, rim and light are settings of their own (`appearance.solid|frosted|liquid.*`); the look itself is `src/surface.rs`. On see-through glass a face fades with `.opacity()` instead of a veil, a GPU layer only while it fades.
|
||||
`appearance.surface.design` picks what the island, the pills, the tray menu, the control centre and its popups are made of: `solid` (the wallpaper's gradient with an accent glow), `frosted` (a thin tint, a hairline white rim, a sheen along the top, a soft shadow) or `liquid` (clear glass, denser toward the bottom right, a light-catching edge, the accent's glow). Each design's opacity, rim and light are settings of their own (`appearance.solid|frosted|liquid.*`); the look itself is `src/surface.rs`, drawn by one shader (`src/surface.wgsl`: the shadow, the fill and the sheen or lit edge in one pass; the rim stays a border). On see-through glass a face fades with `.opacity()` instead of a veil, a GPU layer only while it fades.
|
||||
|
||||
### Performance
|
||||
|
||||
Amane draws rectangles, borders, letters and pictures as cheap quads, and gradients, shadows and `Canvas` paths with vello, which renders over the whole window and then lays the result on top. vello keeps a result between frames only when its shapes didn't change and hold no gradient, so anything drawn with it on every frame costs a pass over the whole window. What redraws every frame is therefore kept off vello: the surfaces are a shader, the pill's bars are rounded rectangles, the candle ring and the equalizer's curve are shaders (`src/ring.wgsl`, `src/curve.wgsl`). A shader's file is written to `$XDG_RUNTIME_DIR/magic-island/` when it is first drawn. A shader must not contain the word `time`, or amane redraws its window on every frame.
|
||||
|
||||
`tools/perf.sh PID [SECONDS]` (on the desktop) prints a process's CPU (and its children's), GPU per engine (DRM fdinfo) and memory.
|
||||
|
||||
Amane can only blur what the shell draws, so the frosting comes from Hyprland: a layer rule for the shell's windows (the namespace match is a full match). `ignore_alpha` leaves pixels at or below that opacity unblurred, which keeps the clear margin around the pills sharp; keep it below the design's thinnest part, or that part shows the desktop unblurred (liquid at its default 0.4 is 0.22 in its top left corner).
|
||||
|
||||
@@ -177,14 +183,15 @@ src/png.rs a stdlib png writer, for tray icons sent as pixels
|
||||
src/system.rs what the control centre shows: iwd, wired cards, openvpn, power, the external GPU
|
||||
src/glyph.rs every drawn icon, as a Canvas or as shapes for a shared one
|
||||
src/theme.rs the shell's colours: the matugen theme file, the cross-fade; watches config.toml
|
||||
src/surface.rs what the island, pills, menus and popups are made of: the solid, frosted and liquid designs
|
||||
src/surface.rs what the island, pills, menus and popups are made of: the solid, frosted and liquid designs as values for surface.wgsl
|
||||
src/*.wgsl shaders: surface (every surface), ring (the candles), curve (the equalizer's line)
|
||||
src/config.rs every setting, declared once (typed accessors + the window's list), config.toml read and written
|
||||
src/hypr.rs Hyprland's options for the config window: hyprctl descriptions/getoption, hl.config, amane.lua
|
||||
src/settings.rs the config window, `config` IPC
|
||||
src/parse.rs pure text parsing with unit tests, no amane dependency
|
||||
matugen/ the matugen template (amane.colors), rendered by skwd-wall into ./theme
|
||||
island-eq saved equalizer curves (a snapshot of ~/.config/amane/island-eq)
|
||||
tools/ remote test driver, fake MPRIS players, a fake tray app (`fake_tray.py name|path`), see AGENTS.md
|
||||
tools/ remote test driver, fake MPRIS players, a fake tray app (`fake_tray.py name|path`), perf.sh (CPU, GPU, memory of a process), see AGENTS.md
|
||||
```
|
||||
|
||||
## Requirements
|
||||
@@ -240,7 +247,7 @@ bind = SUPER, M, exec, amane ipc call island toggle
|
||||
- `~/.config/hypr/amane.lua`: the Hyprland options set in the config window, as `hl.config`; rewritten by the shell.
|
||||
- `$XDG_STATE_HOME/amane/` (`~/.local/state/amane/`): `last-played` (the song the island last heard, `key = value`) and a copy of its cover, for the card shown while nothing plays.
|
||||
- `~/.config/amane/island-eq`: one line per player identity, `<player>\t<preset or Custom>\t<10 gains in dB>`.
|
||||
- `$XDG_RUNTIME_DIR/magic-island/`: downloaded covers, `palette-cover`, `cava.conf`, `eq-<key>.conf`. On tmpfs, gone at logout.
|
||||
- `$XDG_RUNTIME_DIR/magic-island/`: downloaded covers, `palette-cover`, `cava.conf`, `eq-<key>.conf`, the shaders (`*.wgsl`). On tmpfs, gone at logout.
|
||||
- Equalizer nodes are named `magic_island_eq.<key>`. The key is the player's MPRIS bus name without `org.mpris.MediaPlayer2.`, non-alphanumerics as `_` (e.g. `chromium_instance123`).
|
||||
|
||||
## Known limits
|
||||
|
||||
Reference in New Issue
Block a user