Ottimizzazione di un gioco XNA 2D


56

Ha senso implementare la logica per saltare gli oggetti di rendering al di fuori del viewport o non dovrei preoccuparmene e lasciare che sia il Framework a farlo?

Risposte:


79

L'abbattimento è un'ottimizzazione delle prestazioni. Quindi non ha senso farlo solo per il gusto di farlo. Devi avere una ragione.


La GPU (non XNA Framework) abbatte triangoli e pixel a una velocità incredibilmente elevata. Ogni triangolo inviato deve essere trasformato (tramite lo shader di vertice). Quindi elimina quelli che atterrano fuori dallo schermo. Quindi riempie i triangoli rimanenti, eliminando i pixel che sono fuori schermo. I pixel rimanenti vengono quindi disegnati sul buffer posteriore (tramite il pixel shader).

(Quando dico "allora", in realtà fa tutto questo in una pipeline massicciamente parallela.)

Quindi è molto raro e insolito che potresti dover abbattere singoli triangoli. Per raggiungere i limiti del vertice devi disegnare un numero assurdamente grande di triangoli. Per raggiungere i limiti di fill-rate, texture-fetch o pixel-shading, è generalmente necessario disporre di un'elevata complessità di profondità (nel qual caso l'abbattimento di finestre / frustum non sarà di aiuto).


Quindi di solito c'è poco o nessun costo per avere la geometria fuori dallo schermo.

Il costo, in particolare nel contesto del disegno di "oggetti" (di solito oggetti 3D), è in primo luogo quello di inviare tali oggetti alla GPU . Invia troppi oggetti e raggiungi il limite di batch (ottieni qualche migliaio di * batch per frame).

Consiglio di leggere questa risposta e questo mazzo di diapositive collegato per una descrizione approfondita dei lotti.

Per questo motivo, se si implementa l'abbattimento del frustum, è possibile ridurre il numero di batch inviati alla GPU. Se hai un batch limitato, questo ti può portare sotto il limite.


Ora, la tua domanda riguarda l'XNA 2D, quindi presumibilmente stai usando SpriteBatch. Questo è un po 'diverso.

Non è un errore che si chiama "Sprite Batch ". Quello che sta facendo è prendere gli sprite che disegni e fare il possibile per inviare tali sprite alla GPU nel minor numero di lotti possibile raggruppandoli insieme.

Ma SpriteBatch sarà costretto ad avviare un nuovo batch se:

  • Disegna più sprite di quanti ne possano contenere in un singolo batch (2048 sprite in XNA 4)
  • Cambia trama (ecco perché esiste un'opzione di ordinamento per trama)

Quindi l'abbattimento è un'ottimizzazione adatta se ci si imbatte nella prima. Se stai inviando un numero così elevato di sprite che finisci con troppi batch (probabilmente stai utilizzando anche la larghezza di banda, ma sono abbastanza sicuro che prima raggiungerai il limite di batch). Questo accadrà in genere solo se hai un mondo davvero enorme, quindi in questo caso puoi generalmente cavartela con una selezione molto semplicistica, veloce ma imprecisa.

Ora - Se stai disegnando con abbastanza texture-swap da superare il limite del batch, e molti di loro sono effettivamente fuori dallo schermo e la loro eliminazione ti porterebbe sotto il limite del batch. Quindi sì: l'abbattimento è un'ottimizzazione che funzionerà.

Tuttavia , una migliore ottimizzazione da perseguire in questo caso consiste nell'utilizzare atlanti texture (ovvero: fogli sprite). Ciò consente di ridurre il numero di texture-swap e quindi batch, indipendentemente da ciò che è sullo schermo o spento. (Questo è il motivo principale per cui puoi specificare un rettangolo di origine per i tuoi sprite.)


(Come sempre: questo è un consiglio sull'ottimizzazione delle prestazioni. Quindi dovresti misurare e comprendere le prestazioni del tuo gioco e quali limiti stai colpendo, prima di spendere per aggiungere ottimizzazioni.)


5
+1 Per aver menzionato di non fare l'abbattimento solo per il gusto di farlo, ma quando è necessario per le prestazioni contano.
Will Marcouiller

12
+1 per avermi finalmente detto che i fogli sprite hanno davvero un motivo per esistere se non per comodità di programmatore / designer
Bill

3
+1 per una grande spiegazione, ho imparato molto dalla tua risposta.
Jesse Emond

1
Il collegamento al pdf "Batch, Batch, Batch" è interrotto. Eccone uno aggiornato: ce.u-sys.org/Veranstaltungen/…
Marton

13

Secondo un post sui forum di MSDN, il framework XNA non elimina la frustum:

Il framework XNA non farà alcuna scelta di frustum per te - non potrebbe essere perché non ha idea di dove finirà qualcosa. Tutte le trasformazioni vengono eseguite sulla GPU e potrebbero essere uno shader personalizzato.

http://xboxforums.create.msdn.com/forums/p/22763/121897.aspx

Questo post continua dicendo che se hai molti oggetti nella tua scena, potrebbe valere la pena di farne uno tuo.


6
Soprattutto se hai una mappa a scorrimento (hai detto che era in 2D, quindi potrebbe essere rilevante). È solo uno spreco se disegni sezioni grandi che non sono necessarie. Non è tremendamente difficile e potresti vedere qualche tipo di miglioramento.
Michael Coleman,

1

Ho sviluppato motori procedurali per voxel da alcuni anni a XNA. Nella maggior parte dei frame, i motori stanno letteralmente trasformando centinaia di migliaia di quad. Nella mia profilazione, ho scoperto che l'abbattimento di frustum e occlusione migliora le prestazioni.

Il profilo XNA HiDef (non Reach) ha una classe OcclusionQuery che viene utilizzata per eseguire Occlusion Culling. La soppressione dell'occlusione rimuove quei quadratini da una finestra che sono nascosti alla vista da altri quadranti.

Qualcos'altro che dovresti prendere in considerazione è contrastare sia la generazione che la tassellatura separatamente.

Quindi sì, quando ti avvicini a un numero molto elevato di quadrupedi in ogni fotogramma che vengono trasformati, devi pensare attentamente a come applicare le tecniche di abbattimento e threading per mantenere la frequenza dei fotogrammi, riducendo il traffico verso gli shader gpu.

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.