perf(apple): windowed macOS presents — off-main transactional commit, surface prototype, safe-present setting
ci / docs-site (push) Successful in 52s
ci / web (push) Successful in 56s
decky / build-publish (push) Successful in 21s
apple / swift (push) Successful in 1m24s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
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 12s
ci / bench (push) Successful in 5m53s
release / apple (push) Successful in 9m19s
deb / build-publish (push) Successful in 12m27s
arch / build-publish (push) Successful in 12m52s
docker / deploy-docs (push) Successful in 26s
deb / build-publish-host (push) Successful in 13m18s
apple / screenshots (push) Successful in 6m20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m51s
android / android (push) Successful in 18m40s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m15s
ci / rust (push) Successful in 27m38s
ci / docs-site (push) Successful in 52s
ci / web (push) Successful in 56s
decky / build-publish (push) Successful in 21s
apple / swift (push) Successful in 1m24s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
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 12s
ci / bench (push) Successful in 5m53s
release / apple (push) Successful in 9m19s
deb / build-publish (push) Successful in 12m27s
arch / build-publish (push) Successful in 12m52s
docker / deploy-docs (push) Successful in 26s
deb / build-publish-host (push) Successful in 13m18s
apple / screenshots (push) Successful in 6m20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m51s
android / android (push) Successful in 18m40s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m15s
ci / rust (push) Successful in 27m38s
Task 1 (latency): the transactional present now commits from the RENDER
thread inside an explicit CATransaction + flush() instead of hopping to
main. The present harness (2026-07-21, 240 Hz Studio, full-size window)
measured the main hop batching presents at runloop-iteration rate when
main is busy — an active implicit transaction NESTS the explicit one —
which is the field's presents=55 @ fps=240 / display_p50 18.6 ms.
Off-main commits measured immune to main churn: glass p50 ~10 ms,
cadence a clean 4.17 ms at 240. flush() is load-bearing: without it the
render thread's own implicit transaction (drawableSize/colour writes)
swallows the explicit commit and NOTHING reaches glass — the harness
reproduced the exact freeze (every present dropped). Legacy main-hop
kept as PUNKTFUNK_TXN_PRESENT=main for field A/B. New pf-windowed
Console line (subsystem io.unom.punktfunk, category presenter)
decomposes the issue side per second.
Task 1 lever D: the f407f418 IOSurface contents-swap path is
resurrected format-aware as WindowedPresentMode.surface — bgra8 SDR /
rgba16Float+PQ-tagged HDR pool, swap committed off-main from the
completion handler; EDR anchored by the metal layer underneath.
Env-only prototype (PUNKTFUNK_WINDOWED_PRESENT=surface) until the HDR
composite is eyeballed on glass.
Task 2 (setting): punktfunk.windowedSafePresent (default ON =
transactional mitigation; OFF = the fast async path whose panic the
saga is about — the caption says so in plain words). Rows in the touch
Settings (Presentation) and gamepad settings, macOS-only.
PUNKTFUNK_WINDOWED_PRESENT=async|transaction|surface overrides for dev
A/B. maximumDrawableCount stays 3 — the harness measured 2 starving the
render loop (172/s) and worsening glass p50.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -316,6 +316,41 @@ final class PresentPacingTests: XCTestCase {
|
||||
SessionPresenter.pacing(for: .stage4, explicit: .stage4, codec: .pyrowave), .deadline)
|
||||
}
|
||||
|
||||
// MARK: - Windowed present mechanism (the macOS DCP swapID-panic mitigation picker)
|
||||
|
||||
#if os(macOS)
|
||||
/// The safe-present setting: ON/unset → the validated transactional mitigation; an explicit
|
||||
/// OFF → the fast async path (the user accepted the affected-setup panic risk). The
|
||||
/// PUNKTFUNK_WINDOWED_PRESENT env lever overrides both ways, `surface` is env-only (the
|
||||
/// prototype mechanism), and garbage/empty env values are "unset", not an override.
|
||||
func testWindowedPresentModeResolution() {
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: nil, env: nil), .transaction,
|
||||
"unset defaults to the panic mitigation")
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: true, env: nil), .transaction)
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: false, env: nil), .async,
|
||||
"an explicit opt-out gets the fast async path")
|
||||
// The dev env lever wins over the setting, both directions.
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: true, env: "async"), .async)
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: false, env: "transaction"),
|
||||
.transaction)
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: true, env: "surface"), .surface,
|
||||
"the surface prototype is reachable via env only")
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: false, env: "surface"), .surface)
|
||||
// Garbage/empty env = unset.
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: nil, env: "garbage"), .transaction)
|
||||
XCTAssertEqual(
|
||||
SessionPresenter.windowedPresentMode(setting: false, env: ""), .async)
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - Glass-gate depth
|
||||
|
||||
/// The in-flight present budget is 1 EVERYWHERE: any deeper gate keeps a standing queue —
|
||||
|
||||
Reference in New Issue
Block a user