C++ OSX以最小延迟将像素推送到屏幕
我正在尝试开发一些延迟非常低的图形应用程序,但我对通过OpenGL绘制到屏幕所需的时间感到非常失望。我在网上找到的每一个关于它的讨论都涉及到优化OpenGL管道,但都没有得到我需要的结果 看看这个:C++ OSX以最小延迟将像素推送到屏幕,c++,macos,opengl,draw,low-latency,C++,Macos,Opengl,Draw,Low Latency,我正在尝试开发一些延迟非常低的图形应用程序,但我对通过OpenGL绘制到屏幕所需的时间感到非常失望。我在网上找到的每一个关于它的讨论都涉及到优化OpenGL管道,但都没有得到我需要的结果 看看这个: 你可能注意到了这一点:使用C++ OpenGL应用程序,在屏幕上拖动鼠标,在OpenGL中绘制鼠标位置,OpenGL落后3或4帧。显然,OSX可以以很低的延迟将[光标]绘制到屏幕上,但OpenGL要慢得多。假设我不需要做任何漂亮的OpenGL渲染。我只是想把像素推到屏幕上。有没有一种方法可以让我完
你可能注意到了这一点:使用C++ OpenGL应用程序,在屏幕上拖动鼠标,在OpenGL中绘制鼠标位置,OpenGL落后3或4帧。显然,OSX可以以很低的延迟将[光标]绘制到屏幕上,但OpenGL要慢得多。假设我不需要做任何漂亮的OpenGL渲染。我只是想把像素推到屏幕上。有没有一种方法可以让我完全绕过OpenGL,更快地绘制屏幕?或者这种功能会被锁定在内核中某个我无法访问的地方吗?
这里有很多延迟- 输入事件→ 绘图状态延迟
- 三重缓冲/合成延迟
对此,您可以做些什么:
- 关闭合成功能
- 减少输入滞后
尽可能晚地收集和集成用户输入(使用高分辨率睡眠)。如果你只有一个非常简单的场景,你可以把画推到离V-Sync截止日期很近的地方;事实上,英伟达OpenGL的实现有一个特定于供应商的扩展,允许在下一个V-Syc.之前休眠到特定的时间。
如果您的场景很复杂,但可分为需要低延迟用户输入的部分和不太重要的部分,那么您可以更早地绘制高延迟内容,并且只在最后一刻将用户输入集成到其中。当然,如果使用鼠标来控制观看方向,或者更糟糕的是,在为VR头戴式显示器进行渲染时,事情会变得很困难。datenwolf的答案非常好。我只想在关于合成器级别的三重缓冲的讨论中添加一点,因为我非常熟悉Microsoft Windows桌面合成器 我知道您在这里询问有关OSX的问题,但是我将要讨论的实现细节是实现这些东西的最明智的方式,我希望看到其他系统也以这种方式工作 您可能在应用程序级别启用的三重缓冲为交换链添加了第三个缓冲区,该缓冲区被同步以刷新。这种三重缓冲的方式确实增加了延迟,因为第三个缓冲区必须被显示,并且在发生这种情况之前,任何东西都不允许触碰它(这是D3D的强制行为——行为和功能本身在OpenGL中没有定义);但是桌面窗口管理器(Windows)的工作方式略有不同 我见过大多数驱动程序为桌面合成实现的行为是帧丢弃。在刷新之间完成多个帧的任何情况下,除1个帧外,所有这些帧都将被丢弃。实际上,使用窗口而不是全屏+三重缓冲可以降低延迟,因为当第三个缓冲区(由合成器拥有)有一个完成的帧等待显示时,它不会阻止缓冲区交换 如果帧率不合理地一致,则会产生一系列完全不同的视觉问题。从技术上讲,属于丢弃帧的像素具有无限延迟,因此,如果您需要在屏幕上显示绘制的每一帧,那么通过这种方式减少延迟的好处可能毫无价值 我相信,通过禁用VSYNC并在窗口中绘图,可以在OSX上实现这种行为(如果您愿意)。在这种情况下,VSYNC基本上只作为帧调整的一种形式(以延迟换取一致性),而不管您以何种速率绘制,合成器本身都会消除撕裂
关于鼠标光标延迟: 任何现代窗口系统中的光标都将始终以最小延迟跟踪。图形硬件上有一个称为“硬件光标”的功能,其中驱动程序存储光标位置,然后每次刷新一次,让硬件将光标覆盖在帧缓冲区中等待扫描的对象的顶部。因此,即使您的应用程序在60 Hz显示器上以30 FPS的速度绘制,当使用硬件光标时,光标也会每16 ms更新一次 这完全绕过了所有图形API,但非常有限(例如,它使用OS定义)