android - requiere - Dibujando rutas y aceleración de hardware
gpu de renderizado de opengl nvidia (3)
Estoy dibujando un camino bastante grande en mi opinión y estoy teniendo algunos problemas de rendimiento. El camino tiene actualmente 32,000 puntos, pero mi aplicación debería escalar al menos a 128,000 puntos. Realmente no puedo hacer nada sobre el tamaño de la ruta, ya que los conjuntos de datos son tan grandes y necesito poder mostrar toda la ruta a la vez y permitir el acercamiento.
Estoy usando un Nexus 10 con Android 4.2, que tiene habilitada la aceleración de hardware por defecto para las aplicaciones que no lo deshabilitan explícitamente.
La ruta se crea con el siguiente código (omití algunas configuraciones y otras partes irrelevantes):
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);
}
Y luego dibujado en el método onDraw()
:
canvas.drawColor(Color.WHITE);
canvas.drawPath(dataPath, linePaint);
adb shell dumpsys gfxinfo
el tiempo que lleva dibujar mi vista usando adb shell dumpsys gfxinfo
con y sin aceleración de hardware, y para mi sorpresa, la aceleración del hardware es mucho más lenta:
Con aceleración de hardware:
Sin aceleración de hardware:
La versión acelerada por hardware tarda alrededor de 200-300 ms por trama, la mayor parte se gasta en la etapa de Proceso. La versión no acelerada tarda alrededor de 50 ms, con 2/3 en la etapa de Draw y 1/3 en la etapa de proceso.
Obviamente, incluso mi versión más rápida sin aceleración de hardware es aún demasiado lenta para alcanzar 60 fps, o para ser apenas utilizable cuando me desplazo a conjuntos de datos más grandes.
La idea de renderizar la ruta a un mapa de bits y luego solo transformar ese mapa de bits para que se ajuste a la pantalla también es problemático en mi caso. Necesito apoyar el acercamiento muy lejos en la ruta, y para permitir el acercamiento sin que la calidad de la ruta empeore, tendría que renderizar mapas de bits sobredimensionados de la ruta (y probablemente se toparía con los límites de memoria y los límites de tamaño de la textura). Y al acercarme mucho, tendría que crear imágenes más recientes de solo partes de la ruta, o simplemente procesar la ruta directamente, lo que probablemente generaría demoras mayores que la velocidad de cuadros si el rendimiento es similar al que tengo ahora ahora.
Lo que me pregunto ahora es
- ¿Dibujar líneas / rutas es algo en lo que la GPU es mala y que no se debe intentar acelerar el hardware, o es probable que esté haciendo algo mal que causa el mal rendimiento?
- ¿Hay algo que pueda hacer para dibujar caminos tan grandes con un rendimiento aceptable?
¿Dibujar líneas / rutas es algo en lo que la GPU es mala y que no se debe intentar acelerar el hardware, o es probable que esté haciendo algo mal que causa el mal rendimiento?
Las rutas siempre se renderizan usando la CPU. Cuando la aplicación está acelerada por hardware, esto significa que el renderizador primero dibujará su ruta usando la CPU en un mapa de bits, luego cargará ese mapa de bits como una textura a la GPU y finalmente dibujará la textura en la pantalla.
Las líneas están completamente aceleradas por hardware. En lugar de utilizar un Path
le recomiendo que use Canvas.drawLines()
en este caso.
¿Hay algo que pueda hacer para dibujar caminos tan grandes con un rendimiento aceptable?
Debe usar Canvas.drawLines()
o renderizar la ruta usted mismo en un Bitmap
que administre.
Dibujar un camino implicará algo más que simplemente "decirle" a la GPU que dibuje líneas. Un camino tiene muchas características, por ejemplo, cómo se tratan los extremos de las líneas o se puntea una línea, algo que no está acelerado por GPU. Probablemente haya otro aumento cuando encuentre tantas líneas que hace que la combinación de aceleración de CPU y GPU sea más lenta. La solución sugerida anterior para pasar a canvas.drawLines
lugar de canvs.drawPath
y tratar de no usar un método de Paint
fantasía podría ayudar.
Si eso no ayuda, puede intentar usar un GLSurfaceView y representar líneas directamente en ese lugar. Eso implicará algunos conocimientos de OpenGL ES, pero no debería ser increíblemente difícil de hacer y podría ser mucho más efectivo.
Parece que puede encontrarse con un cuello de botella general en la GPU. Eche un vistazo a los siguientes enlaces:
Cómo hacer que el trazado de ruta sea más eficiente
Rendimiento en tiempo real de la ruta de lienzo de Android
Especialmente el primero, que sugiere que se haga un mapa de bits y se dibuje en su lugar. Parece que puede obtener un mejor rendimiento si cambia a OpenGL. Puede haber alguna forma mágica de hacer funcionar el método existente, pero no estoy enterado de eso en este momento.
Por qué está viendo el comportamiento que hace es probablemente porque envía todos los datos a la GPU entre cada sorteo. Debería guardarlo en la GPU y utilizar la traducción en lugar. No recrea los datos y lo envía todo a la GPU. Probablemente estés vinculado a E / S , lo que significa que la velocidad de transmisión entre la CPU y la GPU es lo que limita tu rendimiento. No puedo estar 100% seguro de esto en base a los datos que me ha proporcionado, pero esa es mi mejor suposición. Pruebe diferentes técnicas de almacenamiento en caché, principalmente el png-caché del enlace n. ° 1.