【发布时间】:2014-05-19 20:27:03
【问题描述】:
Vsync 会阻塞 SwapBuffers(),这正是我想要的。我的问题是,由于输入消息进入拥有窗口的同一个线程,因此在 SwapBuffers() 被阻止时进入的任何消息都不会立即处理,但只有在 vsync 触发缓冲区交换并且 SwapBuffers() 返回之后.所以我的所有计算线程都处于空闲状态,而不是使用最新的输入处理场景以在下一帧中渲染。我特别关心具有非常低的延迟。我需要一些方法来从其他线程访问所有待处理的输入消息到窗口。
Windows API 提供了一种使用 MsgWaitForMultipleObjects() 来等待 Windows 事件或输入消息的方法,但没有类似的方法可以与其他东西一起等待缓冲区交换。太可惜了。
我考虑在另一个线程中调用 SwapBuffers(),但这需要在窗口的线程中调用 glFinish(),然后再向 SwapBuffers() 发出另一个线程的信号,并且 glFinish() 仍然是一个阻塞调用,所以它不是一个好的解决方案.
我考虑过挂钩,但这看起来也像死路一条。与 WH_GETMESSAGE 挂钩将不会异步调用 GetMsgProc(),但是当窗口的线程调用 GetMessage()/PeekMessage() 时,它没有帮助。由于需要使用特定的窗口句柄调用 RegisterTouchWindow() 来处理 WM_TOUCH,因此安装全局钩子对我也没有帮助——而且我的输入是触摸。而且,对于鼠标和键盘,您可以安装低级钩子,在消息发布到线程队列时捕获消息,而不是在线程调用 GetMessage()/PeekMessage() 时,似乎没有类似的触摸选项.
我还查看了 wglDelayBeforeSwapNV(),但我看不出是什么阻止了操作系统有时在调用该函数之后但在 SwapBuffers() 之前抢占线程,从而导致错过下一个 vsync 信号。
那么什么是好的解决方法?我可以制作第二个不可见的窗口,它会以某种方式始终处于活动状态,从而获取所有输入消息,而可见的窗口正在显示渲染?根据另一个讨论,仅消息窗口(带有 HWND_MESSAGE 的 CreateWindow)与 WM_TOUCH 不兼容。是否有一些 SwapBuffers() 在内部等待我可以访问并提供给 MsgWaitForMultipleObjects() 的未记录事件?我的目标是一个固定平台(Windows 8.1 64 位),所以我可以使用未记录的功能,如果它存在的话。不过,我确实想避免编写自己的触摸屏驱动程序。
【问题讨论】:
标签: windows multithreading winapi opengl message-queue