Qt 4/5与opengl API在opengl速度上的差异

Difference in opengl speed between Qt 4/5 and Opengl API

本文关键字:opengl 速度 API Qt      更新时间:2023-10-16

我已经阅读了SO上关于qt 4和5 opengl的所有问题。这是最接近OpenGL与Qt 5中的QOpenGL/QtOpenGL:差异和限制,我不知道为什么它被关闭了,因为这是一个很好的问题。我认为它唯一缺少的是速度差。

我也读过这个https://qt-project.org/forums/viewthread/22921它有一个类似的问题,但作为来回关于4对5,主要讨论新的功能。

我的问题是,使用QT5的内置方法是否比直接使用opengl API制作自定义小部件更快?如果我担心性能,使用QT是一个糟糕的选择吗

编辑:

更具体地说,我需要使用physx、tcp/ip通信以及大量快速更新顶点和网格。我们的目标是尽可能实时地完成这项工作。渲染之类的事情不是一个问题,但qt的任何一点开销都是有害的。(所有东西都是用C++制作的3D)

我已经阅读了SO上关于qt 4和5 opengl的所有问题。这是最接近OpenGL与Qt 5中的QOpenGL/QtOpenGL:差异和限制,我不知道为什么它被关闭了,因为这是一个很好的问题。我认为它唯一缺少的是速度差。

更具体地说,我需要使用physx、tcp/ip通信以及大量快速更新顶点和网格。我们的目标是尽可能实时地完成这项工作。渲染之类的事情不是一个问题,但qt的任何一点开销都是有害的。(所有东西都是用C++制作的3D)

您的问题中有多个问题。

"原始"OpenGL与"Qt"OpenGL

这个问题是不合理的,因为没有所谓的"Qt OpenGL"。OpenGL是Khronos拥有和发布的标准。Qt只是使用它。

Qt可以帮助您的应用程序管理一些事情。

窗口/上下文创建

您曾经尝试过在Win32下创建OpenGL上下文吗?它需要一堆样板代码(请参阅此处或此处),其中包括创建一个临时上下文来检查WGL功能,然后最终创建实际上下文。。。

您曾经尝试过在X11下创建OpenGL上下文吗?它需要一堆样板代码(请参阅此处),其中包括检查GLX_ARB_create_context的存在,然后使用它来创建上下文,或者返回到GLX 1.3代码路径,然后。。。

你曾经尝试过在Mac OS X下创建OpenGL上下文吗?

你有没有尝试过在Android下创建OpenGL上下文?

你曾经尝试过在QNX下创建OpenGL上下文吗?

您曾经尝试过在DirectFB/EGLFS下创建OpenGL上下文吗?

哦,等等。来了Qt:

class Window : public QWindow {
QOpenGLContext *context;
public:
Window() {
QSurfaceFormat format;
format.setVersion(3,3);
format.setProfile(QSurfaceFormat::CoreProfile);
setSurfaceType(OpenGLSurface);
setFormat(format);
create();
context = new QOpenGLContext;
context->setFormat(format);
context->create();
}
...

是的,仅此而已。这将创建一个(顶层)OpenGL窗口和一个3.3 Core Profile上下文。将其与QTimer相结合,就可以得到一个可行的渲染器。当然,将在上述所有平台上工作:Win32、Mac、X11、Linux/EGLFS、QNX、iOS、Android


所有这些都需要你支付管理费用吗?是的,当然。但这绝对可以忽略不计;并且只需支付一次,即在创建窗口和上下文时。

真正沉重的东西来自OpenGL绘图本身,它完全在您的控制之下:您使窗口上的上下文成为当前上下文,并开始发出原始OpenGL命令。Qt不在那里。Qt和OpenGL再次相遇的唯一时刻将是交换缓冲区时间;但这是一项几乎没有成本的手术。

因此:Qt不会增加任何可测量的开销

窗口管理

当然,与上述内容捆绑在一起的事实是,您可以在任何平台上使用相同的代码来处理键盘和鼠标输入。或者调整窗口大小。或者将其设为全屏。或者关闭它。

OpenGL辅助对象

Qt不仅提供了一种创建OpenGL表面和上下文的方法(以及相关操作:设置为当前、交换缓冲区等)

