In che modo CPU e GPU interagiscono con Render Computer Graphics?

Sommario:

In che modo CPU e GPU interagiscono con Render Computer Graphics?
In che modo CPU e GPU interagiscono con Render Computer Graphics?

Video: In che modo CPU e GPU interagiscono con Render Computer Graphics?

Video: In che modo CPU e GPU interagiscono con Render Computer Graphics?
Video: La migliore distribuzione Linux simile a Windows - YouTube 2024, Aprile
Anonim
L'unità di elaborazione centrale (CPU) e l'unità di elaborazione grafica (GPU) del computer interagiscono ogni volta che si utilizza il computer per fornire un'interfaccia visiva nitida e reattiva. Continua a leggere per capire meglio come lavorano insieme.
L'unità di elaborazione centrale (CPU) e l'unità di elaborazione grafica (GPU) del computer interagiscono ogni volta che si utilizza il computer per fornire un'interfaccia visiva nitida e reattiva. Continua a leggere per capire meglio come lavorano insieme.

fotografato da sskennel.

La sessione di domande e risposte di oggi ci viene fornita per gentile concessione di SuperUser, una suddivisione di Stack Exchange, un raggruppamento di domande e risposte di community drive.

La domanda

Il lettore SuperUser Sathya ha posto la domanda:

Qui puoi vedere uno screenshot di un piccolo programma C ++ chiamato Triangle.exe con un triangolo rotante basato sull'API OpenGL.

Ammetto che si tratta di un esempio molto semplice, ma penso che sia applicabile ad altre operazioni con le schede grafiche.
Ammetto che si tratta di un esempio molto semplice, ma penso che sia applicabile ad altre operazioni con le schede grafiche.

Ero solo curioso e volevo conoscere l'intero processo facendo doppio clic su Triangle.exe sotto Windows XP fino a quando non riesco a vedere il triangolo che ruota sul monitor. Cosa succede, come interagiscono la CPU (che prima gestisce l'exe) e la GPU (che alla fine emette il triangolo sullo schermo)?

Immagino che la visualizzazione di questo triangolo rotante sia principalmente il seguente hardware / software, tra gli altri:

Hardware

  • HDD
  • Memoria di sistema (RAM)
  • processore
  • Memoria video
  • GPU
  • display LCD

Software

  • Sistema operativo
  • API DirectX / OpenGL
  • Driver Nvidia

Qualcuno può spiegare il processo, magari con una sorta di diagramma di flusso per l'illustrazione?

Non dovrebbe essere una spiegazione complessa che copre ogni singolo passo (suppongo che vada oltre lo scopo), ma una spiegazione che un ragazzo IT intermedio può seguire.

Sono abbastanza sicuro che molte persone che si chiamerebbero anche professionisti IT non potrebbero descrivere correttamente questo processo.

La risposta

Sebbene molti membri della comunità abbiano risposto alla domanda, Oliver Salzburg ha fatto il massimo e ha risposto non solo con una risposta dettagliata ma con un'eccellente grafica di accompagnamento.
Sebbene molti membri della comunità abbiano risposto alla domanda, Oliver Salzburg ha fatto il massimo e ha risposto non solo con una risposta dettagliata ma con un'eccellente grafica di accompagnamento.

Immagine di JasonC, disponibile come sfondo qui.

Lui scrive:

Ho deciso di scrivere un po 'sull'aspetto della programmazione e su come i componenti si parlano tra loro. Forse farà luce su alcune aree.

La presentazione

Cosa serve per avere anche quella singola immagine, che hai postato nella tua domanda, disegnata sullo schermo?

