我一直在研究使用OpenGL编写应用程序来在屏幕上呈现数据,并且有一件事情不断出现 - 将数据复制到GPU中的速度很慢。
我目前正在阅读OpenGL SuperBible第7版和在线阅读各种教程之间切换,当数据实际发送到GPU时我没有遇到过,我只是猜测。
glBufferStorage
/ glCreateVertexArrays
时,是否在GPU的内存中分配了空格?或者这个空间是在我的应用程序的内存中分配的,然后在以后复制?glMapBuffer*
返回指向GPU内存的指针,还是指向我的应用程序内存中分配的空间的指针,然后在以后复制?glCrawArrays
?答案 0 :(得分:8)
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在此时完成。它只需要在GPU实际执行绘图命令之前发生这些DMA。实现可以通过阻塞glDraw*
调用直到DMA完成来实现。但它也可以使用内部GPU同步机制将绘图命令issued与DMA操作的完成联系起来。
唯一能保证上传实际完成的是调用一个能让GPU访问缓冲区的函数,然后将CPU与该命令同步。仅在上传后同步并不保证任何事情。上传本身不是可观察的行为,因此同步可能没有效果。
然后,它可能会。这就是重点;你不能知道。