9

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

为什么?

我正在创建显示跟随鼠标光标的矩形的程序。表面上,OpenGL 在 glXSwapBuffers 函数中提供了一个 vsync 机制,但我发现这并不可靠。使用一些卡驱动程序,您可以获得 vsync;与其他你没有的人。在某些情况下,您会获得垂直同步,但您也会获得额外的 2 帧延迟。

但这不是 OpenGL 中的错误。规范故意含糊不清:“后台缓冲区的内容然后变得未定义。更新通常发生在监视器的垂直回溯期间,而不是在调用 glXSwapBuffers 之后立即发生。” 关键字是“典型地”......基本上glXSwapBuffers 不承诺squat wrt vsync。去搞清楚。

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

不,我不想依赖一些 OpenGL 调用来为我做垂直同步。由于规范中的模糊性,这使得 OpenGL 实现可以根据需要添加尽可能多的延迟。

不,我不想依赖某些 SGI 扩展或必须安装的其他东西才能使其工作。这是图形 101。垂直同步。只需要一种查询其状态的方法。某些内置的、始终安装的 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: %s\n", 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 是图形 101。

请帮忙。

4

4 回答 4

4

当您在 Linux 内核源代码中搜索时FBIO_WAITFORVSYNC,您会看到它仅针对少数显卡实现,但并非针对所有显卡。

因此,如果您碰巧拥有许多其他卡中的一张,您会得到“设备的 ioctl 不合适”,这意味着该显卡驱动程序没有实现。

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

于 2016-09-02T20:54:06.653 回答
2

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

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

  2. 安装 RS232 卡。

  3. 将同步信号连接到 RS232 上的握手线。

  4. 使用适用于任何 Linux 的标准 termios API。

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

于 2017-09-20T16:11:45.423 回答
0

这是图形 101。垂直同步。只需要一种查询其状态的方法。某些内置的、始终安装的 API 必须具有此功能。

不,“必须”没有办法做到这一点。至少,不会有任何暴露给的东西。当然不是任何跨平台的东西。

毕竟,您不拥有屏幕。系统拥有屏幕;您只是租用其中的一部分,因此受制于系统。系统处理vsync;你的工作是填写在那里显示的图像。

考虑一下 Vulkan,它与您现在所获得的水平差不多,但实际上并不是图形驱动程序。它的 WSI 接口被明确设计为避免让你做诸如“等到下一个 vsync”之类的事情。

它的表示系统确实提供了多种模式,但唯一需要实现支持的是FIFO:严格的vsync,但没有撕裂。当然,Vulkan 的 WSI 至少允许您选择所需的图像缓冲量。但是,如果您仅使用带有双缓冲区的 FIFO,并且您提供该图像的时间很晚,那么您的交换将在下一次 vsync 之前可见。

于 2016-09-02T20:32:13.617 回答
0

一个简短的回答是:当视频缓冲很昂贵时,vsync 曾经在计算机上很流行。如今,随着双缓冲动画的普遍使用,它已经不那么重要了。在 Windows 系统之前,我曾经在 IBM-PC 上的显卡上访问 vsync,即使现在我也不介意获得 VSYNC。使用双缓冲,您仍然有可能在将缓冲区 bltting 到视频内存时发生光栅扫描,因此同步它会很好。但是,通过双缓冲,您将消除直接视频绘制中的许多“闪光”效果和其他伪影,因为您正在执行线性 blt 而不是单个像素操作。

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

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

于 2021-05-03T23:13:35.927 回答