何时使用 openGL 将数据发送到 GPU

Posted

技术标签:

【中文标题】何时使用 openGL 将数据发送到 GPU【英文标题】:When is data sent to the GPU with openGL 【发布时间】:2016-10-04 04:23:14 【问题描述】:

我一直在研究使用 OpenGL 编写应用程序以在屏幕上呈现数据,并且不断出现一件事 - 将数据复制到 GPU 中很慢。

我目前正在阅读OpenGL SuperBible 7th Edition和在线阅读各种教程之间切换,并且我还没有遇到数据实际发送到GPU的情况,我只是猜测。

    当我调用glBufferStorage/glCreateVertexArrays 时,GPU 内存中是否分配了空间?或者这个空间是在我的应用程序的内存中分配的,然后在以后复制过来? 从glMapBuffer* 返回的指针是指向 GPU 内存的指针,还是指向在我的应用程序内存中分配的空间的指针,然后稍后复制? 假设数据存储在我的应用程序内存中并复制到 GPU,那么实际何时复制数据?当我打电话给glCrawArrays?

【问题讨论】:

【参考方案1】:

1:glCreateVertexArrays 与缓冲区对象或 GPU 内存(那种)没有任何关系,所以它有点无关紧要。

至于其余部分,OpenGL 何时决定分配实际 GPU 内存取决于 OpenGL 实现。它可以根据需要推迟实际分配。

如果您询问数据何时上传到 OpenGL,OpenGL will always be finished with any pointer you pass it when that function call returns。因此,该实现要么将数据复制到调用本身内的 GPU 可访问内存,要么分配一些 CPU 内存并将您的数据复制到其中,安排传输到实际的 GPU 存储以供以后使用。

出于实用性的考虑,您应该假设复制到缓冲区不会立即发生。这是因为 DMA 通常需要一定的内存对齐,而您传递的指针可能没有对齐。

但通常情况下,您不应该在意。让实现完成它的工作。

2:和上面一样,当你映射内存时,实现可以做任何它想做的事情。它可能会为您提供指向 GPU 可访问内存的真正指针。或者它可能只是分配一块 CPU 内存并在您取消映射内存时将其 DMA。

唯一的例外是persistent mapping。该功能要求 OpenGL 为您提供一个指向缓冲区所在的实际 GPU 可访问内存的实际指针。这是因为当您完成写入/读取时,您从未真正告诉实现记忆。

这也是(部分)为什么 OpenGL 要求您分配不可变的缓冲区存储以便能够使用持久映射。

3:只要实现认为需要,就会复制它。

OpenGL 实现是一个黑盒子。他们的所作所为或多或少取决于他们。规范提出的唯一要求是their behavior act "as if" it were doing things the way the specification says。因此,只要实现感觉想要复制数据,就可以复制数据,只要一切仍然“好像”它立即复制了它一样工作。

进行绘图调用并不要求该绘图命令所依赖的任何缓冲区 DMA 在当时已完成。它只要求这些 DMA 将在 GPU 实际执行该绘图命令之前发生。该实现可以通过阻塞glDraw* 调用来做到这一点,直到DMA 完成。但它也可以使用内部 GPU 同步机制将绘图命令 issued 与 DMA 操作的完成联系起来。

唯一能保证上传已实际完成的方法是调用一个函数,该函数将导致 GPU 访问缓冲区,然后将 CPU 与该命令同步。仅在上传后进行同步并不能保证任何事情。上传本身是不可观察的行为,因此在那里同步可能没有效果。

再一次,它可能会。这才是重点;你无法知道

【讨论】:

以上是关于何时使用 openGL 将数据发送到 GPU的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 优化 - 重复顶点流或重复调用 glDrawElements?

将 Uniform 数据正确发送到 GPU

将大图像时间发送到 GPU

OpenGL 顶点缓冲

初识OpenGL VBO顶点缓冲对象

WebGL - 发送数组缓冲区 VS 将图像/画布/位图从 CPU 发送到 GPU