OpenGL中“缓冲区”和“数组”之间的区别?


12

当我在webGL或OpenGL上阅读文档时,可以看到一些有关如何使用函数和对象名称的模式。但是我不明白缓冲区对象和数组之间的区别。

有“顶点缓冲区对象”,“顶点数组对象”,甚至某种“缓冲区数组”或“ arraybuffer”。

在OpenGL上下文中,什么时候是“数组”,什么时候应该叫做“缓冲区”?


从某些角度来看,可以考虑通过网络获取数据并存储所有接收到的日志。您需要读取套接字并将接收到的数据放在某个地方,以便可以将其传递给缓冲区。它通常可以是本地范围内的,动态分配的简单列表类型。有时它就像char* buffer = socketRead();(伪代码)一样简单。另一方面,日志贯穿整个应用程序生命周期。因此,您可以在任何地方创建一个数组并开始读取套接字,每当获取数据时,便将该块写入数组,从而为您收到的所有数据提供一个整齐的列表。
凯文

Answers:


5

顶点数组对象的命名有些不幸。在您的应用程序中/周围/周围出现(曾经出现过)三种不同的事物,并且它们的名称(从历史上来看)是不同的,名称中带有“ array”或“ buffer”(当然,还有framebuffer对象,但我会忽略这一点)。

  1. 形式上和事实上都存在于您的应用程序中的数据,但是这些数据是由OpenGL一次性提取的(与逐个顶点相反)。曾几何时,您称之为顶点数组
    这样做的目的是提高访问效率,因为当您保证数据一致时,OpenGL可以在定义好的时间一次性复制整个内容,并将其推送到AGP或任何一个块中。这不再存在。
  2. 可以被“绑定”(即变为活动)的句柄遮盖并访问的数据。数据实际上可能存在于主内存中或在图形卡上,或者被移动到了PCIe映射的区域,无论如何,但是您正式拥有的方式都不是(即使它物理上位于RAM中,并且数据是来自应用程序的) )-除非您当前已经通过相应的API“映射”了它,否则返回了一个可写(有时可读)的指针。您还完全无法控制数据发生什么的能力(您可以提供一些提示,但仅此而已)。
    OpenGL可能会或多或少地自由移动这些数据,并且仅允许/能够通过相应的API从缓冲区复制数据/从缓冲区复制数据,或者在映射数据时访问数据。这就是您所说的缓冲区对象(如果顶点缓冲区对象包含顶点,但实际上不是必须的,也可以是图像数据或制服,有时是第一个被支持的顶点)。
    这样做的目的是确保OpenGL可以(原则上)执行所需的操作,甚至可以在绘制之前在PCIe上以推测方式推送缓冲区。之所以可行,是因为您不拥有数据(OpenGL拥有!),并且只能通过给定的API访问它,因此始终知道数据是有效的。当驱动程序需要其他存储空间时,驱动程序甚至可以选择放弃图形卡上的缓冲内存,然后在需要时从其机密副本中恢复。
  3. 一个真正愚蠢的误称,其更好的名字应该是诸如buffer-set或descriptor-set之类的东西,这是臭名昭著的顶点数组对象。从您的角度来看,它只不过是在另一个晦涩的句柄(您可以绑定)下捆绑在一起的一组缓冲区句柄。碰巧的是,现实有点复杂。实际上,VAO更接近实际硬件的工作方式。图形卡具有少量(通常是2、4或8个)描述符集(不仅用于缓冲区,而且还用于采样器),每个描述符集都有很多条目,它们之间可以非常高效地切换。
    现在,顶点数组对象的目的是减少API调用的次数,并减少OpenGL必须在内部进行的一致性检查的次数,当然也要减少使用硬件的工作量。如果绑定5个缓冲区,则每个缓冲区都必须经过一些可能昂贵的检查,并且每个缓冲区都是驱动程序中高速缓存未命中的候选对象,此外,每个缓冲区都需要与图形卡进行通信以更改描述符,等等。绑定一个VAO,驱动程序可以(通常)简单地切换图形卡上设置的描述符,然后完成操作。

8

顶点数组对象(VAO)是包含一个或多个顶点缓冲区对象的对象,旨在存储完整渲染对象的信息。

(从khronos中拉出)

每个缓冲区倾向于构成一个顶点数组(对象)的一个属性。VAO可以包含许多顶点属性(例如,位置,颜色,UV)。每个缓冲区可能都保存在自己的缓冲区中,其中buffer表示一系列无格式的连续字节,并且需要为CPU端OpenGL调用和GPU端着色器工作显式指定每个缓冲区元素的大小(类型)。

那是一种方式。其他可行的方法是:

  • 所有属性都交错存储在单个缓冲区中,或者
  • 一些属性存在于它们自己的专用缓冲区中,而其他属性则共享缓冲区。

下图说明了后两种情况。

在此处输入图片说明

底线:如果在OpenGL中使用“顶点数组”一词时没有限定,则可以假设它表示VAO,这在OpenGL上下文中(具体而言)与缓冲区确实是非常不同的东西。

