【问题标题】:Repeated State changes in OpenglOpengl 中的重复状态变化
【发布时间】:2011-09-21 18:47:52
【问题描述】:
   Its a fact that state changes in Opengl leads to performance degradation. 

//如果我在每一帧重复调用glEnable(GL_DEPTH_TEST)/glBlendFunc。

编辑:>在这里我只是想说'像这样的一些状态变化会导致性能问题'

谁能详细解释一下这个原因?

据我所知,可以在寄存器中维护状态,并且可以在传统渲染 GPU(即时模式类型)中使用,也可以保持状态 基于 Tile 的延迟渲染中每个绘制调用的向量。维护成本真的很高吗? (想知道为什么 GPU 仍然存在这个问题:()

【问题讨论】:

    标签: iphone opengl-es cocos2d-iphone gpu


    【解决方案1】:

    确实,状态更改可能是性能杀手。然而,要问的重要问题是:“哪个州”。某些状态更改非常便宜,因此跟踪它们以尽量减少它们的使用是没有意义的。

    在当今的 OpenGL 实现中,glEnable/glDisable 几乎没有性能损失(当然,某些状态启用/禁用通常会对渲染性能产生很大影响)。

    那么昂贵的状态变化是什么?关于杀死缓存内容的所有内容,以及缓存中的数据将以高带宽或需要高吞吐量访问。

    纹理是最昂贵的数据转换来源。因此,作为基本规则,您使用纹理对场景进行排序,尽可能少地切换纹理。

    另一个代价高昂的状态更改是切换着色器。切换着色器以两种方式对 GPU 产生负面影响:首先,它强制处理单元完全停止,刷新它们的执行管道。重新填充管道直到事情“像发条一样”工作需要几百个周期。另一个问题是,不同的着色器有不同的执行和数据访问模式。执行模式由代码路径预测单元确定,以估计最有可能执行哪些操作。这也意味着知道要预取哪些数据。切换着色器会破坏这些重要信息。

    非常便宜但不是免费的状态是可以用一小组数字来描述的任何东西:制服。切换 Uniform 非常便宜,因为它在与 GPU 的通信中只需要很少的开销,而且由于 Uniform 存在于寄存器中,因此更改它们既不会影响缓存线,也不会影响执行预测。如果您对传统的固定函数 OpenGL 感到疑惑:变换矩阵、光照参数、裁剪平面是统一的(只需查看 OpenGL-2.1 GLSL 规范,其中有内置统一)。

    【讨论】:

    • 这真的很翔实!谢谢大狼!一个小的澄清...在考虑基于 Tile 的延迟渲染(Power VR GPU 卡)时,基于对象的位置(为了更快地获取切片器)排序更好,还是根据纹理索引排序更好?
    • @Ayyappa:我不能肯定地说,但是针对低内存带宽要求优化的 TBDR 的性质表明了这一点。然而,按位置排序需要在 CPU 上进行大量处理,据我所知,PowerVR 使用驱动程序中的几何图形来执行此操作,无论如何都在 CPU 上。因此,如果我不得不做出有根据的猜测,我会说,按通常的方案排序仍然是最好的,尽管 PowerVR 可能会通过按着色器排序来获利。弗兰奇,我会对其进行基准测试,以做出合格的陈述。
    • 感谢您的信息!我也会尝试在空闲时间对其进行基准测试...但是如果您这样做,请分享结果...
    • @datenwolf:哇!这真的让我很惊讶!在我的引擎中,我总是按着色器排序,然后是网格(因为同一个网格的多个实例使用相同的纹理),然后是纹理......你认为改变这个顺序是否值得?
    • 由于您将对许多几何体和纹理使用相同的着色器,并且由于您将为不同的着色器使用一组完全不同的纹理,因此实际的方法是您首先按纹理排序,由着色器秒。由于纹理和着色器之间的关联也最大限度地减少了着色器切换。 ——顺便说一句,长期以来的建议是首先对距离较近的几何进行排序,以有效利用早期深度测试。这仍然在多通道渲染器中完成,它使用遮挡查询来调整其渲染队列和延迟渲染器。
    【解决方案2】:

    我相信glEnable(GL_DEPTH_TEST) 不会导致性能显着下降。

    我认为代价高昂的状态更改是着色器程序绑定、缓冲区绑定、纹理绑定和缓冲区偏移/步幅更改。因为这些需要验证以确保缓冲区足够大等。

    如果您认为这可能会影响性能,您可以在渲染之前订购要按材质(纹理、着色器、深度测试)渲染的元素,并且只执行一次状态更改。

    【讨论】:

    • 好的,那么你能解释一下为什么纹理绑定会成为问题吗?
    • 要么它导致一些昂贵的验证,它是一个有效的纹理吗?如果视频内存(或 iphone 拥有的主内存)之间存在缓存,则可能会导致将纹理数据提取到缓存中。我只能找到一个支持我认为昂贵但没有解释为什么它昂贵的论坛帖子。 gamedev.net/topic/416620-opengl-state-change-benchmark-data
    【解决方案3】:

    只有在您首先禁用某些 opengl 状态时才应该启用它。因此,如果您不需要此类更改,则没有理由在每一帧都调用 glEnable(GL_DEPTH_TEST)glBlendFunc

    【讨论】:

    • 忘记所举的例子,你能帮我解释一下原因吗......与你的回答相矛盾,它是为顶点/颜色数组设置客户端启用状态的一般做法 -当然不推荐。但我只想知道为什么它会导致性能问题。
    • @Ayyappa:实际上我完全同意eyesathousand,启用/禁用深度测试对性能影响不大。回答你的问题:opengl 是一个状态机。因此,一旦您设置了一个状态,它将一直保留到更改为止
    猜你喜欢
    • 2018-08-03
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    相关资源
    最近更新 更多