Usando l'istanzia per tutto?


16

L'istanza migliora le prestazioni (in modo significativo) quando si esegue il rendering di più copie (della stessa quantità?) Della stessa mesh contemporaneamente. Ma quanto overhead ha quando si esegue il rendering esattamente di una copia con una chiamata di disegno? Sarebbe una buona o una cattiva idea usare l'istanziamento per tutta la geometria resa dal motore?

Modifica: supponiamo di creare un gioco FPS. La maggior parte degli oggetti ha un solo esempio: un coltello, una pistola, una mitragliatrice, un edificio e una torre radio. Ma ci sono anche alcuni oggetti con più istanze: alberi (ad es. 3 tipi di alberi con centinaia di istanze), erba e così via ... Quello che voglio dire è: invece di rendere gli oggetti a una istanza il modo "tradizionale" e gli alberi ed erba usando l'istanziamento, li rendiamo tutti usando l'istanziamento. Quindi la nostra torre radio ha solo un'istanza (le cui informazioni memorizziamo in un buffer di dati di istanza) e rendiamo quella torre usando un qualche tipo di DrawInstanced()chiamata con un numero di istanze uguale 1. Lo stesso con tutti gli altri oggetti (ovviamente, alberi ed erba hanno più istanze).

Quindi la mia domanda è: è una cattiva idea disegnare una singola istanza di un oggetto usando l'istanza? L'istanziamento ha un overhead eccessivo (dal punto di vista della memoria e delle prestazioni) o è in qualche modo indesiderato per il rendering di oggetti a istanza singola?

Risposte:


19

Sotto D3D9 con XPDM quasi sicuramente vuoi istanza ovunque possibile. L'overhead delle chiamate è così alto che ha senso. In quello scenario il punto di crossover può essere minimo di 2 o 3 istanze.

Se hai solo un'istanza di una determinata mesh, in superficie può sembrare allettante disegnarla senza istanza. Tuttavia, guarda cosa è coinvolto:

  • È necessario passare dal caricamento dei dati in un buffer per istanza al caricamento delle costanti dello shader.
  • Devi conservare due copie del tuo vertex shader: una per istanza e una per non istanza.
  • Devi conservare due copie del tuo codice di rendering: allo stesso modo.
  • Devi cambiare shader.
  • Devi cambiare i formati dei vertici.
  • Potrebbe essere necessario cambiare i buffer dei vertici.
  • E poi devi ripetere tutto se torni al disegno istanziato per il prossimo gruppo di maglie.

Anche se hai una sola mesh (come il modello di pistola in un FPS) ci sono casi in cui l'istanziamento è utile. Supponiamo che tu stia eseguendo l'accumulo di luce multipass in un renderer in avanti e con una prepass z. Invece di un passaggio aggiuntivo per ogni luce, crei i dati delle tue luci per istanza e li disegni istantaneamente.

Basato sul primo scenario, la morale della storia è che se una classe di oggetti può usare l'istanza, ha senso usare sempre l'istanza per tutti gli oggetti di quella classe.

Basato sul secondo scenario, la morale della storia è che l'istanziamento può avere usi non ovvi che vanno oltre il semplice dire "Ho bisogno di disegnare 20 alberi".


Le ragioni che hai indicato sono le stesse che mi hanno fatto porre questa domanda in primo luogo. Grazie.
NPS

12

(Sul mio sistema, non l'ho provato da nessun'altra parte) In GL, istanziare una singola mesh (disegnando con count = 1) ha un po 'di overhead cattivo, ma non so da dove provenga. Consiglio vivamente di non farlo.

L'ho provato in un'applicazione pratica un paio di mesi fa. Ho codificato alcuni algoritmi di illuminazione globale nella scena Crytek Sponza, che consiste di circa 350 maglie (non ricordo esattamente), di cui una coppia condivide una manciata di istanze. All'inizio l'ho fatto come suggerisci tu, basta istanziare tutto e disegnare il resto con un numero di istanze pari a 1, poiché ha semplificato un po 'il codice di rendering.

Successivamente, durante l'ottimizzazione del renderer, il semplice passaggio dall'istanza del conteggio = 1 oggetti alla loro presentazione nel solito modo mi ha fatto risparmiare circa 3,5 millisecondi per frame di tempo su un i7 3770k (e GTX 770). Passare le mesh con più istanze a semplicemente eseguirle nel modo tradizionale mi ha permesso di risparmiare altri 0,5 ms. Nel complesso, l'applicazione è passata da ~ 120 FPS a circa ~ 230 FPS.

Queste cifre ovviamente dipendono sempre da dove si trovano i colli di bottiglia nella tua applicazione, e gli ultimi 0,5 ms potrebbero effettivamente diventare un rallentamento in un'applicazione in cui sei molto legato al draw-call. Ma per il resto, nella mia esperienza l'istanza ha qualche brutto sovraccarico se non stai disegnando molte cose contemporaneamente.


Interessante, ma sarebbe bello vedere anche i dati per i driver AMD e Intel, altrimenti dovresti davvero dire "Sul mio sistema" invece di "In GL". D'altra parte, anche se non è un problema con altre implementazioni, il fatto che potrebbe essere in alcuni è un motivo sufficiente per evitare di istanziare se non lo si utilizza.
Bcrist

2

Puoi essere certo che disegnare un singolo oggetto istanziato sia più costoso che disegnare un singolo oggetto normalmente. Per istanziare la GPU si sta preparando per una grande quantità di oggetti e questa preparazione sarà diversa rispetto a un singolo oggetto. Tuttavia, l'ampiezza di questo gap prestazionale può essere trovata solo sperimentando ed è molto dipendente dalla configurazione del rendering attuale. L'unico modo per saperlo con certezza è testarlo tu stesso. Il benchmarking di un singolo call draw è difficile qui ci sono diverse idee su come potresti procedere.


2

Sono passati 4 anni ... e penso che sia sicuro dire che è perfettamente corretto inviare chiamate di disegno "istanziate" con 1. Come avrai notato, le nuove API DX12 e Vk hanno entrambe un conteggio di istanze che può essere compreso tra 0 e NUM_INSTANCES . Si noti inoltre che non è disponibile DrawIndexed (...) .

MODIFICARE

Come nota di cautela, quanto sopra probabilmente va bene con queste moderne API, forse usando qualcosa di vecchio come Gl <3.3 o forse DX11 richiederà un po 'di profilazione come menzionato da altri utenti.

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.