编辑您的评论:GL_ARRAY_BUFFER如上所述,表示打算将该缓冲区对象用于顶点属性数据。这是因为缓冲区不仅仅用于顶点属性。但是,由于这是最常见的用例,而您正在询问VAO,因此我将不再赘述。但是,这里列出了可以设置的其他类型的缓冲区。


因此缓冲区是:1.驻留在GPU中,2.大多数时候包含一种数据(仅顶点,仅颜色ect),3.数据被交织,即111122223333 ect。4.不提供访问数据的方法(不是buffer [2]或buffer [vertex_3434])现在,数组是:1.缓冲区的收集,2.存储有关如何解析其包含的缓冲区的信息。(即数组存储步幅) ,元素的大小,偏移量,以便可以正确访问缓冲区中的数据,对吗
coobit

1. 两端都有缓冲区,缓冲区在CPU和GPU之间传输(可能来回传输),否则当从磁盘加载网格时如何填充要上传到GPU的数据?是的,元素在整个缓冲区中具有统一的类型,但是根据您所使用的技术,每个缓冲区元素可以是原始struct类型或类型。每个缓冲区的数据可以交错或完全统一。您可以对其进行索引,就像在CPU上使用传统的C数组一样。数组对象(使用此正确术语或使自己迷惑!)...(下续)
工程师

2.是的,你需要明确地确保您在着色器缓冲声明将匹配您在VAO CPU侧设置的规范:“与由顶点处理器所使用的数据定义的所有状态封装在一个顶点数组对象。” (khronos文档)
工程师

因此,只是打了更多的钉子……在AO仅使用BO之前,人们是如何工作的?还是AO总是存在于OpenGL中,而VAO只是后来在VBO中引入的?
coobit

@coobit io7m.com/documents/history-vertex-spec-这使您了解固定管道(旧式)OpenGL,3Dfx等与现代的可编程管道OpenGL和Direct3D之间的区别。
工程师

5

该术语植根于OpenGL的历史。需要记住的重要一点是,对于此处相关的大多数GL版本,OpenGL都是逐步进行的,并且是通过向现有API中添加新功能而不是更改API来实现的。

OpenGL的第一个版本没有这些对象类型。绘制是通过发出多个glBegin / glEnd调用来实现的,该模型的一个问题是就函数调用开销而言,它的效率很低。

OpenGL 1.1采取了第一步,通过引入顶点数组来解决此问题。现在,您可以直接从C / C ++数组中获取其数据,而不是直接指定顶点数据-从而命名。因此,顶点数组就是这样-顶点数组和指定它们所需的GL状态。

GL 1.5的下一个重大改进是将顶点阵列数据存储在GPU内存中,而不是系统(“客户端”)内存中。GL 1.1顶点数组规范的一个弱点是,每次您要使用它时,都必须将整套顶点数据传输到GPU。如果已经在GPU上,则可以避免这种转移,并获得潜在的性能提升。

因此,创建了一种新型的GL对象,以允许将这些数据存储在GPU上。就像纹理对象用于存储纹理数据一样,顶点缓冲区对象也存储顶点数据。实际上,这只是更普通的缓冲区对象类型的一种特殊情况,它可以存储非特定数据。

使用顶点缓冲对象的API背负在已经存在的顶点数组API上,这就是为什么您会看到诸如将字节偏移量转换为指针之类的怪异事物的原因。因此,现在我们有了一个只存储状态的顶点数组API,数据是从缓冲区对象而不是内存中数组中获取的。

这使我们几乎走到了故事的尽头。指定顶点数组状态时,所得的API相当冗长,因此,另一种优化途径是创建一个新的对象类型,将所有这些状态收集在一起,在单个API调用中允许多个顶点数组状态更改,并允许GPU由于能够提前知道将要使用的状态,因此有可能执行优化。

输入顶点数组对象,该对象将所有这些元素收集在一起。

因此,总而言之,顶点数组的开始是作为状态和数据(存储在数组中)的集合,以便进行绘制。甲顶点缓冲器替换为GL对象类型的内存阵列存储,离开顶点数组只是被状态。甲顶点数组对象仅仅是该状态下的容器对象,允许其更容易地改变,并且以更少的API调用。


0

我已经有一段时间没有使用OpenGL了,所以我可能只说对了一半。一般而言:缓冲区存储未格式化的内存数组。数组是连续内存的总称。

缓冲区需要绑定到上下文,而数组只是数据数组。如果我没记错的话,缓冲区中的数据将被复制到图形卡上(因此进行绑定)。

希望这个对你有帮助


那么GL_ARRAY_BUFFER是什么?为什么这样称呼它?根据您的假设,它是“未格式化的连续内存” :)
coobit

好吧,这个特定的示例只是缓冲区的ID(您将数组绑定到该ID)。数组缓冲区(在您的示例中)用于顶点属性,因此基本上您可以将顶点属性数组绑定到缓冲区。听起来令人困惑,所以让我举一个例子。您在cpu端上有一些数组,可以是颜色,常规,位置等,现在您希望gpu访问它。就是说,当bindBuffer进入时,基本上将您的“ cpu-array”映射到“ gpu-array”。
Juicef '18年

至于为什么这么称呼,我无法回答。我猜想那是因为您在那里输入了一系列不同的数据,颜色,正常值等
。– Juicef
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.