背景
#192(sleep 满帧周期)修复合入后(PR #201),真机探针帧率 22→25.5fps,仍未达 30fps 目标。追查确认存在第二个独立瓶颈。
根因
crates/opentake-render/src/gpu/compositor.rs 的 PendingReadback::finish 每帧同步调用 device.poll(wgpu::Maintain::Wait) 等待 GPU 读回完成——渲染线程每帧都要阻塞等 GPU→CPU 拷贝,构成固定的每帧延迟下限(debug/release 耗时几乎相同,证明不是 CPU 侧计算)。
真机数据(PR #201 探针,/Volumes/mac/1111.mp4,640x360 输出)
优化方向
map_async + 非阻塞轮询,渲染与读回流水线化(N 帧在渲染、N-1 帧在读回)
- 或双缓冲 readback buffer,隔帧取回
- 注意与 preview(暂停单帧 composite)共享代码路径,导出路径(批量)对延迟不敏感但对吞吐敏感,流水线化两边都赚
验收
PR #201 的 src-tauri/tests/playback_probe.rs 探针(真机):3s @30fps 应稳定 ≥85 帧;届时把探针阈值从 73/48/30 恢复到 85/52/40。
背景
#192(sleep 满帧周期)修复合入后(PR #201),真机探针帧率 22→25.5fps,仍未达 30fps 目标。追查确认存在第二个独立瓶颈。
根因
crates/opentake-render/src/gpu/compositor.rs的PendingReadback::finish每帧同步调用device.poll(wgpu::Maintain::Wait)等待 GPU 读回完成——渲染线程每帧都要阻塞等 GPU→CPU 拷贝,构成固定的每帧延迟下限(debug/release 耗时几乎相同,证明不是 CPU 侧计算)。真机数据(PR #201 探针,/Volumes/mac/1111.mp4,640x360 输出)
优化方向
map_async+ 非阻塞轮询,渲染与读回流水线化(N 帧在渲染、N-1 帧在读回)验收
PR #201 的 src-tauri/tests/playback_probe.rs 探针(真机):3s @30fps 应稳定 ≥85 帧;届时把探针阈值从 73/48/30 恢复到 85/52/40。