Hjemmeside » hvordan » Hvordan interagerer CPU og GPU til Computer Graphics?

    Hvordan interagerer CPU og GPU til Computer Graphics?

    Datamaskinens sentrale behandlingsenhet (CPU) og grafikkbehandlingsenhet (GPU) samhandler hvert øyeblikk du bruker datamaskinen, for å gi deg et skarpt og responsivt visuelt grensesnitt. Les videre for bedre å forstå hvordan de jobber sammen.

    Foto av sskennel.

    Dagens Spørsmål & Svar-sesjon kommer til oss med høflighet av SuperUser-en underavdeling av Stack Exchange, en gruppedriving av Q & A-nettsider.

    Spørsmålet

    SuperUser leser Sathya stillte spørsmålet:

    Her kan du se et skjermbilde av et lite C ++-program kalt Triangle.exe med en roterende trekant basert på OpenGL API.

    Ganske vist et veldig grunnleggende eksempel, men jeg tror det er aktuelt for andre grafikkoperasjoner.

    Jeg var bare nysgjerrig og ønsket å vite hele prosessen fra å dobbeltklikke på Triangle.exe under Windows XP til jeg kan se trekanten roterende på skjermen. Hva skjer, hvordan CPU (som først håndterer .exe) og GPU (som til slutt trekker ut trekanten på skjermen) samhandler?

    Jeg antar at det er involvert i å vise denne roterende trekanten, hovedsakelig følgende maskinvare / programvare blant annet:

    maskinvare

    • HDD
    • Systemminne (RAM)
    • prosessor
    • Videominnet
    • GPU
    • LCD-skjerm

    programvare

    • Operativsystem
    • DirectX / OpenGL API
    • Nvidia Driver

    Kan noen forklare prosessen, kanskje med en slags flytskjema for illustrasjon?

    Det bør ikke være en kompleks forklaring som dekker hvert eneste trinn (antar det ville gå utover omfanget), men en forklaring som en mellomliggende IT-fyr kan følge.

    Jeg er ganske sikker på at mange mennesker som selv ville kalle seg IT-fagfolk kunne ikke beskrive denne prosessen riktig.

    Svaret

    Selv om flere fellesskapsmedlemmer besvarte spørsmålet, gikk Oliver Salzburg den ekstra milen og besvarte den ikke bare med et detaljert svar, men utmerket medfølgende grafikk.

    Bilde av JasonC, tilgjengelig som bakgrunn her.

    Han skriver:

    Jeg bestemte meg for å skrive litt om programmeringsaspektet og hvordan komponenter snakker med hverandre. Kanskje det vil kaste lys på enkelte områder.

    Presentasjonen

    Hva tar det for å til og med ha det enkeltbildet, som du skrev inn i spørsmålet ditt, trukket på skjermen?

    Det er mange måter å tegne en trekant på skjermen. For enkelhet, la oss anta at ingen verteksbuffere ble brukt. (EN vertex bufferer et område med minne hvor du lagrer koordinater.) Vi antar at programmet bare fortalte grafikkbehandlingsrørledningen om hvert enkelt toppunkt (et toppunkt er bare en koordinat i rommet) på rad.

    Men, før vi kan tegne noe, må vi først kjøre noen stillas. Vi får se Hvorfor seinere:

    // Fjern skjermen og dybdebufferen glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Tilbakestill gjeldende modellvisningsmatrix glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Tegning ved hjelp av trekanter glBegin (GL_TRIANGLES); // Red glColor3f (1.0f, 0.0f, 0.0f); // Top of Triangle (Front) glVertex3f (0,0f, 1,0f, 0,0f); // Grønn glColor3f (0,0f, 1,0f, 0,0f); // Venstre av trekanten (Front) glVertex3f (-1.0f, -1.0f, 1.0f); // Blå glColor3f (0,0f, 0,0f, 1,0f); // Høyre trekant (Front) glVertex3f (1.0f, -1.0f, 1.0f); // Ferdig tegning glEnd ();

    Så hva gjorde det?

    Når du skriver et program som vil bruke grafikkortet, vil du vanligvis velge en slags grensesnitt til sjåføren. Noen kjente grensesnitt til sjåføren er:

    • OpenGL
    • Direct3D
    • CUDA

    For dette eksempelet holder vi oss med OpenGL. Nå, din grensesnitt til sjåføren er det som gir deg alle verktøyene du trenger for å lage ditt program snakke til grafikkortet (eller driveren, som da samtaler til kortet).

    Dette grensesnittet er forpliktet til å gi deg sikker verktøy. Disse verktøyene har formen på en API som du kan ringe fra programmet.

    Det API er det vi ser blir brukt i eksemplet ovenfor. La oss ta en nærmere titt.

    Stillaset

    Før du virkelig kan gjøre noen konkrete tegninger, må du utføre en oppsett. Du må definere visningsporten din (det området som faktisk skal gjengis), ditt perspektiv (the kamera inn i din verden), hvilken anti-aliasing du skal bruke (å glatte ut kantet av trekanten din) ...

    Men vi vil ikke se på noe av det. Vi tar bare en titt på ting du må gjøre hver ramme. Som:

    Fjerne skjermen

    Grafikkrøret kommer ikke til å fjerne skjermen for hver ramme. Du må fortelle det. Hvorfor? Det er derfor:

    Hvis du ikke tømmer skjermen, vil du ganske enkelt tegne over det hver ramme. Det er derfor vi kaller glClear medGL_COLOR_BUFFER_BIT sett. Den andre delen (GL_DEPTH_BUFFER_BIT) forteller OpenGL å slette dybdebuffer. Denne bufferen brukes til å bestemme hvilke piksler som er foran (eller bak) andre piksler.

    Transformation


    Bildekilde

    Transformasjon er den delen der vi tar alle inngangskoordinatene (kantene på trekanten) og bruker vår ModelView-matrise. Dette er matrisen som forklarer hvordan vår modell (hjørnene) roteres, skaleres og oversettes (flyttes).

    Deretter bruker vi vår projeksjonsmatrise. Dette beveger alle koordinater slik at de møter kameraet vårt riktig.

    Nå omformer vi igjen, med vår Viewport-matrise. Vi gjør dette for å skalere vår modell til størrelsen på skjermen vår. Nå har vi et sett med krysser som er klare til å bli gjengitt!

    Vi kommer tilbake til transformasjon litt senere.

    Tegning

    For å tegne en trekant, kan vi bare fortelle OpenGL for å starte en ny liste over trekanter ved å ringe glBegin med GL_TRIANGLES konstant.
    Det finnes også andre former du kan tegne. Som en trekantstrimmel eller en trekantvifte. Dette er primært optimaliseringer, da de krever mindre kommunikasjon mellom CPU og GPU for å tegne samme antall trekanter.

    Etter det kan vi gi en liste over sett med 3 hjørner som skal utgjør hver trekant. Hver triangel bruker 3 koordinater (som vi er i 3D-plass). I tillegg gir jeg også en farge for hvert toppunkt, ved å ringeglColor3f før ringer glVertex3f.

    Skyggen mellom de 3 hjørnene (de tre hjørnene i trekanten) beregnes av OpenGLautomatisk. Det vil interpolere fargen over hele polygonets ansikt.

    Interaksjon

    Nå, når du klikker på vinduet. Programmet må bare fange vinduet meldingen som signaliserer klikket. Deretter kan du kjøre noen handling i programmet du vil ha.

    Dette får en mye vanskeligere når du vil begynne å samhandle med 3D-scenen din.

    Du må først tydelig vite hvilken piksel brukeren klikket på vinduet. Deretter tar du perspektivmedregnet, kan du beregne retningen til en stråle, fra museklikkpunktet til scenen din. Du kan da beregne om noe objekt i din scene skjærer med den strålen. Nå vet du om brukeren klikket på et objekt.

    Så, hvordan gjør du det rotere?

    Transformation

    Jeg er klar over to typer transformasjoner som vanligvis brukes:

    • Matrise-basert transformasjon
    • Bone-basert transformasjon

    Forskjellen er det bein påvirker singelen toppunkter. Matriser påvirker alltid alle trukket hjørner på samme måte. La oss se på et eksempel.

    Eksempel

    Tidligere lastet vi vår identitetsmatrise før du trekker vår trekant. Identitetsmatrisen er en som bare gir ingen transformasjon i det hele tatt. Så, hva jeg tegner, påvirkes bare av mitt perspektiv. Så trekant vil ikke roteres i det hele tatt.

    Hvis jeg vil rotere det nå, kan jeg enten gjøre matematikken meg selv (på CPU) og bare ringe glVertex3f medannen koordinater (som roteres). Eller jeg kunne la GPU gjøre alt arbeidet, ved å ringe glRotateffør tegning:

    // Roter trekant på y-aksen glRotatef (mengde, 0,0f, 1,0f, 0,0f); 

    beløp er selvsagt bare en fast verdi. Hvis du vil animere, du må holde styr på beløpog øk det hver ramme.

    Så vent, hva skjedde med all matriksprat tidligere?

    I dette enkle eksempelet trenger vi ikke bry oss om matriser. Vi ringer bare glRotatef og det tar seg av alt det for oss.

    glRotate produserer en rotasjon av vinkel grader rundt vektoren x y z. Den nåværende matrisen (seeglMatrixMode) multipliseres med en rotasjonsmatrise med produktet som erstatter den nåværende matrisen, som ifglMultMatrix ble kalt med følgende matrise som argument:

    x 2 ⁡ 1 - c + cx y 1 - c - zxzz 1 - c + y s 0 y x 1 - c + z 2 sy 1 - c + cyz ⁡ 1 - c - xs 0 xzz 1 - c - yzz 1 - c + xzz 2 1 - c + c 0 0 0 0 1

    Vel, takk for det!

    Konklusjon

    Det som blir tydelig er at det er mye snakk til OpenGL. Men det forteller ikke oss hva som helst. Hvor er kommunikasjonen?

    Det eneste som OpenGL forteller oss i dette eksemplet er når det er gjort. Hver operasjon vil ta en viss tid. Enkelte operasjoner tar utrolig lang tid, andre er utrolig raske.

    Sender et toppunkt til GPU vil være så fort, jeg ville ikke engang vite hvordan å uttrykke det. Sende tusenvis av krysser fra CPU til GPU, hver enkelt ramme, er sannsynligvis ikke noe problem i det hele tatt.

    Fjerne skjermen kan ta en millisekund eller verre (husk at du vanligvis bare har ca 16 millisekunder tid til å tegne hver ramme), avhengig av hvor stor visningsporten din er. For å rydde det, må OpenGL tegne hver enkelt piksel i fargen du vil slette til, det kan være millioner av piksler.

    Annet enn det, kan vi ganske enkelt bare spørre OpenGL om mulighetene til grafikkadapteren vår (maks oppløsning, maks anti-aliasing, maks fargedybde, ...).

    Men vi kan også fylle en tekstur med piksler som hver har en bestemt farge. Hver piksel har dermed en verdi og tekstur er en gigantisk "fil" fylt med data. Vi kan laste det inn i grafikkortet (ved å lage en teksturbuffer), og last deretter inn en skygge, fortelle at shader å bruke tekstur som en inngang og kjøre noen ekstremt tunge beregninger på vår "fil".

    Vi kan så "gjengi" resultatet av vår beregning (i form av nye farger) til en ny tekstur.

    Slik kan du gjøre GPU-arbeidet for deg på andre måter. Jeg antar at CUDA utfører ligner det aspektet, men jeg har aldri hatt mulighet til å jobbe med det.

    Vi har egentlig bare litt rørt hele emnet. 3D grafikk programmering er et helvete av et dyr.


    Bildekilde


    Har du noe å legge til forklaringen? Lyde av i kommentarene. Vil du lese flere svar fra andre tech-savvy Stack Exchange-brukere? Sjekk ut hele diskusjonstråden her.