用glBindFramebuffer(GL_FRAMEBUFFER,...)绑定帧缓冲区对象有多昂贵?我在Google上找不到任何关于每帧更改帧缓冲区的实用次数的信息。我问是因为我正在编写一个2D渲染器,该渲染器支持C ++中的后期处理,并且在每次绘制调用(多边形,线条,图像)开始时显式绑定帧缓冲区是最优雅的代码路径,但到目前为止我还没有有足够的东西来进行基准测试。在每个绘制调用开始时绑定帧缓冲区的替代方法是一直保持绑定状态,除非我需要绘制到屏幕上,但这将要求我不要将调用交错到两个不同的渲染器实例(这是可行,但有限制)。
我已经找到了这个问题,但是它已经使用了4年了(引用的文本已经使用了5年以上),并且并不能完全回答相同的问题。每帧多次绑定和取消绑定FBO引起的性能下降是否足以保证手动管理绑定的帧缓冲区?
由于通常具有性能特征,因此没有一个简单的答案。它在很大程度上取决于硬件体系结构,驱动程序优化和使用条件。
首先给您tl; dr:切换渲染表面可以在相当便宜和非常昂贵之间进行。我的建议如下:
我不愿给出有关每帧多少开关无害的数字。主要是因为我没有它们,而且我不喜欢猜测。而且因为它取决于许多因素。我从通常非常可靠的消息来源知道,在至少一个平台上,每帧仅2或3台交换机会对性能产生非常大的负面影响。除了这种非常糟糕的情况外,我的直觉还告诉我,我将尽量避免切换10-100次以上。但这实际上只是一个猜测,而且绝对有可能您可以摆脱更多限制,特别是如果您针对的是有限的一组硬件。
您的问题听起来好像涵盖了两种不同的情况。让我分别讨论:
从您的描述中,听起来您部分地具有这种使用模式:
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glDraw...(...);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glDraw...(...);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
在这种情况下,您可以进行glBindFramebuffer()
调用,但是所有渲染都将到达同一帧缓冲区。我希望大多数驱动程序都能检测到这些绑定调用是多余的,并且不会做任何认真的工作。即使有时在驾驶员是否应该检测到多余的状态变化方面存在哲学争议,但大多数情况下都是这样。
在这种情况下,取决于您对GPU /驱动程序供应商的信任程度。除非我进行了基准测试,否则在这种情况下我倾向于偏执。如果在我的软件体系结构中有任何合理的方法可以避免重复调用。
正如我在简介中所提到的,这里发生的事情高度依赖于GPU和驱动程序。仅将状态切换为将渲染指向其他目标是很便宜的。但是还有更多的东西。
通常,您有与活动渲染目标关联的其他内存分配。典型示例包括用于早期深度测试的缓冲区和压缩的颜色缓冲区。当您切换到其他渲染目标时,这些分配会发生什么情况取决于硬件体系结构,驱动程序的实现以及可能的其他条件:
平铺的架构使事情变得更加有趣,而平铺的架构在移动设备上得到了广泛的应用。平铺体系结构的主要卖点是它们每个像素只能运行片段着色器一次,并且每个平铺块只能写入一次帧缓冲区,这减少了写入帧缓冲区的总内存带宽,还大大提高了这些写入的局部性因为可以一次写入整个图块。
据我所知,用于存储将为每个图块渲染的三角形的图块存储器通常是片上存储器。因此,如果切换帧缓冲区,则必须:
我不知道哪种方法最常用(如果这样做,我可能无法分享)。但是,两者听起来都非常昂贵,并且如果过于频繁地使用基于图块的体系结构,那么它们的全部目的就无法实现。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句