2011-01-31 23 views
41

presupponendo che i dati di trama, vertice e shader siano già presenti nella scheda grafica, non è necessario inviare molti dati alla scheda. ci sono alcuni byte per identificare i dati, e presumibilmente una matrice 4x4, e alcuni altri parametri assortiti.perché le chiamate di prelievo sono costose?

quindi da dove proviene tutto l'overhead? le operazioni richiedono una stretta di mano di qualche tipo con la gpu?

perché è l'invio di una singola mesh contenente un gruppo di piccoli modelli, calcolati sulla CPU, spesso più veloce di inviare l'id del vertice e le matrici di trasformazione? (la seconda opzione sembra che ci siano meno dati inviati, a meno che i modelli siano più piccoli di una matrice 4x4)

+2

Oh sì, grazie per questo Q :) –

risposta

47

Prima di tutto, presumo che con "draw calls", intendi il comando che indica alla GPU di rappresentare un certo insieme di vertici come triangoli con un determinato stato (shader, blend state e così via).

Le chiamate di prelievo non sono necessariamente costose. Nelle versioni precedenti di Direct3D, molte chiamate richiedevano un commutatore di contesto, che era costoso, ma questo non è vero nelle versioni più recenti.

Il motivo principale per effettuare un minor numero di chiamate è che l'hardware grafico può trasformare e rendere i triangoli molto più velocemente di quanto è possibile inviarli. Se si inviano alcuni triangoli per ogni chiamata, si sarà completamente vincolati dalla CPU e la GPU sarà in gran parte inattiva. La CPU non sarà in grado di alimentare la GPU abbastanza velocemente.

Effettuare una chiamata di estrazione singola con due triangoli è economico, ma se si inviano troppi dati con ciascuna chiamata, non si avrà abbastanza tempo di CPU per inviare la maggior quantità di geometria alla GPU che si potrebbe avere.

Ci sono alcuni costi effettivi con le chiamate al sorteggio, richiede un po 'di stato (quale insieme di vertici da usare, quale shader usare e così via), e le modifiche allo stato hanno un costo sia sul lato hardware (aggiornamento di un gruppo di registri) e sul lato driver (convalida e traduzione delle chiamate che hanno impostato lo stato).

Ma ma il costo principale delle chiamate di prelievo si applica solo se ogni chiamata invia troppo piccoli dati, poiché ciò causerà un limite della CPU e impedirà l'utilizzo completo dell'hardware.

Proprio come Josh ha detto, le chiamate di prelievo possono anche causare il comando del buffer da svuotare, ma nella mia esperienza che di solito accade quando si chiama SwapBuffers, non quando si invia la geometria. I driver video in genere cercano di bufferizzare quanto possono farla franca (a volte più fotogrammi!) Per spremere il maggior parallelismo possibile dalla GPU.

Si dovrebbe leggere la presentazione nVidia Batch Batch Batch!, è piuttosto vecchia ma copre esattamente questo argomento.

+1

questo è praticamente esattamente quello che stavo cercando. Grazie! – notallama

+1

Sembra che il collegamento al mazzo nVidia sia morto. Prova questo: http://tinyurl.com/acezt9b. –

10

API grafiche come Direct3D traducono le loro chiamate a livello di API in comandi indipendenti dal dispositivo e le accodano in un buffer. Flushing quel buffer, per eseguire il lavoro effettivo, è costoso - sia perché implica che il lavoro effettivo viene ora eseguito, sia perché può comportare un passaggio da utente a modalità kernel sul chip (e viceversa), che non è quello a buon mercato.

Fino a quando il buffer non viene svuotato, la GPU è in grado di eseguire alcune operazioni di preparazione in parallelo con la CPU, a condizione che la CPU non esegua una richiesta di blocco (ad esempio, il mapping dei dati sulla CPU). Ma la GPU non - e non può - prepara tutto finché non ha bisogno di disegnare effettivamente. Solo perché alcuni dati di vertici o di trama sono presenti sulla carta non significa che siano stati disposti in modo appropriato, e potrebbero non essere modificabili fino a quando non verranno impostati i layout dei vertici o gli shader saranno collegati, eccetera. La maggior parte del lavoro reale avviene durante il comando flush e draw call.

L'SDK di DirectX ha uno section on accurately profiling D3D performance che, sebbene non direttamente correlato alla domanda, può fornire alcuni suggerimenti su ciò che è e non è costoso e (in alcuni casi) perché.

Più rilevante è this blog post (e i post di follow-up here e here), che forniscono una buona panoramica del processo operativo logico di basso livello della GPU.

Ma, essenzialmente (per cercare di rispondere alle vostre domande direttamente), la ragione per le chiamate sono costoso, non è che ci sia necessariamente un sacco di dati da trasferire, ma piuttosto che c'è un grande corpo di lavoro oltre solo la spedizione dei dati attraverso il bus che viene differita fino a quando il buffer dei comandi viene svuotato.

2

Risposta breve: il driver esegue il buffering di parte o del tutto il lavoro effettivo finché non si chiama draw. Questo verrà visualizzato come una quantità relativamente prevedibile di tempo trascorso nella chiamata di estrazione, a seconda di quanto stato è cambiato.

questo è fatto per un paio di motivi:

  • di evitare di fare lavori inutili: Se (inutilmente) di impostare lo stesso stato più volte prima di disegnare si può evitare di fare costosi lavori ogni volta che ciò si verifica. Questo in realtà diventa un evento abbastanza comune in una base di codice di grandi dimensioni, ad esempio un motore di gioco di produzione.
  • poter conciliare internamente sono stati interdipendenti invece di elaborazione immediatamente con informazioni incomplete

risposta alternativo (s):

  • buffer del driver utilizza per memorizzare i comandi rendering è completo e l'app sta effettivamente aspettando che la GPU elabori alcuni dei lavori precedenti. In genere questo si presenta come blocchi estremamente grandi di blocco del tempo in una chiamata a sorteggio casuale all'interno di un frame.
  • Il numero di frame a cui è consentito il buffer del driver è stato raggiunto e l'app è in attesa sulla GPU per elaborarne uno. Questo di solito si presenta come una grossa porzione di blocco temporale nella prima chiamata di disegno all'interno di un frame, o in Present alla fine del frame precedente.
Problemi correlati