2013-05-31 100 views
5

我在问这个问题,因为我不想花时间编写一些代码来重复OpenGL驱动程序的功能。关于OpenGL内存管理的困惑

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

如果我可以依靠驾驶员在需要的时候那么我并不真的需要根/删除这些对象自己巧妙地从“正常” RAM发送纹理/缓冲器/对象的视频RAM。与视频RAM相比,我受到'普通'RAM的限制。

+3

由于内存管理取决于系统(可能因系统而异),并且多个应用程序可能同时使用OpenGL,所以甚至无法确定是否可以使用显卡所具有的所有内存。所以你不会绕过去拥有自己的_resource management_。这可能来自您的interrest:[确定可用的视频内存](http://stackoverflow.com/questions/4552372/determining-available-video-memory) –

+1

是的,司机应该这样做。然而,一旦它开始交换纹理,它可能会非常缓慢。 – jcoder

回答

3

一些额外的信息给我的评论,不适合在那里。

为什么这不是OpenGL的一部分有不同的原因。

它不是系统/驱动器猜测哪些资源,将需要一个简单的任务。如果资源经常需要或很少需要(例如CPU对如果语句并且在该猜测中预先执行代码某些代码部分),则驱动程序肯定可以创建内部启发式。但是GPU不知道(不知道应用程序代码)接下来需要什么资源。它甚至并不知道其中的几何形状是场景的地方(因为你这样做你的模型和视图martix传递给你的shader自己)

如果你如有一个游戏可以在场景中漫步,但通常不会渲染视图外的部分。所以GPU可能会觉得,这些资源不是必需的了,但如果你转身,然后这一切的纹理和几何再次需要,需要从系统内存搬到GPU内存,这可能会导致非常糟糕的表现。但是由于使用了八叉树(或类似的技术)和可以走的路径,游戏引擎本身具有对场景的深入了解以及哪些资源可以从GPU中移除,哪些资源可以移动到GPU在播放时以及需要显示加载屏幕的位置。

如果你看看OpenGL的发展和哪些功能会被弃用,你会发现他们会去除所有的东西,除了图形卡,驱动程序和系统可以做得最好的功能外。其他一切都由用户自行实施以获得最佳性能。 (例如,您自己创建投影矩阵将其传递给着色器,因此OpenGl甚至不知道该对象放置在场景中的哪个位置)。

+0

这很有道理。我从来没有碰3.3之前的OpenGL,所以我不知道它曾经是多么臃肿。然后我会创建自己的缓存机制,因为我知道什么时候需要什么,我很高兴我不需要考虑OpenGL在我背后做什么。 – Niriel

+0

@Niriel它是一条细线,一方面知道幕后做了什么有助于理解可能导致瓶颈的东西(例如,如果绘制多重实例时使用纹理查找或属性除数更好只需一次调用,或者如果重组问题可以在GPU上实现更多的并行化),另一方面可能会为系统实现或某些供应商的GPU优化带来风险,而不是重新考虑问题。 –

7

的办法“内存充沛,所以我并不需要删除”是坏的,而办法“记忆是丰富,所以我永远不会得到内存不足的错误”是有缺陷的。

由于技术原因(见上面的t.niese的评论)和出于意识形态的原因(“你不需要知道,你不想知道”),OpenGL内存管理是不明确的。尽管存在供应商扩展(例如ATI_meminfo),可以让您查询一些非认证号码(非认证,因为它们可以改变下一个毫秒,并且不会像分段考虑那样产生影响)。

一般来说,在大多数情况下,你的假设,你可以使用更多的内存比有GPU的内存是正确的。

但是,您通常不能使用所有可用的内存。更有可能的是,由于对驱动程序可以分配,锁定和DMA的内存区域(以及大小区域)的限制,“所有可用内存”之下存在一个限制。即使您可以正常使用比适合GPU的更多的内存(即使您专门使用它),但这并不意味着不小心的分配最终不会失败,并且也不会最终导致失败。

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

有些GPU甚至没有单独的系统和GPU内存(英特尔Sandy Bridge或AMD Fusion)。

另外,您应该注意删除对象并不一定会删除它们(至少不会立即)。通常,除极少数情况外,删除OpenGL对象仅仅是一个暂时的删除操作,它可以防止您进一步引用该对象。只要需要,驱动程序将保持对象有效。

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

+0

** + 1 **为好的技术信息 –

+0

感谢您的详细信息,它现在有意义。我的第一个想法是使用所有可用内存,并等待内存不足错误发出信号表明我应该删除/交换事物(请求原谅而不是许可)。但gl_out_of_memory不可恢复,所以我留下猜测/希望我不会溢出它。我猜想,分析是要走到这里的方法,我选择一个内存预算并尽量留在里面。 我还没有玩过顶点动画,所以我不太了解流媒体,不理解glBufferData(.. null ..)。你介意解释一下吗? – Niriel

3

这里是我的TL; DR的答案,我建议你阅读守护程序和t.niese的答案,以及:

OpenGL驱动程序/服务器可持有多显卡更多的数据

说,我有足够的视频RAM来保存10个纹理。我可以让OpenGL分配15个纹理而不会收到GL_OUT_OF_MEMORY错误吗?

是的。根据驱动程序/ GPU组合的不同,甚至可以分配超出GPU内存的单个纹理,并将其实际用于渲染。在我目前的职业中,我利用这一事实从大体积数据集中提取任意方向和几何图形的切片,使用着色器在原位对体素数据应用滤镜。工作正常,但不适用于交互式帧速率。