OpenGL更适合批量绘制或具有静态VBO

时间:2011-09-24 04:24:42

标签: performance opengl draw vbo

从效率的角度(或其他观点,如果重要的话),什么是可取的?

场合
一个OpenGL应用程序,每帧(60 fps)在不同位置绘制许多行。可以说有10行。或100 000行。答案会有所不同吗?

  • #1 拥有一个永不改变的静态VBO,包含一行的2个顶点

每一帧每行都会有一个glDrawArrays调用,而在它们之间会有矩阵变换来定位我们的一行

  • #2 使用每帧所有行的数据更新VBO

每一帧都有一次平局调用

1 个答案:

答案 0 :(得分:28)

第二种效率非常高。

改变状态,特别是转换和矩阵,往往会导致重新计算其他状态,并且通常会产生更多的数学。

然而,更新几何图形只需要覆盖缓冲区。

在相当庞大的带宽总线上使用现代视频硬件,发送几个浮点数是微不足道的。它们旨在快速移动大量数据,这是工作的副作用。更新顶点缓冲区正是它们经常和快速执行的操作。如果我们假设每个点32个字节(float4位置和颜色),100000个线段小于6 MB,而PCIe 2.0 x16大约是8 GB / s,我相信。

在某些情况下,根据驱动程序或卡处理变换的方式,更改一个可能会导致某些矩阵乘法并重新计算其他值,包括变换,剔除和剪裁平面等。如果您更改了这个值,这不是问题。状态,画出几千个多边形,并重复,但是当状态经常发生变化时,它们将会产生很大的成本。

之前解决的一个很好的例子是批处理的概念,最小化状态变化,因此可以在它们之间绘制更多的几何。这用于更有效地绘制大量几何体。

作为一个非常明显的例子,考虑#1的最佳情况:变换集触发无额外计算,驱动程序热情且完美地缓冲。要绘制100000行,您需要:

  • 100000矩阵集(在系统RAM中)
  • 100000矩阵集调用函数调用开销(到视频驱动程序,将矩阵复制到缓冲区)
  • 将100000个矩阵复制到视频RAM中,一次性执行
  • 100000次线路调用

单独的函数调用开销将 kill 性能。

另一方面,批处理涉及:

  • 系统RAM中的100000点计算和设置
  • 1 vbo复制到视频RAM。这将是一个很大的块,但一个连续的块,双方都知道会发生什么。它可以很好地处理。
  • 1矩阵集呼叫
  • 1个矩阵复制到视频RAM
  • 1个绘制电话

您可以复制更多数据,但VBO内容很可能不像复制矩阵数据那样昂贵。另外,在函数调用中可以节省大量的CPU时间(200000到2)。这简化了您的生活,驱动程序(必须缓冲所有内容并检查冗余调用并优化和处理下载)以及可能的视频卡(可能必须重新计算)。为了使其清晰,可视化简单的代码:

1

for (i = 0; i < 100000; ++i)
{
    matrix = calcMatrix(i);
    setMatrix(matrix);
    drawLines(1, vbo);
}

(现在解开)

2:

matrix = calcMatrix();
setMatrix(matrix);
for (i = 0; i < 100000; ++i)
{
    localVBO[i] = point[i];
}
setVBO(localVBO);
drawLines(100000, vbo);