Files
RemoteDesk/docs/gpu-acceleration.md
曾志威 19a8e03a83
ci / rust (push) Canceled after 0s
ci / web (push) Canceled after 0s
ci / package-preview (push) Canceled after 0s
ci / package-installer (push) Canceled after 0s
ci / linux-agent (push) Canceled after 0s
ci / edge-service (push) Canceled after 0s
ci / coturn-pop (push) Canceled after 0s
ci / package-windows-host (push) Canceled after 0s
Document all-Rust migration and extend native media stack
2026-08-14 14:31:57 +08:00

12 KiB
Raw Permalink Blame History

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 实现,不能报告为硬件 GPUMicrosoft Basic Display Adapter 也不能视为硬件编码器。

无硬件编码器时,系统自动应用软件上限。默认先尝试 1080p30/60 或实测可承受的更低档位;请求多路 4K/120 时,strict 性能模式返回 HARDWARE_ENCODER_UNAVAILABLEcompatibility 模式降档并明确显示 software/degraded。软件视频队列有界、允许丢帧,且不阻塞输入和音频线程。

2. 渲染架构

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 桌面会话报告实际路径:

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 列表选择固定 AdapterLinux 始终使用 native-video helper。
  3. 手动 GPU 不存在时可回到窗口 Adapter 重新验证,但驱动失效、不支持 codec 或发生跨 GPU copy 时,Linux 严格会话失败且不改写配置。
  4. WARP 仅用于 RDP 或显式 compatibility,不能满足 Linux 双端零拷贝。

GPU 选择持久化使用 LUID/PCI identity 的稳定组合,不只保存容易变化的枚举序号。

配置优先级:主机级手动选择 > 全局手动选择 > 默认模式。运行时诊断同时展示“用户选择”和“实际生效”Adapter。

5. Linux 视频硬解码

5.1 默认原生零拷贝路径

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 软件回退路径

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:

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 framebufferD3D11 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 复制并提示移动窗口或改选 Adaptercompatibility 才显示并允许 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

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 AdapterLinux 仍使用原生渲染器并验证 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/4K30/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/驱动信息在诊断包中脱敏且不包含画面数据。