GL ES: optimización del sombreador de fragmentos

8

Resumen: obtengo la desaceleración de FPS tan pronto como trato de teñir los sprites (es decir: multiplico la textura con el color en el sombreador de fragmentos)

Detalles:

Hardware: iPod touch 4

Estoy dibujando 700 sprites en la pantalla usando glDrawArrays. Y sí, estoy agrupando todo esto en una sola llamada de sorteo. A continuación se muestra la estructura de datos de Vertex:

struct Vertex {
    float Position[2];
    float Color[4];
    float Texture[2];
};

Sí, estoy enviando color con cada vértice porque selectivamente necesito teñir algunos sprites pero no otros. El siguiente es el fragment shader que estoy usando:

varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord );
}

¡Hasta ahora está funcionando GENIAL, dándome 60 FPS completos!

PERO

Tan pronto como cambie el sombreador de fragmentos a lo siguiente (para permitir el tinte):

varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * DestinationColor;
}

Usando la siguiente textura png de 64x64 que contiene un canal alfa, renderizado con glEnable (GL_BLEND):

ingrese la descripción de la imagen aquí

El rendimiento cae a 47 FPS solo debido a este cambio único {simplemente por multiplicación con UN vector} (FPS medido usando instrumentos xcode y detective OpenGL). Alguna idea de lo que está pasando ?

Gracias.

Editar:

También he intentado eliminar por atributo de color de vértice:

struct Vertex {
    float Position[2];
    float Texture[2];
};

Y modificando el sombreador de fragmentos de la siguiente manera:

precision lowp float;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * vec4(1.0,0.0,0.0,1.0);
}

Está funcionando a 52 FPS para 700 sprites (una ganancia de solo 5 FPS). Entonces esto no es interpolación, parece que la multiplicación es extremadamente costosa. ¿Solo esta UNA multiplicación?

fakhir
fuente
¿Tienes vsync habilitado? Los números podrían significar que, después del cambio, empiezas a perderte cualquier otro vsync, lo que lleva a 45 FPS en promedio.
msell
Estoy probando en el iPhone 4, supongo que vsync ya está habilitado de forma predeterminada. Por cierto, muestra 47 FPS en xcode Instruments, así que creo que vsync no es realmente un problema en absoluto. Pero mi verdadera pregunta es: ¿por qué el rendimiento se ralentiza y cómo mejorarlo?
fakhir
1
¿Tu textura tiene un canal alfa? Si la textura no tiene un canal alfa y el rgb se multiplica por un vec3, ¿vuelve a dibujar a 60 fps?
Será
Sí, la textura tiene canal alfa. Por favor vea la textura adjunta arriba.
fakhir
2
El núcleo único SGX 535, pantalla de alta resolución con una GPU nunca tuvo la intención de manejarlo. El rendimiento de los gráficos en resolución nativa en esos dispositivos siempre fue horrible. Debería reducir la resolución o apuntar a 30 fps o apuntar a un hardware más nuevo. Estás esperando milagros de esa GPU. No se necesita mucho para depositarlo.
Sean Middleditch

Respuestas:

2

No creo que el problema de rendimiento esté sucediendo en la multiplicación, sino en la interpolación de DestinationColorlos triángulos, entre los sombreadores de vértices y fragmentos. Tienes cuatro floats para interpolar entre los vértices de los árboles, para cada fragmento para cada sprite.

Para 700 sprites de 64x64 píxeles cada uno, esto es 11468800 operaciones adicionales por fotograma que le está pidiendo a la GPU que realice. Es muy posible que te falten algunos vsyncs y, por lo tanto, caigas a 40 FPS.

Si quieres que cada vértice tenga un color diferente, para que puedas tener gradientes para cada sprite, no tienes suerte. También hay otros trucos que quizás quieras probar, pero creo que este no es el caso.

Dado que lo que parece estar haciendo es teñir cada sprite, puede degradarlo DestinationColora a uniform, usarlo directamente en el sombreador de fragmentos y cambiarlo para cada llamada. De esa manera no se realizarán interpolaciones. Perderá el lote completo, pero es posible que pueda procesar un poco si los ordena por color.

Pijama Panda
fuente
Edité la pregunta anterior y agregué algunos detalles. Básicamente intenté eliminar por color de vértice y simplemente multipliqué la textura con un vector CONSTANTE, es decir: gl_FragColor = texture2D (TextureSampler, TexCoord) * vec4 (1.0,0.0,0.0,1.0); . Obtuve 52 FPS, una ganancia de casi 5 FPS. Pero sigue siendo demasiado lento en comparación con ningún tinte. ¿Desaceleración de 8 FPS solo debido a una multiplicación de un solo vector?
fakhir
3
Pero no es una sola multiplicación, es ~ 11 millones por cuadro.
Maximus Minimus
1
@fakhir La resolución de la pantalla del iPod Touch 4 es de 960x640 píxeles. Eso es 614400 píxeles en total. Desea renderizar 700 sprites de 64x64 píxeles cada uno. Eso es 2867200 píxeles, o casi 5 veces la pantalla completa. Probablemente obtuvo sus 60 fps originales porque el optimizador descubrió lo que estaba haciendo y posiblemente muestreó la imagen solo una vez, pero no espere que eso suceda en todos los casos. La programación gráfica móvil es mucho más limitada que la programación de escritorio, así que actúe en consecuencia.
Panda Pyjama