【问题标题】:Difference in opengl speed between Qt 4/5 and Opengl APIQt 4/5 和 Opengl API 之间的 opengl 速度差异
【发布时间】:2014-03-10 11:29:13
【问题描述】:

我已经阅读了关于 SO 的所有问题,我可以找到关于 qt 4 和 5 opengl 的所有问题。这个是最接近的 OpenGL vs QOpenGL/QtOpenGL in Qt 5: differences and limitations? ,我不知道为什么它被关闭了,因为这是一个很好的问题。我认为它缺少的唯一方面是速度差异。

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

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

编辑:

更具体一点,我需要使用 physx、tcp/ip 通信以及大量快速更新的顶点和网格。目标是尽可能接近实时地执行此操作。渲染之类的事情不是问题,但是 qt 的任何开销都是有害的。 (一切都是用 C++ 制作的 3D)

【问题讨论】:

  • 是的,你问这个是对的,尽管不是出于性能原因。不要使用Qt,除非内置 QML 元素完全满足您的需求。这样做的原因是,Qt 实现者使用了很多未记录的Qt - 这意味着要编写自己的QML 元素,除非它真的很简单,否则你将不得不挖掘大量Qt 代码。一路上你发现了很多错误,发布它们,但没有得到修复。所以你真的需要快速做一些事情(比如 QtQuick 承诺)?倒霉。将 QtQuick 状态与您的应用程序状态分开也非常困难。
  • 你是说不要使用QT,还是不要使用内置的qt函数而是自己制作qt小部件并直接使用QT API?
  • 只有在它提供的控件完全、完全满足您的要求时才使用Qt(很好的例子:没有QML TreeView)。不要为实现自己的Qt Quick 组件而烦恼,因为您很快就会陷入困境。更好地利用你的时间。此外,将 3D 渲染器和 Qt 粘合在一起不一定是一件容易的事,请小心。所以我倾向于,不要使用Qt在所有,如果你在做任何离奇的事情,即使是遥远的感觉。
  • @user1095108 任何使用 QML 的可视化内容都是 Qt Quick 的一部分,而不是 QML,因此请正确使用这些术语。此外,您使用术语“Qt”非常松散,因此您的 cmets 没有帮助。当您谈论“Qt”时,您是在谈论特别是关于 Qt Quick 2不是一般意义上的 Qt。将 Qt 与裸露的 OpenGL 或 Direct3D 代码一起使用当然是完全有效的。除了视觉效果之外,Qt 还提供了更多功能。
  • @KubaOber 如果你想学究气,至少你需要确保你做对了。为什么文档:qt-project.org/doc/qt-4.8/qdeclarativeelements.html 谈论 QML 元素,如果它们是 Qt Quick 的一部分(根据你的说法)而不是 QML,我没有说任何关于使用 Qt 与 DX 或GL,只是这并不容易,因为关于这个主题的很多问题都证明了这一点。提交文档错误,但是哦,这些永远不会得到修复。对于任何不寻常的东西(真的是一个不寻常的 TreeView 吗?)你会遇到问题。

标签: c++ qt opengl qt4 qt5


【解决方案1】:

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

更具体一点,我需要使用 physx、tcp/ip 通信以及大量快速更新的顶点和网格。目标是尽可能接近实时地执行此操作。渲染之类的事情不是问题,但是 qt 的任何开销都是有害的。 (一切都是用 C++ 制作的 3D)

您的问题中有多个问题。

“原始”OpenGL 与“Qt”OpenGL

这个问题不恰当,因为没有“Qt OpenGL”之类的东西。 OpenGL 是 Khronos 拥有和发布的标准。 Qt 只是使用它。

Qt 可以为您做的就是帮助您的应用程序管理几件事情。

窗口/上下文创建

您是否尝试过在 Win32 下创建 OpenGL 上下文?它需要一堆样板代码(参见herehere),其中包括创建一个临时上下文来检查WGL 功能,然后在最后创建实际上下文...

您是否尝试过在 X11 下创建 OpenGL 上下文?它需要一堆样板代码(请参阅here),其中涉及检查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 不会增加任何可测量的开销

窗口管理

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

OpenGL 帮助程序

Qt 不“只是”提供一种创建 OpenGL 表面和上下文的方法(以及相关操作:设置为当前、交换缓冲区等)。它走得更远,并提供了一整套辅助类和函数:

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

有开销吗?是的,但它又一次是最小的,它不涉及您如何在您的 OpenGL 代码中使用这些对象。如果您的 OpenGL 代码速度快且结构良好,那么您会发现这些帮助程序对管理它很有用,而且它们不会让它运行得更慢。

