Linux下如何查询Vsync相位

How to query Vsync phase in Linux

本文关键字:查询 Vsync 相位 何查询 Linux      更新时间:2023-10-16

我需要创建一个c++函数,它将返回到下一个Vsync间隔的秒数作为浮点值。

为什么?

我正在创建显示跟随鼠标光标的矩形的程序。表面上,OpenGL在glXSwapBuffers函数中提供了一个垂直同步机制,但我发现这是不可靠的。对于一些卡驱动程序,你可以实现垂直同步;而其他人则不然。在某些情况下,你得到了垂直同步,但你也得到了额外的2帧延迟。

但这不是OpenGL中的错误。该规范故意含糊不清:返回缓冲区的内容将变得未定义。的垂直回溯期间进行更新监视器,而不是在调用glXSwapBuffers之后立即调用。"关键词是"典型"……基本上glXSwapBuffers不承诺蹲下w.r.t.垂直同步。图。

在我目前尝试解决这个基本问题时,我目前猜测初始的vsync时间,然后假设相位等于经过时间MOD 1/(59.85Hz),这似乎与我当前的监视器同步。但这不是很好,因为我不知道初始阶段。所以我得到了一滴眼泪。至少它不会移动。但我真正需要的是测量当前的垂直同步相位。

不,我不想依靠一些OpenGL调用为我做一个垂直同步。由于规范中的模糊性,这使得OpenGL实现可以随心所欲地增加延迟。

不,我不想依赖一些SGI扩展或其他一些必须安装才能使其工作的东西。这是图形101。Vsync。只需要一种方法来查询它的状态。一些内置的,总是安装的API必须有这个。

也许我可以创建一个次要线程等待Vsync,并记录发生这种情况的时间?但是要注意以下顺序:

#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/fb.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{
  int fb = open("/dev/fb0", O_RDWR);
  assert(fb != -1);
  int zero = 0;
  if (ioctl(fb, FBIO_WAITFORVSYNC, &zero) == -1)
    printf("fb ioctl failed: %sn", strerror(errno));
}

在Debian中不起作用。结果:

% ./a.out
fb ioctl failed: Inappropriate ioctl for device
% ls -l /dev/fb0
crw-rw-rw- 1 root video 29, 0 Sep  1 20:52 /dev/fb0

一定有某种方法可以直接从设备读取相位,或者其他方法OpenGL的电话。OpenGL是用于图像的东西。Vsync是图形学的基础。

请帮助。

当您在Linux内核源代码中搜索FBIO_WAITFORVSYNC时,您可以看到,它仅适用于少数显卡,而不是所有显卡。

所以,如果你碰巧有许多其他显卡中的一个,你会得到"不合适的ioctl for device",这只是意味着这个显卡驱动程序没有实现。

也许如何等待VSYNC在Xlib应用程序?给你一些正确方向的提示。

一个比放弃更好的解决方案的大纲:

  1. 在digi-key上搜索输出同步信号的MAX芯片

  2. 安装RS232卡

  3. 连接RS232上的握手线

  4. 使用可在任何Linux上运行的标准termios API

  5. 将令人惊叹的产品包装在陶瓷环氧块中,售价500美元。

这是图形101。Vsync。只需要一种方法来查询它的状态。一些内置的,总是安装的API必须有这个。

不,"一定"没有办法做到这一点。至少,没有任何东西会暴露在面前。当然也不是跨平台的。

毕竟,屏幕不是你的。系统拥有屏幕;你只租用了其中的一部分,因此你只能任由系统摆布。该系统处理垂直同步;你的工作是填充显示在那里的图像。

考虑Vulkan,如果没有作为的图形驱动程序,它几乎是你现在所能得到的最低级别。它的WSI接口被明确地设计为避免允许你做像"等待下一次vsync"这样的事情。

它的显示系统确实提供了多种模式,但唯一的实现要求支持的是FIFO:严格的垂直同步,但没有撕裂。当然,Vulkan的WSI至少允许您选择需要多少图像缓冲。但是,如果您使用FIFO只有双缓冲区,并且您在提供该图像时晚了,那么您的交换将不会是可见的,直到下一次vsync。

一个简短的答案是:视频同步曾经在计算机上很流行,当时视频缓冲很昂贵。如今,随着双缓冲动画的普遍使用,它变得不那么重要了。在windows系统出现之前,我曾经通过IBM-PC上的显卡访问vsync,即使现在也不介意使用vsync。使用双缓冲时,您仍然存在栅格扫描发生的风险,同时将缓冲区写入视频存储器,因此最好进行同步。然而,使用双重缓冲,您将消除许多"火花"。直接视频绘图的效果和其他工件,因为您正在做线性BLT而不是单个像素操作。

也有可能(正如之前的海报所暗示的),你的两个缓冲区都存在于视频内存中,并且显示管理器可以仔细管理屏幕上的blts(合成)的想法可以渲染效果不存在。

我现在该如何处理?我保留了一个帧计时器,比如每秒30次,我用它来翻转缓冲区。它不是特别地与显卡上的实际帧时间同步。