为什么OpenGL> = 3只允许VBO?


21

我看到OpenGL版本3和更高版本取消了客户端渲染的使用。立即模式已被消除,并且顶点数组似乎已被弃用。相反,如果我理解正确,则VBO是渲染顶点的主要方法。

虽然我看到采用统一的方式呈现所有内容的逻辑,但VBO是否在顶点阵列方面没有重大缺点?我以为VBO通常应该是包含大于1MB数据的大缓冲区。如果我的场景具有许多较小的几何形状怎么办?我有一个场景图,其中包含大量节点,每个节点都需要自己的变换,等等。每个节点也应该能够分别删除,单独添加,等等。我以前使用的是顶点数组。因此,我的第一个问题是,如果我切换到VBO,现在是否需要为每个场景分配一个VBO,这会给我的场景图对象带来更大的开销。

另一个问题是我渲染的几何图形可能是高度动态的。在最坏的情况下,有时可能需要在一段时间内每帧重新发送所有几何图形。在这种用例中,VBO的性能是否会比顶点阵列差,或者最差的VBO的工作量与顶点阵列一样多,但没有更多?

因此,以更简洁的格式,我的问题是:

1)分配/取消分配VBO是否有相当大的开销(我的意思是仅仅建立一个缓冲区)?

2)如果我要每帧更新CPU的数据,这是否会比使用顶点数组的情况差很多?

最后,我想知道:

3)如果对以上两个问题的回答均为“是”,为什么不赞成使用其他渲染模式,而不是VBO?我在这里缺少什么,比如我应该用来减轻这些潜在分配成本等的技术吗?

4)根据我使用的OpenGL版本,这些问题的答案是否会发生实质性变化?如果我通过使用高性能的VBO将代码重构为OpenGL 3或4向前兼容,那么相同的技术可能会在OpenGL 2中很好地发挥作用,或者某些技术在OpenGL 3中可能会快得多+和其他使用OpenGL 2的软件?

我在堆栈溢出时问了这个问题,但是我在这里重新发布,因为我意识到这个站点可能更适合我的问题。


1
为什么要关闭投票?是dup吗?如果是这样,我可以看到一个链接以便从中受益吗?
2012年

Answers:


23

分配/取消VBO是否有相当大的开销(我的意思是仅仅建立一个缓冲区)?

定义“实质”。通常最好不要在框架的中间创建它们;它们应该在初始化期间或任何地方设置。但这对于大多数OpenGL对象都是如此,例如纹理,渲染缓冲区或着色器。

如果我要每帧更新来自CPU的数据,这是否会比使用顶点数组的情况差很多?

它可以?是。OpenGL定义功能而不是性能。您确实可以使事情变慢。或者,您可以使事情更快。这完全取决于您的使用方式。

OpenGL Wiki上有一篇很好的文章,介绍如何正确地传输数据

如果以上问题中的任何一个答案为“是”,为什么不赞成使用比VBO更具优势的其他渲染方式?我在这里缺少什么,比如我应该用来减轻这些潜在分配成本等的技术吗?

首先,它们不仅仅被弃用。弃用意味着在将来的版本中将某些内容标记为“要删除”。在3.0中已弃用,在3.1 core及更高版本中已将其删除

其次,ARB总体上解释了他们从OpenGL中删除内容的原因。它使规格更小,更简单。它使API变得更小,更精简。它使您更容易知道应该使用哪些API。2.1有4种方式提供顶点数据;3.1+具有1。它消除了很多麻烦。等等。

这些问题中的任何一个的答案是否会根据我使用的OpenGL版本而发生很大变化?如果我通过使用高性能的VBO将代码重构为OpenGL 3或4向前兼容,那么相同的技术可能会在OpenGL 2中很好地发挥作用,或者某些技术在OpenGL 3中可能会快得多+和其他使用OpenGL 2的软件?

或多或少没有。显然,只有在MacOSX上,3.1 + core和3.0之前版本之间的区别才真正出现。兼容性配置文件由Linux和Windows的所有驱动程序实现,因此您可以假定这些驱动程序的核心配置文件实际上只是添加检查以阻止您调用兼容性功能。

在Mac OSX 10.7下,可以使用GL 3.2核心,但不能使用兼容性配置文件。对于一个相对于另一个的性能技术,这并不一定意味着什么。但这确实意味着,如果存在差异,那么您将在平台上看到它们。


