DXGI桌面复制屏幕捕捉速度

14

我正在使用桌面复制 API中的AcquireNextFrame来捕获屏幕。屏幕的刷新率为120Hz。当以120FPS运行游戏时,屏幕捕获可以捕获120FPS的帧数。但是当将游戏的帧率增加到240FPS时,屏幕捕获实际上会下降到大约70FPS。我的猜测是额外的帧被累积了,这增加了开销,但我不确定。有没有办法避免这种性能下降?


1
做一些简单的数学计算:视频内存到系统内存的最大传输速率与240 fps(在您选择的分辨率下)所需的带宽相比如何?我敢打赌你正在超载内存总线。 - Richard Critten
@RichardCritten:桌面复制本身不执行视频到系统内存的传输。但API使用者可能会执行这些传输。 - Roman R.
7
这并不是关于“一般计算机硬件和软件”的问题。根据他们的个人资料,那些投票关闭问题的人中没有一个人拥有足够的领域特定知识来理解这个问题。我投票重新开放,并且如果可能的话,我也会投票暂停每个投票关闭者的帐户以防止破坏行为。 - IInspectable
3
这个问题是恰当的主题;请投票重新开放。关闭背后应该有一些不明显的原因,比如盲目跟随其他投票,特别是为了得到相应的徽章,或者失去对他们的帐户的控制。 - Roman R.
2
正是因为这样的东西,人们才会离开SO。这是一个完全合法的问题。 - PhysicalEd
1个回答

12

桌面复制 API 的设计是累积显示器(在 DXGI 中称为“输出”)更新,直到您通过 AcquireNextFrame 请求它们。该 API 并非旨在首先捕获每个更新。此外,您没有指定在 AcquireNextFrame 循环中是否还进行其他操作,或者只是测量性能(问题的语言表明后者)。

也就是说,对于非常密集的前端应用程序,输出复制 API 会错过更新,这是可以预料的。在那里也没有太多的灵活性。也许 MSDN 提供的最重要的提示在ReleaseFrame Remarks 部分中提到:

出于性能原因,我们建议您在调用 IDXGIOutputDuplication::AcquireNextFrame 方法获取下一帧之前释放帧。当客户端不拥有该帧时,操作系统会将所有桌面更新复制到表面上。如果操作系统更新每个帧的同一区域,则可能会导致 GPU 循环浪费。当客户端获取帧时,客户端仅知道此区域的最终更新;因此,在先前帧期间发生的任何重叠更新都是浪费的。当客户端获取帧时,客户端拥有表面;因此,操作系统只能跟踪更新的区域,并且不能将桌面更新复制到表面。由于这种行为,我们建议您尽量缩短释放当前帧和获取下一帧之间的时间。

也就是说,早或晚调用 ReleaseFrame 会影响 API 的内部行为。它要么总体上累积更新,要么还会将实际负载数据复制到复制的帧资源中。


1
我不明白的是这些累积的帧是丢失了还是像FIFO队列一样?因为当由于机器性能问题导致累积帧计数上升时,当机器恢复正常并且我们继续成功获取时,它似乎永远不会下降。 - Simon Mourier
1
@SimonMourier:操作系统维护一个组合桌面帧的副本。这只是您的桌面复制会话的一份资源(纹理),没有任何排队。AcquireNextFrame/ReleaseFrame是与操作系统协作访问此资源的方式。在两个调用之间,纹理是您的,操作系统正在跟踪脏部分。在Acquire/Release之外,系统还更新纹理并进行跟踪。 - Roman R.
1
就性能而言,如果采集速度较慢,系统将简单地覆盖此副本纹理中的更改,直到下一个“AcquireNextFrame”调用到来。上述MSDN引文解释了操作系统将停止更新纹理(仅跟踪哪些区域需要稍后更新),直到“ReleaseFrame”调用为止,并且这种延迟释放有助于防止过多的更新-稍后在释放副本纹理时将进行单个联合更新。 - Roman R.
1
谢谢!我之前没有想到“侧面复制”的概念。 - Simon Mourier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接