gpt4 book ai didi

c++ - 将Qt GUI拆分成多线程用于GUI、模拟、OpenGL是否可行?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:42:48 26 4
gpt4 key购买 nike

我正在尝试使用 Qt 为工作中的仪器模拟程序设计新布局。我们当前的 sim 是在单个窗口中运行所有内容(我们同时使用了 glut(旧)和 fltk),它使用 glViewport(...)glScissor(...) 将仪器读数拆分为自己的 View ,然后使用某种形式的“ortho2D”调用来创建自己的虚拟像素空间。模拟器当前会更新仪器,然后在它们自己的视口(viewport)中一个接一个地绘制,所有这些都在同一个线程中。

我们想找到更好的方法,于是我们选择了 Qt。我在几个大的限制下工作:

  1. 每个仪表板仍需要位于其 OpenGL 视口(viewport)中。有很多按钮和很多仪器。我的暂定解决方案是为每个使用 QOpenGLWidget。我在这方面取得了进展。
  2. sim 不仅是一个漂亮的读数,而且还模拟许多仪器作为仪器设计人员的反馈,因此它有时会占用大量 CPU 负载。它不是一个完整的硬件模拟器,但它确实模拟了逻辑。我认为告诉仪器在其相关小部件的 paintEvent(...) 方法开始时更新自身是不可行的,因此我希望模拟更新在单独的线程中运行。
  3. 我们的客户可能拥有旧计算机,因此已排除更新版本的 OpenGL。我们仍在使用 glBegin()glEnd() 以及介于两者之间的所有内容,并且仪器会绘制大量变量符号,因此绘制会花费大量时间并且我想将绘图拆分成它自己的线程。我还不知道 OpenGL 3 是否在桌面上,这对于渲染到屏幕外缓冲区是必要的(我认为)。

问题: QOpenGLWidget 没有可覆盖的“更新”方法,它只在小部件的paintEvent(...)paintGL( ...) 调用。

暂定方案:将模拟器分成三个线程:

  1. GUI:运行用户输入、paintEvent(...)paintGL(...)
  2. 模拟器:运行所有仪器逻辑并更新符号系统的值。
  3. 绘图:将最新的符号系统呈现到屏幕外缓冲区(将使用帧缓冲区对象 (FBO))。

在这个设计中,跨线程对话是循环和单向的,GUI 线程提供输入,模拟器线程在其下一个循环中考虑该输入,绘图线程读取最新的符号系统并将其呈现给FBO 并将“下一帧可用”标志设置为 true(或者可能发出信号),然后 paintGL(...) 方法将采用该 FBO 并将其吐出到小部件,因此保持事件处理和 GUI 响应能力。继续这个循环。

底线问题:我读过here GUI 操作不能在单独的线程中完成,那么我的方法是否可行?

如果可行,任何其他警告或建议将不胜感激。

最佳答案

每个 OpenGL 小部件都有自己的 OpenGL context ,并且这些上下文是 QObject,因此可以移动到其他线程。与任何其他非线程安全对象一样,您应该只从它们的 thread() 访问它们。

此外 - 这也可以移植到 QML - 您可以使用辅助函数来计算显示列表,然后将其提交给渲染线程以转换为绘制调用。渲染线程不执行任何逻辑,也不计算任何内容:它获取数据(顶点数组等)并将其提交以供绘图。将使用 QtConcurrent::run 提交工作仿函数以在线程池上执行。

因此,您可以拥有一个主线程、一个渲染线程(也许每个小部件一个,但不一定),以及运行模拟步骤的仿函数。

无论如何,卷积逻辑和渲染是一个非常糟糕的主意。无论您是在光栅小部件上使用 QPainter 进行绘图,还是在 QOpenGLWidget 上使用 QPainter,或者使用直接 OpenGL 调用,线程绘图是否不必计算要绘制的内容。

如果您不想打乱 OpenGL 调用,您可以将大部分工作表示为基于数组的 QPainter 调用(例如 drawRects drawPolygons),这些几乎直接转换为 OpenGL 绘图调用,OpenGL 后端将渲染它们,就像您手动编写绘图调用一样快。如果您在 QOpenGLWidget 上使用 QPainter,它会为您完成这一切!

关于c++ - 将Qt GUI拆分成多线程用于GUI、模拟、OpenGL是否可行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39029488/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com