Files
punktfunk/docs/windows-host-goal1-plan.md
T
enricobuehler a3eefc2374 feat(windows-host): HostConfig foundation + staged Goal-1 roadmap (Goal-1 stage 1)
config.rs: typed HostConfig parsed ONCE from env (idd_push/encoder_pref/no_helper/force_helper), replacing per-call env::var re-reads (PUNKTFUNK_ENCODER was re-read on EVERY windows_resolved_backend() call; PUNKTFUNK_IDD_PUSH is read 8x across the host — the recompute that lets capture + encode disagree on the backend, plan §2.4). Migrated the two highest-churn dispatch reads onto it (encode::windows_resolved_backend, punktfunk1::should_use_helper). Behavior-identical: the env is constant for the process lifetime (the service loads host.env before launch), so a lazily-parsed global == parsed-once-at-startup.

docs/windows-host-goal1-plan.md: the ORDERED, independently-shippable execution plan for Goal-1 (the plan's biggest unstarted goal — a from-scratch layered host architecture). Six behavior-preserving, box-verified stages (HostConfig -> SessionPlan -> SessionContext/SessionFactory -> seam-trait tightenings -> src/windows tree), because the host is live-validated and a monolithic rewrite would strand it broken. Stage 1 done here; stages 3-5 rewire the deployed path and require on-glass re-test.

Verified: Linux + box (--features nvenc) cargo check clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 17:02:16 +00:00

4.2 KiB
Raw Blame History

Goal-1 (clean, layered host architecture) — staged execution plan

The design is in windows-host-rewrite.md §2.22.4. This file is the ordered, independently-shippable execution plan, because the host is live-validated (GameStream + punktfunk/1, NVENC + IDD-push on-glass) and Goal-1 rewires its session/config/dispatch flow — so every stage must preserve behavior, compile + box-verify on its own, and be committed before the next starts. The plan's own §14 makes the §1 preservation checklist a mandatory per-module assert contract; honour it.

Why staged (not one big rewrite)

main is at parity and shipping. A monolithic rewrite would put the validated host in a broken intermediate state for a long window and make a regression impossible to bisect. Each stage below is a behaviour-preserving transform with its own verification, so a regression is caught at the stage that introduced it.

Stages (ordered; each = goal · files · risk · verify)

Stage 1 — HostConfig foundation. DONE (this commit). config.rs: typed HostConfig parsed ONCE from env (idd_push/encoder_pref/no_helper/force_helper). Migrated the two highest-churn dispatch reads onto it (encode::windows_resolved_backend, punktfunk1::should_use_helper). Risk: low (env constant at runtime → identical behaviour). Verify: box cargo check --features nvenc.

Stage 2 — finish HostConfig + resolve-once. Migrate the remaining ~64 env::var sites onto HostConfig fields (esp. PUNKTFUNK_IDD_PUSH ×8, PUNKTFUNK_RENDER_ADAPTER, PUNKTFUNK_ZEROCOPY, PUNKTFUNK_SECURE_DDA, PUNKTFUNK_IDD_DEPTH, PUNKTFUNK_NO_WGC, the perf/debug flags). Linux vars (XDG/compositor) included for one config. Risk: medium (must preserve each var's exact semantics — a flipped bool is a silent regression; assert per the §1 checklist). Verify: Linux + box build; grep env::var should reach ~0 outside config.rs.

Stage 3 — SessionPlan (the single biggest clarity lever, plan §2.4). Resolve display/capture/topology/encoder/format/hdr/bit_depth ONCE from HostConfig into a typed SessionPlan; replace the 3-place dispatch (capture_virtual_output, should_use_helper/virtual_stream, windows_resolved_backend) with reads off the plan. Fixes the capture/encode backend-disagreement bug class. Risk: medium-high (rewires the deployed decision). Verify: box build + on-glass re-test (NVENC + IDD-push + a mode switch).

Stage 4 — SessionContext + SessionFactory/Session. Bundle the 1213-arg #[allow(too_many_arguments)] signatures into SessionContext; SessionFactory.build() owns the RAII chain vdm.lease(mode) → open_capturer(vout, fmt) → open_encoder(plan) → spawn pipeline, with Session::drop the ONLY teardown path. Risk: high (teardown ordering — the §1 RAII asserts are mandatory). Verify: box build + on-glass (connect/disconnect/reconnect, no leaked monitors/threads).

Stage 5 — seam-trait tightenings (plan §2.3). Capturer::open_capturer(vout, want: OutputFormat) takes the format IN (kills the capture → encode::windows_resolved_backend() back-reference recomputed in dxgi.rs); HDR/release become VirtualLease methods (session glue names no concrete backend, contains no unsafe); optional encoder features move to EncoderCaps. Risk: medium. Verify: box build + on-glass.

Stage 6 — src/windows/ tree (cfg-sprawl confinement, plan §2.2). Move the Windows backends under src/windows/ + capture/windows/, encode/windows/, inject/windows/, audio/windows/, vdisplay/windows.rs behind one #[cfg(windows)] mod windows; seam. Pure file move + mod/use-path updates — behaviour-identical. Risk: low-but-huge (dozens of files; compile-verify catches all). Do LAST so the earlier semantic stages don't fight path churn. Verify: Linux + box build.

Guardrails (mandatory, plan §14)

  • Each stage is its own commit; box-verify before moving on.
  • Stages 35 touch the deployed path → on-glass re-test (NVENC + IDD-push, a mode switch, a connect/disconnect cycle) before the next stage.
  • Preserve every PUNKTFUNK_* var's exact semantics; when in doubt, assert old==new at the call site.