Kuidas CPU ja GPU suhtlevad arvutigraafika koostamisel?
Arvuti keskprotsessor (CPU) ja graafika töötlusseade (GPU) suhtlevad iga hetk, kui kasutate arvutit, et pakkuda teile teravat ja tundlikku visuaalset liidest. Loe edasi, et paremini mõista, kuidas nad koos töötavad.
pildi autor sskennel.
Tänane küsimuste ja vastuste seanss saabub meiega kohtades, kus on SuperUser-Stack Exchange'i alajaotus, kogukondliku draivi rühmitus Q&A veebisaitidel.
Küsimus
SuperUser-lugeja Sathya esitas küsimuse:
Siin näete ekraanil väikest C ++ programmi, mida nimetatakse Triangle.exe koos pöörleva kolmnurgaga, mis põhineb OpenGL API-l.
Muidugi on see väga põhiline näide, kuid ma arvan, et see on kohaldatav ka teiste graafikakaartide toimingute suhtes.
Ma olin lihtsalt uudishimulik ja tahtsin teada, et kogu protsess on topeltklõpsamine Triangle.exe all Windows XP all, kuni ma näen ekraanil pöörlevat kolmnurka. Mis juhtub, kuidas CPU (mis esmalt tegeleb .exe-ga) ja GPU (mis lõpuks väljastab kolmnurga ekraanile)?
Ma arvan, et selle pöörleva kolmnurga kuvamine on eelkõige järgmine riistvara / tarkvara:
Riistvara
- HDD
- Süsteemi mälu (RAM)
- Protsessor
- Videomälu
- GPU
- LCD ekraan
Tarkvara
- Operatsioonisüsteem
- DirectX / OpenGL API
- Nvidia draiver
Kas keegi suudab protsessi selgitada, võib-olla mingisuguse vooskeemiga illustreerimiseks?
See ei tohiks olla keeruline selgitus, mis hõlmab iga üksikut sammu (arvan, et see ulatub ulatusest kaugemale), kuid selgitus vahepealse IT-mehe jaoks.
Ma olen päris kindel, et paljud inimesed, kes isegi kutsuvad end IT-spetsialistideks, ei suutnud seda protsessi õigesti kirjeldada.
Vastus
Kuigi mitmed kogukonna liikmed vastasid küsimusele, läks Oliver Salzburg ekstra miilile ja vastas sellele mitte ainult üksikasjaliku vastuse, vaid ka suurepärase kaasneva graafikaga.
JasonC pilt, mis on siin saadaval.
Ta kirjutab:
Ma otsustasin kirjutada natuke programmeerimise aspektist ja sellest, kuidas komponendid üksteisega räägivad. Võib-olla valgustab see teatud alasid.
Esitlus
Mida on vaja, et isegi ühe pildi, mida teie küsimuses postitasite, ekraanile?
Kolmnurga joonistamiseks ekraanil on palju viise. Lihtsuse huvides oletagem, et ei kasutata tippude puhvreid. (A tipppuhveron mälupiirkond, kuhu salvestad koordinaadid.) Oletame, et programm lihtsalt rääkis graafikaprotsessorile iga iga tipu kohta (tipp on vaid kosmoses koordinaat).
Aga, enne kui me midagi teha saame, peame kõigepealt käivitama mõned tellingud. Me näeme miks hiljem:
// Ekraani ja sügavuse puhvri kustutamine (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Lähtesta praegune modelview-maatriks glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Joonistamine kolmnurga abil glBegin (GL_TRIANGLES); // Red glColor3f (1.0f, 0.0f, 0.0f); // Kolmnurga ülaosa (ees) glVertex3f (0.0f, 1.0f, 0.0f); // Roheline glColor3f (0.0f, 1.0f, 0.0f); // Kolmnurga vasakpoolne (ees) glVertex3f (-1.0f, -1.0f, 1.0f); // sinine glColor3f (0.0f, 0.0f, 1.0f); // Kolmnurga õigus (ees) glVertex3f (1.0f, -1.0f, 1.0f); // Valmis joonis glEnd ();
Nii et mida see tegi?
Kui kirjutad programmi, mis soovib kasutada graafikakaarti, valite tavaliselt juhile mingisuguse liidese. Mõned tuntud draiveri liidesed on järgmised:
- OpenGL
- Direct3D
- CUDA
Selle näite puhul jääme OpenGL-iga kinni. Nüüd, sinu liidesega on see, mis annab teile kõik vahendid, mida vajate oma programmi loomiseks rääkida graafikakaardile (või draiverile, mis siis kõnelusi kaardile).
See liides on sulle kindlasti kindel tööriistu. Need tööriistad on API kujul, mida saate oma programmilt helistada.
See API on see, mida me näeme ülaltoodud näites. Vaatame lähemalt.
Tellingud
Enne tegelikku joonistamist saate teha a häälestus. Sa pead määratlema oma vaatepordi (ala, mis tegelikult tehakse), oma perspektiivi ( kaamera sinu maailma), millist anti-aliasingut kasutate (kolmnurga servade silumiseks)…
Aga me ei vaata seda. Me vaatame lihtsalt asju, mida peate tegema iga raami. Nagu:
Ekraani puhastamine
Graafiline torujuhe ei kustuta sinu ekraanile iga kaadrit. Sa pead seda ütlema. Miks? See on põhjus, miks:
Kui te ekraani ei kustuta, saate lihtsalt tõmmake üle see on iga raam. Sellepärast me kutsume seda glClear
koosGL_COLOR_BUFFER_BIT
seatud. Teine bit (GL_DEPTH_BUFFER_BIT
) ütleb OpenGL-ilt sügavuspuhvrit. Seda puhvrit kasutatakse selleks, et määrata, millised pikslid on teiste pikslite ees (või taga).
Muutumine
Pildiallikas
Ümberkujundamine on osa, kus võtame kõik sisendkoordinaadid (kolmnurga tipud) ja rakendame meie ModelView maatriksit. See on see maatriks selgitab kuidas meie mudel (tipud) pööratakse, suurendatakse ja tõlgitakse (teisaldatakse).
Järgmisena rakendame oma projektsioonimaatriksit. See liigutab kõik koordinaadid nii, et nad näeksid meie kaamera õigesti.
Nüüd teisendame veel kord oma Viewport'i maatriksiga. Me teeme seda meie mõõtmete mõõtmiseks mudel meie monitori suurusele. Nüüd on meil hulk tippe, mis on valmis renderdamiseks!
Hiljem pöördume tagasi ümberkujundamiseni.
Joonis
Kolmnurga joonistamiseks võime lihtsalt öelda OpenGLile, et alustada uut kolmnurkade loetelu helistades glBegin
koos GL_TRIANGLES
konstantne.
On ka teisi vorme, mida saate joonistada. Nagu kolmnurkriba või kolmnurkventilaator. Need on peamiselt optimeerimised, kuna nad vajavad vähemahulist suhtlust CPU ja GPU vahel, et joonistada sama palju kolmnurka.
Pärast seda saame pakkuda nimekirja kolmest tipust, mis peaksid moodustama iga kolmnurga. Iga kolmnurk kasutab 3 koordinaati (nagu me oleme 3D-ruumis). Lisaks sellele pakun ka a värv iga tipu kohta helistadesglColor3f
enne helistamine glVertex3f
.
3 tippu (kolmnurga 3 nurka) varju arvutab OpenGLautomaatselt. See interpoleerib värvi üle kogu hulknurga näo.
Koostoime
Nüüd, kui klõpsate aknale. Rakendusel peab jäädvustama ainult akna sõnumi, mis näitab klõpsamist. Siis saate käivitada oma programmis mis tahes toimingu.
See saab a palju raskem, kui soovite oma 3D stseeniga suhelda.
Kõigepealt peate selgelt teadma, millisel pikslil kasutaja klõpsas aknale. Siis, võttes oma perspektiiviArvestades saate riba suuna arvutada hiireklõpsuga sinu stseeni. Seejärel saate arvutada, kas teie stseenis esineb mõni objekt lõikub selle kiirusega. Nüüd teate, kas kasutaja klõpsas objekti.
Niisiis, kuidas sa seda pöörad?
Muutumine
Ma olen teadlik kahte tüüpi ümberkujundustest, mida üldiselt kasutatakse:
- Maatriksipõhine transformatsioon
- Luupõhine transformatsioon
Erinevus on see luud mõjutada üksikut tipud. Maatriksid mõjutavad alati kõiki tõmmatud tippe samal viisil. Vaatame näiteks.
Näide
Varem laadisime meie identiteedi maatriks enne kolmnurga joonistamist. Identiteedimaatriks on lihtsalt pakutav mingit ümberkujundamist üleüldse. Niisiis, mida iganes ma joonistan, mõjutab see ainult minu vaatenurgast. Seega ei pöörata kolmnurka üldse.
Kui ma tahan seda nüüd pöörata, siis kas ma saan teha ise matemaatika (CPU-l) ja lihtsalt helistada glVertex3f
koosmuu koordinaadid (mida pööratakse). Või ma võiksin lasta GPU-l teha kõik tööd helistades glRotatef
enne joonistamist:
// Kolmnurga pööramine Y-teljel glRotatef (summa, 0,0f, 1,0f, 0,0f);
summa
on muidugi ainult fikseeritud väärtus. Kui sa tahad animeerida, pead jälgima summa
ja suurendage seda iga kaadri puhul.
Niisiis, oodake, mis juhtus varem maatriksiga rääkima?
Selles lihtsas näites ei pea me maatriksite eest hoolt kandma. Me helistame lihtsalt glRotatef
ja see hoolitseb kõigi eest meie eest.
glRotate
tekitab pöörlemistnurk
kraadi ümber vektori x y z. Praegune maatriks (seeglMatrixMode) korrutatakse rotatsioonmaatriksiga, kui toode asendab jooksvat maatriksit, kuna ifglMultMatrix kutsuti oma argumendina järgmise maatriksiga: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
Tänan selle eest!
Järeldus
Mis saab ilmseks, on palju rääkida kuni OpenGL. Aga see ei räägi meid midagi. Kus on side?
Ainus asi, mida OpenGL meile selles näites ütleb, on kui see on tehtud. Iga operatsioon võtab teatud aja. Mõned toimingud on uskumatult pikad, teised on uskumatult kiire.
Tippu saatmine GPU-le on nii kiire, et ma isegi ei tea, kuidas seda väljendada. Tuhandete tippude saatmine CPU-lt GPU-le, iga kord, on tõenäoliselt üldse probleem.
Ekraani puhastamine võib võtta millisekundit või halvem (pidage meeles, et igal raamil on tavaliselt umbes 16 millisekundit aega), sõltuvalt sellest, kui suur on teie vaateava. Selle kustutamiseks peab OpenGL joonistama iga piksliga värvi, mida soovite kustutada, mis võib olla miljoneid piksleid.
Peale selle saame päris palju paluda ainult OpenGL-il meie graafikaadapteri võimaluste kohta (maksimaalne eraldusvõime, max anti-alias, max värvisügavus,…).
Kuid me saame täita ka pikslitega tekstuuri, millel on iga konkreetne värv. Iga piksel omab seega väärtust ja tekstuur on hiiglaslik „fail”, mis on täidetud andmetega. Me saame selle laadida graafikakaardile (koostades tekstuuripuhvri), seejärel laadida varjutaja, öelda, et varjur kasutab meie tekstuuri sisendina ja käivitab meie „failis” äärmiselt raskeid arvutusi.
Seejärel saame oma arvutuse (uute värvide kujul) tulemuse muuta “uueks” tekstuuriks.
Nii saate GPU-d teile muul viisil tööd teha. Eeldan, et CUDA toimib sarnaselt sellele aspektile, kuid mul ei olnud kunagi võimalust sellega koostööd teha.
Me puudutasime tõesti vaid kogu teemat. 3D graafika programmeerimine on metsalise põrgu.
Pildiallikas
Kas teil on midagi lisada selgitusele? Hääletage kommentaarides. Kas soovite lugeda rohkem vastuseid teistelt tech-savvy Stack Exchange'i kasutajatelt? Vaadake siin täielikku arutelu lõiku.