SFML vsync始终打开



我一直在玩游戏循环和物理。前几天,我添加了一些调试语句,以查看游戏循环的每一帧花费了多少时间。正如预期的那样,结果在16毫秒的范围内。然而,我尝试禁用vsync,但这些结果没有改变。显然vsync仍在发生。我评论掉了SFML显示调用,果不其然,帧加速了。

好吧,那么为什么vsync一直处于开启状态呢?起初,我认为这一定是DSFML(D语言的SFML绑定)中的一个错误。我用C++创建了一个简单的测试用例,它直接使用SFML,性能特性完全相同!

我的系统如下:

$inxi-SMG
系统:主机:c7内核:3.16.4-1-ARCH x86_64(64位)桌面:i3 4.8 Distro:ARCH Linux机器:系统:谷歌产品:Parrot v:1.0
Mobo:N/A型号:N/A Bios:coreboot v:4.0-4744-gac16405脏日期:2013年10月23日
图形:卡:英特尔第二代核心处理器系列集成图形控制器
显示服务器:X.Org 1.16.1驱动程序:intel分辨率:1366x768@60.02hz
GLX渲染器:Mesa DRI Intel Sandybridge Mobile GLX版本:3.0 Mesa 10.3.1

SFML vsync测试用例如下所示,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();
        }
    }
}

在谷歌上搜索这个问题,结果表明图形驱动程序正在强制打开vsync。但后来我想知道为什么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);
        }
    }
}

现在我禁用了vsync,这是一个测试用例,正如预期的那样,帧时间在0ms范围内!因此,SFML实现vsync的方式在我的系统上是有缺陷的,而SDL似乎处理得很好。

导致这种不同行为的两个库在实现上的差异是什么?它能得到解决吗?我该如何使用SFML获得正确的行为?

这是一个有缺陷的驱动程序。glXSwapIntervalMESA有效。为glXSwapIntervalSGI返回的指针是有效的,因此如果不采取类似SDL的方法,SFML就无法检测到这个问题。

相关内容

  • 没有找到相关文章