1
由于您只是交叉发布了这个问题,因此我将交叉发布我的答案。
Nicol Bolas 2012年

保持API简洁的另一个优点是,它使OpenGL API易于实现。这是原始OpenGL ES规范中的重要考虑因素。
notlesh 2012年

@stephelton:很有道理。我的“为什么不赞成使用除VBO之外的所有东西”的问题是基于这样的想法,即保持API精简是完全合理的,但在许多用例中,淘汰可能比VBO更好的功能是没有道理的。从我听到的信息来看,使用VBO似乎没有任何缺点,因此,不推荐使用其他任何东西都是很有意义的。
重力

@gravity你不具备使用VBO的。您也可以使用顶点数组。
notlesh 2012年

18

OpenGL的工作方式是,无论何时使用非VBO数据,驱动程序都必须复制它-实际上是创建一个临时VBO-因为在两次调用OpenGL之间没有任何修改您的用户空间裸数组的操作。

可能会有一些驱动程序方面的技巧来使临时分配更快,但是您无法采取任何措施避免复制。

所以,是的,只要您-和驱动程序开发人员-正确完成所有工作,VBO就应该始终加快速度。


6
我更喜欢这个答案。它更短,更精确。
TravisG 2012年

@JariKomppa:听起来像是一个非常合理的解释。我仍然有一个问题:VBO应该是相当大的对象,上次检查时通常分配为1MB-4MB缓冲区。如果我的几何对象没有那么大怎么办,但是由于我有很多对象,我仍然担心性能如何?我担心VBO可能只是用于与我现有的用例不同的用例。我应该将多个对象集中在一个VBO中,然后用于glDrawRangeElements绘制每个对象,还是像顶点数组那样效率低下?
重力

我怀疑这会有所不同,但是如果您感到担心,请对其进行基准测试。
Jari Komppa

@JariKomppa:您怀疑会有什么改变?glDrawRangeElements在每个VBO上多次使用几个VBO,而不是给每个对象自己的VBO?
重力

1
究竟。我怀疑您会在其中看到很大的不同,但是对一些测试用例进行概要分析应该可以为您提供更多信息。我现在也不用担心,因为这样的更改可以在以后需要时应用。
贾里·康帕

9

和顶点数组似乎已被弃用。相反,如果我理解正确,

不完全的。顶点数组是顶点缓冲区对象的基础。只有存储从客户端移动到服务器端。

如果我的场景具有很多较小的几何形状怎么办?

将较小的几何图形集合并到较大的VBO中。每个几何批次不需要一个VBO。您可以完美地解决要渲染的VBO子集的问题。对gl…Pointer数据参数使用nonzereo偏移量。

2)如果我要每帧更新CPU的数据,这是否会比使用顶点数组的情况差很多?

为此,有GL_DYNAMIC_DRAW和GL_STREAM_DRAW缓冲区使用标志。

如果以上问题中的任何一个答案为“是”,为什么不赞成使用可能比VBO更具优势的其他渲染方式?

因为没有优势。在任何情况下,几何数据都必须传输到GPU。使用常规的客户端顶点阵列仍将导致DMA传输到GPU,并且即时模式将构建一批要首先传输的批处理。

不使用VBO绝对没有好处。


因此,只有在我将模式正确设置为GL_STREAM_DRAW的情况下,使用VBO的性能通常不会比使用顶点数组差。
重力

@Gravity:的确如此。但是,缓冲模式仅是关于预期使用情况的提示,但是当然,该提示应该与您要执行的操作相同。同样不要忘记,您可以将缓冲区映射到进程地址空间中进行更新(glMapBuffer,glUnmapBuffer)。
datenwolf 2012年

但是缓冲区不能在VRAM中,对吗?还是会保留在VRAM中,但只能通过进程空间地址寻址?使用这种技术,随机访问会便宜吗?还是我还是应该尝试仅更新少量连续范围?
重力

@Gravity:缓冲区可以映射为只读,只读或读写。对于更新,您可以选择只写。现在,重要的是要了解现代OS如何通过页面内存来管理虚拟地址空间。在只写映射的情况下,您将映射一个DMA传输内存,并且对该映射范围的写入将或多或少地直接传输到GPU内存(内容首先写入CPU RAM,然后通过DMA传输到GPU传递)。与数据通过客户端顶点数组相比,这是更直接的路径很重要:常规进程内存不适合DMA
datenwolf 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.