我一直认为计算FPS的正确方法是简单地计算绘制循环迭代所需的时间。互联网的大部分似乎都是一致的。
现代图形卡被视为异步服务器,因此绘制循环发送已经在GPU上的顶点/纹理/等数据的绘图指令。在GPU上的请求完成之前,这些调用不会阻塞调用线程,只是将它们添加到GPU的任务队列中。那么“传统”(而且无处不在)的方法肯定只是衡量呼叫发送时间吗?
促使我提出的问题是我已经实现了传统方法,并且它提供了始终如一的荒谬高帧率,即使渲染的内容导致动画变得不连贯。重新阅读我的OpenGL SuperBible让我进入glGenQueries,它允许我计算渲染管道的各个部分。
总而言之,计算FPS的“传统”方式是否完全不再使用(几乎没有)现代显卡?如果是这样,为什么GPU分析技术相对未知?
答案 0 :(得分:13)
测量fps很难。由于各种想要测量fps的人不一定想要测量同样的事情,所以事情变得更难了。所以问问自己这个。你为什么想要一个fps号?
在我继续深入探讨所有陷阱和潜在解决方案之前,我想指出这绝不是特定于现代图形卡的问题"。如果有的话,过去更糟糕的是,使用SGI类型的机器,渲染实际上发生在可能远离客户端的图形系统上(如物理远程)。 GL1.0实际上是根据客户端服务器定义的。
反正。回到手头的问题。
fps,意味着每秒帧数,实际上是试图在一个数字中传达一个关于应用程序性能的粗略概念,其数量可以直接与屏幕刷新率等相关。对于性能的第一级近似,它做得很好。一旦你想深入研究更精细的分析,它就会彻底打破。
问题实际上是最重要的事情,而且感觉是顺畅的感觉"一个应用程序,是你画的画面最终在屏幕上。重要的第二件事是在触发动作的时间和屏幕上的效果显示之间需要多长时间(总延迟)。
当一个应用程序绘制一系列帧时,它会在时间s0,s1,s2,s3,......提交它们,并最终在t0,t1,t2,t3,...显示在屏幕上。
为了感觉顺利,你需要做以下所有事情:
当您测量渲染的CPU时间时,最终测量s1-s0以接近t1-t0。事实证明,这个平均,与事实相差不远,因为客户端代码将永远不会过去" (这是假设您一直在渲染帧。请参阅下面的其他案例)。实际上发生的事情是,当它试图走得太远时,GL将最终阻塞CPU(通常在SwapBuffer时间)。阻塞时间大致是GPU与单帧上的CPU相比所花费的额外时间。
如果您真的想要测量t1-t0,正如您在自己的帖子中提到的那样,查询更接近它。但是......事情从来没有那么简单。第一个问题是,如果您的CPU受限(意味着您的CPU不够快,无法始终为GPU提供工作),那么时间t1-t0的一部分实际上是空闲的GPU时间。这不会被查询捕获。您遇到的下一个问题是,根据您的环境(显示合成环境,vsync),查询实际上可能只测量应用程序在渲染到后台缓冲区时所花费的时间,这不是完整的渲染时间(因为显示尚未显示)当时更新)。它确实让您大致了解渲染需要多长时间,但也不准确。另请注意,查询也受图形部分的异步性影响。因此,如果您的GPU在一段时间内处于空闲状态,则查询可能会错过该部分。 (例如,假设您的CPU需要很长时间(100毫秒)才能提交帧.GPU会在10毫秒内执行完整帧。您的查询可能会报告10毫秒,即使总处理时间接近100毫秒......)。 / p>
现在,关于"基于事件的渲染"而不是我到目前为止所讨论过的连续的。这些类型的工作负载的fps并没有多大意义,因为目标不是尽可能多地绘制f。 GPU性能的自然度量是ms / f。也就是说,它只是图片的一小部分。什么真的重要的是从您决定要更新屏幕的时间和发生的时间。不幸的是,这个数字很难找到:它通常在您收到触发流程的事件时开始,并在屏幕更新时结束(您只能通过捕获屏幕输出的相机来测量...)。
问题在于,在两者之间,CPU和GPU处理之间可能存在重叠(或者甚至在CPU停止提交命令和GPU开始执行命令之间有一些延迟)。这完全取决于实施的决定。您可以做的最好的事情是在渲染结束时调用glFinish以确保GPU已完成处理您发送的命令,并测量CPU上的时间。该解决方案确实会降低CPU方面的整体性能,如果您要在......之后立即提交下一个事件,则可能会降低GPU方面的性能。
最后关于模拟增量时间"
的"硬约束的讨论典型的动画使用帧之间的增量时间来向前移动动画。主要的问题是,对于完全平滑的动画,你真的想要在s1将帧提交为t1-t0时使用的增量时间(这样当t1显示时,从前一帧实际花费的时间确实是t1 -T0)。问题当然是你不知道在提交s1时t1-t0是什么...所以你通常使用近似值。许多人只是使用s1-s0,但这可能会破坏 - 例如SLI类型的系统在各种GPU之间的AFR渲染中可能有一些延迟。您还可以尝试通过查询使用t1-t0(或更可能是t0-t(-1))的近似值。这种错误的结果很可能是SLI系统上的微观口吃。
最强大的解决方案是说"锁定到30fps,并始终使用1 / 30s"。它也是允许内容和硬件余地最小的一个,因为你 以确保你的渲染确实可以在那些33ms完成...但是一些控制台开发人员选择了do(固定硬件使它更简单)。
答案 1 :(得分:1)
“而且大部分互联网似乎都是一致的。”对我来说似乎并不完全正确:
大多数出版物都会测量多次迭代需要多长时间,然后进行标准化。通过这种方式,您可以合理地假设,填充(和填充)管道只是总时间的一小部分。