2011-12-14 7 views
19

Stavo leggendo this articolo, e l'autore scrive:È scarto negativo per le prestazioni del programma in OpenGL?

Ecco come scrivere applicazioni ad alte prestazioni su ogni piattaforma in due semplici passaggi:
[...]
seguire le migliori pratiche. Nel caso di Android e OpenGL, questo include cose come "batch draw calls", "non usare scarto in frammenti shader" e così via.

Non ho mai sentito dire che lo scarto avrebbe un impatto negativo sulle prestazioni o simili e lo abbiamo utilizzato per evitare la fusione quando non è stato necessario un alfa dettagliato.

Qualcuno potrebbe spiegare perché e quando utilizzare lo scarto potrebbe essere considerato una cattiva pratica e come scartare + approfondimento si confronta con la combinazione alpha +?

Modifica: Dopo aver ricevuto una risposta a questa domanda, ho eseguito alcune verifiche eseguendo il rendering di un gradiente di sfondo con un quadratino di trama.

  • Uso GL_DEPTH_TEST e un frammento shader termina con la linea "if( gl_FragColor.a < 0.5){ discard; }" dato circa 32 fps.
  • La rimozione dell'istruzione if/discard dallo framment-shader ha aumentato la velocità di rendering di a circa 44 fps.
  • Uso GL_BLEND con la funzione blend "(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)" anziché GL_DEPTH_TEST anche portato a circa 44 fps .
+0

Domanda molto interessante, spero che qualcuno sarà in grado di rispondere. – bvd

risposta

16

È dipendente dall'hardware. Per l'hardware PowerVR e altre GPU che utilizzano il rendering basato su tile, utilizzando discard significa che il TBR non può più presumere che ogni frammento disegnato diventerà un pixel. Questa ipotesi è importante perché consente al TBR di valutare tutte le profondità prima, quindi valutare solo gli ombreggiatori di frammenti per i frammenti più in alto. Una sorta di approccio di rendering differito, tranne che nell'hardware.

Si noti che si otterrebbe lo stesso problema attivando il test alfa.

+1

Ah, capisco. Quindi, se si usa lo scarto, avrà effetto su ogni tessera, o solo su quello in cui un frammento è stato scartato? Se interessa solo una tessera, dovrebbe comunque essere più efficiente di usare alpha/blending, corretto? – Jave

+1

Cosa intendi con "alpha/blending"? In ogni caso, interesserà ogni riquadro che esegue uno shader di frammenti che utilizza la parola chiave 'scarta', indipendentemente dal fatto che la chiami o meno. –

+0

Con alpha/blending, intendo semplicemente usare una texture con una alphamap per determinare la visibilità del frammento corrente. Se ricordo che non funziona correttamente, a meno che GL_BLEND non sia abilitato e non GL_DEPTH_TEST (se si esegue il rendering di un oggetto davanti ad un altro oggetto, ad esempio)? – Jave

17

"scarto" è negativo per ogni tecnica di accelerazione grafica mainstream - IMR, TBR, TBDR. Questo perché la visibilità di un frammento (e quindi la profondità) è determinabile solo dopo l'elaborazione del frammento e non durante l'HSR di Early-Z o PowerVR (rimozione di superfici nascoste) ecc. Più in basso la pipeline grafica viene rilevata prima della rimozione per indicare il suo effetto su prestazione; in questo caso più elaborazione di frammenti + interruzione dell'elaborazione in profondità di altri poligoni = cattivo effetto

Se è necessario utilizzare lo scarto, assicurarsi che solo il tris che ne ha bisogno sia reso con uno shader che lo contiene e, per minimizzare il suo effetto su prestazioni di rendering complessive, renderizza i tuoi oggetti nell'ordine: opaco, scartato, miscelato.

