performance significato perché le chiamate al sorteggio sono costose?




clausola riscatto azioni (3)

Risposta breve: il driver memorizza parte o tutta l'attività effettiva fino a quando 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 alcuni motivi:

  • per evitare di fare lavori inutili: se (inutilmente) si imposta lo stesso stato più volte prima di disegnarlo, si può evitare di fare un lavoro costoso ogni volta che si verifica ciò. Questo in realtà diventa un evento abbastanza comune in una base di codice di grandi dimensioni, ad esempio un motore di gioco di produzione.
  • essere in grado di riconciliare ciò che internamente sono stati interdipendenti invece di elaborarli immediatamente con informazioni incomplete

Risposta alternativa (s):

  • Il buffer utilizzato dal driver per memorizzare i comandi di rendering è pieno e l'app attende effettivamente che la GPU elabori parte del lavoro precedente. 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.

supponendo che i dati di trama, vertice e shader siano già presenti sulla 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.

quindi da dove proviene tutto il sovraccarico? le operazioni richiedono una stretta di mano di qualche tipo con la gpu?

perché inviare 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 dovrebbero essere meno dati inviati, a meno che i modelli non siano più piccoli di una matrice 4x4)


Le 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 alcuni lavori di preparazione in parallelo con la CPU, a condizione che la CPU non esegua una richiesta di blocco (come ad esempio la mappatura 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.

DirectX SDK ha una sezione sulla profilazione accurata delle prestazioni D3D che, pur non essendo direttamente correlata alla tua domanda, può fornire alcuni suggerimenti su cosa è e non è costoso e (in alcuni casi) perché.

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

Ma, in sostanza (per cercare di rispondere direttamente alle tue domande), il motivo per cui le chiamate sono costose non è che ci sia necessariamente un gran numero di dati da trasferire, ma piuttosto che c'è un gran numero di lavoro oltre la semplice spedizione dei dati attraverso il bus che viene posticipato fino a quando il buffer dei comandi viene svuotato.


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

Le chiamate di estrazione 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.

La ragione principale per fare meno richiami di draw è che l'hardware grafico può trasformare e rendere i triangoli molto più velocemente di quanto tu possa inviarli. Se invii pochi triangoli per ogni chiamata, sarai completamente vincolato dalla CPU e la GPU sarà per lo più inattiva. La CPU non sarà in grado di alimentare la GPU abbastanza velocemente.

Fare una singola chiamata con due triangoli è economico, ma se si inviano troppi dati per ogni chiamata, non si avrà abbastanza tempo per la CPU per inviare tutta la geometria alla GPU che si potrebbe avere.

Ci sono alcuni costi reali con le chiamate al draw, richiede un po 'di stato (quale set di vertici da usare, che shader usare e così via), e le modifiche dello stato hanno un costo sia sul lato hardware (aggiornando un mucchio dei registri) e sul lato del conducente (convalida e traduzione delle chiamate che impostano lo stato).

Tuttavia, il costo principale delle chiamate al sorteggio si applica solo se ciascuna chiamata invia troppo pochi dati , poiché ciò causerà il vincolo della CPU e impedirà l'utilizzo completo dell'hardware.

Proprio come ha detto Josh, anche le call draw possono causare il flush del buffer dei comandi, ma nella mia esperienza, che di solito accade quando chiami SwapBuffers, non quando invii 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.

Dovresti leggere la presentazione nVidia Batch Batch Batch! , è abbastanza vecchio ma copre esattamente questo argomento.





gpu