Phase 1b: video mirror via Windows Graphics Capture

Mirror the injected game's window into the host's borderless window so Steam
RPT streams a live copy of the game. No injection needed for video.

- capture/window_capture: WGC capture of a target HWND. Wraps our D3D11 device
  as an IDirect3DDevice, creates a free-threaded frame pool + capture session,
  hides the cursor and (best-effort) the capture border. Frames arrive on a WGC
  thread and are handed to the render thread, which copies the newest into a
  shader-resource texture and draws it -- keeping all D3D11 context use on one
  thread. Handles window resize via frame-pool Recreate.
- capture/frame_renderer: fullscreen-triangle shader that blits the captured
  texture letterboxed (aspect-preserved) into the window.
- capture_panel: "Mirror game window" toggle + lifecycle; target HWND comes
  from the hook's reported game window.
- main: winrt apartment init; mirrored frame drawn as background, ImGui on top.
- CMake: link windowsapp + d3dcompiler.

Verified: builds clean; host starts (apartment init + shader compile succeed).
Visual capture quality/latency to be judged on a real game.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 01:03:59 +02:00
parent a0a12d69fe
commit e38df6cf88
10 changed files with 615 additions and 12 deletions

View File

@@ -57,8 +57,12 @@ the focused window. A hook→host status back-channel shows whether the hook is
attached and how fast the game is polling it. The in-process `hook_selftest`
validates the IPC + hook core without needing a game.
Still ahead (scoped in the plan): video mirror (WGC, then a `Present` hook),
audio (WASAPI process loopback), and x86 support.
**Phase 1b — video mirror (current).** The host captures the injected game's
window with Windows Graphics Capture and draws it letterboxed as its background,
so RPT streams a live mirror of the game. See the test steps below.
Still ahead (scoped in the plan): a `Present`-hook capture path if WGC latency
disappoints, audio (WASAPI process loopback), and x86 support.
## Building
@@ -149,3 +153,21 @@ forwarded — while the game is unfocused it won't receive OS keyboard/mouse.
For a quick sanity check of the forwarding core without a game, run
`bin\Debug\hook_selftest.exe` — it should print `SELFTEST PASS`.
## Phase 1b: video mirror (Windows Graphics Capture)
The **Video mirror** panel captures the injected game's window (via Windows
Graphics Capture — no injection needed for video) and draws it, letterboxed, as
the host window's background. This is what Steam RPT streams to guests.
1. Inject into a game as in Phase 1a (the hook reports the game's window, which
the mirror uses as its source).
2. In the **Video mirror** panel, tick **Mirror game window**. The host window
should now show a live copy of the game; the panel reports the capture
resolution and render FPS.
3. The game can be behind the host window — WGC still captures occluded (but not
minimized) windows, and focus spoofing keeps it rendering.
Requires Windows 10 1903+ for WGC; hiding the capture border needs build 20348+.
This is the place to judge capture latency/stutter; if it's not good enough, the
fallback is a `Present`-hook capture path in the same injected DLL.