¿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.

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

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.

  • Vertex Buffer Objects (VBO) no funciona en Android 2.3.3, con GLES20
  • Error al intentar obtener Alraedy creado Surface y recibir EGLNativeWindowType ya conectado a otro error de API
  • Problemas de prueba OpenGL ES2 Alpha
  • ¿Es posible deformar la imagen subyacente con OpenGL ES 2.0?
  • Error "Permiso denegado" al instalar apk en el dispositivo
  • Cómo depurar el error de OPENGL ES 2.0 en Nexus 4 sin tener el dispositivo?
  • GlDepthMask (GL_FALSE) trashes el búfer de cuadros en algunas GPUs
  • Android: Descripción de OnDrawFrame, FPS y VSync (OpenGL ES 2.0)
  • ¿Hay alguna forma de comprobar si el dispositivo Android es compatible con openGL ES 2.0?
  • Android.grapics.matrix to OpenGL 2.0 ES traducción de la textura
  • Cómo renderizar la imagen de la cámara YUV-NV21 de Android en el fondo en libgdx con OpenGLES 2.0 en tiempo real?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.