Expand description
Render-world half of morphFilter: the freeze (stealing the layer’s
on-screen pixels as the “from” snapshot), the per-frame blend pass, and
the morph composite gate.
Per frame, for each layer with an extracted morph
(ExtractedMorph — an active crate::filters::MorphState plus a
resolved single-pass chain):
freeze_morph_snapshot+maintain_morph_blend(called fromprepare_layer_textures, bracketing its realloc) maintain theMorphSlot. A newfreeze_seqsteals the pixels currently on screen — the previous blend (an interrupted morph’s in-flight mix) or the capture texture itself — assnapshot, before the realloc that a same-frame content/size change would trigger drops them. No blit/copy: taking over the texture is free and survives reallocs by construction. Nothing valid to freeze (startup) degrades to no snapshot — the blend becomes a self-blend of the live capture (a visual snap while progress runs, never garbage).prepare_layer_morphs(PrepareBindGroups, afterprepare_layer_textures, beforeprepare_layer_filters) stages the single blend pass every frame while the morph is in flight (progress moves — the uniforms change even when nothing else does), reusing the content-filter pipeline wholesale: binding 0 = the live capture (the “to”), binding 3 = the snapshot (the “from” — layout-anchored, plain 0..1 UV stretches it onto the current capture rect), target = the dedicatedblendtexture. The engine writes the reservedparams[7].x= progress (see the MORPH CONTRACT infilter_prelude.wgsl).run_morph_passes(called fromui_layer_capture_pass, after the layer’s capture, before its regular filter run) executes the pass.- The regular
filterchain (if any) sources the blend instead of the capture — morph first, then filters; a morph-ONLY layer’s composite quad samplesblenddirectly, gated bymorph_gatewith the same never-show-partial-content discipline as the content-filter gate.
The blend target is deliberately NOT a prepended ping-pong pass: with a ≥2-pass regular chain, pass 2 would overwrite the blend’s ping-pong slot, and the interrupt freeze (which steals the blended output) would freeze a re-filtered image instead. A dedicated texture keeps the regular chain’s indices untouched and the freeze source well-defined.
Structs§
- Extracted
Morph - A layer’s morph, as seen by the render world this frame. Present iff the
main-world
crate::filters::MorphStateis active AND the resolved morph chain has exactly one pass (the resolver’s cap). - Morph
Meta - Per-frame morph staging, index-aligned with
ExtractedUiLayers::layers. Owns its own uniform buffer (the shared- buffer order-coupling rule — seeBackdropMeta). - Morph
Slot - A layer’s persistent morph resources: the frozen
snapshot(the “from” texture, stolen at freeze) and the dedicatedblendtarget the morph pass writes (what the regular chain — or the composite — samples). Preserved acrossLayerSlotreallocs (the snapshot must survive a same-frame capture resize on the freeze frame); cleared when the extracted morph disappears (settle, unset, demote).
Functions§
- freeze_
morph_ snapshot - Consume a new
freeze_seq: steal the pixels currently on screen as the snapshot and reset the slot’s morph state around it. MUST run before the caller’s realloc branch — the steal reads the pre-realloc textures — and the caller must preserveslot.morphacross that realloc. - maintain_
morph_ blend - Post-realloc maintenance: clear the slot when the morph ended, and track the capture size with the blend target (a mid-flight resize re-allocates the blend only — the snapshot survives untouched).
- morph_
gate - Whether a morph-ONLY layer’s composite may draw this frame, maintaining
the gate-warn bookkeeping. Returns the bind group over
blendwhen ready. Same discipline as the content-filter gate: never fall back to the raw capture (the mid-blend flash this gate exists to prevent). - prepare_
layer_ morphs - Stage every morphing layer’s blend pass for this frame. Mirrors
prepare_layer_filters’ three phases; staging is unconditional per in-flight frame (progress moves every frame). Ordered afterprepare_layer_textures(the slot/blend exist) and beforeprepare_layer_filters(the regular chain’s validity prediction readsMorphSlot::output_valid). - run_
morph_ passes - Execute one layer’s staged morph pass inside the capture-pass encoder:
capture (already rendered) + snapshot → blend. Called per layer from
ui_layer_capture_pass, after the capture, before the regular filter replay (which sources the blend).