# RemoteDesk Windows 客户端 GPU 加速设计 ## 1. 目标 Windows 客户端的 UI、远程视频、RDP 图形和终端均支持 GPU 加速。核心目标: - Linux H.264 由原生 helper 在 D3D11 surface 中硬解和呈现。 - 避免持续 GPU→CPU→GPU 往返。 - RDP 只上传变化区域,不重复复制完整 framebuffer。 - 终端和 UI 使用 GPU 渲染。 - 支持 Intel、AMD、NVIDIA 以及多 GPU 主机。 - 驱动重置或硬解不可用时严格模式明确失败,显式 compatibility 才允许回退。 这里的“零拷贝”特指未压缩视频像素从捕获到编码、或从解码到呈现不经过 CPU map/copy。压缩码流和 RTP 包仍可经过普通内存。跨 Adapter GPU copy 不算零拷贝。 ### Windows Headless compatibility 模式 没有独立 GPU 不等于一定没有 DXGI 输出:机器可能存在 Intel 核显、虚拟 GPU、Microsoft Basic Display Adapter 或 WARP。采集端必须以运行时结果区分这些情况,不得因为成功创建 ID3D11Texture2D 就报告硬件加速。 探测顺序: 1. 枚举 DXGI Adapter 和 Output。 2. 尝试创建 D3D11 device 和 Desktop Duplication。 3. 尝试 AcquireNextFrame,并验证连续帧。 4. 探测 NVENC、AMF/VCE/VCN、Quick Sync 的实际编码能力。 5. 硬件路径不可用时,若用户显式选择 compatibility,则允许 WARP/CPU surface 和 x264、x265、SVT-AV1。 compatibility 路径必须报告 adapter_type、surface_type、cpu_map_count、cpu_upload_bytes、encoder_backend、software_encode_latency_us、encode_fps 和 degraded。WARP 是软件 D3D 实现,不能报告为硬件 GPU;Microsoft Basic Display Adapter 也不能视为硬件编码器。 无硬件编码器时,系统自动应用软件上限。默认先尝试 1080p30/60 或实测可承受的更低档位;请求多路 4K/120 时,strict 性能模式返回 HARDWARE_ENCODER_UNAVAILABLE,compatibility 模式降档并明确显示 software/degraded。软件视频队列有界、允许丢帧,且不阻塞输入和音频线程。 ## 2. 渲染架构 ```text Tauri Client ├── WebView2 UI -> Chromium GPU compositor ├── xterm.js -> WebView2 GPU text compositor ├── RDP helper -> IronRDP/D3D11 native window └── Native video helper -> GStreamer/D3D11 native window ``` JavaScript 不读取远程视频像素;原生 helper 的视频帧不经过 Tauri IPC。 ## 3. 零拷贝状态模型 每个 Linux 桌面会话报告实际路径: ```text zero_copy 同一 GPU surface 直接经过硬件编解码/呈现 gpu_copy 原始像素仅在 GPU 间或 GPU surface 间复制 cpu_upload CPU 捕获/解码后上传 GPU software CPU 色彩转换或软件编解码 ``` Agent 和 native helper 只有在 tracer/ETW/驱动指标证明原始帧未被 CPU map 时才能报告 `zero_copy`。默认 `required_end_to_end` 要求两端均为 `zero_copy`;任一端为其他状态都结束媒体协商。`compatibility` 必须由用户显式开启。切换 GPU、分辨率或显示器后必须重新验证,不能沿用之前状态。 ## 4. GPU 枚举与选择 客户端通过 DXGI 枚举: - Adapter LUID、名称、Vendor/Device ID。 - Dedicated/Shared video memory。 - D3D feature level。 - Hardware/Software/Remote adapter 类型。 - 每个显示器所属 output 与 adapter。 选择模式: 1. 默认(推荐):Linux native helper 和 RDP helper 都选择窗口当前显示器 Adapter。 2. 手动:从 Rust 枚举的物理 GPU 列表选择固定 Adapter;Linux 始终使用 native-video helper。 3. 手动 GPU 不存在时可回到窗口 Adapter 重新验证,但驱动失效、不支持 codec 或发生跨 GPU copy 时,Linux 严格会话失败且不改写配置。 4. WARP 仅用于 RDP 或显式 compatibility,不能满足 Linux 双端零拷贝。 GPU 选择持久化使用 LUID/PCI identity 的稳定组合,不只保存容易变化的枚举序号。 配置优先级:主机级手动选择 > 全局手动选择 > 默认模式。运行时诊断同时展示“用户选择”和“实际生效”Adapter。 ## 5. Linux 视频硬解码 ### 5.1 默认原生零拷贝路径 ```text RTP H.264 -> GStreamer depay/parse -> D3D11 hardware decoder -> GstD3D11Memory -> d3d11videosink -> native HWND ``` decoder、sink、swap chain 和窗口 output 必须位于同一 DXGI Adapter。通过 GStreamer tracer、ETW/GPUView 和 CPU map 计数共同验证;仅成功创建硬件 decoder 不足以报告 `zero_copy`。 ### 5.2 Compatibility 软件回退路径 ```text RTP H.264 -> software decoder -> CPU frame -> D3D11 upload -> child HWND ``` 该路径同样只属于显式 compatibility。触发条件包括: - 硬件不支持 codec/profile/level。 - 驱动创建 decoder 失败。 - GPU session 数量达到限制。 - device removed/reset 后重建失败。 UI 明确显示“软件解码”,并降低最大分辨率/帧率,防止 CPU 过载被误诊为网络问题。严格模式不进入该路径。 ## 6. 编码能力协商 Native helper 报告经过验证的精确解码能力和实际会话 stats: ```text codec profile/level max_width/max_height max_fps bit_depth hardware/software adapter_id ``` 能力检测必须尝试创建 decoder 或执行短样本解码。仅查询 API 支持列表不足以证明驱动可用。 Windows `native-video --probe-h264-file` 已提供真实 H.264 容器首帧解码源码入口,并强制输出同 device NV12 DXGI texture;`--play-h264-file` 进一步按媒体时间戳读取动态可见尺寸,以 D3D11 VideoProcessor 将 texture subresource 转换和缩放到同 device swap chain,全链路不调用 CPU frame map。它们用于排除纯 capability 查询和明显 CPU buffer 路径。最终硬解/零拷贝结论仍必须结合 ETW/GPUView,不能只依据 `IMFDXGIBuffer` 或 VideoProcessor。 首版 H.264 8-bit。HEVC/AV1 在 Intel、AMD、NVIDIA 的实际硬解矩阵通过后增加。HDR、10-bit 和色彩管理单独设计,不与基础 GPU 加速捆绑。 ## 7. RDP GPU 路径 IronRDP 图形输出分两类: 1. 已解码 bitmap/dirty rect:上传变化区域到 D3D11 texture。 2. 可获得的现代 RDP 视频 surface:评估直接硬解和 GPU surface 路径。 当前源码已在一次 redraw 前把所有待呈现区域合并为一个有界矩形,并满足: - 重叠或邻近区域合并。 - 已被新 update 覆盖的旧区域丢弃。 - 上传 buffer 复用,不为每个 rect 分配资源。 - IronRDP 只转换 dirty region 的像素块,不为每次更新重建完整 CPU framebuffer。 - 纹理尺寸只在远端 framebuffer 尺寸变化时重建。 - 输入和控制不等待 GPU fence。 该实现优先保证更新不丢失;相距很远的区域也会合并为包围矩形,后续可在实机 profile 证明收益后改为有限多矩形上传。会话诊断返回最近一次上传模式和实际上传像素数,便于判断合并范围是否过大。 RDP AVC/AVC444 硬解是否可由 IronRDP 暴露,属于 M0 验证项。若只能获得 CPU framebuffer,D3D11 upload 仍保持呈现端加速,但不能宣称完整硬件解码。 RDP 不受 Linux `zero_copy_policy` 强制约束。CPU framebuffer 路径固定报告 `cpu_upload`;未来只有解码 surface 能直接导入同一 D3D11 Adapter 并通过 ETW 验证时,才报告 `zero_copy`。 ## 8. UI 与终端 - Tauri UI 使用 WebView2 GPU compositor。 - xterm.js 使用浏览器文本/Canvas renderer,但不承担视频帧。 - RDP helper 的轻量 egui 工具栏使用 wgpu。 - WebView2 GPU process crash 由主程序检测并重建对应窗口。 - UI 动画不能抢占远程视频线程或频繁触发全窗口重绘。 ## 9. 多 GPU 常见场景:核显连接显示器,独显负责高性能任务。策略: - Native 默认让 decoder/sink 跟随窗口显示器 Adapter;手动模式使用指定 Adapter。 - 用户选择独显解码但显示器属于核显时,严格模式拒绝跨 GPU 复制并提示移动窗口或改选 Adapter;compatibility 才显示并允许 `gpu_copy`。 - 跨显示器移动完成并稳定一段时间后,再评估重建 pipeline。 - 不在拖动过程中连续重建 decoder。 - 重建时保持最后一帧,完成后请求 IDR。 - 多会话按 Adapter 统计硬解 session 和显存预算。 ## 10. 显存与资源预算 每个会话记录: - decode surfaces 数量与格式。 - framebuffer/texture 尺寸。 - swap chain buffers。 - staging/upload buffers。 - terminal glyph atlas。 策略: - 队列有界,过期视频帧优先丢弃。 - 后台会话降低呈现帧率。 - 显存压力上升时先降低非活动会话质量。 - 达到硬解 session 上限时,严格会话提示用户关闭其他会话;只有 compatibility 可以软件回退。 - 4K/多显示器连接前估算资源,不等 OOM 后处理。 ## 11. Device Lost Native helper 处理 `DXGI_ERROR_DEVICE_REMOVED/RESET/HUNG`: ```text Running -> GpuLost -> stop presenting/input capture -> collect removal reason -> release swap chain/decoder resources -> recreate adapter/device/pipeline -> request keyframe/full RDP refresh -> Running | SoftwareFallback | Failed ``` GPU 重建不销毁远端会话。连续失败超过阈值后,严格模式结束本地呈现;compatibility 才允许回退软件,并保留可导出的错误信息。 ## 12. 色彩和缩放 - 首版统一 SDR sRGB 输出。 - 保留视频原始颜色信息用于诊断。 - 缩放在 GPU 完成,支持 fit、1:1 和 stretch(默认不使用 stretch)。 - 黑边和 viewport 必须参与鼠标坐标逆变换。 - HiDPI 变化同时更新 WebView CSS/device pixel ratio、native helper 像素尺寸和远端显示请求。 - HDR/ICC/10-bit 属于后续专项,不能未经验证直接透传。 ## 13. 用户设置 GPU 选项: - 默认(推荐):Linux native helper 与 RDP 使用窗口显示器 Adapter。 - 手动:下拉选择 Intel/AMD/NVIDIA Adapter,Linux 仍使用原生渲染器并验证 output 是否同 Adapter。 - Compatibility:用户明确允许原生 helper 使用软件解码,不满足双端零拷贝。 全局设置定义默认策略,每个 HostProfile 可以选择“继承全局”或覆盖 GPU。切换 Linux GPU 只重建当前 native 会话的 decoder/sink,不重启主程序。 诊断页展示实际生效值: - GPU、LUID、驱动版本。 - 配置模式、用户选择与实际生效 Adapter。 - 解码器和 profile。 - D3D11/CPU memory path。 - Native renderer mode 和 hardware decode 状态。 - decode/render/upload time。 - dropped/late frames。 - device reset count。 ## 14. 性能目标 | 场景 | 工程目标 | |---|---| | 1080p60 Linux Native | Agent/client 双端已验证零拷贝,原始帧无 CPU/cross-GPU copy | | 4K60 Linux Native | 同 Adapter D3D11 surface 零拷贝;跨 GPU 时拒绝严格会话 | | 1080p RDP | dirty rect 上传,静态桌面低 GPU/CPU 占用 | | 多会话 | 后台限帧,前台输入与呈现不受阻塞 | | 终端高频输出 | GPU 字形复用,滚动缓存有界 | 目标数值需要在 M0 使用真实硬件基线锁定,不仅依靠虚拟 GPU 或软件适配器。 ## 15. 测试矩阵 - Intel 核显、AMD 显卡、NVIDIA 显卡。 - 单 GPU、混合 GPU、RDP/虚拟环境下 WARP。 - H.264 不同 profile/level 和异常码流。 - 720p/1080p/1440p/4K,30/60 fps。 - 单/双显示器,100%~200% DPI。 - 跨 GPU 显示器移动。 - 驱动重置、睡眠恢复和显示器热插拔。 - 多会话显存/硬解 session 压力。 - Compatibility 软件回退与恢复硬件路径,以及严格模式拒绝路径。 - 手动 GPU 触发 native helper,并验证实际 Adapter LUID。 - 零拷贝 `required_end_to_end/compatibility`、DMA-BUF/D3D11 surface、跨 GPU 和 CPU/software 拒绝。 测试使用 GPUView/ETW、GStreamer tracer 和应用 metrics 交叉验证,不能只看任务管理器的“Video Decode”百分比。 ## 16. 发布门槛 - 至少 Intel/AMD/NVIDIA 各一种环境通过 1080p60。 - Native 路径证明客户端没有 GPU→CPU→GPU 或跨 Adapter copy。 - Wayland DMA-BUF 与 Xorg DRI3 到硬件编码器通过 CPU map/copy 验证,严格模式不会静默回退。 - Device Lost 可恢复或明确回退,不导致应用整体崩溃。 - 多 GPU 选择可诊断,错误 Adapter 不会静默黑屏。 - Compatibility 软件回退时自动降低质量上限;严格模式从不自动进入该路径。 - GPU/驱动信息在诊断包中脱敏且不包含画面数据。