  • QMatrix4是一个…4x4矩阵。它具有OpenGL程序中所需的所有漂亮功能:lookAt()ortho()perspective()normalMatrix()等等
  • QOpenGLContext::hasExtensionQOpenGLContext::getProcAddress是解决OpenGL入口点的独立于平台的方法
  • QOpenGLContext::versionFunctions返回一个对象,该对象包含已解析的给定版本/配置文件的所有OpenGL入口点
  • QOpenGLBuffer包装缓冲区对象
  • QOpenGLVertexArrayObject包装一个顶点数组对象(并有一个RAII助手来绑定和取消绑定VAO)
  • QOpenGLTexture包装纹理对象
  • QOpenGLFrameBufferObject包装帧缓冲区对象
  • QOpenGLShaderQOpenGLShaderProgram包装着色器和着色器程序,为将QMatrix4x4设置为统一变量提供方便的方法。因此,您可以使用上述方法在CPU上计算给定网格的MVP,然后将其设置为均匀
  • QOpenGLDebugLogger封装GL_KHR_debug以调试OpenGL应用程序
  • 还有一堆我现在不记得了

有开销吗?是的,但它也是最小的,并且它不涉及如何在OpenGL代码中使用这些对象。如果你的OpenGL代码快速且结构良好,你会发现这些助手对管理它很有用,而且它们不会让它运行得更慢。

("有助于管理它"的示例:QOpenGLVertexArrayObject将允许您在OpenGL 3.0上使用VAO,或在任何存在GL_ARB_vertex_array_object扩展的Desktop OpenGL版本上使用VA奥,或在存在GL_OES_vertex_array_object的OpenGL ES2上使用VA0。您不需要根据运行时来解析正确的函数集。Qt将为您做到这一点,并为创建、绑定、发布和销毁VAO提供相同的API)

一切都好吗?不,我必须在这里说实话,有些零碎的东西会从爱中受益。

例如,QOpenGLFrameBufferObject有一个有限的API,不支持任何数量的颜色附件。QOpenGLBuffer将需要一些工作来支持更多的缓冲区类型/绑定目标。仍然没有对程序管道的支持。仍然不支持统一缓冲区。

另一方面,您有QOpenGLTexture之类的东西,它支持最近的功能,如不可变存储和纹理视图。

这是否意味着你不能使用这些功能?你当然可以。如果您需要Qt现在没有提供的功能,请返回原始OpenGL代码。或者,考虑将这些功能贡献给Qt!

Qt

当然,一旦你走上Qt的道路,你就有了Qt。这意味着,仅在QtCore和QtGui库中:

  • 事件循环
  • 定时器
  • 信号和插槽
  • 螺纹
  • Unicode字符串+i18n
  • 集装箱
  • 正则表达式
  • 文件处理
  • 插件加载
  • 设置
  • 模拟类型
  • 输入处理
  • 图像I/O
  • 使用光栅引擎的二维命令式绘画
  • JSON
  • XML
  • 还有一堆我现在不记得了

当然,以上都是跨平台的。

顺便说一下,Qt还有:

  • 用于跨平台2d小部件的QtWidgets
  • 用于数据库访问的QtSql
  • 用于TCP/UDP/SSL套接字以及高级HTTP/FTP引擎的Qt网络
  • Qt单元测试
  • 用于嵌入webkit的QtWebkit
  • 还有一堆我现在不记得了

OpenGL在Qt 4与5中的对比

OpenGL在Qt4和Qt5中的处理方式有什么巨大的区别吗?不是。。。

在Qt4中,用于进行OpenGL渲染的类是QGLWidget。它存在于QtOpenGL模块中(而不是QtGui中——请记住,在Qt4中,小部件也存在于Qt Gui中)。此外,我上面列出的Qt 5 OpenGL助手的一个子集实际上是以QGLFoo的名称提供的(例如QGLBuffer而不是QOpenGLBuffer)。

在Qt 5中,QtOpenGL模块仍然存在,以保持旧应用程序的工作。但是:

  • QtGui和QtWidgets被拆分。QtGui现在包含了处理WM的低级位,创建GL上下文和曲面,2d绘画,以及基本上我上面列出的东西。QtWidgets包含小部件本身。

  • QtOpenGL仍然包含QGL*类,但现在链接到QtWidgets(因为它包含QGLWidget)这意味着使用QGLWidget意味着即使你根本不使用小部件,你也会链接到一个很大的库(因为你的应用程序是纯OpenGL)。

  • 正如我之前所展示的,QtGui足以创建一个顶级OpenGL窗口。但是,如果您想将其嵌入到基于小部件的应用程序中,该怎么办?然后,您仍然可以使用QGLWidget或通过QWidget::createWindowContainer嵌入QWindow除了QGLWidget,您不应该使用任何其他QtOpenGL(即QGL)类。使用QtGui中的对应项(即QOpenGL类)

  • 以上所有QOpenGL*类都在QtGui中,而不在QtOpenGL中;它们比QGL*的对应产品更多(例如,没有QGLVertexArrayObject),它们有更多的功能(例如,QOpenGLShader支持几何体和镶嵌着色器,QGLShader不支持),而且通常是要使用的功能(因为它们会看到错误修复和改进,QGL*不会)。

