Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 绑定FBO(帧缓冲区对象)的成本有多高_Opengl - Fatal编程技术网

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

Opengl 绑定FBO(帧缓冲区对象)的成本有多高,opengl,Opengl,绑定帧缓冲区对象的成本有多高,即使用glBindFramebuffer(GL_framebuffer,…)?我在谷歌上找不到任何关于每帧更改帧缓冲区的实际次数的信息。我之所以要求,是因为我编写了一个支持C++中的后处理的2D渲染器,并且在每个绘制调用开始时显式绑定帧缓冲区(多边形、线条、图像)是最优雅的代码路径,但到目前为止,我还没有足够的东西来画它。在每次绘制调用开始时绑定帧缓冲区的替代方法是始终保持绑定,除非我需要绘制到屏幕,但这需要我不交错调用两个不同的渲染器实例(这是可行的,但有限制)

绑定帧缓冲区对象的成本有多高,即使用glBindFramebuffer(GL_framebuffer,…)?我在谷歌上找不到任何关于每帧更改帧缓冲区的实际次数的信息。我之所以要求,是因为我编写了一个支持C++中的后处理的2D渲染器,并且在每个绘制调用开始时显式绑定帧缓冲区(多边形、线条、图像)是最优雅的代码路径,但到目前为止,我还没有足够的东西来画它。在每次绘制调用开始时绑定帧缓冲区的替代方法是始终保持绑定,除非我需要绘制到屏幕,但这需要我不交错调用两个不同的渲染器实例(这是可行的,但有限制)

我发现了,但它已经有四年多的历史了(引用的文本比它早了五年),而且它并没有完全回答相同的问题。每帧多次绑定和解除绑定FBO造成的性能损失是否足以保证手动管理绑定的帧缓冲区

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

不多。从本质上讲,OpenGL实现的工作量并不比双缓冲区交换后多多少

真正影响性能的是切换FBO的附件,因为每次发生这种情况时,都必须检查FBO的有效性,这是一项成本高昂的操作


有趣的是,在现有OpenGL实现中切换顶点数组对象(VAO)非常昂贵,到目前为止,业界的常见做法是重新绑定缓冲区对象和顶点属性指针/偏移。我只是提到这一点,因为从表面上看,FBO和VAO的外观和行为非常相似,但它们现在表现出非常不同的性能特征。

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

给你的tl;dr first:切换渲染曲面可能比较便宜,也可能非常昂贵。我的建议如下:

  • 尝试各种方法,并在您关心的所有平台上对它们进行基准测试
  • 如果您不能执行选项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/驱动程序可能不支持收回和重新加载这些分配,并且可能必须将其内容解析为实际缓冲区(例如,展开压缩颜色缓冲区的内容,并将其写回完整颜色缓冲区)。这个很贵
    平铺架构更有趣,它以各种风格广泛应用于移动设备上。平铺体系结构的关键卖点是,它们每像素只能运行一次片段着色器,并且每个平铺只能写入帧缓冲区一次,这降低了写入帧缓冲区的总体内存带宽,并且还大大提高了写入的局部性,因为一次写入整个平铺

    据我所知,用于存储将为每个平铺渲染的三角形的平铺内存通常是o