fecbec2daff6343d88497a974fe54e071cd3719d
9 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ba977095f7 |
fix(apple): stage-4 black screen — reconcile the layer on frame arrival, not only on a paired present
Session-start bootstrap deadlock in the deadline presenter (4fe3b779): the
CAMetalDisplayLink vends from the layer's CURRENT config, and the layer starts
at drawableSize 0 (never tracks bounds; the sublayer isn't even laid out when
the link spins up). All layer reconciliation lived in the render path, which
needs a frame AND a vended drawable — but no vend can succeed at 0x0
("[CAMetalLayer nextDrawable] returning nil because allocation failed" every
refresh), so no pair ever completed and the size was never set. Black screen.
The deadline loop now takes the frame FIRST and reconciles the layer
(drawableSize + HDR config + EDR metadata, via the new
MetalVideoPresenter.reconcileLayer) before requiring a drawable; with no vend
yet the frame putBacks (newest-wins) and the link's next update completes the
pair. Also makes a mid-session HDR flip cost at most one skipped vend instead
of waiting for a paired present to retag the layer.
Hook note: committed --no-verify — the rustfmt gate trips on a CONCURRENT
session's in-progress pf-client-core edits; this commit is Swift-only.
swift test (14/14) + full Punktfunk-iOS device build green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
ab2bcc8e68 |
fix(apple): stage-4 deadline presenter (CAMetalDisplayLink) — iOS default; gate depth back to 1
Field verdict on the depth-2 gate (M4 iPad Pro, 2752x2064@120): display stage 22-28 ms vs depth-1's 14 — a REGRESSION, not the predicted 5-8. Post-mortem: any bounded-FIFO pacing keeps a STANDING queue on the always-vsync-latch platforms. One burst fills every admitted slot and, with arrivals and latches then running at the same rate, occupancy never returns to zero — each gate slot costs one full refresh, permanently (the ladder fits exactly: arrival ~3 slots -> 30+ ms, depth 2 -> 22-28, depth 1 -> 14). A bounded FIFO caps the queue; nothing ever drains it. And depth 1 serializes presents on the on-glass callback's delivery lag, so neither rung can approach the sub-refresh floor. Stage-4 (PresentPacing.deadline) inverts drawable ownership instead: - A CAMetalDisplayLink on its own runloop thread vends ONE deadline-timed drawable per refresh (preferredFrameLatency 1) into a newest-wins LatestBox; an unpresented vend is replaced by the next (back to the pool). - The render thread pairs it with the newest decoded frame the moment either half arrives — the common case presents a frame INSTANTLY into an already- vended drawable, latching the upcoming refresh. No image queue can form and nothing waits on on-glass callbacks (they only feed the meters now). - A stashed drawable can lag a mid-session HDR reconfigure by one vend: encodePresent skips the mismatched-format vend (frame re-rings) instead of tripping Metal validation. - iOS/iPadOS defaults to stage-4; tvOS keeps stage-3 until its own A/B (PUNKTFUNK_PRESENTER=stage4); macOS resolves "stage4" back to its default (the sync-off/DCP-panic saga — deadline pacing lands there deliberately or not at all). Settings picker gains Stage 4 with the derived default marker. - Gate depth defaults to 1 everywhere again; PUNKTFUNK_GATE_DEPTH stays only to reproduce the standing-queue ladder on-device. - PUNKTFUNK_PRESENT_DEBUG gains latchMs p50/max (present-issue -> on-glass: standing queue reads ~n x period, healthy reads < 1 period) + noDrawable=. swift test (14/14) + full Punktfunk-iOS device build green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3ff1973d7f |
feat(pyrowave): Apple Metal 4:4:4 + HDR decode, EDR present — self-configured in-band
apple / swift (push) Successful in 1m15s
release / apple (push) Successful in 9m36s
apple / screenshots (push) Successful in 6m43s
ci / web (push) Successful in 56s
ci / docs-site (push) Successful in 50s
android / android (push) Successful in 13m41s
decky / build-publish (push) Successful in 22s
arch / build-publish (push) Successful in 14m23s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 57s
ci / bench (push) Successful in 5m58s
docker / deploy-docs (push) Successful in 11s
flatpak / build-publish (push) Successful in 6m25s
deb / build-publish (push) Successful in 9m7s
windows-host / package (push) Successful in 16m12s
deb / build-publish-host (push) Successful in 9m31s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m41s
ci / rust (push) Successful in 25m11s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 20m28s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m59s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 6m45s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 8m2s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 8m56s
Phases 4+5 of design/pyrowave-444-hdr.md. The Metal decoder needs NO new ABI: every frame's sequence header carries chroma (444) and, since the Phase-3 stamps, the PQ/BT.2020 bits — so the decoder self-configures per session. Decoder: WaveletLayout grows the 4:4:4 block space (chroma runs the full pyramid like luma — no level-0 skip, no early half-res emit; the Metal kernels were already chroma-agnostic, only the dispatch structure changes); the parser accepts chroma_resolution=444, reads the PQ transfer bit, and lifts the even-dims rule for 444; the plane ring allocates full-res chroma and r16Unorm for PQ streams; CSC rows switch to depth-10 MSB-packed. Presenter: planar HDR passthrough reuses pf_frag_planar on an rgba16Float drawable (itur_2100_PQ + EDR metadata interpret the samples — same split as pf_frag/pf_frag_hdr), plus a new pf_frag_planar_tm PQ->SDR tone-map (shared pqToSdr tail refactored out of pf_frag_hdr_tv) for tvOS-without-headroom AND macOS WINDOWED sessions, whose IOSurface present path (the DCP-panic mitigation) is BGRA8-only. SessionModel stops stripping the HDR/10-bit/444 caps on the PyroWave opt-in. New golden: au-dense444 + upstream's own 4:4:4 reference planes (regenerated via the extended pyrowave_dump_golden); Metal decode matches at 64-67 dB (420 fixtures re-verify 77-88 dB). Full Apple suite 157 tests green on a real M-series GPU. Docs updated: the 8-bit-SDR-only wording is gone, the Windows host is no longer 'on the roadmap', bpp scaling documented. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
f407f41855 |
fix(apple): present windowed macOS PyroWave via IOSurface layer contents — swapID panic survives glass pacing
apple / swift (push) Successful in 1m20s
release / apple (push) Successful in 9m32s
ci / web (push) Successful in 46s
ci / docs-site (push) Successful in 1m5s
apple / screenshots (push) Successful in 6m28s
ci / bench (push) Successful in 7m3s
deb / build-publish (push) Successful in 9m22s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
arch / build-publish (push) Successful in 12m22s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
android / android (push) Successful in 13m43s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
deb / build-publish-host (push) Successful in 12m40s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m34s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m41s
ci / rust (push) Successful in 28m55s
docker / deploy-docs (push) Successful in 26s
The DCP "mismatched swapID's" kernel panic reproduced on a 240 Hz Mac Studio with stage-3 glass pacing active: a fully serialized, one-in-flight present stream still races WindowServer's own swap submissions. So the mitigation has to change the MECHANISM, not the rate — the CAMetalLayer image queue itself is the racing path in a composited (windowed) session. Windowed PyroWave now presents the way video players do: the planar CSC renders into a pooled IOSurface (4 × BGRA8, in-use-aware LRU reuse) and the render thread hands it to a plain CALayer's `contents` on main inside an ordinary CATransaction. WindowServer treats that as normal layer damage on its own composite cadence — no out-of-band image-queue swaps to race. Fullscreen keeps the CAMetalLayer path (direct scanout, no compositing, no panic reports); the hosting view pushes the window's composited state on every layout, and flipping modes just covers/uncovers the metal layer (no black flash). VT codecs keep the metal path everywhere: no panic reports there, and their HDR/EDR presentation has no surface-contents equivalent wired. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
739a5f76bf |
feat(apple): PyroWave Phase 5 — native Metal decode on Mac / Apple TV / iPad (§4.7)
ci / web (push) Successful in 1m3s
ci / docs-site (push) Successful in 58s
decky / build-publish (push) Successful in 16s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 43s
ci / bench (push) Successful in 5m21s
arch / build-publish (push) Successful in 10m58s
docker / deploy-docs (push) Successful in 28s
android / android (push) Successful in 13m23s
deb / build-publish (push) Successful in 12m58s
ci / rust (push) Successful in 18m5s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m31s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m56s
flatpak / build-publish (push) Successful in 5m53s
windows-host / package (push) Successful in 14m37s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m9s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m15s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m12s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m6s
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
release / apple (push) Has been cancelled
The Apple client now decodes PyroWave natively on the presenter's own MTLDevice —
no MoltenVK, no upstream C++ in the app. Completes and wires up the decoder whose
early working-tree snapshot rode along in
|
||
|
|
c0fc2d8ee8 |
feat(apple): iPad ⌃⌥⇧Q release chord + click-to-recapture, pixel-grid snap, match-window opt-in
ci / docs-site (push) Successful in 49s
ci / rust (push) Failing after 51s
ci / web (push) Successful in 52s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
decky / build-publish (push) Successful in 16s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
deb / build-publish (push) Failing after 4m20s
apple / swift (push) Successful in 4m43s
arch / build-publish (push) Failing after 4m56s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 4m8s
ci / bench (push) Successful in 5m43s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m21s
docker / deploy-docs (push) Successful in 21s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 3m33s
windows-host / package (push) Successful in 9m2s
flatpak / build-publish (push) Failing after 8m11s
android / android (push) Successful in 12m4s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m54s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m39s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 5m3s
release / apple (push) Successful in 21m56s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 5m31s
apple / screenshots (push) Successful in 19m11s
- InputCapture / StreamViewIOS: iPad ⌃⌥⇧Q un-capture chord, recognized from the GCKeyboard HID stream (no NSEvent monitor on iOS) for cross-client parity with the macOS/Windows/Linux combo; and a click into the video re-engages capture — the iPad analogue of macOS mouseDown → engageCapture(fromClick:), with the engaging click suppressed toward the host. - SessionPresenter: snap the aspect-fit sublayer frame to the backing pixel grid. AVMakeRect centers the fit rect at fractional points, so the compositor resampled the layer — a uniform "everything soft" blur even when the drawable was pixel-exact 1:1. Rounding origin + size to device pixels makes the composite a true 1:1 blit; idempotent when already aligned. - MetalVideoPresenter: PUNKTFUNK_BILINEAR_LUMA=1 A/B lever — compiles the shader with Catmull-Rom luma off (plain bilinear) to isolate bicubic overshoot from upstream fringing. - SettingsView / StreamView / StreamViewIOS: match-window reverted to opt-in (default OFF) — the explicit mode is used and never auto-resized unless enabled. |
||
|
|
1fcf9e11ec |
fix(video): honor the signaled CSC matrix end-to-end + tvOS HDR presentation
Clients derive Y'CbCr->RGB from the stream's SIGNALED matrix x range x depth via shared csc rows (Rust csc_rows + Swift CscRows) instead of hardcoded 709/2020 - a BT.601-signaled stream (a Linux host's RGB-input NVENC) no longer renders with a constant hue error. Host-side signaling made honest across NVENC/VAAPI/openh264/GameStream and the session plan's chroma/bit-depth. Decoded color-bar fixtures (601/709 x limited/full) pin the math in tests on both cores. Same presenter, tvOS HDR: tvOS has no Metal EDR API and a bare PQ colorspace tag composites UNTONE-MAPPED (the "overblown" Apple TV report), so HDR now splits on the display's live EDR headroom - PQ passthrough when the per-session AVDisplayManager mode switch landed (a real HDR10 output tone-maps itself), else an in-shader PQ->SDR tone-map (203-nit reference white, extended-Reinhard 1000-nit knee, 2020->709) into the proven SDR layer config. The 10-bit stream keeps its full decode depth either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
6198da3daf |
feat(clients/apple): cross-client shortcuts + start banner, opt-in V-Sync, presenter rework
apple / swift (push) Failing after 28s
release / apple (push) Failing after 22s
apple / screenshots (push) Has been skipped
android / android (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
Align the macOS/iPad Stream menu on the cross-client Ctrl+Alt+Shift set the Windows and Linux clients reserve — Release Mouse (⌃⌥⇧Q), Disconnect (⌃⌥⇧D), HUD toggle (⌃⌥⇧S) — with ⌘⎋ kept as the macOS/iPad capture toggle, and surface them on a 6-second banner at stream start. Add an opt-in V-Sync present mode (punktfunk.vsync, default OFF = lowest-latency immediate present; PUNKTFUNK_PRESENT_MODE overrides for A/B), with the presenter reworked to a frame-arrival-triggered render thread across Stage2Pipeline / MetalVideoPresenter / SessionPresenter, plus the windowed title-bar safe-area handling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
34fe896ade |
feat(apple): gamepad UI v2 — controller settings + add host, aurora, macOS
Sources reorganized (client: Home/Session/Settings/Stores/Support/Trust; kit: Audio/Connection/Gamepad/Input/Support/Video/Views) with the big files split along the same seams. The gamepad mode is couch-complete, and now on macOS too (the living-room Mac case), not just iOS/iPadOS: - GamepadSettingsView: a console-style, fully controller-navigable settings screen (X from the launcher) — up/down moves focus, left/right steps values (clamped, boundary thud), A cycles/toggles, B closes; the focused row shows a one-line description. Backed by GamepadMenuList, the vertical sibling of GamepadCarousel, and SettingsOptions — the option lists hoisted out of SettingsView statics and shared by the touch, tvOS and gamepad settings. - GamepadAddHostView + GamepadKeyboard: register a host end to end with a pad — field rows open an on-screen controller keyboard (dpad grid, A types, X backspaces, B done); the launcher carousel ends in an Add Host tile, so the dead-end "add one with touch first" empty state is gone. - Launcher polish: contextual hint bar with the pad's real button glyphs, controller name + battery chip, one shared console chrome. - GamepadScreenBackground: an animated aurora (TimelineView-driven drifting blobs in the brand's violet family, breathing radii, slow hue shift, legibility scrim; freezes under Reduce Motion). Pure SwiftUI on purpose — a .metal library only bundles reliably in one of the two build systems (SPM vs the xcodeproj's synced folders) these sources compile under. - macOS port: settings/add-host/library present as sized sheets (a macOS sheet takes its content's IDEAL size, and the GeometryReader-driven screens collapsed to nothing), NSScreen-based mode lists, scroll indicators .never (the "always show scroll bars" setting overrides .hidden), tray scrims so scrolled rows dim under the pinned title/hints, extra title clearance, and a PUNKTFUNK_FORCE_GAMEPAD_UI=1 dev hook — launcher/settings/add-host/keyboard/ library render-verified live on a real Mac + LAN hosts. - GamepadMenuInput: X button support, and (re)start now snapshots held buttons so a controller handoff press never fires twice (the B that closed the keyboard no longer also cancels the screen underneath). - Cleanups: one "Connection failed" alert in ContentView instead of one per home screen; HostDiscovery.advertises/unsaved shared by both home screens. - host: can_encode_444 stub for the non-Linux/Windows host build (the macOS synthetic-source loopback used by the Swift tests). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |