2014-10-18 80 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的方法。