代码之家  ›  专栏  ›  技术社区  ›  Alexander Rafferty

多线程处理OpenGL/WinAPI应用程序

  •  0
  • Alexander Rafferty  · 技术社区  · 14 年前

    注:请在发帖前通读,你会明白原因的。

    所以我有一个OpenGL/WinAPI应用程序。我正在做你所期望的,通过循环处理消息,然后渲染帧,处理消息,渲染帧…

    问题是,当我调整窗口大小或移动窗口时,屏幕会冻结,而且看起来很难看。我从OpenGL以前的到期中了解到,限制帧之间要处理的消息数量(按数量或时间)是很关键的。似乎每当我的应用程序移动/调整窗口大小时,Windows都会阻止它。从过期开始,我知道将Windows消息处理放到另一个线程中并忽略它会很好地工作,并且也有助于计时。

    我的问题是:有没有更好、更不具破坏性或无线程的方法来实现这一点?我在做什么有什么坏处吗(除了多线程的戏剧)。我想知道多线程是否可以避免。

    2 回复  |  直到 7 年前
        1
  •  3
  •   Chris Becke    14 年前

    当用户单击窗口的非客户端区域以移动或调整窗口大小时,defwindowproc将进入模式循环,因此不再执行游戏循环-直到用户取消或完成模式操作。

    有一些窗口消息可用于检测模式操作的开始和结束: WM_ENTERSIZEMOVE 例如。

    关键是,如果你的OpenGL窗口不是全屏的,或者它显示消息框,那么你不能依靠一个简单的游戏循环来继续渲染游戏-你需要切换到一个基于计时器的渲染器。

    SetTimer 可以创建一个计时器 WM_TIMER 消息,即使模式操作正在进行。

    ps.线程处理注意事项:OpenGL上下文不是线程安全的,如果在线程间共享上下文,则必须对其进行序列化(由用户代码手动进行)。即使使用多个上下文,对实际设备的访问也会被序列化,因此多线程处理一个基于OpenGL的渲染器对性能没有好处-除非(具有讽刺意味的是)您做了大量CPU密集型工作(然后像OpenMP这样的并行循环将有助于不仅仅是尝试设计一个更高级别的多线程渲染作业调度器)。基本上:坚持使用OpenGL的单线程渲染器——它的性能比几乎任何线程尝试都要好,而且更容易预测。

    PPS。对于有窗口的OpenGL应用程序,它可能也更好地放弃传统的游戏循环方法来渲染每一帧,并依赖于 RedrawWindow 发送 WM_PAINT 给窗口的消息:在 BeginPaint/EndPaint 块意味着您的应用程序呈现行为更加可预测,并且桌面WindowManager进程可以处理其应用Aero Glass效果的工作,并尝试更有效地将桌面的垂直同步更新实现到显示器上。

        2
  •  0
  •   eile    14 年前

    一个解决方法是:渲染到FBO中,在每个调整大小的消息上将FBO快速放到窗口中(可能会对其进行缩放),并在消息队列为空时以正确的分辨率重新渲染FBO。

    通过这种方式,您可以获得可预测的重绘,只需很少的工件和线程。