SFML vsync всегда включен?

Я играл с игровыми циклами и физикой. На днях я добавил несколько отладочных операторов, чтобы посмотреть, сколько времени занимает каждый кадр моего игрового цикла. Как и ожидалось, результаты были в диапазоне 16 мс. Однако я попытался отключить vsync, и эти результаты не изменились. Очевидно, что vsync все еще происходил. Я закомментировал вызов дисплея SFML и, конечно же, ускорил кадры.

Хорошо, тогда почему vsync зависает? Сначала я подумал, что это ошибка в DSFML (привязки SFML для языка D). Я создал простой тестовый пример в C++, который использует SFML напрямую, и характеристики производительности точно такие же!

Моя система выглядит следующим образом:

$ inxi -SMG
Система: Хост: c7 Ядро: 3.16.4-1-ARCH x86_64 (64 бит) Рабочий стол: i3 4.8 Дистрибутив: Arch Linux Машина: Система: Google продукт: Parrot v: 1.0
Mobo: N / A модель: N/A Bios: coreboot v: 4.0-4744-gac16405-dirty дата: 23.10.2013
Graphics: Card: интегрированный графический контроллер семейства процессоров Intel второго поколения.
Сервер дисплея: X.Org 1.16.1 драйвер: intel Разрешение: 1366x768@60.02hz
GLX Renderer: 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 в этом тесте и вижу время кадра в диапазоне 0 мс, как и ожидалось! Итак, способ, которым SFML реализует vsync, содержит ошибки в моей системе, в то время как SDL, похоже, справляется с этим правильно.

Какая разница в реализации между двумя библиотеками, вызывающая это разное поведение, и можно ли ее устранить? Как бы я получить правильное поведение с SFML?

1 ответ

Решение

Это глючный драйвер. glXSwapIntervalMESA работает. Указатель, возвращаемый для glXSwapIntervalSGI, действителен, поэтому SFML не может обнаружить эту проблему, не применяя подход, аналогичный SDL.

Другие вопросы по тегам