Per inciso, solo l'hardware PowerVR determina la visibilità nella fase posticipata (quindi è l'unica GPU definita "TBDR"). Altre soluzioni possono essere basate su tile (TBR), ma stanno ancora utilizzando le tecniche Early Z dipendenti dall'ordine di presentazione come fa un IMR. I TBR e i TBDR fanno il blending su chip (più veloce, meno affamato di energia rispetto alla memoria principale), quindi la fusione dovrebbe essere favorita per la trasparenza. La normale procedura per rendere correttamente i poligoni miscelati è disabilitare le scritture di profondità (ma non i test) e renderizzare tris in ordine di profondità back-to-front (a meno che l'operazione di fusione non sia indipendente dall'ordine). Spesso lo smistamento approssimativo è abbastanza buono. La geometria dovrebbe essere tale da evitare ampie aree di frammenti completamente trasparenti. Più di un frammento viene ancora elaborato per pixel in questo modo, ma l'ottimizzazione della profondità HW non viene interrotta come con i frammenti scartati.

+0

"la visibilità di un frammento (e quindi la profondità) è determinabile solo dopo l'elaborazione del frammento e non durante l'HSR di Early-Z o PowerVR (rimozione di superfici nascoste) ecc." Questo non è completamente vero. O Early-Z o scarto può impedire che un frammento venga disegnato. Quindi è molto possibile fare uno e poi l'altro. PowerVR non può per le ragioni che tu e io abbiamo affermato. Ma i renderizzatori tradizionali certamente possono. In caso contrario, sarebbe solo perché la logica di scartamento è associata alla logica di test di profondità. Questo è un problema di progettazione hardware, non una necessità algoritmica. –

+0

Ho omesso il caso in cui un frammento di scarto viene reso "dietro" alla geometria esistente: S - è questo che intendi? Sia la prima Z che HSR rifiuteranno i frammenti senza elaborazione dei frammenti in quella situazione. Anche in questo caso, Early-Z richiede che i frammenti oscuranti siano resi prima che gli oscurati, gli scarti o lo shader degli scarti debbano ancora essere eseguiti affinché tali frammenti determinino la profondità. HSR non dipende dall'ordine di presentazione in questo caso - alla fine di un frame, se i frammenti di scarto sono dietro a frammenti opachi, questi non vengono elaborati da PowerVR. – gmaclachlan

+0

Impossibile eseguire il rendering di un frammento per molte ragioni. Il test di profondità è uno, lo scarto è un altro. Early-Z esegue semplicemente il test di profondità prima. L'unico motivo per cui lo scarto potrebbe interferire con questo è se la logica di scarto fosse legata alla logica del test di profondità nell'hardware. Solo perché qualcosa passa il test di profondità non significa che passerà tutto. Se la profondità e lo scarto sono accoppiati, è solo perché l'hardware è costruito in quel modo, non perché * deve * essere fatto in quel modo dall'algoritmo. Dovresti essere in grado di eseguire i test Early-Z e poi ancora scartare. –

1

L'oggetto A si trova di fronte all'oggetto B. L'oggetto A ha uno shader che utilizza "scarta". Come tale, non posso fare correttamente 'Early-Z' perché ho bisogno di sapere quali sezioni dell'Oggetto B saranno visibili attraverso l'Oggetto A. Ciò significa che l'Oggetto A deve passare attraverso la pipeline di elaborazione fino quasi all'ultimo momento (fino all'elaborazione del frammento) prima di poter determinare se l'oggetto B è effettivamente visibile o meno.

Questo è un problema per HSR e 'Early-Z' poiché gli oggetti potenzialmente occlusi devono sedersi e attendere che le informazioni sulla profondità vengano aggiornate prima che possano essere elaborate. Come detto sopra, è un male per tutti, o, in un modo un po 'più amichevole, "Amici non permettete agli amici di usare Scarta".

2

Inoltre, la semplice istruzione "if" nel framment shader può causare un grosso rallentamento su alcuni componenti hardware. (In particolare, le GPU pesantemente pipeline, o che eseguono istruzioni singole/dati multipli, avranno grosse penalizzazioni in termini di prestazioni dalle dichiarazioni del ramo.) Quindi i risultati del test potrebbero essere una combinazione dell'istruzione "se" e degli effetti menzionati da altri.

(Per quel che vale, il test sul mio Galaxy Nexus ha mostrato un'enorme accelerazione quando sono passato all'analisi di profondità dei miei oggetti semitrasparenti e li ho riportati in primo piano, invece di eseguire il rendering in ordine casuale e scartare i frammenti nello shader.)

Problemi correlati