refactor(windows-host): confine platform code under windows/ + linux/ folders (Goal-1 stage 6)

Move 36 platform-specific files into per-module `windows/` and `linux/` subfolders (and the
shared HID codecs into `inject/proto/`):
  capture/{windows,linux}/  encode/{windows,linux}/  inject/{windows,linux,proto}/
  audio/{windows,linux}/  vdisplay/{windows,linux}/
  src/windows/ (service, wgc_helper, win_adapter, win_display)
  src/linux/  (dmabuf_fence, drm_sync, zerocopy/)

Done with `#[path]`, NOT a module rename: every file moves into its folder while the
`crate::*::*` module names stay FLAT, so all caller paths and every internal `super::`/`crate::`
reference are unchanged — only the parent `mod` decls gained `#[path = "..."]`. This is the
codebase's existing pattern (inject's gamepad_windows) and makes the move byte-identical in
behaviour with ZERO reference churn, far lower risk than collapsing to a single
`crate::capture::windows::` namespace (that deeper rename is an optional follow-on; this delivers
the cfg-sprawl folder confinement the stage is about). Done LAST, after the semantic stages, so
the path churn didn't fight them.

Verified: Linux cargo check + clippy (-D warnings) clean; my mod-decl changes fmt-clean (the 3
remaining fmt diffs are pre-existing local-rustfmt-version skew that moved with their files); all
36 `#[path]` targets exist; no internal `#[path]`/`include!`/file-child-mod in any moved file
(the inline `mod X {` blocks are self-contained). Box build to follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-25 18:53:45 +00:00
parent a0427cd2a3
commit 38c68c33e5
49 changed files with 62 additions and 6 deletions
@@ -0,0 +1,66 @@
//! Backend-neutral DXGI adapter selection.
//!
//! The discrete render-GPU LUID picker used to live in the SudoVDA backend (`vdisplay::sudovda`) — a
//! historical accident, since it is display-utility, not SudoVDA-specific. It lives here so the capturers
//! (IDD-push) and the pf-vdisplay backend depend on it as a *peer* instead of reaching into the SudoVDA
//! module — breaking that circular reach-in so SudoVDA can eventually be dropped without losing this
//! helper (audit §9 / Goal 2). This is the plan's `windows/adapter.rs`.
use windows::Win32::Foundation::LUID;
/// Pick the discrete render GPU LUID: the adapter with the most `DedicatedVideoMemory`, skipping
/// WARP / Basic-Render and the SudoVDA software adapter (≈0 VRAM). `PUNKTFUNK_RENDER_ADAPTER=<substring>`
/// forces a match by Description (Apollo's `adapter_name`). Used by the IDD direct-push capturer (to
/// create its shared textures on the same discrete GPU it pins, where NVENC runs) and SET_RENDER_ADAPTER.
///
/// # Safety
/// Creates + enumerates a DXGI factory; the COM calls run in the caller's apartment (the existing callers
/// already satisfy this).
pub(crate) unsafe fn resolve_render_adapter_luid() -> Option<LUID> {
use windows::Win32::Graphics::Dxgi::{CreateDXGIFactory1, IDXGIFactory1};
let want = crate::config::config()
.render_adapter
.clone()
.filter(|s| !s.is_empty());
let factory: IDXGIFactory1 = CreateDXGIFactory1().ok()?;
let mut best: Option<(LUID, u64, String)> = None;
let mut i = 0u32;
while let Ok(a) = factory.EnumAdapters1(i) {
i += 1;
let Ok(d) = a.GetDesc1() else { continue };
let name = String::from_utf16_lossy(&d.Description);
let name = name.trim_end_matches('\u{0}').to_string();
let lname = name.to_ascii_lowercase();
if lname.contains("basic render") || lname.contains("warp") {
continue; // never pin to the software rasterizer
}
if let Some(w) = &want {
if lname.contains(&w.to_ascii_lowercase()) {
tracing::info!(
adapter = name,
"render adapter chosen by PUNKTFUNK_RENDER_ADAPTER"
);
return Some(d.AdapterLuid);
}
continue;
}
let vram = d.DedicatedVideoMemory as u64; // SudoVDA software adapter ≈ 0 → loses to the dGPU
if best.as_ref().is_none_or(|(_, v, _)| vram > *v) {
best = Some((d.AdapterLuid, vram, name));
}
}
match best {
Some((luid, vram, name)) => {
tracing::info!(
adapter = name,
vram_mb = vram / (1024 * 1024),
"render adapter chosen (max VRAM)"
);
Some(luid)
}
None => {
tracing::warn!("no suitable render adapter found for SET_RENDER_ADAPTER");
None
}
}
}