作为优化我的 3D 游戏/模拟引擎的一部分,我正在尝试使引擎进行自我优化。
基本上,我的计划是这样的。首先,让引擎测量每帧的 CPU 周期数。然后测量各种子系统消耗的 CPU 周期数(最小值、平均值、最大值)。
鉴于此信息,仅在帧循环中的几个特定点,引擎可以估计有多少“额外 CPU 周期”可用于执行现在可以有效执行的“可选处理”(相关数据现在在缓存中),但如果当前帧有运行不足 CPU 周期的危险,则可能会延迟到某个后续帧。
我们的想法是在繁重的工作上尽可能领先于游戏,因此每个可能的 CPU 周期都可用于处理“要求苛刻的帧”(如“单帧期间的许多碰撞”),而不会调用 glXSwapBuffers( ) 及时在 vsync 的最新可能时刻之前交换后/前缓冲区)。
上述分析假定交换后/前缓冲区是确保恒定帧速率的基本要求。我见过声称这不是唯一的方法,但我不明白其中的逻辑。
我在 glXSwapBuffers() 之前和之后捕获了 64 位 CPU 时钟周期时间,发现帧相差大约 2,000,000 个时钟周期!这似乎是由于 glXSwapBuffers()直到 vsync(当它可以交换缓冲区时)才阻塞,而是立即返回。
然后我在 glXSwapBuffers() 之前添加了 glFinish(),这将变化减少到大约 100,000 个 CPU 时钟周期......但随后 glFinish() 被阻塞了 100,000 到 900,000 个 CPU 时钟周期(大概取决于多少工作 nvidia 驱动程序必须在交换缓冲区之前完成)。由于 glXSwapBuffers() 完成处理和交换缓冲区可能需要多长时间的这种变化,我想知道是否有任何“智能方法”有希望。
最重要的是,我不确定如何实现我的目标,这似乎相当简单,并且似乎并没有对底层子系统(例如 OpenGL 驱动程序)提出太多要求。但是,即使在 glXSwapBuffers() 之前使用 glFinish(),我仍然看到“帧时间”有大约 1,600,000 个周期变化。我可以平均测量的“每帧 CPU 时钟周期”速率,并假设平均值产生实际帧速率,但是由于变化如此之大,我的计算实际上可能会导致我的引擎通过错误地假设它可能取决于这些值而跳过帧。
对于所涉及的各种 GLX/OpenGL 函数的细节,或者在实践中可能比我尝试的更好的一般方法,我将不胜感激。
PS:当核心减速或加速时,我的 CPU 的 CPU 时钟频率不会改变。因此,这不是我问题的根源。