关于OpenGL内存管理的困惑

Nir*_*iel 5 opengl

我问这个问题是因为我不想花时间编写一些复制OpenGL驱动程序功能的代码.

OpenGL驱动程序/服务器可以容纳比视频卡更多的数据吗?说,我有足够的视频RAM来容纳10个纹理.我可以要求OpenGL分配15个纹理而不会出现GL_OUT_OF_MEMORY错误吗?

如果我可以依赖驱动程序在需要时巧妙地将纹理/缓冲区/对象从"普通"RAM发送到视频RAM,那么我自己并不需要生成/删除这些对象.我受限于"正常"RAM,与视频RAM相比,它通常很丰富.

Dam*_*mon 7

"内存丰富,所以我不需要删除"的方法很糟糕,而且"内存丰富,所以永远不会出现内存错误"的方法存在缺陷.

由于技术原因(参见上面的t.niese评论)和意识形态原因("你不需要知道,你不想知道"),OpenGL内存管理是模糊的.虽然存在供应商扩展(例如ATI_meminfo),但是可以让您查询一些非授权号码(非授权号码,因为它们可能会改变下一毫秒,并且它们不会考虑碎片化等影响).

通常,在大多数情况下,您假设可以使用比GPU内存更多的内存是正确的.

但是,您通常无法使用所有可用内存.更可能的是,由于对驱动程序可以分配,锁定和DMA到哪些内存区域(以及有多大区域)的限制,存在远低于"所有可用RAM"的限制.即使您通常可以使用比GPU上更多的内存(即使您专门使用它),但这并不意味着不小心的分配不会也不会最终失败.

通常,但不一定,您也会消耗与GPU内存一样多的系统内存(不知道,驱动程序会秘密地执行此操作).由于驱动程序根据需要交换资源,因此需要维护副本.有时,需要保留2或3个副本(例如,在流式传输或ARB_copy_buffer操作时).有时,映射缓冲区对象是特殊分配块中的另一个副本,有时您可以直接写入驱动程序的内存.另一方面,PCIe 2.0(以及PCIe 3.0甚至更多)足以从主内存流式传输顶点,因此您甚至不需要GPU内存(小缓冲区除外).一些驱动程序将直接从系统内存流式传输动态几何.

有些GPU甚至没有单独的系统和GPU内存(Intel Sandy Bridge或AMD Fusion).

此外,您应该注意删除对象不一定会删除它们(至少不会立即删除).通常,除了极少数例外,删除OpenGL对象只是暂时删除,这会阻止进一步引用该对象.只要需要,驱动程序将保持对象有效.

另一方面,你真的应该删除你不再需要的东西,你应该尽早删除.例如,您应该在将着色器附加到程序对象后立即删除它.这可以确保您不会泄漏资源,并确保它可以正常工作.在流式传输时删除并重新指定正在使用的顶点或像素缓冲区(通过调用glBufferData(... NULL);是一个众所周知的习语.这只会影响您对象的视图,并且它允许驱动程序继续并行使用旧对象因为它需要.


t.n*_*ese 3

我的评论中的一些附加信息不适合其中。

有多种原因导致它不属于 OpenGL。

对于系统/驱动程序来说,猜测需要哪些资源以及将需要哪些资源并不是一件容易的事。如果经常或很少需要资源,驱动程序肯定可以创建一个内部启发式(就像 CPU 对if 语句所做的那样,并根据该猜测预执行代码的某些代码部分)。但 GPU 将不知道(在不知道应用程序代码的情况下)接下来需要什么资源。它甚至不知道几何体在场景中的位置(因为您使用自己传递给着色器的模型和视图 martix 来执行此操作)

例如,如果您有一个可以在场景中行走的游戏,那么您通常不会渲染视图之外的部分。因此 GPU 可能会认为不再需要这些资源,但如果你转身,那么所有这些纹理和几何图形都将再次被需要,并且需要从系统内存移动到GPU 内存,这可能会导致性能非常糟糕。但由于八叉树(或类似技术)的使用以及可能行走的路径,游戏引擎本身对场景有深入的了解,知道哪些资源可以从 GPU 中删除,哪些资源可以移动到播放时的 GPU 以及需要显示加载屏幕的位置。

如果您观察 OpenGL 的演变以及哪些功能已被弃用,您会发现它们正朝着删除所有内容的方向发展,除了真正需要的功能(这些功能可以由显卡、驱动程序和系统完成)之外。其他一切都取决于用户自己实施以获得最佳性能。(例如,您自己创建投影矩阵以将其传递给着色器,因此 OpenGl 甚至不知道对象放置在场景中的位置)。