DXGI桌面复制API屏幕捕获帧率下降问题咨询
解决Desktop Duplication API在高游戏帧率下捕获帧率下降的问题
首先,你的猜测是对的——当游戏帧率远高于显示器刷新率时,确实容易出现帧堆积带来的性能开销,进而拉低捕获帧率。结合Desktop Duplication API的工作机制,这里有几个实用的优化方向:
1. 让捕获帧率与显示器刷新率同步
屏幕本身只有120Hz,意味着实际显示到屏幕上的帧最多只有120FPS,游戏生成的240FPS里有一半是不会被输出到显示器的(除非用了DLSS 3这类插帧技术,但本质还是受限于显示器物理刷新率)。强行捕获超过屏幕刷新率的帧完全是浪费资源,反而会让API内部队列堆积。
你可以:
- 用
QueryDisplayConfig获取当前显示器的准确刷新率,计算出每帧的间隔(比如120Hz对应约8.33ms) - 用定时器或基于垂直同步的信号触发
AcquireNextFrame调用,而不是无限循环调用该方法 - 这样既能保证捕获到每一个实际显示的帧,又能避免不必要的API调用开销
2. 拆分捕获与处理流水线
如果你的代码在调用AcquireNextFrame后,立刻在同一个线程里做像素复制、编码这类耗时操作,当游戏高帧率运行时,捕获线程会被阻塞,导致新的帧不断堆积在API队列里。
优化方案:
- 把捕获和处理拆分成两个独立线程:
- 捕获线程:只负责调用
AcquireNextFrame,拿到帧数据后立刻交给处理线程(比如用线程安全的队列传递),然后释放帧资源 - 处理线程:单独完成像素处理、编码等耗时操作
- 捕获线程:只负责调用
- 这样捕获线程能快速完成API调用,避免队列阻塞
3. 主动跳过冗余帧
当游戏无VSYNC运行时,显卡会生成大量未被显示器显示的帧,这些帧会进入Desktop Duplication的内部缓存。你可以通过OutputDuplicateFrameInformation里的LastPresentTime字段判断当前帧是否是“有效显示帧”:
- 记录上一次捕获到的有效帧的
LastPresentTime - 当新捕获到的帧与上一帧的时间间隔远小于显示器刷新率对应的间隔(比如120Hz下的8.33ms),直接调用
ReleaseFrame丢弃这个帧,不做处理 - 只保留那些符合显示器刷新率间隔的帧,减少无效处理开销
4. 减少系统层面的额外开销
高帧率游戏本身已经占用大量GPU/CPU资源,桌面合成的额外特效会进一步挤压捕获的资源:
- 关闭Windows的透明效果、动画特效(比如在个性化设置里切换到“最佳性能”模式)
- 捕获期间关闭其他占用GPU的后台程序(比如视频播放器、直播软件)
- 确保显卡驱动是最新版本,部分驱动更新会优化Desktop Duplication的性能
5. 检查GPU负载与API参数
- 用任务管理器或GPU-Z查看游戏运行时的GPU负载,如果已经接近100%,那Desktop Duplication很难拿到足够的资源,此时可以适当降低游戏画质,给捕获留出GPU空间
- 调整
AcquireNextFrame的TimeoutInMilliseconds参数:不要设置过长的超时(比如超过10ms),当队列中有堆积时,短超时能让API更快返回最新帧,避免等待旧帧
内容的提问来源于stack exchange,提问作者availn