Ci sono molti modi per disegnare un triangolo sullo schermo. Per semplicità, supponiamo che non siano stati utilizzati buffer di vertice. (UN buffer dei verticiè un'area di memoria in cui si memorizzano le coordinate. Supponiamo che il programma abbia semplicemente detto alla pipeline di elaborazione grafica su ogni singolo vertice (un vertice è solo una coordinata nello spazio) di seguito.

Maprima che possiamo disegnare qualsiasi cosa, dobbiamo prima eseguire alcune impalcature. Vedremo perché dopo:

// Clear The Screen And The Depth Buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset The Current Modelview Matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Drawing Using Triangles glBegin(GL_TRIANGLES); // Red glColor3f(1.0f,0.0f,0.0f); // Top Of Triangle (Front) glVertex3f( 0.0f, 1.0f, 0.0f); // Green glColor3f(0.0f,1.0f,0.0f); // Left Of Triangle (Front) glVertex3f(-1.0f,-1.0f, 1.0f); // Blue glColor3f(0.0f,0.0f,1.0f); // Right Of Triangle (Front) glVertex3f( 1.0f,-1.0f, 1.0f); // Done Drawing glEnd();

Quindi cosa ha fatto?

Quando scrivi un programma che vuole utilizzare la scheda grafica, di solito scegli un tipo di interfaccia per il driver. Alcune interfacce ben note al driver sono:

  • OpenGL
  • Direct3D
  • CUDA

Per questo esempio continueremo con OpenGL. Adesso tuo interfaccia al driver è ciò che ti offre tutti gli strumenti necessari per realizzare il tuo programma parlare alla scheda grafica (o al driver, che quindi trattativa alla carta).

Questa interfaccia è destinata a darti certezze utensili. Questi strumenti prendono la forma di un'API che puoi chiamare dal tuo programma.

Quell'API è ciò che vediamo essere usato nell'esempio sopra. Diamo un'occhiata più da vicino.

The Scaffolding

Prima che tu possa davvero fare un disegno reale, dovrai eseguire un impostare. Devi definire il tuo viewport (l'area che verrà effettivamente renderizzata), la tua prospettiva (il telecamera nel tuo mondo), quale anti-aliasing userai (per appianare il bordo del tuo triangolo) …

Ma non vedremo nulla di tutto ciò. Daremo solo una sbirciatina alle cose che dovrai fare ogni frame. Piace:

Cancellare lo schermo

La pipeline grafica non cancellerà lo schermo per te ogni fotogramma. Dovrai dirlo. Perché? Ecco perché:

Image
Image

Se non si cancella lo schermo, lo farai semplicemente attirare ogni frame Ecco perché chiamiamo

glClear

con il

GL_COLOR_BUFFER_BIT

impostato. L'altro bit (

GL_DEPTH_BUFFER_BIT

) dice a OpenGL di cancellare il profonditàbuffer. Questo buffer viene utilizzato per determinare quali pixel si trovano davanti (o dietro) altri pixel.

Trasformazione

 Fonte immagine
Fonte immagine

La trasformazione è la parte in cui prendiamo tutte le coordinate di input (i vertici del nostro triangolo) e applichiamo la nostra matrice ModelView. Questa è la matrice che spiega come il nostro modello (i vertici) sono ruotati, ridimensionati e tradotti (spostati).

Successivamente, applichiamo la nostra matrice di proiezione. Questo sposta tutte le coordinate in modo che facciano fronte alla nostra fotocamera correttamente.

Ora trasformiamo ancora una volta, con la nostra matrice Viewport. Facciamo questo per ridimensionare il nostro modello alle dimensioni del nostro monitor. Ora abbiamo un set di vertici pronti per essere renderizzati!

Torneremo alla trasformazione un po 'più tardi.

Disegno

Per disegnare un triangolo, possiamo semplicemente dire a OpenGL di iniziare una nuova lista di triangoli a chiamata

glBegin

con il

GL_TRIANGLES

costante. Ci sono anche altre forme che puoi disegnare. Come una striscia triangolare o un ventilatore a triangolo.Si tratta principalmente di ottimizzazioni, poiché richiedono meno comunicazioni tra CPU e GPU per disegnare la stessa quantità di triangoli.

Dopodiché, possiamo fornire un elenco di serie di 3 vertici che dovrebbero costituire ciascun triangolo. Ogni triangolo usa 3 coordinate (dato che siamo nello spazio 3D). Inoltre, fornisco anche un colore per ogni vertice, chiamando

glColor3f

prima chiamata

glVertex3f

L'ombra tra i 3 vertici (i 3 angoli del triangolo) viene calcolata da OpenGL automaticamente. Interpola il colore su tutta la faccia del poligono.

Interazione

Ora, quando fai clic sulla finestra. L'applicazione deve solo acquisire il messaggio della finestra che segnala il clic. Quindi puoi eseguire qualsiasi azione nel programma che desideri.

Questo ottiene a lotto più difficile una volta che vuoi iniziare a interagire con la tua scena 3D.

Per prima cosa devi sapere chiaramente a quale pixel l'utente ha fatto clic sulla finestra. Quindi, prendendo il tuo prospettivain considerazione, è possibile calcolare la direzione di un raggio, dal punto del clic del mouse nella scena. È quindi possibile calcolare se qualsiasi oggetto nella scena interseca con quel raggio. Ora sai se l'utente ha fatto clic su un oggetto.

Quindi, come lo fai ruotare?

Trasformazione

Sono a conoscenza di due tipi di trasformazioni che vengono generalmente applicate:

  • Trasformazione basata su matrice
  • Trasformazione basata sull'osso

La differenza è questa ossatura affetto singolo vertici. Le matrici influenzano sempre tutti i vertici disegnati nello stesso modo. Diamo un'occhiata a un esempio.

Esempio

In precedenza, abbiamo caricato il nostro matrice identità prima di disegnare il nostro triangolo. La matrice di identità è quella che fornisce semplicemente nessuna trasformazione affatto. Quindi, qualunque cosa io tragga, è influenzata solo dalla mia prospettiva. Quindi, il triangolo non verrà ruotato affatto.

Se voglio ruotarlo ora, potrei fare il calcolo da solo (sulla CPU) e semplicemente chiamare

glVertex3f

conaltro coordinate (che sono ruotate). Oppure potrei lasciare che la GPU faccia tutto il lavoro, chiamando

glRotatef

prima del disegno:

// Rotate The Triangle On The Y axis glRotatef(amount,0.0f,1.0f,0.0f);

amount

è, ovviamente, solo un valore fisso. Se lo desidera animare, dovrai tenerne traccia

amount

e aumentalo ogni fotogramma.

Quindi, aspetta, cosa è successo a tutti i discorsi sulla matrice prima?

In questo semplice esempio, non dobbiamo preoccuparci delle matrici. Chiamiamo semplicemente

glRotatef

e si prende cura di tutto ciò per noi.

glRotate

produce una rotazione di

angle

gradi attorno al vettore x y z. La matrice corrente (seeglMatrixMode) viene moltiplicata per una matrice di rotazione con il prodotto che sostituisce la matrice corrente, come se glMultMatrix fosse chiamata con la seguente matrice come argomento:

x 2 ⁡ 1 - c + cx ⁢ y ⁡ 1 - c - z ⁢ sx ⁢ z ⁡ 1 - c + y ⁢ s 0 y ⁢ x ⁡ 1 - c + z ⁢ sy 2 ⁡ 1 - c + cy ⁢ z ⁡ 1 - c - x ⁢ s 0 x ⁢ z ⁡ 1 - c - y ⁢ sy ⁢ z ⁡ 1 - c + x ⁢ sz 2 ⁡ 1 - c + c 0 0 0 0 1

Bene, grazie per quello!

Conclusione

Ciò che diventa ovvio è, ci sono molte parole a OpenGL. Ma non sta dicendo noi nulla. Dov'è la comunicazione?

L'unica cosa che OpenGL ci sta dicendo in questo esempio è quando è finito. Ogni operazione richiederà un certo periodo di tempo. Alcune operazioni impiegano incredibilmente a lungo, altre sono incredibilmente veloci.

L'invio di un vertice alla GPU sarà così veloce, non saprei nemmeno come esprimerlo. L'invio di migliaia di vertici dalla CPU alla GPU, ogni singolo fotogramma, è, molto probabilmente, nessun problema.

Cancellare lo schermo può richiedere un millisecondo o peggio (tieni presente che di solito hai solo 16 millisecondi di tempo per disegnare ogni fotogramma), a seconda di quanto è grande il tuo viewport. Per cancellarlo, OpenGL deve disegnare ogni singolo pixel nel colore a cui si desidera cancellare, che potrebbe essere milioni di pixel.

Oltre a questo, possiamo semplicemente chiedere a OpenGL le funzionalità del nostro adattatore grafico (risoluzione massima, anti-aliasma max, profondità di colore massima, …).

Ma possiamo anche riempire una trama con pixel che hanno ciascuno un colore specifico. Ogni pixel contiene quindi un valore e la trama è un "file" gigante pieno di dati. Possiamo caricarlo nella scheda grafica (creando un buffer di texture), quindi caricare uno shader, dire allo shader di usare la nostra texture come input ed eseguire calcoli estremamente pesanti sul nostro "file".

Possiamo quindi "rendere" il risultato del nostro calcolo (sotto forma di nuovi colori) in una nuova trama.

È così che puoi far funzionare la GPU per te in altri modi. Presumo che CUDA funzioni in modo simile a questo aspetto, ma non ho mai avuto l'opportunità di lavorare con esso.

Abbiamo davvero toccato solo un po 'l'argomento. La programmazione grafica 3D è una bestia infernale.

 Fonte dell'immagine
Fonte dell'immagine

Hai qualcosa da aggiungere alla spiegazione? Sound off nei commenti. Vuoi leggere più risposte dagli altri utenti di Stack Exchange esperti di tecnologia? Controlla la discussione completa qui.

Consigliato: