工具:完善串流对照测试并同步开发进度
This commit is contained in:
parent
853bcb7574
commit
b2de05c6a6
43
MEMORY.md
43
MEMORY.md
@ -2,7 +2,48 @@
|
||||
|
||||
完整对话总结在:`D:\DAIMA\vdi-cloud\PROJECT_CONTEXT.md`
|
||||
|
||||
## 2026-11-03 午后鼠标进一步优化(最新)
|
||||
## 2026-11-03 U 盘真实设备透传 POC
|
||||
- 用户明确要求 Windows 枚举真实 USB。已开发 Rust terminal/usb-monitor(标准库),usbredir+受限SSH隧道+PVE QMP usb-redir;盒子不调用PVE API。
|
||||
- Kingston 0951:1666 / USB序列号408D5C1653D4E44179789251,物理3-1(USB2/480M);Windows正常枚举USB Mass Storage / Kingston USBSTOR,KINGSTON F:、FAT32、Removable、Healthy。
|
||||
- 独立VDI_USB_TEST_20261103-173342目录新增1MiB文件并复制回VM,三份SHA一致;用户安全弹出后真实拔插,17:34:43断开、17:34:53重连,F:恢复且文件SHA一致。原文件未改,测试目录保留。
|
||||
- 仅固定VID/PID/serial纯存储,拒绝键鼠/复合设备/本地挂载/holder/swap;udev只禁止这只盘本地自动挂载。最初口报-71,换口后成功,不是软件修好了原口。
|
||||
- 盒子vdi-usb-monitor.service、PVE vdi-usb-tunnel-100.service active/enabled;QMP端点vdi_usb_box_100/vdi_usb_redir_100仅运行时,VM/PVE重启需管理员重新attach。未验收开机恢复/多用户生产能力。
|
||||
- 盒子备份~/vdi-terminal/backups/usb-device-20261103-172709;PVE密钥/etc/vdi-usb-poc/vm100,回环40001经SSH。未装Windows驱动、开测试签名、重启或改GPU/串流;Moonlight PID46934保留,GTX965M错误0。
|
||||
- 详见docs/usb-device-poc-20261103.md及evidence/usb-device-20261103;工具deploy-usb-device-poc.py、usb-device-qmp.py、test-usb-device-poc.ps1。
|
||||
|
||||
## 2026-11-03 Windows保留单个2K主屏(最新)
|
||||
- 用户明确授权:不影响2K才能改,否则不动。现场VDD已变DISPLAY4,原主屏2560×1440@60;Basic DISPLAY1另扩展2K64,NV DISPLAY2原本无活动输出。
|
||||
- 已只停用Basic桌面输出,VDD成为唯一活动主屏,保持2K60;未禁用/卸载任何显卡、未重启。原Moonlight PID46934/2K45继续,截图正常;GPU错误0,Sunshine重建h264_nvenc,编码10%。
|
||||
- 新工具set-single-vdi-display.ps1、run-single-vdi-display.py支持Query/Apply/Restore,有2K60主屏前置条件、XML布局备份、读回失败恢复、设备身份校验;临时任务已删除。备份C:\ProgramData\VDI\single-display-20261103\before.xml。
|
||||
- 布局已按当前用户保存,但未重启/重登验收;设备管理器仍有适配器,不能说卸载设备或保证设置界面不列未连接输出。详见docs/single-display-20261103.md及对应evidence。
|
||||
|
||||
## 2026-11-03 独立光标受控原型
|
||||
- 已实测Windows真实箭头/文字/左右缩放/忙碌静态形状导出和盒子X11本地显示,热点正确,隐藏全透明;短暂停Moonlight小于0.5秒,本地指针仍移动,已恢复SIGCONT。
|
||||
- 最后完整轮32/32跨区点击正确,归一化坐标最大差1px;10项边界测试通过,0.8秒辅助状态租约到期退出/SDL资源归还通过。未测物理输入到屏幕延迟。
|
||||
- 这是脚本形状回放和受控Sunshine全局N快捷键交接,不是自动形状同步,不是生产独立光标;没有替换正常Moonlight/Sunshine二进制。正式须改双方控制通道、帧边界ACK/租约与SDL生命周期,并适配Weston。
|
||||
- 首两轮辅助连接退出后XFixes图像不可用,修正为XFixes临时隐藏下成对切Moonlight本地C快捷键,让SDL重新设置其拥有的隐藏指针;第三轮完整通过。静止画面N切换旧箭头留旧帧也已实测,不能靠快捷键直接上线。
|
||||
- 已停删VDICursorPOC,正常PID31694/2K45/原SHA保留,VDD2K60、GPU错误0/NVENC编码11%、显示守护active;最后本地透明1×1,正常Windows单个白色远程箭头。未重启/改ROM/VFIO/主题。
|
||||
- 详见docs/independent-cursor-feasibility-20261103.md及对应evidence。新增cursor-poc工具仅实验,不自动启动;verify-cursor-poc-box.py点击仅可用于临时Windows测试窗口。
|
||||
|
||||
## 2026-11-03 GPU修复后联调与45帧落地
|
||||
- 用户确认运维修复结束,授权的鼠标优化任务已恢复。现场复核GTX965M错误码0、vBIOS84.04.2b.00.13、
|
||||
Sunshine实际h264_nvenc、NVENC会话1;正常重连后编码占用18%。本轮未改ROM/VFIO、未重启任何机器。
|
||||
- 修正的测试源实测约59.4~59.8FPS;2K30实渲染29.83FPS;2K60接收58.82但只渲染46.11,
|
||||
客户端等待队列7.54ms,GPU89~95%/800MHz。原长队列渲染仍46且排队36ms;nearest实验42;VSync24,均未采用。
|
||||
- 已落地Windows VDD2560x1440@60、正常kiosk票据45FPS;短测实渲染44.22/队列1.30ms,
|
||||
约两分半持续动态会话43.14/队列1.55ms/网络实际丢帧0。不能称稳定2K60或零延迟。
|
||||
- Windows活动VDD变为DISPLAY3,动态查找;登录脚本tools/set-2k-display.ps1默认60、支持RefreshRate30。
|
||||
已备份/部署并手动运行原VDISet2KDisplay任务,独立Query确认60Hz;未通过重启验收登录触发。
|
||||
Windows原脚本/任务XML:C:\ProgramData\VDI\backups\display-refresh-20261103-142920。
|
||||
- tools/set-terminal-fps.py支持30/45/60、原子写入和备份;当前30票据备份
|
||||
~/vdi-terminal/backups/fps-20261103-143333-297521/desktops.json。正常流程重新连接PID31694实际fps45。
|
||||
- 正常二进制仍35de7b...afa00f,RKMPP/DRM PRIME/EGL、最新帧队列、无VSync/无pacing,第三补丁不开。
|
||||
nearest实验保留terminal/moonlight/experiments/0004-vdi-egl-exact-size-sampling.patch,已撤回正常源码且不进构建器。
|
||||
- Windows临时基准任务已停止并删除,256次交替点击记录全部位置正确;用户原应用保留,恢复正常Windows串流。
|
||||
显示守护active,2560x1440输出正常。独立光标尚未实现;稳定2K60需继续验证更低开销呈现路径。
|
||||
- 详细对照、限制与回退见docs/2k60-validation-20261103.md,证据docs/evidence/2k60-20261103/。
|
||||
|
||||
## 2026-11-03 午后鼠标进一步优化(历史,已恢复联调)
|
||||
- 用户要求制定计划并执行;随后明确运维正在修复GPU Code43。Windows多次被外部qmshutdown/qmstart,
|
||||
本轮已停止Windows配置/串流测试,不能与运维并发改VM;没有发出VM/宿主/显卡重启指令。
|
||||
- 新增0003-vdi-input-priority.patch:帧前连续输入最多32条/2ms,保留焦点/窗口/退出等边界;
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
这是用户要求“制定计划并按照计划干”后的本轮记录,与此前已部署的两个输入补丁分开。
|
||||
|
||||
后续更新:用户确认运维修复后已恢复联调;当前已落地VDD60Hz/客户端45FPS,约43~44FPS渲染,详见`docs/2k60-validation-20261103.md`。下文保留运维期间的历史记录,不再代表当前GPU故障或联调暂停状态。
|
||||
|
||||
最新补充:用户要求尝试独立光标,已完成受控X11本地指针原型,四种真实Windows静态形状/热点、隐藏、暂停客户端时独立移动、32/32区域点击和辅助租约超时清理均通过。没有实现自动形状同步或正式双方交接协议;测试已收尾并恢复单个Windows远程白色光标,2K45及正常二进制保留。详见`docs/independent-cursor-feasibility-20261103.md`,勿将下文历史“未实现”理解为本地原型未做,也勿将原型误报为产品已部署。
|
||||
|
||||
## 实际进度
|
||||
|
||||
用户确认运维正在处理 GPU Code43。测试中 Windows 多次外部关机/启动;本轮未发出任何 VM/设备/宿主重启指令。已暂停 Windows 配置修改和串流测试,继续完成盒子端开发与文档,尚未达到最终性能验收。
|
||||
|
||||
@ -37,3 +37,7 @@
|
||||
用户确认运维正在处理 GPU Code43,已暂停 Windows 配置修改和串流测试,避免同时操作。盒子端新增第三补丁已编译并通过普通/ASAN测试,但当前独立渲染线程没有主线程呈现调用,未证明新调度收益,因此默认客户端已恢复本轮前版本。60Hz对照尚未完成,独立光标只完成设计,尚未实现。
|
||||
|
||||
本轮逐项结果、初测数据限制、候选版本和恢复联调步骤见 `docs/mouse-optimization-execution-20261103.md`。独立光标协议和单光标交接要求见 `docs/independent-cursor-design-20261103.md`。
|
||||
|
||||
## 运维修复后的继续执行
|
||||
|
||||
用户提供GPU修复验收后已恢复联调,现场复核错误码0和实际NVENC。修正测试源对比表明:当前盒子请求2K60实际仅渲染约46FPS,原队列/VSync/nearest实验均未改善;按实测将默认落为VDD60Hz、Moonlight45FPS,实际约43~44FPS,客户端队列约1.3~1.6ms。已保存配置、验证登录显示脚本、从正常入口重连并清理临时任务。完整数据与回退见`docs/2k60-validation-20261103.md`;稳定2K60与独立光标尚未完成。
|
||||
|
||||
@ -38,3 +38,7 @@ VDI_TEST_SANITIZE=1 ASAN_OPTIONS=detect_leaks=1 bash tools/test-moonlight-latenc
|
||||
新增 `test_input_priority.cpp` 验证优先调度不越过焦点/窗口/退出/解码器重置事件,保持输入 FIFO,隔离其他窗口与合成触摸,并验证数量与时间限制。普通与 ASAN 版本均通过。当前 RKMPP/EGL 没有主线程呈现事件,新调度开关不能用作该路径的性能提升宣传。
|
||||
|
||||
现场数据、局限与完整回退入口见 `docs/input-rendering-optimization-20261103.md`。
|
||||
|
||||
GPU修复后实测见`docs/2k60-validation-20261103.md`:当前正常二进制保持不变,VDD60Hz/串流45FPS已配置并从kiosk重连;约43~44FPS渲染。2K60请求受当前盒子呈现路径限制,不能宣称稳定60。`experiments/0004-vdi-egl-exact-size-sampling.patch`为未采用的精确尺寸采样实验,未进入正常构建器;默认仍为原GL_LINEAR取样。该实验候选二进制也未被正常wrapper使用。
|
||||
|
||||
独立光标已完成受控X11辅助程序原型,结果见`docs/independent-cursor-feasibility-20261103.md`。尚无自动服务端形状同步和可靠帧交接,未加入正常构建/启动流程;不能把Ctrl+Alt+Shift+C显示本地箭头和Sunshine全局N切换直接当生产方案。现有客户端保持单个Windows远程白色光标。
|
||||
|
||||
@ -6,9 +6,11 @@ task_root="${VDI_RKMPP_BUILD_ROOT:-$HOME/vdi-build/rkmpp-experiment}"
|
||||
label="${1:?label required}"
|
||||
fps="${2:?FPS required}"
|
||||
priority="${3:-0}"
|
||||
hold="${VDI_BENCH_HOLD_SECONDS:-12}"
|
||||
[[ "$label" =~ ^[a-zA-Z0-9-]+$ ]] || exit 2
|
||||
[[ "$fps" = 30 || "$fps" = 60 ]] || exit 2
|
||||
[[ "$fps" = 30 || "$fps" = 45 || "$fps" = 60 ]] || exit 2
|
||||
[[ "$priority" = 0 || "$priority" = 1 ]] || exit 2
|
||||
[[ "$hold" =~ ^[0-9]+$ ]] && ((hold <= 180)) || exit 2
|
||||
exec 9>"$task_root/mouse-bench.lock"
|
||||
flock -n 9 || { echo 'Another benchmark is active'; exit 1; }
|
||||
if pgrep -f '^/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight.* stream ' >/dev/null; then
|
||||
@ -20,8 +22,12 @@ export LD_LIBRARY_PATH="$task_root/runtime/lib:$task_root/deps/usr/lib/aarch64-l
|
||||
export QML2_IMPORT_PATH="$task_root/deps/usr/lib/aarch64-linux-gnu/qt5/qml"
|
||||
export QT_PLUGIN_PATH="$task_root/deps/usr/lib/aarch64-linux-gnu/qt5/plugins"
|
||||
export H264_DECODER_HINT=h264_rkmpp HEVC_DECODER_HINT=hevc_rkmpp
|
||||
export VDI_LATEST_FRAME=1 VDI_INPUT_TIMING=1 VDI_INPUT_PRIORITY="$priority"
|
||||
export VDI_LATEST_FRAME="${VDI_LATEST_FRAME:-1}" VDI_INPUT_TIMING=1 VDI_INPUT_PRIORITY="$priority"
|
||||
export GL_IS_SLOW=0 SDL_RENDER_DRIVER=opengles2 SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR=1
|
||||
sync_args=(--no-vsync --no-frame-pacing)
|
||||
if [ "${VDI_BENCH_VSYNC:-0}" = 1 ]; then
|
||||
sync_args=(--vsync --no-frame-pacing)
|
||||
fi
|
||||
client="${VDI_RKMPP_CLIENT:-$task_root/build/moonlight/app/moonlight}"
|
||||
mkdir -p "$task_root/mouse-bench"
|
||||
log="$task_root/mouse-bench/$label.log"
|
||||
@ -43,8 +49,8 @@ trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
"$client" stream 192.168.1.70 Desktop --resolution 2560x1440 --fps "$fps" \
|
||||
--bitrate 30000 --display-mode fullscreen --video-codec H.264 \
|
||||
--video-decoder hardware --absolute-mouse --keep-awake --no-vsync \
|
||||
--no-frame-pacing --audio-on-host > "$log" 2>&1 &
|
||||
--video-decoder hardware --absolute-mouse --keep-awake "${sync_args[@]}" \
|
||||
--audio-on-host > "$log" 2>&1 &
|
||||
child=$!
|
||||
ready=0
|
||||
for ((i=0;i<35;i++)); do
|
||||
@ -56,7 +62,10 @@ test "$ready" = 1 || { echo 'No video readiness'; exit 1; }
|
||||
echo "Ready: $label; injecting motion"
|
||||
python3 "$task_root/mouse-bench/inject-mouse-sweep.py"
|
||||
python3 "$task_root/mouse-bench/inject-input-burst.py"
|
||||
sleep 12
|
||||
for ((i=0;i<hold;i++)); do
|
||||
kill -0 "$child" || { echo 'Benchmark stream exited during hold'; exit 1; }
|
||||
sleep 1
|
||||
done
|
||||
# Do not send the exit chord into an unrelated foreground application.
|
||||
focus_pid=$(xdotool getwindowfocus getwindowpid 2>/dev/null || true)
|
||||
if [ "$focus_pid" != "$child" ]; then
|
||||
|
||||
@ -4,14 +4,19 @@ import base64
|
||||
from pathlib import Path
|
||||
import runpy
|
||||
import sys
|
||||
import re
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("action", choices=["Query", "List", "Apply", "Restore"])
|
||||
parser.add_argument("--hz", type=int, default=60)
|
||||
parser.add_argument("--backup-tag", default="", help="Separate backup for this verification run")
|
||||
args = parser.parse_args()
|
||||
if not 24 <= args.hz <= 240:
|
||||
parser.error("--hz must be in 24..240")
|
||||
if args.backup_tag and not re.fullmatch(r"[A-Za-z0-9_-]{1,64}", args.backup_tag):
|
||||
parser.error("--backup-tag must contain 1..64 letters, digits, underscores or hyphens")
|
||||
backup_name = "display-before" + ("-" + args.backup_tag if args.backup_tag else "") + ".json"
|
||||
root = Path(__file__).resolve().parent
|
||||
term = runpy.run_path(str(root / "pve_term_exec.py"))
|
||||
vm = runpy.run_path(str(root / "pve_vm.py"))
|
||||
@ -33,7 +38,7 @@ $rule=New-Object Security.AccessControl.FileSystemAccessRule($user,'Modify','Con
|
||||
$acl.SetAccessRule($rule)
|
||||
Set-Acl -LiteralPath $folder -AclObject $acl
|
||||
[IO.File]::WriteAllBytes("$folder\mode.ps1",[Convert]::FromBase64String('__VDI_PAYLOAD__'))
|
||||
$run="try { & '$folder\mode.ps1' -Action __VDI_ACTION__ -RefreshRate __VDI_HZ__ | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt' } catch { `$_ | Out-String | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt'; exit 1 }"
|
||||
$run="try { & '$folder\mode.ps1' -Action __VDI_ACTION__ -RefreshRate __VDI_HZ__ -BackupPath '$folder\__VDI_BACKUP__' | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt' } catch { `$_ | Out-String | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt'; exit 1 }"
|
||||
$encoded=[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($run))
|
||||
$action=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -EncodedCommand $encoded"
|
||||
$principal=New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Limited
|
||||
@ -53,7 +58,7 @@ try {
|
||||
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
|
||||
Unregister-ScheduledTask -TaskName $task -Confirm:$false
|
||||
}
|
||||
""".replace("__VDI_ACTION__", args.action).replace("__VDI_HZ__", str(args.hz)).replace("__VDI_PAYLOAD__", payload)
|
||||
""".replace("__VDI_ACTION__", args.action).replace("__VDI_HZ__", str(args.hz)).replace("__VDI_BACKUP__", backup_name).replace("__VDI_PAYLOAD__", payload)
|
||||
out, error = vm["agent"](ticket, csrf, ["powershell.exe", "-NoProfile", "-Command", command])
|
||||
print(out)
|
||||
if error or "task_result=0" not in out:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user