Я делаю простое графическое приложение на OSX. Я только начал контролировать частоту кадров, проверив разницу в системном времени между кадрами. Кажется, он висит немного каждые несколько кадров.Почему двойная буферизация OpenGL кажется непоследовательной по производительности?
Приложение работает на объекте NSTimer, в настоящее время установленном на 200 кадров в секунду (5 мс кадров). Чтобы убедиться, что не только мой основной код работает медленно, я прокомментировал весь основной цикл, за исключением [self.context flushBuffer]; (и, конечно, код выборки частоты кадров). Даже повторение этого единственного вызова заставляет его зависать в течение нескольких кадров за раз. Вот пример моего консольного вывода:
4
5
6
10
5
5
5
4
6
10
5
5
5
5
5
5
20
4
5
6
20
5
5
5
Это время в миллисекундах между каждой итерацией цикла. При скорости 200 кадров в секунду он должен составлять около 5 мс для каждого кадра, но он несколько раз висит на 10, 15 или даже 20 мс. Vsyncing отключен, как вы можете видеть в моей функции -initOpenGL.
-(void)initOpenGL{
NSOpenGLPixelFormatAttribute attributes[] = {NSOpenGLPFADoubleBuffer, 0};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: attributes];
self.context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
[self.context setView:[self.window contentView]];
[self.context makeCurrentContext];
//Disable Vsync
int temp = 0;
[self.context setValues: &temp forParameter: NSOpenGLCPSwapInterval];
glViewport(0, 0, windowWidth, windowHeight);
glMatrixMode(GL_PROJECTION);
glOrtho(0, windowWidth, 0, windowHeight, -1, 100);
//Flip all textures right side up
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Edit, новая информация: Я могу подтвердить, что это что-то делать с двойной буферизацией против сингла. Когда я инициализирую NSOpenGLPixelFormat без атрибута DoubleBuffer, он отлично работает со скоростью 200 кадров в секунду. Принимая во внимание, что с этим атрибутом я продолжаю заикаться.
Спасибо, что ответили! Мне всегда казалось, что NSTimer является стандартом для управления частотой кадров на устройствах Apple; он, кажется, используется чаще, чем что-либо еще. Что было бы лучшей альтернативой? Кроме того, я опустил код рендеринга, потому что он, похоже, не имеет отношения к проблеме. Как я уже сказал, это происходит, даже когда все прокомментировано, и я буквально называю [context flushBuffer] ;. Поэтому представляется логичным, что мы можем исключить что-либо в моем коде (если я неправильно выполнил что-то в OpenGL). –
Я также немного сузил его немного; прочитайте редактирование на OP. –
Стандарт для управления частотой кадров на Apple, а также любая другая платформа, которую я знаю, это включить v-sync.Таймеры (или, что еще хуже, сон) не являются и никогда не были «стандартными» из-за их довольно непредсказуемого не-реального времени (в операционных системах, отличных от RT, например, OSX). Кроме того, использование таймера неразумно, потому что два разных часовых пояса (таймер приложения и v-sync) в конечном итоге всегда будут выходить из синхронизации (думаю, загорается индикатор на двух автомобилях!). Я не могу сказать, почему отключение двойной буферизации, похоже, «работает» лучше, но это не меняет того факта, что подход является ошибочным. – Damon