2014-10-18 85 views
2

我一直在玩遊戲循環和物理。有一天,我添加了一些調試語句來查看我的遊戲循環中每幀的時間是多少。如預期的那樣,結果在16ms範圍內。 但是,我嘗試禁用vsync,並且這些結果沒有改變。 顯然vsync仍然存在。我評論了SFML顯示調用,並確信幀速度加快。SFML vsync始終在?

好吧,爲什麼然後vsync卡在?起初我認爲它一定是DSFML(用於D語言的SFML綁定)中的一個錯誤。我用C++直接使用SFML創建了一個簡單的測試用例,性能特點完全相同!

我的系統如下:

$ inxi -SMG
系統:主持人:C7 內核:3.16.4-1-ARCH x86_64的(64位)桌面:I3 4.8發行版:拱Linux 機器:系統:Google產品:Parrot v:1.0
Mobo:N/A型號:不適用Bios:coreboot v:4.0-4744-gac16405-dirty日期:10/23/2013
顯卡: 英特爾第二代核心處理器家族集成圖形控制器
顯示服務器:X.Org 1.16.1驅動程序:英特爾分辨率:[email protected]
GLX渲染:梅薩DRI英特爾的Sandy Bridge移動GLX版本:3.0梅薩10.3.1

的SFML VSYNC測試情況如下,與垂直同步開啓:

#include <chrono> 
#include <iostream> 
#include "SFML/Graphics.hpp" 

int main() 
{ 
    auto* window = new sf::RenderWindow(sf::VideoMode(640, 480), "test", 
     sf::Style::Titlebar | sf::Style::Close); 
    window->setVerticalSyncEnabled(true); 
    auto firstTime = std::chrono::high_resolution_clock::now(); 
    while(window->isOpen()) 
    { 
     //print frame timing 
     { 
      auto secondTime = std::chrono::high_resolution_clock::now(); 
      using dMsecs = std::chrono::duration<double, std::chrono::milliseconds::period>; 
      auto elapsed = dMsecs(secondTime - firstTime); 
      firstTime = secondTime; 
      std::cout << elapsed.count() << '\n'; 
     } 
     //event handler 
     { 
      sf::Event e; 
      while(window->pollEvent(e)) 
      { 
       if(e.type == sf::Event::EventType::Closed) 
        window->close(); 
      } 
     } 
     //render 
     { 
      window->clear(); 
      window->display(); 
     } 
    } 
} 

谷歌搜索這個問題與結果暗示圖形驅動程序迫使sync上出現。 但後來我想知道爲什麼vsync適用於我係統上的其他程序?

我使用SDL2又寫測試用例,此時:

#include <chrono> 
#include <iostream> 
#include "SDL2/SDL.h" 

int main() 
{ 
    SDL_Init(SDL_INIT_VIDEO); 
    SDL_Window* window = SDL_CreateWindow("test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); 
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); 
    auto firstTime = std::chrono::high_resolution_clock::now(); 
    auto quit = false; 
    while(!quit) 
    { 
     //print frame timing 
     { 
      auto secondTime = std::chrono::high_resolution_clock::now(); 
      using dMsecs = std::chrono::duration<double, std::chrono::milliseconds::period>; 
      auto elapsed = dMsecs(secondTime - firstTime); 
      firstTime = secondTime; 
      std::cout << elapsed.count() << '\n'; 
     } 
     //event handler 
     { 
      SDL_Event e; 
      while(SDL_PollEvent(&e)) 
      { 
       if(e.type == SDL_QUIT) quit = true; 
      } 
     } 
     //render 
     { 
      SDL_RenderClear(renderer); 
      SDL_RenderPresent(renderer); 
     } 
    } 
} 

現在我禁用垂直同步是本次測試的情況下,看幀時間在0毫秒範圍內,符合市場預期! 所以,然後SFML實現vsync的方式在我的系統上很麻煩,而SDL似乎正確地處理它。

導致這種不同行爲的兩個庫之間的實現有什麼區別,是否可以解決?我將如何着手使用SFML獲得正確的行爲?

+0

雖然從理論上講,SFML中某處可能存在一些只在非常特殊情況下才會發生的bug,但這聽起來確實更可能是某種驅動程序問題(或者它確實是一些奇怪的競爭條件或一些奇怪的庫星座,錯誤發生)。 你有沒有嘗試分析你的最小例子,看看大部分時間花在哪裏/等待? – Mario 2014-10-20 06:31:57

回答

0

這是一個有問題的驅動程序。 glXSwapIntervalMESA起作用。爲glXSwapIntervalSGI返回的指針是有效的,因此SFML無法檢測到此問題,而不採用類似於SDL的方法。