  • 考虑到现在QtGui提供了OpenGL支持,很自然地会期望QGLWidget的替代品直接出现在QtWidgets中。事实上,它将有望在5.4中实现(准备工作将进入5.3;但不幸的是,功能本身将错过功能冻结)。


是否有任何理由期待Qt 4和Qt 5之间的巨大性能差异不。我希望您的总账代码执行完全相同的操作。最后,Qt并没有真正妨碍你。

桌面GL/ES 2

您可以通过配置时间开关编译支持"Desktop GL"或"ES 2"的Qt 5。很明显,它将改变QtGui在编译时使用的头文件,以及它将链接到的库(libGL或libGLES2等)。它还将改变默认的表面格式:上面的QWindow代码将创建一个漂亮的OpenGL ES2表面(可能会失败,因为没有OpenGL ES 3.3,哦,好吧)。

但你明白了:使用相同的代码,你也可以支持ES2。

问题(在我看来)是,它还将改变其他一些更微妙的东西:例如,QOpenGLShader将插入一些宏,如

#define highp
#define mediump
#define lowp

如果您使用的是Desktop GL,请在所有着色器之前使用。原因是它允许您在ES2和Desktop GL中重复使用相同的着色器,后者缺少精度限定符;因此,它们会通过扩展为零的宏被擦除。

我认为这些小事并不是真正的收获。也许它们减少了对非常小和简单的着色器(以及仅由顶点和碎片着色器制作的程序)的维护。如果Qt hand没有试图变得那么聪明,那会更好。

但是您的Desktop GL代码路径可能使用了更多的着色器阶段;或者只是一般地使用在ES2上不可用的特征。最终,它将明显偏离ES2代码路径。(想想看,在3.3 Core中,必须使用VAO,而ES2本身并不知道什么是VAO。)

个人咆哮:我讨厌,讨厌,讨厌ES2不像OpenGL配置文件,而是独立的。为了让ES2满意,基本上必须有一个发散的代码库。巴哈

Windows

进入痛苦的世界也称为Windows下的OpenGL驱动程序状态。

基本上,除了NVIDIA之外,任何人都会在Windows上发布损坏的OpenGL驱动程序。

至少,"开箱即用"。升级驱动程序通常有效,但您并不总是要求用户升级其驱动程序。他们是最终用户,而不是职业玩家。也许他们甚至没有管理员权限

这是OpenGL应用程序的一个问题,尤其是Qt最强大的工具之一:Qt Quick 2。Qt试图通过使用ANGLE来解决这个问题,ANGLE是OpenGL ES2->Direct3D转换层。因此,在Windows下,您可以在之间进行选择

  • 桌面OpenGL构建
  • 通过ANGLE构建OpenGL ES2

选择是不平等的——ES2当然意味着忘记做任何严肃的现代GL。但除此之外,这里还有这样或那样的理由。

Qt Quick 2

这很重要,我认为这本身就值得一提。

但首先让我们澄清一下:你需要使用Qt Quick 2在Qt下构建OpenGL应用程序吗NO、NO和NO。Qt Quick 2是一项完全独立的技术,它还利用OpenGL进行渲染。因此,您可以忽略它,只构建OpenGL应用程序。

但Qt Quick 2究竟是什么?它是一个建立在QML语言之上的库,QML语言是一种为创建动态UI而诞生的声明性语言(现在用于构建系统……哦,好吧)。

请记住区别:QML是语言,Qt Quick 2是一个库,包含一组可视化项目(以及用于创建自己的C++API),您可以在QML中编程。

碰巧Qt Quick 2使用OpenGL绘制这些视觉项目。这保证了不错的60 FPS无撕裂的结果,非常低的CPU使用率,所有类型的基于着色器的眼睛糖果,等等

那又怎样?好吧,你可能有兴趣踢一下。例如,API允许将其叠加到您绘制的任何纯OpenGL内容上。因此,您可以考虑使用Qt Quick 2来处理更传统的UI位——按钮、滑块等,同时控制主要内容的呈现。

或者,你可以忽略它的存在,继续使用OpenGL。

我认为你的问题和收到的评论中有很多误解。问题的根源在于"Qt"一词的使用非常松散。

Qt是一个大型跨平台应用程序开发框架。它结合了许多独立框架提供的功能。它提供了许多完全与gui无关的功能。即跨平台容器、线程、变体、带内省的元对象系统、计时器、网络、使用qtscript或javascript(通过qml)的脚本、xml、json、状态机等。Qt用于编写web服务,例如,在任何地方都没有一行UI代码。

说到用户界面,Qt为您提供了四个UI工具包。最终使用哪个工具包完全由您自己选择。您还可以混合和匹配所有这些——您可以在一个工具包中实现UI的一部分,在另一个工具箱中实现部分。一切都取决于您的要求。

我认为"Qt5"指的是Qt Quick 2,它是使用QML作为描述/脚本平台的场景图和UI工具包的实现。如果您只需要一个基于场景图的2D工具包,那么Qt Quick 2是一个不错的选择。它不提供任何三维功能,因此对于三维功能,您可以自己使用。Qt不会妨碍您-事实上,它会帮助您,因为它为OpenGL提供了一个可移植的包装器API,它隐藏了访问OpenGL时的一些平台差异。它还提供了ANGLE,这是OpenGL在Direct3D之上的捆绑实现。这使您可以在OpenGL中进行开发,同时仍以Windows上的Direct3D为目标。

对于TCP/IP和一般的非ui功能,你应该使用Qt——它让生活变得非常简单。对于3D,您将通过Qt提供的包装器直接使用OpenGL。然后,您可以在Qt的OpenGL和ANGLE构建之间进行选择,以决定是直接使用平台OpenGL驱动程序,还是使用在DirectX(ANGLE)之上实现的OpenGL。由于您使用了physx,因此您已经拥有了良好的nvidia驱动程序,并且OpenGL实现良好,因此不使用ANGLE是首选。我就是这么看的。