(“管理它有用”的示例:QOpenGLVertexArrayObject 将允许您在 OpenGL 3.0 上使用 VAO,或者在存在 GL_ARB_vertex_array_object 扩展名的任何桌面 OpenGL 版本上使用 VAO,或者在 OpenGL ES2 上使用 GL_OES_vertex_array_object存在。您不需要根据运行时解析正确的函数集。Qt 会为您做这件事,并为创建、绑定、释放和销毁 VAO 提供相同的 API。

一切都那么好吗?不,我必须在这里说实话,有些细节会从一些爱中受益。

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

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

这是否意味着您不能使用这些功能?当然可以。如果您需要 Qt 目前没有提供的功能,请返回原始 OpenGL 代码。或者,考虑contributing those features to Qt

Qt

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

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

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

顺便说一句,Qt还有:

  • 用于跨平台二维小部件的 QtWidgets
  • 用于数据库访问的 QtSql
  • 用于 TCP/UDP/SSL 套接字的 QtNetwork,以及高级 HTTP/FTP 引擎
  • 用于单元测试的 QtTest
  • 用于嵌入 webkit 的 QtWebkit
  • 还有一堆我现在不记得的东西

Qt 4 与 5 中的 OpenGL

在 Qt 4 和 Qt 5 中处理 OpenGL 的方式是否存在巨大差异?不是真的……

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

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

  • QtGui 和 QtWidget 被拆分。 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 之间的巨大性能差异? 不,我希望您的 GL 代码执行完全相同。最后,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下的OpenGL驱动状态。

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

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

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

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

选择并不相同——ES2 当然意味着忘记做任何严肃的现代 GL。但除此之外,可以使用here

Qt 快速 2

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

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

但是 Qt Quick 2 到底是什么?这是一个建立在QML language 之上的库,这是一种为创建动态用户界面而生的声明性语言(现在用于build systems...哦,好吧)。

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

Qt Quick 2 恰好使用 OpenGL 来绘制这些视觉项目。这保证了良好的 60 FPS 无撕裂效果、极低的 CPU 使用率、各种基于着色器的视觉效果等等。

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

或者,您可以忽略它存在的事实并继续使用 OpenGL。

【讨论】:

  • 对于所有这些错误的好东西,您必须通过链接巨大的DLLs 或.sos 来付费。最终,人们确实看到了炒作之外的东西。
  • “巨大”的衡量标准是什么? QtCore 和 QtGui 在 Linux/AMD64 上的发布模式下总共为 10-12MB。正如我所说,它们提供的不仅仅是 OpenGL 包装器。
  • @user1095108 如果你编写原始的 openGL,你最终会自己重新实现这些好东西,而且没有理由期望它们会比 Qt 更少“错误”。 Qt 带有一个相当广泛的测试套件,其中包括性能回归测试。许多人使用这些好东西,并且很快就会解决主要错误。
  • @user1095108 Peppe's 是正确的球场。对我来说,一个小型 Windows 7 应用程序,编译 statically,在 MSVC2012 下使用 LTCG 和 RTTI,使用 Qt5.2 的核心、gui 和小部件模块,重量约为 10MB,UPX 压缩后为 4.5MB。这是一个完整的、独立的应用程序,它不依赖于除了 Windows 本身附带的那些 DLL 之外的任何 DLL。它比使用 Qt 4.8 编译的相同代码多 1.5MB。我不会称它为巨大的。
  • 您的评论没有建设性。您仍然没有提供任何技术论据或事实证据来支持您的观点。你带来的那些(“巨大的 DLL”、“buggy”)是如此明显的错误,很容易被证明是错误的。那么我们为什么要相信你是可靠的,“你的经验”说的是实话呢?
【解决方案2】:

我认为您的问题及其收到的 cmets 存在很多误解。问题的根源在于“Qt”一词的使用非常松散。

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

在用户界面方面,Qt 为您提供four UI toolkits。最终使用哪个工具包完全是您的选择。您也可以混合搭配所有这些 - 您可以在一个工具包中实现部分 UI,在另一个工具包中实现部分。一切都取决于您的要求。

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

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

【讨论】:

  • 如此巨大的选择和一个比下一个更糟糕的选择。自 Qt5.2 起不再提供捆绑的 ANGLE,您可以将其作为独立的 .DLL 单独安装。简单的说,你就是聊聊Qt的伟大之处。看在上帝的份上,有些事情需要开发者来实现。那么,如果有 4 个工具包,如果它们不能提供您需要的东西,那又如何。您尝试自己实现它,却陷入了Qt 中未记录/记录不充分的部分。即使是应该正确记录的内容通常也不是,您必须进行源代码挖掘。
  • @user1095108 由于我使用捆绑 ANGLE 的 5.2,因此您显然错了。至少在 Qt 中,您可以从经过良好测试的代码开始,即使它没有记录 :) Qt 做了很多工作,没有人会在一个下午重新实现它的主要部分 - 甚至不是单个模块的主要部分。
  • @user1095108 Qt 是共同努力的结果。我敢肯定,如果您通过向 gerrit 提交补丁来解决您认为文档缺陷的问题,那将受到广泛的赞赏。注册很简单,你应该在几分钟内启动并运行。 Qt 的文档在行业中堪称典范,但它仍然可以做得更好,这是毫无疑问的。
  • @user1095108 鉴于 Qt 实现了许多特定于平台的功能,而这些功能本身的文档记录很差,我发现仅仅使用 Qt 就像间接获得更好的底层平台功能文档。
猜你喜欢
  • 1970-01-01
  • 2013-11-26
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多