GL ES: ottimizzazione di shader di frammenti


8

Riepilogo: ottengo il rallentamento dell'FPS non appena provo a colorare gli sprite (cioè: moltiplica la trama con il colore nel frammento shader)

Dettagli:

Hardware: iPod touch 4

Sto disegnando 700 sprite sullo schermo usando glDrawArrays. E sì, sto raggruppando tutti questi in una singola chiamata di sorteggio. Di seguito mostra la struttura dei dati del vertice:

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

Sì, sto inviando colore con ciascun vertice perché devo selettivamente tingere alcuni sprite ma non altri. Di seguito è riportato il framment shader che sto usando:

varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

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

Fino ad ora funziona alla grande, dandomi 60 FPS completi !!!

MA

Non appena cambio lo shader di frammenti nel modo seguente (per consentire la colorazione):

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

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

Utilizzando la seguente trama 64x64 png contenente canale alfa, rendering con glEnable (GL_BLEND):

inserisci qui la descrizione dell'immagine

Le prestazioni scendono a 47 FPS solo a causa di questo singolo cambiamento {solo per moltiplicazione con ONE vector} (FPS misurato utilizzando strumenti xcode e detective OpenGL). Qualche idea su cosa sta succedendo?

Grazie.

Modificare:

Ho anche provato a rimuovere per attributo colore vertice:

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

E modificando lo shader di frammenti come segue:

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);
}

Funziona a 52 FPS per 700 sprite (un guadagno di soli 5 FPS). Quindi questa non è interpolazione, sembra che la moltiplicazione sia estremamente costosa. Solo questa UNICA moltiplicazione?


Hai vsync abilitato? I numeri potrebbero significare che dopo la modifica inizi a perdere ogni altro vsync, il che porta a 45 FPS in media.
msell,

Sto testando su iPhone 4, suppongo che vsync sia già abilitato per impostazione predefinita. A proposito, mostra 47 FPS in xcode Instruments, quindi penso che vsync non sia affatto un problema. Ma la mia vera domanda è: perché le prestazioni rallentano e come migliorarle?
fakhir,

1
La tua trama ha un canale alfa? Se la trama non ha un canale alfa e l'rgb viene moltiplicato con un vec3, disegna nuovamente a 60 fps?
Sarà

Sì, la trama ha un canale alfa. Si prega di vedere la trama allegata sopra.
fakhir,

2
SGX 535 single core, display ad alto DPI con una GPU non ha mai pensato di gestirlo. Le prestazioni della grafica a risoluzione nativa su quei dispositivi erano sempre orribili. Dovresti ridimensionare la risoluzione o scegliere come target 30 fps o come target hardware più recente. Ti aspetti miracoli da quella GPU. Non ci vuole molto per riempirlo.
Sean Middleditch,

Risposte:


2

Non credo che il problema di prestazioni sta accadendo sulla moltiplicazione, ma sul interpolazione della vostra DestinationColorattraverso i triangoli, tra il vertice e shader frammento. Hai quattro floats da interpolare tra i vertici dell'albero, per ogni frammento per ogni sprite.

Per 700 sprite 64x64 pixel ciascuno, si tratta di 11468800 operazioni aggiuntive per frame che si richiede alla GPU di eseguire. È del tutto possibile che ti mancheranno alcuni vsync e quindi scendere a 40 FPS.

Se vuoi che ogni vertice abbia un colore diverso, quindi puoi avere sfumature per ogni sprite, sei sfortunato. Ci sono anche altri trucchi che potresti voler provare, ma penso che non sia così.

Poiché ciò che sembra fare è colorare ogni sprite, è possibile ridurlo DestinationColora uniform, utilizzarlo direttamente nello shader di frammento e modificarlo per ogni chiamata. In questo modo non si verificheranno interpolazioni. Perderai l'intero batch, ma potresti essere in grado di raggruppare un po 'se li ordini per colore.


Ho modificato la domanda sopra e ho aggiunto alcuni dettagli. Fondamentalmente ho provato a togliere il colore per vertice e semplicemente moltiplicare la trama con un vettore COSTANTE, cioè: gl_FragColor = texture2D (TextureSampler, TexCoord) * vec4 (1.0,0.0,0,0,1,0); . Hai 52 FPS, un guadagno di quasi 5 FPS. Ma ancora troppo lento rispetto a nessuna tinta. Rallentamento di 8 FPS solo a causa di una moltiplicazione di un singolo vettore?
fakhir,

3
Ma non è una singola moltiplicazione - è ~ 11 milioni per frame.
Massimo Minimo

1
@fakhir La risoluzione del display di iPod Touch 4 è di 960x640 pixel. Sono 614400 pixel in totale. Si desidera eseguire il rendering di 700 sprite 64x64 pixel ciascuno. Sono 2867200 pixel, o quasi 5 volte l'intero schermo. Probabilmente hai ottenuto i tuoi 60 fps originali perché l'ottimizzatore ha capito cosa stavi facendo e probabilmente ha campionato l'immagine una volta sola, ma non aspettarti che ciò accada in tutti i casi. La programmazione grafica mobile è molto più limitata della programmazione desktop, quindi agisci di conseguenza.
Panda Pajama,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.