Kako CPU i GPU stupaju u interakciju s računalnom grafikom?
Središnja procesorska jedinica (CPU) računala i grafička procesorska jedinica (GPU) međusobno djeluju svaki trenutak kada upotrebljavate računalo da bi vam pružili oštar i odgovarajući vizualno sučelje. Čitajte dalje kako biste bolje razumjeli kako rade zajedno.
Fotografija od sskennel.
Današnja sesija pitanja i odgovora dolazi nam ljubaznošću SuperUser-a, podjele Stack Exchangea, grupne grupacije web-lokacija s pitanjima i odgovorima..
Pitanje
Čitatelj SuperUser Sathya je postavio pitanje:
Ovdje možete vidjeti snimku zaslona malog programa C ++ nazvanog Triangle.exe s rotirajućim trokutom koji se temelji na OpenGL API-ju.
Doduše, vrlo jednostavan primjer, ali mislim da je primjenjivo na druge operacije grafičkih kartica.
Bio sam samo znatiželjan i htio sam znati cijeli proces od dvostrukog klika na Triangle.exe pod Windows XP dok ne vidim trokut koji se okreće na monitoru. Što se događa, kako CPU (koji prvi upravlja s .exe) i GPU-om (koji na kraju izlazi s trokuta na zaslon), međusobno djeluju?
Pretpostavljam da je prikazivanje ovog rotirajućeg trokuta ponajprije sljedeći hardver / softver:
Hardver
- HDD
- Memorija sustava (RAM)
- CPU
- Video memorija
- GPU
- LCD zaslon
Softver
- Operacijski sustav
- DirectX / OpenGL API
- Nvidia upravljački program
Može li itko objasniti proces, možda s nekom vrstom dijagrama tijeka za ilustraciju?
To ne bi trebalo biti složeno objašnjenje koje pokriva svaki pojedini korak (pretpostavite da bi to bilo izvan opsega), ali objašnjenje koje srednji IT tip može slijediti.
Prilično sam siguran da mnogi ljudi koji bi se i sami nazivali IT profesionalci nisu mogli ispravno opisati taj proces.
Odgovor
Iako je više članova zajednice odgovorilo na pitanje, Oliver Salzburg je otišao na dodatnu milju i odgovorio ne samo detaljnim odgovorom, nego i izvrsnom pratećom grafikom..
Slika JasonC, dostupna kao pozadina ovdje.
Piše:
Odlučio sam napisati nešto o aspektu programiranja i kako komponente razgovaraju jedna s drugom. Možda će baciti malo svjetla na određena područja.
Prezentacija
Što je potrebno da se čak i ta pojedinačna slika, koju ste objavili u svom pitanju, nacrta na zaslonu?
Postoji mnogo načina za crtanje trokuta na zaslonu. Radi jednostavnosti, pretpostavimo da nisu korišteni vršni odbojnici. (A međuspremnik vrhaje područje memorije gdje pohranjuju koordinate.) Pretpostavimo da je program jednostavno rekao grafičkoj obradi cjevovod o svakom pojedinom vrhu (vrh je samo koordinata u prostoru) u nizu.
Ali, prije nego što možemo izvući nešto, prvo moramo pokrenuti neke skele. Vidjet ćemo zašto kasnije:
// Obrišite zaslon i dubinu međuspremnika glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Resetiraj trenutnu matricu prikaza modela glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Crtanje pomoću trokuta glBegin (GL_TRIANGLES); // Red glColor3f (1.0f, 0.0f, 0.0f); // Vrh trokuta (Prednji) glVertex3f (0.0f, 1.0f, 0.0f); // Zeleni glColor3f (0.0f, 1.0f, 0.0f); // lijevo od trokuta (prednji) glVertex3f (-1.0f, -1.0f, 1.0f); // Blue glColor3f (0.0f, 0.0f, 1.0f); // Desno od trokuta (prednji) glVertex3f (1.0f, -1.0f, 1.0f); // Završeno crtanje glEnd ();
Što je to učinilo??
Kada napišete program koji želi koristiti grafičku karticu, obično ćete izabrati neku vrstu sučelja za upravljački program. Neki dobro poznati sučelja za upravljački program su:
- OpenGL
- Direct3D
- CUDA
Za ovaj primjer ćemo se držati OpenGL-a. Sada, vaš sučelje vozaču je ono što vam daje sve alate potrebne za izradu programa razgovor na grafičku karticu (ili upravljački program, koji tada razgovori na karticu).
Ovo sučelje sigurno će vam dati sigurno alat. Ovi alati poprimaju oblik API-a koji možete pozvati iz svog programa.
Taj API je ono što vidimo da se koristi u gornjem primjeru. Pogledajmo izbliza.
Skela
Prije nego što možete stvarno napraviti bilo koji crtež, morat ćete izvršiti a postaviti. Morate definirati svoj prikaz (područje koje će se zapravo prikazati), vašu perspektivu ( fotoaparat u svoj svijet), koje ćete anti-aliasing koristiti (za izravnavanje rubova vašeg trokuta) ...
Ali nećemo gledati ništa od toga. Samo ćemo zaviriti u stvari koje ćete morati učiniti svaki okvir. Kao:
Brisanje zaslona
Grafički cjevovod neće očistiti zaslon za svaki kadar. Morat ćete to reći. Zašto? To je razlog zašto:
Ako ne očistite zaslon, jednostavno ćete draw over svaki okvir. Zato zovemo glClear
sGL_COLOR_BUFFER_BIT
postavljen. Drugi dio (GL_DEPTH_BUFFER_BIT
) javi OpenGL-u da obriše dubinapufer. Ovaj se međuspremnik koristi za određivanje piksela koji se nalaze ispred (ili iza) drugih piksela.
Transformacija
Izvor slike
Transformacija je dio gdje uzimamo sve ulazne koordinate (vrhove našeg trokuta) i primjenjujemo našu ModelView matricu. To je matrica koja objašnjava kako naše model (vrhovi) su rotirani, skalirani i prevedeni (premješteni).
Zatim primjenjujemo našu Projekcijsku matricu. To pomiče sve koordinate kako bi ispravno gledale na našu kameru.
Sada se još jednom transformiramo pomoću naše Viewport matrice. Mi to radimo kako bismo proširili naše model veličine našeg monitora. Sada imamo skup vrhova koji su spremni za prikazivanje!
Vratit ćemo se na transformaciju malo kasnije.
Crtanje
Da bi nacrtali trokut, jednostavno možemo reći OpenGL-u da pokrene novo popis trokuta pozivom glBegin
s GL_TRIANGLES
konstantno.
Postoje i drugi oblici koje možete nacrtati. Poput trokuta ili trokutastog ventilatora. To su prije svega optimizacije jer zahtijevaju manje komunikacije između CPU-a i GPU-a za crtanje iste količine trokuta.
Nakon toga, možemo dati popis skupova od 3 vrhova koji bi trebali činiti svaki trokut. Svaki trokut koristi 3 koordinate (kao što smo u 3D-prostoru). Osim toga, također pružam a boja za svaki vrh, pozivomglColor3f
prije zvanje glVertex3f
.
Nijansu između 3 vrha (3 ugla trokuta) izračunava OpenGLautomatsko. To će interpolirati boju preko cijelog lica poligona.
Interakcija
Sada, kada kliknete na prozor. Aplikacija mora samo obuhvatiti poruku prozora koja signalizira klik. Tada možete pokrenuti bilo koju radnju u svom programu koju želite.
Ovo dobiva mnogo teže kada želite započeti interakciju s 3D scenom.
Prvo morate jasno znati na kojem pikselu je korisnik kliknuo prozor. Onda uzmite svoj perspektivau obzir, možete izračunati smjer zraka, od točke miša u vašu scenu. Zatim možete izračunati je li neki objekt u vašoj sceni ukrštava s tom zrakom. Sada znate je li korisnik kliknuo objekt.
Dakle, kako to učiniti rotirati?
Transformacija
Svjestan sam dviju vrsta transformacija koje se općenito primjenjuju:
- Matrična transformacija
- Transformacija na temelju kostiju
Razlika je u tome kosti utječu na pojedinačno vrhovi. Matrice uvijek utječu na sve nacrtane vrhove na isti način. Pogledajmo primjer.
Primjer
Ranije smo napunili naš Matrica identiteta prije crtanja našeg trokuta. Matrica identiteta je ona koja jednostavno pruža nema transformacije uopće. Dakle, na što god crtam, utječe samo moja perspektiva. Dakle, trokut se uopće neće rotirati.
Ako ga sada želim rotirati, mogu ili napraviti matematiku (na CPU-u) i jednostavno nazvati glVertex3f
sdrugo koordinate (koje se rotiraju). Ili bih mogao dopustiti GPU-u da obavi sav posao pozivom glRotatef
prije crtanja:
// Rotiraj trokut na osi Y glRotatef (iznos, 0.0f, 1.0f, 0.0f);
iznos
je, naravno, samo fiksna vrijednost. Ako želiš animirati, morat ćete pratiti iznos
i povećati svaki okvir.
Dakle, pričekajte, što se dogodilo sa svim matričnim razgovorima ranije?
U ovom jednostavnom primjeru ne moramo brinuti o matricama. Jednostavno zovemo glRotatef
i sve to brine za nas.
glRotate
proizvodi rotacijukut
stupnjeva oko vektora x y z. Trenutna matrica (seeglMatrixMode) množi se s rotacijskom matricom s proizvodom koji zamjenjuje trenutnu matricu, kao što je ifglMultMatrix pozvan sa sljedećom matricom kao svojim argumentom:x 2 - 1 - c + cx y - 1 - c - z sx z 1 - c + y 0 s 0 y x - 1 - c + z sy 2 - 1 - c + cy z 1 - c - x 0 s 0 x z 1 - c - y sy z 1 - c + x z sz 2 - 1 - c + c 0 0 0 0 1
Pa, hvala na tome!
Zaključak
Ono što postaje očigledno jest, da se mnogo govori do OpenGL. Ali to ne govori nas bilo što. Gdje je komunikacija?
Jedino što nam OpenGL govori u ovom primjeru jest kada je gotovo. Svaka operacija traje određeno vrijeme. Neka operacija traje nevjerojatno dugo, drugi su nevjerojatno brzi.
Slanje vrha na GPU će biti tako brzo, ne bih ni znao kako to izraziti. Slanje tisuća točaka iz CPU-a GPU-u, svaki okvir, najvjerojatnije nije problem.
Brisanje zaslona može potrajati nekoliko milisekundi ili lošije (imajte na umu, obično imate samo oko 16 milisekundi vremena za crtanje svakog okvira), ovisno o tome koliko je vaš okvir velik. Da bi ga očistio, OpenGL mora izvući svaki pojedinačni piksel u boji koju želite razjasniti, što može biti milijuni piksela.
Osim toga, OpenGL možemo pitati samo o mogućnostima našeg grafičkog adaptera (maksimalna razlučivost, maksimalno anti-aliasing, maksimalna dubina boje, ...).
Ali možemo također popuniti teksturu pikselima koji imaju specifičnu boju. Svaki piksel tako ima vrijednost, a tekstura je ogromna "datoteka" ispunjena podacima. Možemo to učitati u grafičku karticu (stvaranjem spremnika teksture), a zatim učitati shader, reći tom shaderu da koristi našu teksturu kao ulaz i pokrenuti neke iznimno teške izračune na našoj "datoteci".
Tada možemo rezultat "izračunati" (u obliku novih boja) pretvoriti u novu teksturu.
Tako možete GPU-u raditi za vas na druge načine. Pretpostavljam da CUDA nastupa slično tom aspektu, ali nikad nisam imao priliku raditi s njom.
Stvarno smo samo malo dotakli cijelu temu. Programiranje 3D grafike je paklena zvijer.
Izvor slike
Imate li što dodati objašnjenju? Zvuk isključen u komentarima. Želite li pročitati više odgovora od drugih tehničkih korisnika Stack Exchangea? Pogledajte cjelokupnu temu za raspravu ovdje.