# Windows 云桌面渲染优化执行记录(2026-11-02) ## 执行顺序 1. 复核 GPU、实际编码器、客户机解码器、显示刷新率,保存原始证据。 2. 用持续动画做同步参数 A/B;排除静态桌面的按需发帧影响。 3. 在独立目录接通 MPP、RKMPP、DRM PRIME,先验证真实视频解码,再验证 Moonlight 串流。 4. 只有真实串流通过后才启用新客户端,保留系统 Moonlight 的回退入口。 5. GPU/NVENC 恢复后再做 1080p60、1440p30/60 和输入到屏幕延迟验收。 ## 当前 GPU 证据 本轮经 Guest Agent 重新采集:GTX 965M 的 ConfigManagerErrorCode=43,NVML 查询失败, DXGI 没有枚举到 NVIDIA 适配器,Sunshine 的最新实际编码器为 `libx264`。配置已是 `sw_preset=ultrafast`,当前 Windows 虚拟屏为 2560x1440@30。 没有再次复位设备、重载 VFIO、替换 ROM 或重启宿主机。本轮未改变其他 VM。 仍没有证据确认唯一故障原因;匹配此板卡的生产版 vBIOS 或另一块可稳定直通的 GPU 是下一轮服务端验证的候选条件,而非已完成修复。 验收工具更新为 `tools/validate-sunshine-nvenc.ps1` + `tools/probe-nvidia-d3d.cs`: 实际创建 NVIDIA D3D11 设备、检查 PnP 错误码、检查最新一次实际编码器创建及时间, 并核验 NVENC 会话与编码利用率。不会把启动阶段的编码器探测记录当作实际串流。 ## 同步参数 A/B 环境:系统 Moonlight 6.2.0,H.264 软件解码,2560x1440@20、30Mbps,输出约60Hz, MATE compositor 已关闭,SDL OpenGL ES 2。Windows 用 `tools/stream-motion-test.html` 持续移动条纹与棋盘;源 RAF 约30 FPS。 125% DPI 下页面显示逻辑2048x1152,视频流和 HDMI 仍是物理2560x1440。 下表来自两段完整会话结束日志,包含启动/退出阶段,时长不同;属于现场初步对照, 不构成严格统计学基准。原始日志与叠图保存在 `evidence/moonlight-20261102/`。 | 指标 | smooth | low-latency | |---|---:|---:| | 接收/解码 FPS | 17.16 | 17.07 | | 渲染 FPS | 17.07 | 17.01 | | 主机处理平均 ms | 33.6 | 35.4 | | 网络丢帧 | 0.00% | 0.00% | | jitter 分类丢帧 | 0.44% | 0.29% | | 网络延迟平均 ms | 11 | 11 | | 解码平均 ms | 14.07 | 16.96 | | 帧队列平均 ms | 0.95 | 1.14 | | 呈现平均 ms(含同步) | 8.38 | 10.87 | 系统客户端软件解码的对照中,关闭同步没有改善帧率或排队,因此软件基线保留 smooth。上述耗时 不能直接相加当作端到端输入延迟;后续须用高速摄像/外部触发测量 P50/P95。 日志中的启动测试 EGLImage 导出失败和单次队列溢出,不能单独证明持续运行时故障。 最终选中的系统路径是软件视频帧上传后的 SDL 呈现;`Using DRM renderer` 也不等于 已经使用 VPU 或直接扫描输出。 ## RKMPP 已验证部分 - 为 `/dev/mpp_service`、`/dev/rga`、`/dev/dma_heap/*` 增加 video 组读写权限; 持久化规则为 `terminal/kiosk-shell/etc/70-vdi-rockchip-video.rules`。 - 普通用户执行 MPP H.264 初始化,create/init/destroy 全部返回0。 - 从固定提交构建 MPP 和 FFmpeg-Rockchip 6.1,目录是 `/home/armbian/vdi-build/rkmpp-experiment`;依赖只下载解包,不安装或升级系统包。 - 用 `generate-h264-sample.c` 生成60帧2560x1440 H.264样本。`h264_rkmpp` 全部解出,0错误。 - CPU NV12输出耗时2.620秒;`-hwaccel rkmpp -hwaccel_output_format drm_prime` 输出耗时 0.290秒,CPU时间0.120秒,日志明确为 DRM PRIME 帧,0解码错误。 样本纹理简单且测试期间有编译负载;这些数字仅证明硬解/帧导出可工作,不能替代 Moonlight 真实串流、显示呈现、复杂内容或2K60验收。 ## 产品接入点 `VDI_STREAM_STATS=1` 独立于 profile,可公平比较两档。解码器覆盖只接受 software/hardware/auto;RKMPP通过 `H264_DECODER_HINT=h264_rkmpp` 选择,不把 `h264_rkmpp` 当作 Moonlight `--video-decoder` 的值。 `VDI_MOONLIGHT_PROGRAM` 可指定独立客户端启动器。`vdi-kiosk-start` 支持读取 `~/.config/vdi-terminal/render.conf` 的 allowlist 字段,不执行配置文件: ```ini profile=smooth stats=0 program=/home/armbian/vdi-terminal/bin/vdi-moonlight-rkmpp decoder=hardware codec=H.264 ``` 文件不存在时沿用系统客户端。上述为 smooth 档示例;本机实际部署档位见下表后说明。 ## 构建与页面接入修正 私有客户端固定为 Moonlight v6.2.0 `de2467e433821664cdd2224aad8c89a625be1ad9`, MPP `7916c3cc000fefc0bdf96636b7d54fe174724f44`,FFmpeg-Rockchip 6.1 `797387de1c9caa9170100d7217ee093d1897f750`。复现入口为 `tools/build-rkmpp-client.sh`,仅在盒子的用户目录下载、解包和构建依赖。 - Qt 5 构建需要显式为上游 `drm.h` 补入 ``,脚本幂等应用。 - 补齐 EGL 开发依赖,重新执行 qmake 功能探测,并在缺少 HAVE_EGL 时终止构建。 - qmake 改变功能开关不会自动使旧对象失效;构建脚本记录编译/链接参数指纹, 参数变化时清理应用对象,防止“探测有 EGL、实际对象无 EGL”。 - RKMPP 使用独立测试解码器,上游成功路径不输出旧的 `Test decode successful`, 而输出 `Not reusing test decoder for h264_rkmpp`。页面就绪解析同时兼容两者, 仍要求实际 renderer 已选中,并在连接失败时拒绝进入就绪状态。 - 私有启动器设置 QML、Qt 插件和共享库目录,系统 Moonlight 不被覆盖。 第一轮真实串流已输出 2560x1440 的 `h264_rkmpp / drm_prime`,但显示选中 SDL, 并出现 `Selected hwframe->swframe ... (mapping: yes)`,因此该轮不作为零拷贝验收。 对应证据为 `rkmpp-stale-sdl.txt` 与 `rkmpp-first.png`,包含构建负载和启动阶段。 另已核查用户注册表:`MouseTrails=0`、`DragFullWindows=1`,不通过添加第二个光标 或重新设置透明光标来掩盖视频延迟。 ## 后续顺序与验收要求 1. 先验证硬解实际串流与 EGL 呈现,记录持续动画下的接收、解码、呈现 FPS, 解码/排队/呈现耗时及丢帧;没有通过则保留系统软件客户端默认入口。 2. 通过后接入页面启动链,验证过场层退出、快捷键回列表、再次连接及持久配置。 保留2K20现有配置作为基线,只有实测更好才提高请求帧率。 3. 服务端 GPU 修复需匹配板卡的生产 ROM 或可稳定直通的替代设备,并重复通过 PnP、NVML、DXGI/D3D11、真实 NVENC 以及重启后的验收。 4. 服务端恢复后按1080p60、1440p30、1440p60逐档验证,并同步虚拟屏刷新率。 1440p60还需要将当前30Hz虚拟屏调整到60Hz,不能只改客户端FPS参数。 5. 用高速摄像或外部触发测输入到显示的P50/P95,另外观察快速拖窗与光标残影。 如延迟仍主要来自光标随视频传输,再评估服务端光标位置/形状侧通道与客户端 单光标显示的二次开发,需同时保证隐藏视频中的旧光标,不能直接叠加本地光标。 客户端应优先接通硬解与显示路径;镜像内安装补帧/运动插值插件不能修复 GPU Code 43, 也不能代替真实输入响应。当前不把插帧作为低延迟方案。 ## 真实串流对照与现场选择 清理旧对象后,日志明确选择 `Renderer 'EGL/GLES' with 'DRM' backend chosen`, 实际解码尺寸2560x1440、`h264_rkmpp`、`drm_prime`,呈现使用 EGLImage。 未见实际运行路径的 hwframe→swframe 映射回退。四组均为持续动画、30Mbps、 源RAF30FPS、终端HDMI约60Hz、服务端libx264;均为约2分钟会话,统计包含启动/退出。 会话按顺序进行,网络与服务端负载会波动,不能当作严格控制变量的实验室基准。 | 客户端/请求档位 | 接收/解码 FPS | 呈现 FPS | 主机平均 ms | 解码 ms | 队列 ms | 呈现 ms | 网络/jitter丢帧 | |---|---:|---:|---:|---:|---:|---:|---| | 系统软件解码 / 2K20 smooth(先前基线) | 17.16 | 17.07 | 33.6 | 14.07 | 0.95 | 8.38 | 0% / 0.44% | | RKMPP+EGL / 2K20 smooth | 19.14 | 18.97 | 38.4 | 10.53 | 2.78 | 2.54 | 0% / 0.20% | | RKMPP+EGL / 2K30 smooth | 24.21 | 23.29 | 46.2 | 8.24 | 31.95 | 4.19 | 0% / 3.02% | | RKMPP+EGL / 2K30 low-latency | 23.56 | 23.46 | 46.8 | 9.11 | 2.39 | 5.41 | 0% / 0.10% | | RKMPP+EGL / 2K30 VSync开、Frame Pacing关 | 23.26 | 22.63 | 47.5 | 8.28 | 28.93 | 4.14 | 0% / 2.23% | 对应原始统计分别为 `rkmpp-egl-20-smooth.txt`、`rkmpp-egl-30-smooth.txt`、 `rkmpp-egl-30-lowlatency.txt`、`rkmpp-egl-30-vsync-no-pacing.txt`,均在证据目录中。 本机选择2K30、`profile=low-latency`、RKMPP硬解、H.264,常态关闭叠图。 这是在当前设备上的取舍:相较2K30 smooth,平均帧队列少约30ms;关闭VSync存在 撕裂风险,需要现场动态观察。保留2K20 smooth作为平稳显示的回退档,不将其删除。 截图可见单个白色远程光标,但静态截图不能证明快速移动没有残影或输入延迟为零。 当前会话平均呈现仍只有约23FPS,未达到请求的30FPS;服务端GPU故障和libx264路径 仍未修复。不能将这一轮称为2K60、NVENC恢复或“鼠标无延迟”验收通过。 ## 正式入口部署验证 已运行 `tools/deploy_kiosk.sh` 同步、编译、CTest、安装和重启盒子的kiosk受管栈; CTest 2/2通过。render.conf选择上述私有硬解客户端,桌面卡请求帧率持久保存为30, 原文件备份在盒子 `~/.config/vdi-terminal/desktops.before-rkmpp-20261102.json`。 两次从实际列表页点击Windows连接,日志分别在约10.1秒、9.7秒进入stream_ready, 均明确选中 `EGL/GLES + DRM`、`h264_rkmpp`,过场层退出后画面可见。 `Ctrl+Alt+Shift+Q` 正常退出code=0并回列表,再次连接通过;没有遗留第二条串流。 配置已经写入现有自启链,但本轮未重启盒子、VM或宿主机;不声称完成重启后验收。 截图 `kiosk-rkmpp-session.png`、`kiosk-rkmpp-disconnect.png`、 `kiosk-rkmpp-reconnect.png` 保留了产品入口验证。单白光标可见,未修改原光标策略。 自动化拖窗未形成可计量的动态验收结果,仍需现场鼠标操作与外部摄像测量。 专用Edge测试浏览器已关闭,临时VDIRenderBench任务已删除,未关闭其他浏览器。