[英]How to query Vsync phase in Linux
我需要創建一個 C++ 函數,它將返回到下一個 Vsync 間隔的秒數作為浮點值。
為什么?
我正在創建顯示跟隨鼠標光標的矩形的程序。 表面上,OpenGL 在 glXSwapBuffers 函數中提供了一個 vsync 機制,但我發現這是不可靠的。 使用某些卡驅動程序,您可以獲得 vsync; 與其他人你不。 在某些情況下,您會獲得 vsync,但也會獲得額外的 2 幀延遲。
但這不是 OpenGL 中的錯誤。 規范故意含糊其辭:“后台緩沖區的內容然后變得未定義。更新通常發生在監視器的垂直回溯期間,而不是在調用 glXSwapBuffers 之后立即發生。” 關鍵詞是“通常”......基本上 glXSwapBuffers 不承諾蹲下 wrt vsync。 去圖。
在我目前解決這個基本問題的嘗試中,我目前猜測初始垂直同步時間,然后假設相位等於經過時間 MOD 1/(59.85Hz),這似乎與我當前的顯示器同步。 但這並不奏效,因為我實際上並不了解初始階段。 所以我得到一滴眼淚。 至少它不會四處走動。 但我真正需要的是以某種方式測量當前的 vsync 相位。
不,我不想依賴一些 OpenGL 調用來為我做一個 vsync。 由於規范中的含糊不清,這使得 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: %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。
請幫忙。
當您在 Linux 內核源代碼中搜索FBIO_WAITFORVSYNC
時,您可以看到,它僅適用於少數顯卡,而不適用於所有顯卡。
因此,如果您碰巧擁有許多其他卡中的一張,則會收到“設備的 ioctl 不合適”,這僅意味着未針對此顯卡驅動程序實現。
也許如何在 Xlib 應用程序中等待 VSYNC? 給你一些正確方向的提示。
一個比放棄更好的解決方案的概述:
在 digi-key 上搜索輸出同步信號的 MAX 芯片。
安裝 RS232 卡。
將同步信號連接到 RS232 上的握手線。
使用適用於任何 Linux 的標准 termios API。
將驚人的產品裝入陶瓷環氧樹脂塊中,售價 500 美元。
這是圖形 101。Vsync。 只需要一種查詢其狀態的方法。 一些內置的、總是安裝的 API 必須有這個。
不,“必須”沒有辦法做到這一點。 至少,不是任何暴露給你的東西。 當然不是任何跨平台的東西。
畢竟,您不擁有屏幕。 系統擁有屏幕; 您只是租用了其中的一部分,因此受制於系統。 系統處理vsync; 你的工作是填寫顯示在那里的圖像。
考慮一下 Vulkan,它的級別與您現在將要獲得的級別一樣低,而實際上不是圖形驅動程序。 它的 WSI 接口經過明確設計,以避免允許您執行諸如“等到下一次 vsync”之類的操作。
它的演示系統確實提供了多種模式,但唯一需要實現支持的是 FIFO:嚴格的 vsync,但沒有撕裂。 當然,Vulkan 的 WSI 至少允許您選擇所需的圖像緩沖量。 但是,如果您僅將 FIFO 與雙緩沖區一起使用,並且您遲遲沒有提供該圖像,那么您的交換將在下一次 vsync 之前不可見。
一個簡短的回答是:當視頻緩沖很昂貴時,vsync 曾經在計算機上流行。 如今,隨着雙緩沖動畫的普遍使用,它變得不那么重要了。 在使用 Windowing 系統之前,我曾經從 IBM-PC 上的顯卡訪問 vsync,即使現在也不會介意獲得 VSYNC。 使用雙緩沖,您仍然有可能在將緩沖區寫入視頻內存時發生光柵掃描的風險,因此同步它會很好。 但是,通過雙緩沖,您將消除直接視頻繪制中的許多“閃光”效果和其他偽影,因為您正在執行線性 blt 而不是單個像素操作。
也有可能(如前一張海報所暗示的)兩個緩沖區都存在於視頻內存中的事實,以及顯示管理器可以仔細管理屏幕上的 blts(合成)的想法都可以渲染不存在的效果。
我現在如何處理? 我保留了一個幀計時器,例如每秒 30 次,用於翻轉緩沖區。 它與顯卡上的實際幀時間並不特別同步。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.