Miten CPU ja GPU toimivat vuorovaikutuksessa tietokoneen grafiikan tarjoamiseen?
Tietokoneesi keskusyksikkö (CPU) ja grafiikkakäsittely-yksikkö (GPU) ovat vuorovaikutuksessa joka hetki, kun käytät tietokonettasi, jotta saat selkeän ja reagoivan visuaalisen käyttöliittymän. Lue lisää siitä, miten he toimivat yhdessä.
Kuva: sskennel.
Nykypäivän Kysymys- ja vastaus -istunto tulee meille suotuisasti SuperUser-Stack Exchange -palvelun osa-alueesta..
Kysymys
SuperUser-lukija Sathya esitti kysymyksen:
Täältä näet kuvakaappauksen pienestä C ++ -ohjelmasta, jonka nimi on Triangle.exe ja jossa on pyörivä kolmio, joka perustuu OpenGL API -ohjelmaan.
On totta, että se on hyvin perusmuotoinen esimerkki, mutta mielestäni sitä voidaan soveltaa muihin graafisen kortin toimintoihin.
Olin vain utelias ja halusin tietää koko prosessin kaksoisnapsauttamalla Triangle.exe-tiedostoa Windows XP -käyttöjärjestelmässä, kunnes näen näytössä pyörivän kolmion. Mitä tapahtuu, miten CPU (joka ensin käsittelee .exe: n) ja GPU: n (joka vie lopulta kolmiota näytölle)?
Oletan, että tämän pyörivän kolmion näyttäminen on lähinnä muun muassa seuraava laitteisto / ohjelmisto:
Laitteisto
- HDD
- Järjestelmämuisti (RAM)
- prosessori
- Videomuisti
- GPU
- LCD-näyttö
Ohjelmisto
- Käyttöjärjestelmä
- DirectX / OpenGL API
- Nvidia-ohjain
Voiko kukaan selittää prosessia, ehkä jonkinlaisen vuokaavion avulla?
Sen ei pitäisi olla monimutkainen selitys, joka kattaa kaikki yksittäiset vaiheet (arvailu, joka ulottuisi soveltamisalan ulkopuolelle), mutta selitys, jonka välituote IT-kaveri voi seurata.
Olen varma, että monet ihmiset, jotka jopa kutsuvat itseään IT-ammattilaisiksi, eivät voineet kuvata tätä prosessia oikein.
Vastaus
Vaikka useat yhteisön jäsenet vastasivat kysymykseen, Oliver Salzburg meni ylimääräiselle mailille ja vastasi siihen paitsi yksityiskohtaisella vastauksella, mutta erinomaisella grafiikalla.
Kuva JasonC: ltä, saatavilla taustakuvana.
Hän kirjoittaa:
Päätin kirjoittaa hieman ohjelmoinnista ja siitä, miten komponentit puhuvat keskenään. Ehkä se valaisee joitakin alueita.
Esitelmä
Mitä se kestää, jotta saisit jopa yhden kuvan, jonka lähetit kysymykseesi, piirrettynä ruudulle?
On monia tapoja piirtää kolmiota näytölle. Yksinkertaisuuden vuoksi oletetaan, ettei vertex-puskureita käytetty. (A huippupuskurion muistialue, johon tallennat koordinaatteja.) Oletetaan, että ohjelma kertoi yksinkertaisesti grafiikan käsittelyputkelle jokaisesta yksittäisestä huippupisteestä (kärki on vain koordinaatti avaruudessa) peräkkäin.
Mutta, Ennen kuin voimme tehdä mitään, meidän on ensin suoritettava joitakin rakennustelineitä. Katsotaan miksi myöhemmin:
// Tyhjennä näyttö ja syvyyspuskuri (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Nollaa nykyinen Modelview-matriisi glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Piirustus kolmioista glBegin (GL_TRIANGLES); // Punainen glColor3f (1.0f, 0.0f, 0.0f); // Ylös kolmio (edessä) glVertex3f (0.0f, 1.0f, 0.0f); // Vihreä glColor3f (0.0f, 1.0f, 0.0f); // Vasemmanpuoleinen kolmio (etu) glVertex3f (-1.0f, -1.0f, 1.0f); // Sininen glColor3f (0.0f, 0.0f, 1.0f); // Kolmio (oikea) glVertex3f (1.0f, -1.0f, 1.0f); // Valmis Piirustus glEnd ();
Joten mitä se teki?
Kun kirjoitat ohjelman, joka haluaa käyttää näytönohjainta, valitset yleensä jonkinlaisen käyttöliittymän ohjaimelle. Joitakin hyvin tunnettuja kuljettajan rajapintoja ovat:
- OpenGL
- Direct3D
- CUDA
Tässä esimerkissä pidämme kiinni OpenGL: stä. Nyt, sinun käyttöliittymä on se, mikä antaa sinulle kaikki työkalut, joita tarvitset ohjelman tekemiseksi puhua näytönohjaimeen (tai kuljettajaan, joka sitten neuvottelut kortille).
Tämä käyttöliittymä on varmasti antanut sinulle varmuuden Työkalut. Nämä työkalut muodostavat API: n, jonka voit soittaa ohjelmastasi.
Tämä API on se, mitä näemme yllä olevassa esimerkissä. Katsotaanpa tarkemmin.
Rakennustelineet
Ennen kuin voit tehdä todellisen piirustuksen, sinun on suoritettava a perustaa. Sinun on määritettävä näkymisportti (alue, joka todella tehdään), näkökulma ( kamera omaan maailmaasi), mitä anti-aliaseja käytät (kolmion reunan tasoittamiseksi)…
Mutta emme katso mitään. Otamme vain kurkistelemaan mitä sinun tarvitsee tehdä jokainen kehys. Kuten:
Näytön tyhjentäminen
Grafiikkaputki ei tyhjennä ruutua jokaista kehystä varten. Sinun täytyy kertoa se. Miksi? Tämän vuoksi:
Jos et tyhjennä näyttöä, yksinkertaisesti piirtää se on jokainen kehys. Siksi me kutsumme glClear
kanssaGL_COLOR_BUFFER_BIT
sarja. Toinen bitti (GL_DEPTH_BUFFER_BIT
) kertoo OpenGL: n tyhjentämään syvyyspuskuri. Tätä puskuria käytetään määrittämään, mitkä pikselit ovat muita pikseleitä edessä tai takana.
muutos
Kuvan lähde
Transformaatio on osa, jossa otamme kaikki syöttökoordinaatit (kolmion pisteet) ja käytämme ModelView-matriisia. Tämä on matriisi selittää miten meidän malli- (pisteet) pyöritetään, skaalataan ja käännetään (siirretään).
Seuraavaksi käytämme Projisointimatriisia. Tämä siirtää kaikki koordinaatit niin, että ne kohtaavat kameramme oikein.
Nyt muutamme vielä kerran, meidän Viewport -matriisi. Teemme tämän skaalata meidän malli- näytön koon mukaan. Nyt meillä on joukko huippupisteitä, jotka ovat valmiita tekemään!
Palaan muutokseen hieman myöhemmin.
Piirustus
Piirtääksesi kolmion, voimme yksinkertaisesti kertoa OpenGL: lle uuden luettelo kolmioista soittamalla glBegin
kanssa GL_TRIANGLES
jatkuva.
Voit myös piirtää muita lomakkeita. Kuten kolmionauha tai kolmion tuuletin. Nämä ovat ensisijaisesti optimointeja, koska ne edellyttävät vähemmän yhteydenpitoa CPU: n ja GPU: n välillä, jotta saadaan sama määrä kolmioita.
Tämän jälkeen voimme tarjota luettelon kolmesta pisteestä, jotka muodostavat kunkin kolmion. Jokainen kolmio käyttää kolmea koordinaattia (kuten 3D-tilassa). Lisäksi annan myös a väri- kutakin huippua kohti soittamallaglColor3f
ennen kutsumus glVertex3f
.
OpenGL laskee 3 pisteiden välistä varjoa (kolmion kulmat 3)automaattisesti. Se interpoloi värin monikulmion koko kasvot.
vuorovaikutus
Kun napsautat ikkunaa. Sovelluksen on vain tallennettava ikkunan viesti, joka ilmoittaa napsautuksesta. Sitten voit suorittaa haluamasi toiminnon.
Tämä saa a erä vaikeampi, kun haluat aloittaa vuorovaikutuksen 3D-kohtauksen kanssa.
Sinun täytyy ensin tietää selvästi, millä pikselillä käyttäjä napsautti ikkunaa. Sitten ottamalla näkökulmaVoit laskea säteen suunnan hiiren napsautuksen paikasta kohtaasi. Tämän jälkeen voit laskea, onko jokin esine näkymässäsi leikkaa sen kanssa. Nyt tiedät onko käyttäjä napsauttanut kohdetta.
Joten, miten teet sen kiertymään?
muutos
Olen tietoinen kahdesta yleisesti sovellettavasta muunnoksesta:
- Matriisipohjainen muunnos
- Luu-pohjainen transformaatio
Ero on siinä luut vaikuttaa yksittäiseen kärkipisteet. Matriisit vaikuttavat aina kaikkiin piirrettyihin pisteisiin samalla tavalla. Katsotaanpa esimerkkiä.
esimerkki
Aiemmin lataimme identiteettimatriisi ennen kolmio. Identiteettimatriisi on sellainen, joka yksinkertaisesti tarjoaa ei muutosta ollenkaan. Joten, mitä minä piirrän, vaikuttaa vain näkökulmastani. Niinpä kolmiota ei kierretä lainkaan.
Jos haluan kääntää sen nyt, voisin joko tehdä itse matematiikan (CPU: ssa) ja yksinkertaisesti soittaa glVertex3f
kanssamuut koordinaatit (joita kierretään). Tai voisin antaa GPU: n tehdä kaiken työn soittamalla glRotatef
ennen piirustusta:
// Kierrä kolmiota Y-akselilla glRotatef (määrä, 0,0f, 1,0f, 0,0f);
määrä
on tietenkin vain kiinteä arvo. Jos haluat elävöittää, sinun täytyy seurata määrä
ja lisää sitä jokaista kehystä kohti.
Joten, odota, mitä tapahtui kaikki matriisikeskustelut aikaisemmin?
Tässä yksinkertaisessa esimerkissä meidän ei tarvitse välittää matriiseista. Soitamme vain glRotatef
ja se huolehtii kaikesta meille.
glRotate
tuottaa pyörimisenkulma
astetta vektorin x y z ympärillä. Nykyinen matriisi (seeglMatrixMode) kerrotaan pyörimismatriisilla, jossa tuote korvaa nykyisen matriisin, koska ifglMultMatrix kutsuttiin seuraavalla matriisilla argumenttina: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
No, kiitos siitä!
johtopäätös
On selvää, että on paljon puhetta että OpenGL. Mutta se ei kerro meille mitä vain. Missä on viestintä?
Ainoa asia, jonka OpenGL kertoo meille tässä esimerkissä, on kun se on tehty. Jokainen toiminta kestää jonkin aikaa. Jotkut toiminnot kestävät uskomattoman pitkiä, toiset ovat uskomattoman nopeita.
Pisteen lähettäminen GPU: lle tulee olemaan niin nopea, en edes tiedä, miten sitä ilmaisisi. Tuhansien huippujen lähettäminen CPU: sta GPU: hun, jokainen yksittäinen kehys, ei todennäköisesti ole ongelma.
Näytön tyhjentäminen voi kestää millisekunnin tai huonompi (pidä mielessä, että sinulla on yleensä noin 16 millisekuntia aikaa kunkin kehyksen piirtämiseen) riippuen siitä, kuinka suuri näkymä on. Poistaaksesi sen, OpenGL: n on piirrettävä jokainen yksittäinen pikseli, jonka haluat poistaa, mikä voi olla miljoonia pikseleitä.
Muuten voimme vain kysyä OpenGL: ltä vain grafiikkasovittimen ominaisuuksista (maksimi resoluutio, max anti-aliasing, max värisyvyys,…).
Mutta voimme myös täyttää tekstuurin pikseleillä, joilla kullakin on tietty väri. Jokaisella pikselillä on siten arvo ja tekstuuri on jättiläinen ”tiedosto”, joka on täynnä tietoja. Voimme ladata sen grafiikkakorttiin (luomalla tekstuuripuskurin) ja ladata sitten varjostimen, kertoa, että varjostin käyttää tekstuuriamme tulona ja suorittaa joitakin äärimmäisen raskaita laskelmia "tiedostollamme".
Sitten voimme “laskea” laskelmamme (uuden värin muodossa) tuloksen uudeksi tekstuuriksi.
Näin voit tehdä GPU: n toimimaan muilla tavoilla. Oletan, että CUDA toimii samanlaisella tavalla, mutta minulla ei ollut koskaan mahdollisuutta työskennellä sen kanssa.
Olemme todella vain hieman koskettaneet koko aihetta. 3D-grafiikkasuunnittelu on peto härkä.
Kuvan lähde
Onko jotain lisättävää selitykseen? Ääni pois kommenteista. Haluatko lukea lisää vastauksia muilta tech-savvy Stack Exchange -käyttäjiltä? Tutustu koko keskusteluketjuun täällä.