在交错的 openGL 顶点缓冲区对象之间复制

Posted

技术标签:

【中文标题】在交错的 openGL 顶点缓冲区对象之间复制【英文标题】:copying between interleaved openGL Vertex Buffer Objects 【发布时间】:2011-02-15 15:04:28 【问题描述】:

使用 opengl 3.3、radeon 3870HD、c++..

我有关于交错数据数组的问题。我在向量中获得了我的应用程序结构,它作为数据发送到缓冲区对象。像这样的:

struct data
  int a;
  int b;
  int c;
;

std::vector<data> datVec;
...
glBufferData(GL_ARRAY_BUFFER, sizeof(data)*datVec.size(), &datVec[0], GL_DYNAMIC_DRAW);

没关系,我经常使用这个东西。但我创建的是交错数组,所以数据如下:

a1,b1,c1,a2,b2,c2,a3,b3,c3

现在我将这个东西发送到 GPU 中进行处理,并通过转换反馈读回缓冲区,例如 b 变量。所以它看起来像:

bU1, bU2, bU3

我想将更新后的值复制到交错缓冲区中,这可以通过诸如 glCopyBufferSubData 之类的单个命令来完成吗?这个不合适,因为它只需要偏移量和大小而不是步幅(可能类似于 c++ 中的 memcpy)......结果应该如下所示:

a1, bU1, c1, a2, bU2, c2, a3, bU3, c3

如果没有,还有比这两个更好的方法吗?

    映射更新的缓冲区,将值复制到应用程序的临时存储中,取消映射更新,映射数据缓冲区并通过它迭代设置新值

    在常量缓冲区和变量缓冲区上分开缓冲区。常量会随着时间的推移保持不变,但使用 glCopyBufferSubData 变量可以在一次调用中更新..

谢谢

【问题讨论】:

我会将更新后的数据与您的 2 分开。 【参考方案1】:

glMapBuffer 似乎是您正在做的更好的解决方案。

据我所知,基本思想是将缓冲区映射到您的地址空间,然后使用您自己的更新方法手动更新缓冲区(可能是迭代循环)。

glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
void *buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

if (buffer == NULL)
  //Handle Error, usually means lack of virtual memory

for (int i = 1; i < bufferLen; i += stride /* 3, in this case */)
  buffer[i] = newValue;

glUnmapBuffer(GL_ARRAY_BUFFER);

【讨论】:

好吧,所以没有一步功能......顺便说一句,同时映射 2 个缓冲区怎么样?因为那只是写,但实际上正在进行读/写操作..在客户端内存中使用一些存储,或者是否可以完全在服务器端进行 据我所知,glMapBuffer 只允许将缓冲区映射到客户端内存,并且每个类型只能映射一个缓冲区。从外观上看,您可以映射多个不同类型的缓冲区。 实际上,您可以通过在对glMapBuffer 的调用之间绑定不同的缓冲区来映射多个缓冲区,并且在所有缓冲区都已映射/更新之前不调用glUnmapBuffer 是的,有 2 个缓冲区准备用于复制操作 GL_COPY_READ(WRITE)_BUFFER 我想.. 我只是好奇是否可以同时有 2 个映射缓冲区。但是您说的更多是“将缓冲区映射到客户端内存”.. 意思是整个缓冲区被复制到客户端内存中? (我以为返回的指针指向图形内存...) 我相信它只是将您的客户端虚拟地址空间映射到显卡内存,因此没有副本。【参考方案2】:

我会将动态部分与静态部分分开(您的第 2 点)。

如果您仍希望将它们交错保存到单个缓冲区中,并且您有一些空闲的视频内存,您​​可以执行以下操作:

    将原始交错阵列复制到备份阵列中。这需要所有组件的内存,而不仅仅是动态组件,就像原来一样。 将反馈转换为原始交错,保持静态值不变。

【讨论】:

好吧,我有足够的内存,但实际上我想尽可能多地使用,仅此而已......试图养成你知道的好习惯 :) 但现在有 2 个答案有 2 个不同建议.. 那么性能差异有多大?因为所有内容都有 2 个缓冲区而不是 1 个缓冲区,所以代码可能会变得混乱,如果没有很大的性能命中映射似乎是更好的解决方案。那么为什么要使用单独的缓冲区呢? 就这么简单 - 映射需要通过系统总线将数据传输到 RAM 并返回到 VRAM,更不用说复制所花费的 CPU 时间了。另一方面,TF 可以在不离开 VRAM 的情况下在 GPU 上完成你需要的一切,所以我敢打赌 :) 是的,正如我在其他评论中提到的那样,我认为映射是在 VRAM 中完成的,而不是整个东西都进入本地 RAM。现在它需要一些好的命名来跟踪什么是什么,但是谢谢。

以上是关于在交错的 openGL 顶点缓冲区对象之间复制的主要内容,如果未能解决你的问题,请参考以下文章

我的OpenGL学习进阶之旅介绍一下 映射缓冲区对象和复制缓冲区对象

带有附加数据的 OpenGL 索引缓冲区对象

为啥 OpenGL 缓冲区解除绑定顺序很重要? [复制]

C++ 和 OpenGL,VBO 顶点与骨骼信息交错

OpenGL 顶点数组/缓冲区对象

OpenGL 顶点缓冲区绑定点可以在不同的 VAO 之间重复使用吗?