Подтвердить что ты не робот

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

Я рисую довольно большой путь в моем представлении, и у меня возникают проблемы с производительностью. Путь в настоящее время составляет 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 с аппаратным ускорением и без него, и, к моему удивлению, аппаратное ускорение происходит гораздо медленнее:

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

enter image description here

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

enter image description here

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

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

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Активность в режиме реального времени в холдинге Android

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

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

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

Ответ 3

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

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