绑定FBO(帧缓冲区对象)的成本有多高

用户名

用glBindFramebuffer(GL_FRAMEBUFFER,...)绑定帧缓冲区对象有多昂贵?我在Google上找不到任何关于每帧更改帧缓冲区的实用次数的信息。我问是因为我正在编写一个2D渲染器,该渲染器支持C ++中的后期处理,并且在每次绘制调用(多边形,线条,图像)开始时显式绑定帧缓冲区是最优雅的代码路径,但到目前为止我还没有有足够的东西来进行基准测试。在每个绘制调用开始时绑定帧缓冲区的替代方法是一直保持绑定状态,除非我需要绘制到屏幕上,但这将要求我不要将调用交错到两个不同的渲染器实例(这是可行,但有限制)。

我已经找到了这个问题,但是它已经使用了4年了(引用的文本已经使用了5年以上),并且并不能完全回答相同的问题。每帧多次绑定和取消绑定FBO引起的性能下降是否足以保证手动管理绑定的帧缓冲区?

雷托·科拉迪(Reto Koradi)

由于通常具有性能特征,因此没有一个简单的答案。它在很大程度上取决于硬件体系结构,驱动程序优化和使用条件。

首先给您tl; dr:切换渲染表面可以在相当便宜和非常昂贵之间进行。我的建议如下:

  1. 尝试各种方法,并在您关注的所有平台上对它们进行基准测试。
  2. 如果您无法执行选项1,但您仍然想确信自己的代码在各种体系结构中都能正常运行,请按渲染目标对渲染进行分组,并避免不必要的切换。

我不愿给出有关每帧多少开关无害的数字。主要是因为我没有它们,而且我不喜欢猜测。而且因为它取决于许多因素。我从通常非常可靠的消息来源知道,在至少一个平台上,每帧仅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和驱动程序。仅将状态切换为将渲染指向其他目标是很便宜的。但是还有更多的东西。

通常,您有与活动渲染目标关联的其他内存分配。典型示例包括用于早期深度测试的缓冲区和压缩的颜色缓冲区。当您切换到其他渲染目标时,这些分配会发生什么情况取决于硬件体系结构,驱动程序的实现以及可能的其他条件:

  • 只要有足够的空间,就有可能使您循环遍历的所有渲染表面的这些分配保持活动状态,并在它们之间进行切换以及实际的渲染目标开关。在这种情况下,几乎没有开销。
  • 如果这些分配位于片上存储器中,则空间可能非常有限。如果没有足够的空间将它们全部保留在芯片上,则旧表面的分配可能被驱逐到视频内存(如果GPU有)或系统内存,然后重新加载新表面的分配。这可能会相当昂贵。
  • GPU /驱动程序可能不支持逐出并重新加载这些分配,并且可能必须将其内容解析到实际缓冲区中(例如,扩展压缩的颜色缓冲区的内容,并将其写回到完整的颜色缓冲区中)。这很贵。

平铺的架构使事情变得更加有趣,而平铺的架构在移动设备上得到了广泛的应用。平铺体系结构的主要卖点是它们每个像素只能运行片段着色器一次,并且每个平铺块只能写入一次帧缓冲区,这减少了写入帧缓冲区的总内存带宽,还大大提高了这些写入的局部性因为可以一次写入整个图块。

据我所知,用于存储将为每个图块渲染的三角形的图块存储器通常是片上存储器。因此,如果切换帧缓冲区,则必须:

  • 执行渲染每个图块并将结果写回到帧缓冲区的整个过程。
  • 将旧表面的图块内存保存到系统内存中,并为新表面加载以前保存的图块内存。

我不知道哪种方法最常用(如果这样做,我可能无法分享)。但是,两者听起来都非常昂贵,并且如果过于频繁地使用基于图块的体系结构,那么它们的全部目的就无法实现。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

是否有最大允许数量的帧缓冲区对象?

来自分类Dev

OpenGL帧缓冲区绑定目标

来自分类Dev

如何检查OpenGL中当前绑定了哪个帧缓冲区对象?

来自分类Dev

绑定帧缓冲区还是设置ReadBuffer?

来自分类Dev

FBO深度缓冲区为红色

来自分类Dev

将可见帧缓冲区读取到像素缓冲区对象

来自分类Dev

从OpenGL中的默认帧缓冲区读取像素数据:FBO与PBO的性能

来自分类Dev

如何将FBO的文本附件绘制到默认帧缓冲区?

来自分类Dev

将立方体贴图纹理附加到帧缓冲区对象(FBO)时为GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

来自分类Dev

如何从帧缓冲区对象读取像素

来自分类Dev

如何从帧缓冲区对象读取像素

来自分类Dev

LibGDX帧缓冲区

来自分类Dev

具有多个绘制缓冲区的帧缓冲区

来自分类Dev

glDeleteFramebuffers删除帧缓冲区对象,它是否删除附加到该帧缓冲区的纹理?

来自分类Dev

每次绑定具有不同分辨率的帧缓冲区时,都必须调用glViewport吗?

来自分类Dev

有关统一缓冲区对象的问题

来自分类Dev

JOGL中具有顶点缓冲区对象的问题

来自分类Dev

OpenGL FBO不增加深度缓冲区

来自分类Dev

什么是深帧缓冲区?

来自分类Dev

libGDX帧缓冲区Alpha问题

来自分类Dev

什么是“哑”帧缓冲区?

来自分类Dev

OpenGL帧缓冲区+ LibGDX

来自分类Dev

复制并粘贴到帧缓冲区

来自分类Dev

处理大于缓冲区大小的帧

来自分类Dev

什么是深帧缓冲区?

来自分类Dev

深度+模板帧缓冲区问题

来自分类Dev

什么是内核帧缓冲区?

来自分类Dev

libGDX帧缓冲区Alpha问题

来自分类Dev

什么是“哑”帧缓冲区?