【问题标题】:How taxing are OpenGL glDrawElements() calls compared to basic logic code?与基本逻辑代码相比,OpenGL glDrawElements() 调用有多繁重?
【发布时间】:2016-05-27 20:49:36
【问题描述】:

我打算对我的 OpenGL 程序进行一些优化(它不需要优化,但我这样做是为了它)。出于好奇,与基本逻辑代码相比,OpenGL 绘图功能有多贵?目前,我正在开始一个游戏,其中屏幕充满了方块,以表示 2D 块状景观。这意味着多次调用正方形(两个三角形)的绘制调用。目前,我计划添加一些代码来查看当前帧中块的位置,并将它们组合在一起。例如,如果有一列是 7 块高,我可以调用一个函数来绘制一个 1 x 7 的矩形,而不是执行 7 个单独的 drawBlock() 函数(其中包含 glDrawElements() 调用)在整个屏幕上打开。

如果计算要绘制什么的代码实际上比单独绘制块消耗的 CPU 更多,我不会费心这样做。

【问题讨论】:

  • 我不确定您的问题与glDrawElements 有何关系。听起来您正在尝试决定合并相邻的四边形是否值得;在这种情况下,最好的决定方法是通过分析。
  • @ColonelThirtyTwo:通常情况下进行分析是有必要的,但在这种情况下,这是已成定局。 glDrawElements 是出了名的昂贵。
  • glDrawElements() 通话非常非常昂贵。我建议将所有背景块放入单个 VBO,然后您可以为整个背景调用一次 glDrawElements()。或者将其分成块,如果太大的话……但是每个 glDrawElements() 一个四边形不会导致每帧有很多四边形。
  • 我一直到最后一句“...但是每个 glDrawElements() 一个四边形不会导致每帧有很多四边形”好吧,这就是我现在正在做的事情,所以如果它不会产生很多四边形,你的意思是我应该让它更有效率吗?向数组添加顶点似乎有点被欺骗了!无论如何感谢您的帮助:)

标签: c++ opengl


【解决方案1】:

glDrawElements(或任何其他OpenGL rendering command)的成本无法真正估算。这是因为它的成本很大程度上取决于您在两次绘制调用之间更改的 OpenGL 状态。调用 OpenGL 状态更改函数(基本上,任何不是某种形式的 glGet 或某种形式的 glDraw 的 OpenGL 函数)的成本会相对较快。但它会使下一次绘制调用变慢。

This video on OpenGL performance 显示哪些状态更改在绘制时比其他状态更改成本更高。真正精彩的部分从大约 31 分钟开始。

如果您没有在两次绘制调用之间更改任何 OpenGL 状态,则绘制调用会相对较快。不同的状态对绘图调用有不同的影响。从最快到最慢(根据上面 NVIDIA 的介绍,因此请持保留态度):

现在,draw call 将比“基本逻辑”更昂贵。它们并不便宜,即使它们之间没有状态变化。如果效率对您的代码很重要,那么将方块分组是个好主意。

【讨论】:

    【解决方案2】:

    实际数字高度依赖于平台和供应商。不同操作系统上的驱动程序架构差异很大,其中一些比其他更有效。最重要的是,驱动程序实现和硬件可能会导致很大的性能差异。例如,在相同的平台和可比的硬件上,我发现一个供应商的绘图调用吞吐量比另一供应商高 10-20 倍。

    基于此,以下任何数字都只是一个非常粗略的数量级。您确实需要根据您关心的配置自行衡量这一点。

    有了所有这些免责声明,我希望可以在 100 条指令(CPU 周期)的范围内处理绘图调用。这适用于您只需进行背靠背绘图调用且管道中没有其他瓶颈的情况。

    正如@NicolBolas 已经指出的那样,处理绘图调用最昂贵的部分通常是处理延迟状态更改。大多数情况下,您将在两次绘制调用之间进行状态更改。在这种情况下,对于相对便宜的状态更改(例如绑定纹理或缓冲区,或更改某些属性),通常需要 100 条指令。

    切换帧缓冲区通常非常昂贵,并且在某些平台上非常昂贵。除此之外,我过去在优化和基准测试状态更改时测量的数字显示的顺序与@NicolBolas 答案中的列表完全不同。但同样,这高度依赖于平台和供应商/硬件。

    还有几个方面使得这个测量有点棘手:

    • 您的线程可能不会消耗大部分 CPU 时间。许多驱动程序是多线程的,这意味着处理 OpenGL 调用所需的大部分工作被卸载到辅助线程。如果您的应用程序没有使用所有 CPU 内核,并且您没有受到功率/热量限制的限制,这意味着许多驱动程序工作可以并行发生,而不会大大降低您的应用程序的速度。但尤其是在移动设备和笔记本电脑上,性能通常受到功耗的限制,因此驱动程序开销仍然会减慢您的速度。
    • 驱动程序消耗的 CPU 时间只是降低应用程序代码速度的一部分。另一个考虑因素是缓存污染。如果您的应用程序使用的缓存内容在 OpenGL 实现处理您的绘图调用时被清除,您自己的代码将获得更多的缓存未命中,并且运行速度会变慢。因此,测量在 OpenGL 调用中花费的时间只能显示部分内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 2015-04-08
      相关资源
      最近更新 更多