2014-01-07 1 views
0

У меня очень простое приложение, которое отображает квадрат с opengl, входные данные считываются с помощью GLSurfaceView, а последняя позиция обменивается с потоком рендеринга с использованием изменчивой переменной.В чем причина (ы) задержки ввода/отображения в андроиде?

То, что я наблюдаю (а также было хорошо описано в https://www.mail-archive.com/[email protected]/msg235325.html), заключается в том, что между положением касания и дисплеем существует задержка (задержка).

При активации опции для разработчиков, чтобы показать позицию прикосновения, я вижу, что при быстром движении:

  • круга отслеживание сенсорного положения, показанном в системе 1 см отсроченных по сравнению с моим положением пальца. Я предполагаю, что это зависит от системы/оборудования и не может быть исправлено приложением.

  • но движение, сделанное в моем приложении, также откладывается на 1 см после круга отладки. Так что на практике задержка вдвое больше, чем может быть.

Когда движение пальца замедляется, конечная позиция чертежа останавливается и текущее положение касания синхронизируется. Точно так же, как показано в этом видео (ссылка найдена в обсуждении выше) http://www.youtube.com/watch?v=fWZGshsXDhM

По-прежнему я не знаю, что вызывает вторую задержку, я назначил время обмена позиции из onTouchEvent на поток рендеринга, и это только несколько мс. Рендеринг происходит с частотой 18 мс.

Я попытался использовать скорость, чтобы сократить время задержки, предсказав положение 18 мс, но это не изменило восприятие задержки.

Есть ли у кого-то объяснение такого рода задержки? Это связано с системными слоями, прежде чем получить доступ к нему в onTouchEvent? В случае с я не видел никакого способа исправить это.

Не было никакого конкретного ответа в группе google. Также меня беспокоит то, что в потоке упоминается, что задержка исчезает с использованием canva вместо OpenGL. Что вызывает больше вопросов, на которые он отвечает.

+1

Это входная латентность, классическая проблема, связанная с асинхронной работой CPU/GPU. Большинство реализаций GL будут принимать и возвращаться из команд независимо от того, являются ли они полными или нет, и это может привести к тому, что команды с несколькими кадрами будут стоять в очереди в любой момент времени. Прежде чем команды, полученные из пользовательского ввода, пробиваются к окончательному отображаемому изображению, все остальные команды в очереди должны заканчиваться первым. Кроме того, действительно ли дисплей вашего устройства работает с частотой обновления или 55,5 Гц, или вы произвольно выбрали 18 мс в качестве вашего интервала обновления? –

+0

Вы можете выпустить 'glFinish (...)' в стратегических точках, чтобы уменьшить количество «рендеринга», но вы как бы нарушаете современный принцип проектирования компьютерной графики в реальном времени ..., который должен поддерживать Процессор и графический процессор работают асинхронно. Это кратко обсуждается [здесь] (http://www.opengl.org/wiki/Swap_Interval#GPU_vs_CPU_synchronization). –

+0

@ Поведение Andon Tbe выглядит так, как вы описали: как будто кадр был поставлен в очередь. Следуя вашему предложению, я попытался вызвать glFinish и glFlush, но это не изменило поведения. Время в 18 мс - среднее, я просто его измеряю. – yves

ответ

1

Недавно я изучал то же самое. Там хорошее объяснение Android графиков стека Внутренности здесь:

https://source.android.com/devices/graphics/architecture.html

По существу SurfaceViews на андроид представляет конец продуцента очереди буфера. Потребителем этих буферов является SurfaceFlinger, который обрабатывает обновление отображаемых поверхностей на следующем vsync. Главное, что это очередь. Выполнение eglSwapBuffers фактически не блокирует , если очередь не заполнена. Это означает, что если ваш рендеринг прост, GLSurfaceView очень быстро создает первые несколько кадров, заполняя буферную очередь, а затем переходит в устойчивое состояние «рендеринга каждые 16 мс».

Вы можете увидеть количество заполненных буферов в очереди с помощью systrace. Вы заметите, что GLSurfaceView обычно запускает период vsync с 1 кадром в очереди, когда ваша функция рендеринга заканчивается, это доходит до 2, что означает, что вам нужно будет ждать 2 vsyncs перед ее отображением (фактически, 3, я думаю, потому что SurfaceFlinger добавляет еще один для композиции, но это то же самое для всех).

Холст рисуется по требованию, а не постоянно, и поскольку этот чертеж обычно происходит намного меньше, чем скорость обновления дисплея, BufferQueue для этого окна обычно пуст, поэтому новый контент потребляется немедленно SurfaceFlinger на следующем vsync.

Вы можете зарегистрироваться для обратных вызовов на vsync, чтобы вы никогда не отображали больше, чем частоту обновления дисплея. Это позволяет избежать эффекта «заполнить очередь как можно быстрее» непрерывного рендеринга GLSurfaceView. Однако я не уверен, что гарантия не будет заполнена, так как возможно, что SurfaceFlinger пропустит бит, в результате чего ваша очередь будет расти в любом случае. У меня есть вопрос о том, что здесь:

Minimize Android GLSurfaceView lag

Я сделал тест, где я вынести на VSync, но пропустить несколько кадров каждые несколько сотен, чтобы гарантировать очередь очищается должным образом. В этом случае объекты, созданные GL-объектами, перемещаются в блокировку с помощью перекрестия наложения «указательный след».«Круг отладки», похоже, все еще немного впереди - я думаю, что это реализовано как простая перестановка слоя во время композиции SurfaceFlinger нарисованных поверхностей, которая добавила бы дополнительный кадр перед другим рендерингом.

0

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

События ввода выдаются через поток пользовательского интерфейса Android, а рисунок - в потоке OpenGL приложения. Предполагая, что ваше тестовое приложение выполнено, как связанный с вами (оптимизированный) пример, вы устанавливаете переменную x и y в потоке пользовательского интерфейса и используете те, которые используются в потоке чертежа без синхронизации. На многоядерном процессоре (как в современных телефонах, таких как S3), скорее всего, эти протечки работают на разных ядрах (поскольку поток OGL активен все время). Таким образом, каждое ядро ​​имеет кешированную версию ваших x и y переменных, которые не гарантируются для немедленного обновления с другим ядром.

Эта проблема может быть решена путем внесения переменных volatile. Из спецификации Java 7:

Язык программирования Java позволяет потокам получать доступ к общим переменным (§17.1).Как правило, для обеспечения постоянного и надежного обновления общих переменных поток должен гарантировать, что он имеет исключительное использование таких переменных, получая блокировку, которая, как правило, обеспечивает взаимное исключение для этих общих переменных.

Язык программирования Java предоставляет второй механизм, изменчивые поля, который более удобен, чем блокировка для некоторых целей.

Поле может быть объявлено изменчивым, и в этом случае модель памяти Java гарантирует, что все потоки будут видеть согласованное значение для переменной (§17.4).

Последний комментарий в группе, которую вы связали, также предлагает это решение (это, вероятно, последний комментарий, потому что он сработал). Он также комментирует проблему использования двух изменчивых переменных, которые всегда используются и обновляются вместе (иногда вы можете увидеть эффект первой обновленной переменной, но не второй для одного кадра). Лучшим решением является использование для этого ONE volatile variable или применение механизма блокировки, который также обеспечивает атомарность.

Я написал несколько приложений OpenGL и никогда не сталкивался с этой проблемой «входного лага», всегда используя изменчивые переменные. Конечно, вы должны ожидать, что на дисплее будет один кадр за входом, потому что вы только обновляете входные данные один раз за кадр. Таким образом, ваш объект, находящийся за рамкой отладки, кажется совершенно нормальным.

+0

Я уже использую переменную volatile, как вы описали, поэтому это не должно быть проблемой синхронизации. – yves

Смежные вопросы