¿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.
- Pasar atributos personalizados a un shader de fragmentos personalizado
- For-loop en código de sombreado que trabaja con un número codificado pero no con una variable uniforme
- OpenGL se bloquea al vincular el programa, LG Nexus 4
- Cómo renderizar vídeo a través de openGLES2 con Android NDK
- ¿Cómo acceder a OpenGL ES 2 a través de C ++ / NDK si EGL_NATIVE_RENDERABLE no es compatible?
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
- ¿Hay algún dispositivo Android con un tamaño de pantalla mayor que GL_MAX_TEXTURE_SIZE?
- Adreno 220 GLSL bug
- Android opengl-es-2.0 - explicación rotateM
- Cómo agregar ScrollView a GLSurfaceview en Opengl ES2.0 en Android
- ¿Cómo determinar si una subida de textura tuvo éxito en OpenGL ES 2?
- Problema de detección de colisiones basado en píxeles con OpenGLES 2.0 bajo Android
- No se puede lograr 60fps rendering quad simple, Android, Opengl ES 2.0
- Android GLES20.glBlendEquation no funciona?
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 ()