【问题标题】:OpenGL core profile incredible slowdown on OS XOS X 上的 OpenGL 核心配置文件令人难以置信的减速
【发布时间】:2013-05-07 08:56:13
【问题描述】:

我在我的引擎中添加了一个新的 GL 渲染器,它使用核心配置文件。虽然它在 Windows 和/或 nvidia 卡上运行良好,但在 OS X 上却慢了 10 倍(3 fps 而不是 30)。奇怪的是,我的兼容性配置文件渲染器运行良好。

我使用 Instruments 和 GL profiler 收集了一些痕迹:

https://www.dropbox.com/sh/311fg9wu0zrarzm/31CGvUcf2q

这表明应用程序将时间花在 glDrawRangeElements 中。 我尝试了以下方法:

  • 改用 glDrawElements(无效)
  • 翻转剔除(不影响速度)
  • 禁用一些 GL_DYNAMIC_DRAW 缓冲区(无效)
  • 绘制时在VAO后绑定索引缓冲区(无效)
  • 将索引转换为 4 字节(无效)
  • 使用 GL_BGRA 纹理(无效)

我没有尝试将我的顶点对齐到 16 字节边界和/或将索引转换为 4 字节,但说真的,如果这会是问题,那么为什么要执行标准允许吗?

我正在创建这样的上下文:

NSOpenGLPixelFormatAttribute attributes[] =
{
    NSOpenGLPFAColorSize, 24,
    NSOpenGLPFAAlphaSize, 8,
    NSOpenGLPFADepthSize, 24,
    NSOpenGLPFAStencilSize, 8,
    NSOpenGLPFADoubleBuffer,
    NSOpenGLPFAAccelerated,
    NSOpenGLPFANoRecovery,
    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
    0
};

NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil];

[self.view setOpenGLContext:context];
[context makeCurrentContext];

尝试了以下规格:

  • Radeon 6630M,OS X 10.7.5
  • Radeon 6750M,OS X 10.7.5
  • geforce GT 330M,OS X 10.8.3

你有什么想法我可能做错了吗?同样,它适用于兼容性配置文件(但不使用 VAO)。

更新:向 Apple 报告。

更新:Apple 并不在乎这个问题......无论如何,我创建了一个实际上很好的小型测试程序。现在我将调用堆栈与 Instruments 进行了比较,发现在使用引擎时,glDrawRangeElements 进行了两次调用:

  • gleDrawArraysOrElements_ExecCore
  • gleDrawArraysOrElements_Entries_Body

在测试程序中它只调用第二个。现在第一个调用执行类似于立即模式渲染(gleFlushPrimitivesTCLFunc,gleRunVertexSubmitterImmediate)的操作,因此显然会导致速度变慢。

【问题讨论】:

  • "但是说真的,如果这会是问题,那为什么标准会允许它呢?" 因为标准没有定义性能。只有功能。
  • 这听起来几乎像是在回归软件。您应该对其进行分析并查看减速在哪里。另外,你能用 OpenGL Profiler 运行它并打开所有的错误断点吗?它可能会指出您遗漏的一些东西(如果它回退到软件,它会告诉您)。
  • 我确实启用了错误检查,以及中断 sw 回退,但什么也没发生。顺便提一句。我附加的日志显示引擎也在每帧检查 GL 错误。正如我提到的,减速显然是在 glDrawRangeElements 中。
  • 你渲染的缓冲区数据有多大?
  • 既然 GL_UNSIGNED_SHORT 足够了,它不能太大,而且无论如何它都可以在 GL 2 上正常工作。我尝试了更小甚至更大的模型,但无论着色器或几何复杂性如何,它们都运行得很慢。

标签: performance macos opengl profile core


【解决方案1】:

最后,我能够重现减速。这简直太疯狂了……这显然是由在“my_Position”属性上调用 glBindAttribLocation 引起的。现在我做了一些测试:

  • 1 是默认值(由 glGetAttribLocation 返回)
  • 如果我将它设置为零,则没有问题
  • 如果我将它设置为 1,渲染会变慢
  • 如果我将它设置为更大的数字,它又会变慢

显然我重新链接了程序(检查代码)。这在实现中不是问题,我也用“正常”值对其进行了测试。

测试程序:

https://www.dropbox.com/s/dgg48g1fwgyc5h0/SLOWDOWN_REPRO.zip

如何复制:

  • 用 XCode 打开
  • 打开 common/gext.h(不要被名字打扰)
  • 将 GLDECLUSAGE_POSITION 常量从 0 修改为 1
  • 编译并运行 => 慢
  • 变回零 => 好

【讨论】:

  • 谢谢!我花了几天时间试图找出为什么我在 2013 MacBook Pro 上的 50K Tris 模型获得 15FPS。 FPS 跳到无穷大(需要更高分辨率的计时器:P)
【解决方案2】:

在以下情况下,我设法让自己遇到了同样的问题 OS X Mavericks:

  • 使用数组缓冲区进行实例化渲染,为每个实例提供自己的modelToWorldinverseNormal 矩阵;属性位置是通过布局指定的,而不是使用glGetAttribLocation

  • shader 中保留未使用的这些数组缓冲区之一,其中声明了位置,但该属性实际上并未用于glsl 代码中的任何内容

在这种情况下,对glDrawElementsInstanced 的调用会占用大量 CPU 时间(在正常情况下,即使绘制数千个实例,此调用也会使用几乎为零的 CPU)。

如果glDrawElementsInstanced 中使用的几乎所有 CPU 时间都花在gleDrawArraysOrElements_ExecCore 上,您就可以看出您遇到了这个特定问题。确保在您的shader 代码中实际引用了所有数组缓冲区,从而将 CPU 时间修复为(几乎)为零。

我怀疑这是在 glsl 中将变量从 main() 中留出的情况之一,这会使编译器混淆以删除对该变量的所有引用,从而使您对属性或制服的引用悬空。

【讨论】:

  • 我建议你也向 Apple 报告这个问题 :) 显然他们也没有解决我的问题。
  • 我对非常​​简单的着色器也有类似的问题。感谢 Deekey,虽然我没有使用实例化渲染,但未使用的矢量缓冲区确实会使矢量着色器在 CPU 上运行。
  • 要进一步详细说明它有多糟糕,即使未使用的变量被禁用,使用带有未使用但绑定变量的 VAO 也会使顶点着色器在软件中运行。
猜你喜欢
  • 2012-06-30
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
相关资源
最近更新 更多