¿Por qué está bloqueando glClear en OpenGLES?
Estoy tratando de perfil mi procesador, y estoy viendo un comportamiento de perfil extraño que no puedo explicar.
Estoy usando un glSurfaceView, que he fijado para hacer continuamente.
- La forma correcta de dibujar texto en OpenGL ES 2
- ¿Cómo se consigue rajawali para trabajar (tutorial 1 en git)
- Monitor de GPU de Android Studio no funcionará para OpenGLES2
- Implementación de problemas GLSurfaceView.Renderer
- La mejor práctica para usar Sprites en un juego usando AndEngine GLES2
Así es como mi onDrawFrame()
está estructurado
public void onDrawFrame(GL10 unused) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); executeAllDrawCommands(); }
Esto se comportaba lentamente bajo carga ligera, así que creé una clase de temporizador y comencé a perfilar esto. Me sorprendió mucho lo que vi.
Puse algunas sondas en mi método onDrawFrame así:
public void onDrawFrame(GL10 unused) { swapTimer.end(); clearTimer.start(); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); clearTimer.end(); drawTimer.start(); executeAllDrawCommands(); drawTimer.end(); swapTimer.start(); }
clearTimer
mide el tiempo que se tarda en llamar a glClear, drawTimer
mide el tiempo que tarda en ejecutar todas mis llamadas de draw y swapTimer
mide el tiempo desde que onDrawFrame sale y cuando regresa (el tiempo que se tarda en llamar a eglSwapBuffers).
Cuando corrí una escena muy ligeramente cargada, conseguí algunos números realmente extraños que no puedo explicar:
swapTimer : 20ms (average) clearTimer : 11ms (average) drawTimer : 2ms (average)
Esperaba que el tiempo de intercambio para ser un poco largish, ya que creo que el dispositivo tiene forzada vsync habilitar a ~ 30fps, aunque no sé por qué la llamada "claro" actual es el bloqueo de 11 milisegundos? Pensé que se suponía que debía emitir un comando asíncrono y volver?
Cuando dibujo una escena mucho más ocupada, los números cambian bastante:
swapTimer : 2ms (average) clearTimer : 0ms (average) drawTimer : 44ms (average)
En esta escena mis llamadas de dibujo están tomando tanto tiempo que parece que esconden mucho del período vsync, y el bloque en la llamada clara desaparece totalmente.
¿Hay alguna explicación de por qué glClear está bloqueando mi escena ligeramente cargada?
Enlace a mi código fuente de la clase 'Timer' en caso de que alguien sospeche de mi técnica de medición: http://pastebin.com/bhXt368W
- OpenGL ES 2.0 vs OpenGL 3 - Similitudes y diferencias
- Compartir el contexto EGL2.0 entre 2 GLSurfaceViews causó EGL_BAD_ACCESS en las tabletas Android
- Optimización de un dibujo VBO enorme en dispositivos Android / iOS
- Tamaños de textura razonables en android
- Fondos de Android Live con OpenGL ES 2.0?
- Cómo pasar los datos correctos a un programa de shader OpenGL-ES 2.0
- Cómo dibujar / hacer una colisión de física de bala cuerpo / forma?
- Uso del flujo de vídeo como textura abierta de GL ES 2.0
Pongo un glFinish (y finishTimer.start () / end () a su alrededor), y toma todo el tiempo lejos de glClear. Ahora glFinish toma un cierto número de milisegundos, y glClear se convierte en instantáneo.
Eso lo explica.
Cuando su escena es muy ligera y los dibujos son renderizados muy rápido, el tiempo para borrar y rellenar los píxeles con el nuevo color tomará algún tiempo (siempre tomará tiempo, de lo contrario el renderizador está detrás y es currenty dibujo nuevo material). Los dispositivos Android más nuevos tienen límites de llenado. Por ejemplo, Nexus One tiene un bloqueo de llenado a 30 Hz – la pantalla se sincronizará a esa frecuencia sin importar lo rápido que vayan los dibujos. Si los dibujos terminan por debajo de 30 Hz, el procesador se sincronizará con la pantalla. Esta es la razón por la que se nota este retraso, que debe observar incluso si quita la llamada glClear()
. El procesador es anterior y más rápido que las actualizaciones de la pantalla.
Cuando el renderizador tiene muchos objetos que dibujar, la sincronización se detendrá (dados los datos del perfil de la escena ocupada) porque el procesador está ahora después de las actualizaciones de la pantalla.
Cuando utiliza glFinish()
, elimina el tiempo que la función glClear()
podría causar, lo cual, siguiendo la lógica de fillrate, significa que glFinish()
es ahora la función que garantiza la sincronización con la pantalla.
Cálculos :
F = 1 / T
Escena fácil :
F = 1 / T = 1 / ((20 + 11 + 2) * 10 ^ -3) = ~ 30 Hz
El tiempo de retardo de sincronización aparece en su generador de perfiles. Renderer se está sincronizando con la pantalla. Esto significa que si quita la glClear()
o glFinish()
, la demora aparecería en otro lugar.
Escena pesada :
F = 1 / T = 1 / ((2 + 0 + 44) * 10 ^ -3)) = ~ 22 Hz
El tiempo de retardo de sincronización no aparece en su profiler. Renderer es después de la frecuencia de actualización de la pantalla.
Parece que esto está relacionado con vsync
Eso parece correcto.
- ¿Cómo obfuscate el proyecto con Dagger 2.0 usando Proguard?
- Android.os.FileUriExposedException: file.jpg expuesto más allá de la aplicación a través de ClipData.Item.getUri ()