Пути рисования и аппаратное ускорение

Я рисую довольно большой путь на мой взгляд, и у меня возникают проблемы с производительностью. Путь в настоящее время составляет 32 000 точек, но мое приложение должно масштабироваться как минимум до 128 000 точек. Я не могу ничего сделать с размером пути, так как массивы данных просто такие большие, и мне нужно иметь возможность отображать весь путь сразу и разрешать масштабирование.

Я использую Nexus 10 под управлением Android 4.2, у которого есть аппаратное ускорение по умолчанию для приложений, которые явно не отключили его.

Путь создается со следующим кодом (я пропустил некоторые настройки и другие нерелевантные части):

dataPath.moveTo(0, offset - (float) data[leftLimit]/ scalingFactor); for (int i = leftLimit; i < rightLimit; ++i) { x = (i - leftLimit) * dx; y = offset - (float) data[i]/ scalingFactor; dataPath.lineTo(x, y); } 

И затем нарисован в onDraw() :

 canvas.drawColor(Color.WHITE); canvas.drawPath(dataPath, linePaint); 

Я измерил время, затрачиваемое на то, чтобы нарисовать мой взгляд, используя adb shell dumpsys gfxinfo с аппаратным ускорением и без него, и к моему удивлению ускорение аппаратного обеспечения происходит гораздо медленнее:

С аппаратным ускорением:

Введите описание изображения здесь

Без аппаратного ускорения:

Введите описание изображения здесь

Аппаратная ускоренная версия занимает около 200-300 мс за кадр, большую часть затраченного на этапе процесса. Не ускоряемая версия занимает около 50 мс, с 2/3 в стадии рисования и 1/3 на этапе процесса.

Очевидно, что даже моя более быстрая версия без аппаратного ускорения все еще слишком медленна, чтобы достичь 60 кадров в секунду, или даже едва использовать, когда я перехожу к более крупным наборам данных.

Идея визуализации пути к растровому изображению, а затем только преобразование этого растрового изображения в соответствии с экраном также проблематично в моем случае. Мне нужно поддерживать масштабирование очень далеко на пути, и чтобы включить масштабирование без ухудшения качества пути, мне пришлось бы отображать негабаритные растровые изображения пути (и, скорее всего, будут работать с ограничениями по памяти и ограничениями размера текстуры). И при масштабировании в далеком будущем мне придется либо создавать более новые изображения только частей пути, либо переключиться на просто визуализацию пути напрямую, что, вероятно, приведет к задержкам, превышающим частоту кадров, если производительность по-прежнему будет близка к тому, что у меня есть Теперь.

Теперь мне интересно,

  • Является ли рисование линий / путей просто чем-то, на чем работает графический процессор, и что не следует пытаться ускорить аппаратное ускорение, или я, вероятно, что-то неправильно делаю, что приводит к плохой производительности?
  • Есть ли что-нибудь, что я могу сделать, чтобы нарисовать такие огромные пути с приемлемой производительностью?

Является ли рисование линий / путей просто чем-то, на чем работает графический процессор, и что не следует пытаться ускорить аппаратное ускорение, или я, вероятно, что-то неправильно делаю, что приводит к плохой производительности?

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

Линии полностью аппаратно ускорены. Вместо использования Path я рекомендую использовать Canvas.drawLines() в этом случае.

Есть ли что-нибудь, что я могу сделать, чтобы нарисовать такие огромные пути с приемлемой производительностью?

Вы должны либо использовать Canvas.drawLines() либо сами сделать путь в Bitmap которым вы управляете.

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

Как сделать маршрут более эффективным

Эффективность воспроизведения в режиме холста Android

Переход с холста на OpenGL

Особенно первый, который предполагает, что вы делаете растровое изображение и рисуете это вместо этого. Похоже, вы можете получить лучшую производительность, если вы перейдете на openGL. Может быть какой-то волшебный способ заставить существующий метод работать, но я не знаю об этом в данный момент.

Почему вы видите поведение, которое вы делаете, вероятно, потому, что вы отправляете все данные на графический процессор между каждой ничьей. Вы должны кэшировать его на графическом процессоре и вместо этого использовать перевод. Не воссоздавать данные и отправлять их на GPU. Вероятно, вы связаны с I / O , что означает, что скорость передачи между CPU и GPU ограничивает вашу производительность. Я не могу быть на 100% уверен в этом, основываясь на данных, которые вы предоставили, но это мое лучшее предположение. Попробуйте различные методы кэширования, в основном png-cache из ссылки # 1.

При рисовании пути будет больше, чем просто «рассказывать» графическому процессору, чтобы рисовать линии. Путь имеет много характеристик, например, как обрабатываются концы строк или что линия пунктирна, что ускоряет GPU. Вероятно, есть еще один hickup, когда вы сталкиваетесь с таким количеством строк, что делает комбинацию ускорения процессора и графического процессора медленнее. Предлагаемое решение выше, чтобы перейти на canvas.drawLines вместо canvs.drawPath и попытаться не использовать причудливый метод Paint может помочь.

Если это не поможет, вы можете попытаться использовать GLSurfaceView и визуализировать строки непосредственно в этом. Это будет связано с некоторыми знаниями OpenGL ES, но не должно быть невероятно сложно сделать и может быть намного более эффективным.