我的.Net Winforms应用程序在我的主窗口中创建了三个OpenGL渲染上下文,然后允许用户弹出其他窗口,其中每个窗口有两个以上的渲染上下文(使用拆分器)。在第26个渲染环境中,事情开始变得非常缓慢。新渲染上下文不需要花费几毫秒来渲染帧,而是需要5到10秒。它仍然有效,只是真的很慢!并且OpenGL不会返回任何错误(glGetError)。
其他窗口工作正常。只是在一定数量减慢后的新渲染上下文。如果我关闭那些窗户,一切都很好 - 直到我重新打开足够的窗户才能通过限制。每个渲染上下文都有自己的线程,每个线程使用一个简单的着色器。当我上传纹理时,似乎会发生减速。但是纹理的大小对我可以创建的上下文数量没有影响,OpenGL窗口的大小也没有影响。
我正在运行nVidia显卡,并在不同的GPU上看到这种情况,具有不同的内存量和不同的驱动程序版本。这是怎么回事?应用程序可以创建多少渲染上下文是否有一些限制?
是否有其他人同时拥有大量渲染上下文的应用程序?
正如Nathan Kidd所说,限制是特定于实现的,您所能做的就是在常见硬件上运行一些测试。
我在今天的部门会议上感到无聊,所以我试图拼凑一些创建OpenGL上下文并尝试渲染的代码。我尝试使用和不使用纹理进行渲染,使用和不使用前向兼容的OpenGL上下文。
事实证明,GeForce卡的限制相当高(甚至没有限制)。对于桌面Quadro,有128个上下文的限制能够正确重绘,程序能够创建128个上下文而没有错误,但窗口包含垃圾。
它在ATi Radeon 6950上更加有趣,重绘在#105窗口停止,创建渲染上下文#200失败。
如果您想亲自尝试,可以在此处找到该程序: Max OpenGL上下文测试 (有完整的源代码+ win32二进制文件)。
这就是结果。一条建议 - 尽可能避免使用多个上下文。在多个监视器上运行的应用程序中可以理解多个上下文,但单个监视器上的应用程序应该使用单个上下文。上下文切换很慢。而且这还不是全部。 OpenGL窗口与其他窗口重叠的应用程序需要硬件剪辑区域。 GeForce上有一个硬件剪辑区域,Quadro上有八个或更多硬件剪辑区域(CAD应用程序通常使用与游戏窗口重叠的窗口和菜单,与游戏相比)。如果需要更多的区域,渲染会回归软件 - 所以再次 - 拥有大量的OpenGL窗口(上下文)并不是一个好主意。
最好的选择是这个问题没有真正的答案。它可能取决于驱动程序的一些内部限制,甚至操作系统的硬件。您可能想要检查的是使用的可用纹理单位数 glGet(GL_MAX_TEXTURE_UNITS)
但这可能是也可能不是指示性的。
避免这种情况的常见解决方案是在单个上下文中创建多个视口,而不是在单个窗口中创建多个上下文。将两个共享窗口的两个上下文联合到具有两个视口和某种UI小部件的单个上下文以作为拆分器应该不会太难。多个窗口是一个不同的故事,如果确实需要26个独立的OpenGL窗口,您可能需要考虑完全重新思考您的UI设计。
我现在很难想到一个真正的UI用例,它实际上需要26个不同的OpenGL窗口同时运行。也许另一个选择是创建一个说5-10个上下文的池,并仅在用户当前可见的窗口(标签?)中重用它们。我没有尝试过但是应该可以在普通窗口内创建一个不包含任何其他东西的上下文,然后将该窗口从父窗口移动到父窗口到需要它的任何顶级窗口。
编辑 -
嗯,实际上想起一个并不难。支持WebGL的最新Chrome(9.x.x)可能希望打开许多带有WebGL上下文的选项卡......我想知道他们是否以任何方式处理这个问题。只是尝试了它并且在13个选项卡之后内存不足...这对你来说实际上是一个很好的检查,看看你做错了什么或者chrome和firefox(4.0.x-beta)是否有相同的东西问题
鉴于OpenGL驱动程序的多样性,您最好的选择可能是检查主要驱动程序(AMD / Intel / NVIDIA / MS软件渲染)的行为,并在首次启动时运行测试。例如。如果你能看到NVIDIA总是像你看到的那样减速,那么只需运行一个快速循环,直到你看到该机器的限制在哪里(或者说卡片)。这并不是很有趣,但我认为很难可靠地推动限制。
换句话说,“最好的赌注”就像之前的回答一样,你事先无法知道。
如果你以过多的多线程方式设置OpenGL会遇到很多麻烦,你也可以从中受益并考虑切换到Vulkan。通过设计,OpenGL架构可以将所有难以获得的上下文/线程分离的绘图操作汇集到一个单独的驱动程序线程中,然后将所有这些调用重新分配到映射到每个上下文的虚拟硬件线程上。驱动程序本质上是一个巨大的瓶颈,因为它本身并没有螺纹,尽管任何glewmx坐着。它根本不是为处理这个问题而设计的。
也就是说,我很好奇你是否使用了旧版本的Glew,或者你是否以其他方式进行了所有的扩展处理,因为最新的glew libs不再支持mx。切换的另一个原因。