我正在开发一个 OpenGL 3D 渲染器。我正在使用 Java 和 JOGL API。现在我正在尝试对我的延迟渲染器进行性能调整。为此,我使用 VisualVM Profiler 来查看是什么占用了我宝贵的 CPU 周期,并使用 gDEBugger 来跟踪我的 OpenGL 函数调用。现在,即使只有 20 到 30 个灯光(并且需要点亮的实际网格数量非常少),它的 FPS 也会下降到 30 帧以下。而且我什至还没有添加阴影贴图和法线贴图之类的东西。
这就是它目前的样子(41 盏灯,但只有 20 FPS):
在 VisualVM 中,我注意到大部分CPU时间都花在了本机jogamp.opengl.windows.wgl.WGLUtil.SwapBuffers
方法上。但是,我不确定这些信息是否与我的着色器的运行时间相关或以任何方式相关。调用的运行时间glDrawArrays
可以忽略不计,这证实了这个方法只是向 GPU 发出调用,并且显然没有等待它们完成后再返回。为什么我的应用程序的大部分时间都花在该函数调用上?
同样比较奇怪的是:当我有 3-4 盏灯时,我以 60FPS 的速度运行。当我将该数字增加到 20 时,该数字下降到 20FPS。当我添加 1000-1100 盏灯时,我仍然可以获得大约 10 FPS。这是为什么?由于光照计算是相加的,当有 1000 个光照时,每个像素运行的片段着色器应该比有 20 个光照时多得多,这意味着渲染器理论上应该比 20 个光照慢得多。为什么从 3-4 盏灯跳到 20 盏灯时会出现如此巨大的性能?
现在我的问题的第二部分:就像我之前说的,我也开始使用 gDEBugger 来分析我的 OpenGL 调用,但是,遗憾的是,我似乎无法找到一种方法来准确确定执行时间最长的内容 -我只获得有关哪些函数被调用最多的信息。在尝试寻找冗余状态更改之类的事情时它会有所帮助,但对于我所处的阶段,我确信存在更大的问题会减慢我的渲染器速度。
有谁知道一种可靠的方法来跟踪我的片段着色器的执行时间,并准确查看哪些片段中哪些计算花费的时间最长?我知道 nVidia nSight 提供了一些出色的图形调试功能,但其中大部分仅适用于 DirectX 应用程序。