我一直在玩游戏循环和物理。
前几天,我添加了一些调试语句,以查看游戏循环的每一帧花费了多少时间。
如预期的那样,结果在16ms范围内。
但是,我尝试禁用vsync,并且这些结果没有改变。
显然,vsync仍在发生。我注释掉了SFML显示调用,并确保足够的帧加速了。

好吧,那为什么还要继续使用vsync?起初,我认为这一定是DSFML(D语言的SFML绑定(bind))中的错误。我用C++创建了一个简单的测试用例,它直接使用SFML,并且性能特征完全相同!

我的系统如下:



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获得正确的行为?

最佳答案

这是一辆 buggy 司机。 glXSwapIntervalMESA起作用。为glXSwapIntervalSGI返回的指针是有效的,因此SFML如果不采取与SDL类似的方法就无法检测到此问题。

关于c++ - SFML vsync始终打开?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26437078/

10-11 07:45