2017-05-03 140 views
3

我正在构建一个OpenGL应用程序。它与OpenGL唯一不方便的地方是它使用了少量(5个或更多)相当大(2000x2000及更大)的纹理。其余的是非常默认的现代OpenGL 3.3的东西(FBO的,VBO的,IBO的,VOA的,着色器等)。由于这些纹理非常大,需要的位深度超过8位,因此我使用内部像素格式来减少内存(但是,将其更改为简单的内容并不会帮助(请参见下方))。现在,这里是一个事物:完全相同的代码,运行在Windows,Linux和MacOS上(我使用SDL作为抽象层)。在同一硬件上(我的2011年末MacBook Pro 13“,Intel HD Graphics 3000 @ 1280x800),同样的编译器(clang -O3 -mavx),Linux和macOS之间的性能差异是巨大的在macOS上,我的帧时间大约是30ms到80ms。然而,在Linux上,这是一个惊人的1ms到4ms。同样的笔记本电脑,只是在不同的操作系统中重新启动。缩短应用程序窗口大约600x400,在macOS上将帧时间降低到13ms因此,像素着色器/光栅化(我的着色器的确是非常复杂的)Linux与macOS,相同硬件的巨大OpenGL性能差异

我必须说我在macOS上有更好的帧时间(大约13ms到20ms)所以,在发现这些之后我越来越怀疑Apple可能会通过系统更新有意地“降级”英特尔HD Graphics 3000的图形驱动程序,以将购买者推向b你的新产品。我必须说,我一直在考虑购买一台新的笔记本电脑,但是自从我发现这一点以后,突然感到厌恶。

现在的问题是:你认为在这里会发生什么?越野车司机?苹果故意让事情变慢?驱动程序中包含一个未优化的GLSL编译器?或者,也许在应用程序中的OpenGL代码中有一些不好的做法?驱动程序对非8位纹理格式的支持很普遍吗?

我只是讨厌这个应用程序在Linux中非常棒,在macOS中非常令人愉快。硬件能够做得更好。


一些测试,如通过要求@BDL:

  • 通过因子4在每一个降维的尺寸纹理(因而16次存储器少,留给我们一个500×500的纹理,大约),不影响帧时间。
  • 使用GL_RGB8或GL_SRGB8作为内部格式不会影响帧时间。
  • 减少很多着色器的复杂性确实有帮助:当我在片段着色器中删除大量计算时,我可以将其平均降低到8ms。

我会尝试一个GLSL着色器优化的明天:https://github.com/aras-p/glsl-optimizer 希望这有助于一点。

+0

@NicolBolas我希望你停下来:) –

+0

你应该使用仪器和/或OpenGL Profiler来描述你的应用程序。它使用了很多CPU时间吗?它花了很多时间在纹理格式转换?你也应该试一试你的代码。你使用'GL_R11F_G11F_B10F'似乎是问题的可能原因。 –

+0

难道你不能再缩小性能有问题的部分吗?例如,是否使用较小的纹理帮助?降低着色器复杂性有助于吗?在MacOS上,哪些OpenGL调用占用了所有时间? – BDL

回答

-2

这通常很难得到这些问题上堆栈溢出的底部,因为我们没有访问您的代码,但这里有一些东西,你可以尝试:

  • 更新驱动程序到最新版本受OS支持。
  • 打开图形调试器并检查缓冲区大小,纹理大小,RAM使用情况,内存使用情况等。

这可能只是一些时间问题,必须在OSX和Linux之间进行排序,您还可以通过SDL获取指向原始窗口资源的指针并以此方式解决问题。

+2

“更新驱动程序”?你意识到图形驱动程序是Mac OS操作系统的一部分,对吧? – duskwuff

+0

你能否详细说明“解决时间问题”?你在谈论什么时机问题? –

+0

@MartijnCourteaux您是手动设置framelimit还是应用程序运行得尽可能快? –

2

你用什么方法来测量帧渲染时间?在我关于各种OpenGL实现的时序行为的实验中,Mesa/Intel HD驱动程序有关于最难解释时序行为的内容。

用于MacOS X的Intel HD Graphics驱动程序是一个完全不同的代码库(零源代码重叠!),由一个完全不同的开发团队(主要是Apple People AFAIK)编写。

请记住,OpenGL采用异步执行模型,说明缓冲区交换调用的确切时间没有硬指定。在Linux上,AMD和NVidia OpenGL几乎都有…SwapBuffers区块,直到V-Sync(如果启用V-Sync)。然而,我发现Mesa/Intel实现将…SwapBuffers视为另一个排队命令,只有命令队列已满并且正在进行的调用最终只能在缓冲区交换后才能执行(如清除后台缓冲区)。

为了削减长话短说,我发现实际测量帧渲染免耕presentation¹通过将glClear通话时间正确…SwapBuffers(即结算为下一个帧的来下一次迭代中唯一可靠的方法)并测量从渲染开始到异常放置glClear之后的时间。

无论如何,通过查询对象可以更好地测量纯粹的渲染时间(不包含表示部分)。