From e5c9ee8327062dd7def15ee1b7ad17b9c8e8b430 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Thu, 25 Jun 2026 13:02:22 +0000 Subject: [PATCH] =?UTF-8?q?feat(windows-host):=20activate=20render-adapter?= =?UTF-8?q?=20pin;=20gamepad=20SHM=20from=20proto=20(audit=20=C2=A74.2h/?= =?UTF-8?q?=C2=A76.1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §4.2h (C2): the host already pins the discrete GPU via IOCTL_SET_RENDER_ADAPTER on the IDD-push path; now that the pf-vdisplay driver implements it (0a7ae5e), correct the stale 'driver returns STATUS_NOT_IMPLEMENTED / STEP-4 stub' comments. Hybrid iGPU+dGPU boxes now actually pin the NVENC GPU. §6.1 (C5): switch the host gamepad SHM consumers (inject/{dualsense,gamepad}_windows.rs) to derive size/offsets/magic/name from pf_vdisplay_proto::gamepad::{PadShm,XusbShm} via offset_of!/size_of!/helpers, instead of hand-literal OFF_*/140 — proto is now the single source of truth (driver-side switch follows with the gamepad-driver unification). The DualShock4 backend reuses the same pub(super) consts unchanged. Verified: host clippy (nvenc) clean on the RTX box (x86_64-pc-windows-msvc). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/inject/dualsense_windows.rs | 24 ++++++++------ .../src/inject/gamepad_windows.rs | 31 ++++++++++--------- .../src/vdisplay/pf_vdisplay.rs | 18 +++++------ 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/crates/punktfunk-host/src/inject/dualsense_windows.rs b/crates/punktfunk-host/src/inject/dualsense_windows.rs index 28b7ac0..1a0b081 100644 --- a/crates/punktfunk-host/src/inject/dualsense_windows.rs +++ b/crates/punktfunk-host/src/inject/dualsense_windows.rs @@ -40,17 +40,21 @@ use windows::Win32::System::Memory::{ }; use windows::Win32::System::Threading::{CreateEventW, SetEvent, WaitForSingleObject}; -/// Shared-section layout — must match `packaging/windows/dualsense-driver/src/lib.rs`. `pub(super)` -/// so the sibling DualShock 4 backend ([`super::dualshock4_windows`]) reuses the exact offsets. -pub(super) const SHM_SIZE: usize = 256; -pub(super) const SHM_MAGIC: u32 = 0x5046_4453; // "PFDS" -pub(super) const OFF_INPUT: usize = 8; -pub(super) const OFF_OUT_SEQ: usize = 72; -pub(super) const OFF_OUTPUT: usize = 76; +/// Shared-section layout — the single source of truth is [`pf_vdisplay_proto::gamepad::PadShm`] (offset +/// asserts pin every field; the `pf_dualsense` driver maps the same struct). Derive the size/offsets/magic +/// from it so a layout change is a compile error, not a hand-synced literal (audit §6.1). `pub(super)` so +/// the sibling DualShock 4 backend ([`super::dualshock4_windows`]) reuses the exact offsets. +pub(super) const SHM_SIZE: usize = core::mem::size_of::(); +pub(super) const SHM_MAGIC: u32 = pf_vdisplay_proto::gamepad::PAD_MAGIC; // "PFDS" +pub(super) const OFF_INPUT: usize = core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, input); +pub(super) const OFF_OUT_SEQ: usize = + core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, out_seq); +pub(super) const OFF_OUTPUT: usize = core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, output); /// Device-type selector the driver reads to choose which HID identity/descriptor it serves: 0 = /// DualSense (the default — the section is zeroed), 1 = DualShock 4. -pub(super) const OFF_DEVTYPE: usize = 140; -pub(super) const DEVTYPE_DUALSHOCK4: u8 = 1; +pub(super) const OFF_DEVTYPE: usize = + core::mem::offset_of!(pf_vdisplay_proto::gamepad::PadShm, device_type); +pub(super) const DEVTYPE_DUALSHOCK4: u8 = pf_vdisplay_proto::gamepad::DEVTYPE_DUALSHOCK4; /// A single virtual DualSense: the SwDeviceCreate'd `pf_pad_` software devnode (the driver /// loads on it and the HID DualSense appears to games) plus the shared-memory section the driver maps. @@ -239,7 +243,7 @@ pub(super) fn create_swdevice(p: &SwDeviceProfile) -> Result { /// caller stamps the device-type + initial input report and finally the magic. Shared by both Windows /// pad backends (DualSense + DualShock 4). pub(super) fn create_shm_section(index: u8) -> Result<(HANDLE, *mut u8)> { - let name = HSTRING::from(format!("Global\\pfds-shm-{index}")); + let name = HSTRING::from(pf_vdisplay_proto::gamepad::pad_shm_name(index)); let mut psd = PSECURITY_DESCRIPTOR::default(); // SAFETY: the SDDL literal is valid; psd receives an allocated descriptor (freed by the OS when diff --git a/crates/punktfunk-host/src/inject/gamepad_windows.rs b/crates/punktfunk-host/src/inject/gamepad_windows.rs index 209fe92..ff41d34 100644 --- a/crates/punktfunk-host/src/inject/gamepad_windows.rs +++ b/crates/punktfunk-host/src/inject/gamepad_windows.rs @@ -32,19 +32,22 @@ use windows::Win32::System::Memory::{ }; use windows::Win32::System::Threading::{CreateEventW, SetEvent, WaitForSingleObject}; -// Shared-section layout — must match `packaging/windows/xusb-driver/src/lib.rs`. -const SHM_SIZE: usize = 64; -const SHM_MAGIC: u32 = 0x5558_4650; // "PFXU" -const OFF_PACKET: usize = 4; -const OFF_BUTTONS: usize = 8; -const OFF_LT: usize = 10; -const OFF_RT: usize = 11; -const OFF_LX: usize = 12; -const OFF_LY: usize = 14; -const OFF_RX: usize = 16; -const OFF_RY: usize = 18; -const OFF_RUMBLE_SEQ: usize = 24; -const OFF_RUMBLE: usize = 28; // large @28, small @29 +// Shared-section layout — the single source of truth is `pf_vdisplay_proto::gamepad::XusbShm` (offset +// asserts pin every field; the `pf_xusb` driver maps the same struct). Derive the size/offsets/magic from +// it so a layout change is a compile error, not a hand-synced literal (audit §6.1). +use pf_vdisplay_proto::gamepad::XusbShm; +const SHM_SIZE: usize = core::mem::size_of::(); +const SHM_MAGIC: u32 = pf_vdisplay_proto::gamepad::XUSB_MAGIC; // "PFXU" +const OFF_PACKET: usize = core::mem::offset_of!(XusbShm, packet); +const OFF_BUTTONS: usize = core::mem::offset_of!(XusbShm, buttons); +const OFF_LT: usize = core::mem::offset_of!(XusbShm, left_trigger); +const OFF_RT: usize = core::mem::offset_of!(XusbShm, right_trigger); +const OFF_LX: usize = core::mem::offset_of!(XusbShm, thumb_lx); +const OFF_LY: usize = core::mem::offset_of!(XusbShm, thumb_ly); +const OFF_RX: usize = core::mem::offset_of!(XusbShm, thumb_rx); +const OFF_RY: usize = core::mem::offset_of!(XusbShm, thumb_ry); +const OFF_RUMBLE_SEQ: usize = core::mem::offset_of!(XusbShm, rumble_seq); +const OFF_RUMBLE: usize = core::mem::offset_of!(XusbShm, rumble_large); // large @28, small @29 /// Context for the `SwDeviceCreate` completion callback: an event to signal + the HRESULT it reports. #[repr(C)] @@ -157,7 +160,7 @@ struct XusbWinPad { impl XusbWinPad { /// Create + map `Global\pfxusb-shm-`, stamp the magic, then spawn the devnode. fn open(index: u8) -> Result { - let name = HSTRING::from(format!("Global\\pfxusb-shm-{index}")); + let name = HSTRING::from(pf_vdisplay_proto::gamepad::xusb_shm_name(index)); // Permissive DACL so the WUDFHost (whatever account) can open the section. let mut psd = PSECURITY_DESCRIPTOR::default(); diff --git a/crates/punktfunk-host/src/vdisplay/pf_vdisplay.rs b/crates/punktfunk-host/src/vdisplay/pf_vdisplay.rs index e2e7b25..fda8ce4 100644 --- a/crates/punktfunk-host/src/vdisplay/pf_vdisplay.rs +++ b/crates/punktfunk-host/src/vdisplay/pf_vdisplay.rs @@ -245,16 +245,17 @@ unsafe fn create_monitor(device: isize, mode: Mode, watchdog_s: u32) -> Result or the IDD-push path (which MUST run NVENC on - // the discrete render GPU it pins here). NOTE: the pf-vdisplay driver currently returns - // STATUS_NOT_IMPLEMENTED for this IOCTL (a STEP-4 stub), so the call below is tolerated to fail. + // the discrete render GPU it pins here). The pf-vdisplay driver now IMPLEMENTS this IOCTL + // (IddCxAdapterSetRenderAdapter); a failure is still tolerated (the driver also reports its real + // render LUID in the shared header, so the host binds to the right GPU regardless). let pinned = if std::env::var("PUNKTFUNK_RENDER_ADAPTER").is_ok() { unsafe { resolve_render_adapter_luid() } } else if std::env::var_os("PUNKTFUNK_IDD_PUSH").is_some() { // P2 direct frame push: the host opens the driver's shared textures AND runs NVENC on the // RENDER adapter, so on a hybrid box (dGPU + iGPU) it MUST be the discrete encoder GPU — an - // iGPU-rendered surface is untouchable by NVENC. pf-vdisplay HONORS SET_RENDER_ADAPTER (once - // implemented), so pin the discrete GPU; the driver also reports the resulting render LUID in - // the shared header, so the host binds correctly even if this is overridden. + // iGPU-rendered surface is untouchable by NVENC. pf-vdisplay now IMPLEMENTS + // SET_RENDER_ADAPTER, so pin the discrete GPU; the driver also reports the resulting render LUID + // in the shared header, so the host binds correctly even if this is overridden. tracing::info!("IDD push: pinning the discrete render GPU (SET_RENDER_ADAPTER)"); unsafe { resolve_render_adapter_luid() } } else { @@ -270,11 +271,10 @@ unsafe fn create_monitor(device: isize, mode: Mode, watchdog_s: u32) -> Result tracing::warn!( - "pf-vdisplay SET_RENDER_ADAPTER failed (driver stub / not implemented — \ - continuing): {e:#}" + "pf-vdisplay SET_RENDER_ADAPTER failed (continuing on the natural adapter): {e:#}" ), } }