Performance OpenGL性能

Performance OpenGL性能,performance,opengl,Performance,Opengl,首先让我解释一下应用程序。这是一款视频安全软件,一次最多可以显示48个摄像头。每个视频流都有自己的Windows HDC,但它们都使用共享的OpenGL上下文。我使用OpenGL获得了相当好的性能,它在Windows/Linux/Mac上运行。在后台,上下文是使用wxWidgets 2.8 wxGLCanvas创建的,但我认为这与问题无关 现在问题来了。假设我拿着同样的相机,在我所有的48个窗口中显示它。这基本上意味着我只解码30fps(这是在另一个线程anywa上完成的),但显示高达1440f

首先让我解释一下应用程序。这是一款视频安全软件,一次最多可以显示48个摄像头。每个视频流都有自己的Windows HDC,但它们都使用共享的OpenGL上下文。我使用OpenGL获得了相当好的性能,它在Windows/Linux/Mac上运行。在后台,上下文是使用wxWidgets 2.8 wxGLCanvas创建的,但我认为这与问题无关

现在问题来了。假设我拿着同样的相机,在我所有的48个窗口中显示它。这基本上意味着我只解码30fps(这是在另一个线程anywa上完成的),但显示高达1440fps的速度,以使解码从图片中消失。我使用PBOs来传输图像,这取决于是否支持像素着色器和多文本,我可以使用它们在GPU上进行YUV->RGB转换。然后我使用一个四边形来定位纹理并调用SwapBuffers。所有OpenGL调用都来自UI线程。此外,我还尝试在CPU上进行YUV->RGB转换,并尝试使用GL_RGBA和GL_BGRA纹理,但所有格式的性能仍然大致相同。现在的问题是,在可能的1440fps中,我只得到了大约1000fps(我知道我不应该用fps来测量,但在这种情况下更容易)。上面的场景使用的是320x240(YUV420)视频,大约只有110MB/秒。如果我使用1280x720相机,那么我得到的帧速率大致相同,接近1.3GB/秒。这告诉我,这当然不是纹理上传速度。如果我在CPU上进行YUV->RGB转换和缩放,并使用Windows DC绘制,那么我可以轻松获得完整的1440fps

另一件需要提及的事情是,我在视频卡上以及通过OpenGL使用wglSwapIntervalEXT禁用了vsync。此外,没有报告OpenGL错误。然而,使用very sleepy评测应用程序时,它似乎将大部分时间都花在了SwapBuffers上。我假设这个问题与我在某处使用多个HDC或SwapBuffers有关,但是,我不知道我在做什么

我不是OpenGL方面的专家,所以如果有人有任何建议或任何事情,我都很想听听。如果我正在做的任何事情听起来是错误的,或者我可以以任何方式更有效地完成同样的事情,我很乐意听到

这里有一些到glIntercept日志的链接,以便更好地了解所有正在进行的OpenGL调用:

简单RGB:

着色器YUV:

分析信息: 所以在分析之后,它报告了几个冗余的状态变化,对此我并不感到惊讶。我排除了所有这些,并没有看到我所期望的明显的性能差异。每个渲染循环有34个状态更改,我使用了几个不推荐使用的函数。我将研究如何使用顶点数组来解决这些问题。但是,我只是在每个渲染循环中执行一个四元组,所以我并不期望这会对性能产生太大影响。还要记住,我不想把所有的东西都撕下来,全部使用VBO,因为我仍然需要支持一些相当旧的英特尔芯片组驱动程序,我相信这些驱动程序只是OpenGL 1.4

我真正感兴趣的事情是,每个上下文都有自己的前后缓冲区,这是我以前从未想到的。因为我只使用了一个上下文,所以前一个HDCs渲染调用必须在交换发生之前完成对后缓冲区的写入,然后下一个调用才能再次开始写入后缓冲区。使用多个上下文真的会更有效吗?或者我应该研究渲染到纹理(我认为是FBO)并继续使用一个上下文

编辑:最初的描述提到使用多个OpenGL上下文,但我错了,我只使用了一个OpenGL上下文和多个HDC。
EDIT2:在使用gDEBugger分析后添加了一些信息。

我试图让您的应用程序更快。我制作了一个OpenGL渲染线程(如果您有2个或更多视频卡,则可以制作更多)。视频卡不能一次处理多个上下文,您的多个OpenGL上下文正在等待一个上下文。此线程将仅使OpenGL工作,如YUV->RGB转换(使用FBO渲染到纹理)。Camere的线程将图像发送到此线程,UI线程可以拾取图像并显示在窗口中。 您需要在OpenGL上下文中处理查询,并且可以将多个帧组合到一个纹理中,以便一次转换它。它可能很有用,因为你有多达48个摄像头。作为另一个变体,如果OpenGL线程现在很忙,您可以在CPU上转换一些帧

从日志中,我看到您经常调用相同的方法:

glEnable(GL_TEXTURE_2D)
glMatrixMode(GL_TEXTURE)
glLoadIdentity()
glColor4f(1.000000,1.000000,1.000000,1.000000)
您可以在每个上下文中调用它一次,而不是在每个渲染中调用它

如果我纠正你使用3个纹理为每个平面的YUV

glTexSubImage2D(GL_TEXTURE_2D,0,0,0,352,240,GL_LUMINANCE,GL_UNSIGNED_BYTE,00000000)
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,176,120,GL_LUMINANCE,GL_UNSIGNED_BYTE,000000)
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,176,120,GL_LUMINANCE,GL_UNSIGNED_BYTE,00000000)

尝试使用一种纹理,并在着色器中使用计算来为像素获取正确的YUV值。这是可能的,我是在我的应用程序中实现的。

除非您的代码非常、非常、非常错误,否则任何软件探查器都会显示大部分时间花在交换函数或其他状态更改调用上。原因是驱动程序尽可能多地缓存,然后在进行不可缓存调用(交换和某些状态更改)时将其全部转储。你需要使用一个可以直接与驱动程序或硬件通信的图形分析器,否则你会一直看到这种情况。我对图形评测了解不多,但我听说过gDEBugger。还有其他建议吗?关于找什么还有其他的建议吗?我将试用gDEBugger,然后发布更多信息,谢谢。我看到的一个问题是上下文现在将同步交换。除非您使用其中一个交换分组扩展您还可以使用swap_interval扩展将除一个上下文外的所有上下文设置为非同步交换,并在主上下文中使用交换上的事件,同步交换上下文以触发所有其他上下文中的交换。DatenWalf,我非常喜欢这个想法,但我有点担心它可能不适用于应用程序。文件