Массивная задержка Android onDrawFrame()

У меня есть игра, использующая GLSurfaceView.Renderer обычным способом для рендеринга 3D-графики с помощью OpenGL ES 2.0. Весь код рендеринга находится в методе onDrawFrame(), и по времени его выполнение занимает около 24 мс; это легко даст результат 30 FPS. Однако я обнаружил, что сам вызов onDrawFrame() часто вызывается только каждые 50–100 мс, так что общее время onDrawFrame() на самом деле составляет от 70 до 120 мс, что дает в лучшем случае результат 14 кадров в секунду.

Почему Android так долго вызывает onDrawFrame()? Читая об этом в stackoverflow и других местах, я собираю onDrawFrame() «блокировок», пока графический процессор не отрендерит кадр, и поэтому мне интересно, может ли быть так, что рендеринг моего графического процессора занимает очень много времени, а не что-то конкретное в Android вызывает задержку?


person bevis    schedule 01.11.2014    source источник


Ответы (1)


Да, судя по вашему описанию, очень вероятно, что рендеринг на GPU ограничивает вашу частоту кадров.

Представьте, что ваши вызовы OpenGL передают работу графическому процессору. После завершения всего кода в вашем вызове onDrawFrame() это означает, что весь ваш рендеринг был отправлен на GPU. Но это не значит, что GPU завершил работу. Это может занять сколь угодно много времени, в зависимости от объема и сложности отправленной вами работы.

В Android система будет пытаться перерисовывать с частотой обновления экрана, которая обычно составляет 60 Гц. Но если GPU не может производить 60 кадров в секунду, потому что ваш рендеринг слишком сложен, нет смысла по-прежнему вызывать ваш метод onDrawFrame() 60 раз в секунду. Это приведет к тому, что все больше и больше работы GPU будет поставлено в очередь, что приведет к увеличению объема системных ресурсов, используемых для ожидающих выполнения команд GPU, и к увеличению задержки между вашим кодом, выполняющим вызовы рендеринга, и результатом, отображаемым на дисплее.

Чтобы избежать этого нежелательного поведения, система ограничивает вызовы onDrawFrame() до такой степени, что графический процессор может не отставать от рендеринга создаваемых вами кадров. Это может позволить вам получить 1 или 2 кадра раньше того, что уже сделал графический процессор, но затем будет блокироваться до тех пор, пока графический процессор не выполнит достаточно работы, прежде чем попросить вас нарисовать еще один кадр.

person Reto Koradi    schedule 01.11.2014