2009-03-24 1 views
4

Это то, что происходит:Что вызывает колебания времени выполнения при представлении Renderbuffer? (OpenGL)

  • Функция drawGL вызывается в точном конце кадра благодаря usleep, как это было предложено. Это уже поддерживает постоянную частоту кадров.

  • Фактическое представление renderbuffer имеет место с drawGL(). Измеряя время, необходимое для этого, дает мне колебания времени выполнения, что приводит к заиканию в моей анимации. Этот таймер использует mach_absolute_time, поэтому он очень точен.

  • В конце моей рамки я измеряю timeDifference. Да, это в среднем 1 миллисекунда, но он отклоняется от, от 0,8 миллисекунды до 1,2 с пиками до более чем 2 миллисекунд.

Пример:

// Every something of a second I call tick 
-(void)tick 
{ 
    drawGL(); 
} 

- (void)drawGL 
{ 
    // startTime using mach_absolute_time; 

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

// endTime using mach_absolute_time; 
// timeDifference = endTime - startTime; 
} 

Я понимаю, что после того, как фреймбуфер был создан, представляя renderbuffer всегда должно принимать такое же усилие, независимо от сложности кадра? Это правда? А если нет, как я могу это предотвратить?

Кстати, это пример приложения для iPhone. Поэтому мы говорим об OpenGL ES, хотя я не думаю, что это проблема конкретной платформы. Если это так, то что происходит? И не должно ли это быть не происходит? И снова, если да, как я могу предотвратить это?

ответ

1

Отклонения, с которыми вы сталкиваетесь, могут быть вызваны множеством факторов, включая планировщик ОС, который запускает и дает CPU другому процессу или аналогичным проблемам. На самом деле нормальный человек не скажет разницу между временем рендеринга 1 и 2 мс. Движущиеся изображения работают со скоростью 25 кадров в секунду, что означает, что каждый кадр отображается примерно на 40 мс, и он выглядит жидким для человеческого глаза.

Что касается анимационного заикания, вы должны изучить, как вы поддерживаете постоянную скорость анимации. Наиболее распространенный подход, который я видел, выглядит примерно так:

while(loop) 
{ 
    lastFrameTime; // time it took for last frame to render 
    timeSinceLastUpdate+= lastFrameTime; 

    if(timeSinceLastUpdate > (1 second/DESIRED_UPDATES_PER_SECOND)) 
    { 
    updateAnimation(timeSinceLastUpdate); 
    timeSinceLastUpdate = 0; 
    } 

    // do the drawing 

    presentScene(); 
} 

Или вы могли бы просто передать lastFrameTime на updateAnimation каждый кадр и интерполировать анимации состояний. Результат будет еще более жидким.

Если вы уже используете что-то вроде выше, возможно, вам стоит искать виновников в других частях цикла визуализации. В Direct3D дорогостоящими вещами были призывы к рисованию примитивов и изменению состояний отображения, поэтому вы можете проверить их аналоги с OpenGL.

+0

На самом деле, я уже провел время для расчетов, чтобы поддерживать стабильную частоту кадров. Фактический рисунок всегда имеет место в точном конце кадра. (Я использую для этого таймер сна) Я уточню вопрос для этого. – Kriem

0

Лучше не полагаться на высокую постоянную частоту кадров по ряду причин, самое главное, что ОС может что-то делать в фоновом режиме, что замедляет работу. Лучше пробовать таймер и определять, сколько времени прошло каждый кадр, это должно обеспечить плавную анимацию.

0

Возможно ли, что таймер не соответствует уровню субсчет, хотя он возвращает десятичные значения 0,8-> 2,0?

+0

Может быть. Это NSTimer. Несмотря на это, даже если частота кадров кажется заикающейся. – Kriem

1

Мое любимое выражение OpenGL всех времен: «конкретная реализация». Я думаю, что здесь очень хорошо.

+0

Не могли бы вы уточнить? – Kriem

+0

Я не думаю, что спецификатор абсолютно востребован тем, что время рендеринга для последующих кадров одного и того же контента должно быть абсолютно одинаковым. То есть, разработчику графического процессора, вероятно, разрешено изменять время. –

1

Быстрый поиск результатов mach_absolute_time в этой статье: Link

Похоже, точность этого таймера на iPhone с только 166,67 нс (и, возможно, хуже). Хотя это может объяснить большую разницу, это не объясняет, что есть разница вообще.

три основные причины, вероятно:

  • Различные пути исполнения во время renderbuffer презентации. Многое может произойти в 1 мс, и только потому, что вы вызываете одни и те же функции с одинаковыми параметрами, это не означает, что выполняются точные инструкции. Это особенно верно, если задействовано другое оборудование.
  • Прерывания/другие процессы, всегда происходит что-то еще, что отвлекает процессор. Насколько я знаю, iPhone OS не является операционной системой реального времени, поэтому нет гарантии, что какая-либо операция завершится в течение определенного срока (и даже ОС реального времени будет иметь временные вариации).
  • Если есть другие вызовы OpenGL, которые все еще обрабатываются графическим процессором, которые могут задержать presentRenderbuffer. Это проще всего проверить, просто вызовите glFinish(), прежде чем начать время начала.
Смежные вопросы