Hjemmeside » hvordan » Hvordan interagerer CPU'en og GPU'en med at udføre computergrafik?

    Hvordan interagerer CPU'en og GPU'en med at udføre computergrafik?

    Din computers centrale behandlingsenhed (CPU) og Graphics Processing Unit (GPU) interagerer hvert øjeblik, hvor du bruger din computer, for at give dig en skarp og lydhør visuel grænseflade. Læs videre for bedre at forstå, hvordan de arbejder sammen.

    Foto af sskennel.

    Dagens Spørgsmål og Svar session kommer til os med venlig hilsen af ​​SuperUser-en underafdeling af Stack Exchange, en community-drive gruppering af Q & A websteder.

    Spørgsmålet

    SuperUser læser Sathya stillede spørgsmålet:

    Her kan du se et screenshot af et lille C ++ program kaldet Triangle.exe med en roterende trekant baseret på OpenGL API.

    Ganske vist et meget grundlæggende eksempel, men jeg synes det er relevant for andre grafikkortoperationer.

    Jeg var bare nysgerrig og ønskede at kende hele processen fra at dobbeltklikke på Triangle.exe under Windows XP, indtil jeg kan se trekanten roterende på skærmen. Hvad sker der, hvordan CPU (som først håndterer .exe) og GPU (som endelig udsender trekanten på skærmen) interagerer?

    Jeg tror at involveret i at vise denne roterende trekant er primært følgende hardware / software blandt andre:

    Hardware

    • HDD
    • Systemhukommelse (RAM)
    • CPU
    • Videohukommelse
    • GPU
    • LCD display

    Software

    • Operativ system
    • DirectX / OpenGL API
    • Nvidia Driver

    Kan nogen forklare processen, måske med en slags flowdiagram til illustration?

    Det bør ikke være en kompleks forklaring, der dækker hvert enkelt trin (gætte, der ville gå ud over anvendelsesområdet), men en forklaring, en mellemliggende IT-fyr kan følge.

    Jeg er temmelig sikker på, at mange mennesker, der selv ville kalde sig IT-fagfolk, ikke kunne beskrive denne proces korrekt.

    Svaret

    Selv om flere fællesskabsmedlemmer besvarede spørgsmålet, gik Oliver Salzburg den ekstra mile og besvarede det ikke kun med et detaljeret svar, men fremragende ledsagende grafik.

    Billede af JasonC, tilgængelig som tapet her.

    Han skriver:

    Jeg besluttede at skrive lidt om programmeringsaspektet og hvordan komponenter taler med hinanden. Måske vil det kaste lys på bestemte områder.

    Præsentationen

    Hvad tager det for at have det eneste billede, som du skrev i dit spørgsmål, trukket på skærmen?

    Der er mange måder at tegne en trekant på skærmen. For enkelhed, lad os antage, at der ikke blev anvendt vertex buffere. (EN vertex bufferer et område af hukommelse, hvor du lagrer koordinater.) Lad os antage, at programmet bare fortalte grafikbehandlingsrørledningen om hvert enkelt vertex (et vertex er bare en koordinat i rummet) i en række.

    Men, før vi kan tegne noget, skal vi først køre nogle stilladser. Vi får at se hvorfor senere:

    // Ryd skærmen og dybdebufferen glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Nulstil den aktuelle modelviewmatrix glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Tegning ved hjælp af trekanter glBegin (GL_TRIANGLES); // Red glColor3f (1,0f, 0,0f, 0,0f); // Top of Triangle (Front) glVertex3f (0,0f, 1,0f, 0,0f); // Grøn glColor3f (0,0f, 1,0f, 0,0f); // Venstre af trekanten (Front) glVertex3f (-1.0f, -1.0f, 1.0f); // Blå glColor3f (0,0f, 0,0f, 1,0f); // Triangle højre (Front) glVertex3f (1.0f, -1.0f, 1.0f); // Done Drawing glEnd ();

    Så hvad gjorde det?

    Når du skriver et program, der vil bruge grafikkortet, vælger du normalt en slags interface til føreren. Nogle kendte grænseflader til føreren er:

    • OpenGL
    • Direct3D
    • CUDA

    Til dette eksempel holder vi os med OpenGL. Nu, din interface til føreren er hvad der giver dig alle de værktøjer, du har brug for til at lave dit program tale til grafikkortet (eller driveren, som da foredrag til kortet).

    Denne grænseflade er forpligtet til at give dig sikker værktøjer. Disse værktøjer har form af et API, som du kan ringe fra dit program.

    Det API er det, vi ser at blive brugt i eksemplet ovenfor. Lad os kigge nærmere.

    Stilladserne

    Før du virkelig kan lave en konkret tegning, skal du udføre en Opsætning. Du skal definere dit visningsport (det område, der rent faktisk skal gengives), dit perspektiv ( kamera ind i din verden), hvilken anti-aliasing du vil bruge (for at glatte ud den kantede af din trekant) ...

    Men vi vil ikke se på noget af det. Vi tager bare et kig på de ting, du skal gøre hver ramme. Synes godt om:

    Fjernelse af skærmen

    Grafisk pipeline vil ikke rydde skærmen for dig hver ramme. Du bliver nødt til at fortælle det. Hvorfor? Det er derfor:

    Hvis du ikke rydder skærmen, vil du simpelthen trække over det hver ramme. Derfor kalder vi glClear medGL_COLOR_BUFFER_BIT sæt. Den anden bit (GL_DEPTH_BUFFER_BIT) fortæller OpenGL at rydde dybdepuffer. Denne buffer bruges til at bestemme hvilke pixels der er foran (eller bag) andre pixels.

    Transformation


    Billedkilde

    Transformation er den del, hvor vi tager alle indgangskoordinaterne (vinklerne i vores trekant) og anvender vores ModelView matrix. Dette er matrixen der forklarer hvordan vores model (vinklerne) roteres, skaleres og oversættes (flyttes).

    Dernæst anvender vi vores projektionsmatrix. Dette bevæger alle koordinater, så de står over for vores kamera korrekt.

    Nu omformer vi igen med vores Viewport-matrix. Vi gør dette for at skalere vores model til størrelsen af ​​vores skærm. Nu har vi et sæt hjørner, der er klar til at blive gengivet!

    Vi kommer tilbage til transformation lidt senere.

    Tegning

    For at tegne en trekant kan vi blot fortælle OpenGL om at starte en ny liste over trekanter ved at ringe glBegin med GL_TRIANGLES konstant.
    Der er også andre former, du kan tegne. Ligesom en trekantstrimmel eller en trekant fan. Disse er primært optimeringer, da de kræver mindre kommunikation mellem CPU'en og GPU'en for at tegne det samme antal trekanter.

    Derefter kan vi give en liste over sæt med 3 hjørner, som skal udgøre hver trekant. Hver trekant bruger 3 koordinater (som vi er i 3D-rum). Derudover giver jeg også en farve for hvert hjørne ved at ringeglColor3f Før ringer glVertex3f.

    Skyggen mellem de 3 hjørner (de tre hjørner af trekanten) beregnes af OpenGLautomatisk. Det vil interpolere farven over hele polygonets overflade.

    Interaktion

    Nu, når du klikker på vinduet. Programmet skal kun fange vinduesmeddelelsen, der signalerer kliket. Derefter kan du køre enhver handling i dit program, du ønsker.

    Dette får en masse sværere, når du vil begynde at interagere med din 3D-scene.

    Du skal først vide, på hvilket pixel brugeren klikker på vinduet. Så tager du din perspektivi betragtning kan du beregne retningen af ​​en stråle fra museklikspunktet til din scene. Du kan derefter beregne om noget objekt i din scene skærer med den stråle. Nu ved du, om brugeren klikte på et objekt.

    Så, hvordan får du det til at rotere?

    Transformation

    Jeg er opmærksom på to typer af transformationer, der generelt anvendes:

    • Matrix-baseret transformation
    • Benbaseret transformation

    Forskellen er det knogler påvirker single knuder. Matricer påvirker altid alle trukket hjørner på samme måde. Lad os se på et eksempel.

    Eksempel

    Tidligere lastede vi vores identitetsmatrix før du tegner vores trekant. Identitetsmatrixen er en, der simpelthen giver ingen transformation overhovedet. Så uanset hvad jeg tegner, påvirkes kun mit perspektiv. Så vil trekanten ikke roteres overhovedet.

    Hvis jeg vil rotere det nu, kunne jeg enten lave matematikken mig selv (på CPU) og bare ringe glVertex3f medAndet koordinater (der roteres). Eller jeg kunne lade GPU'en gøre alt arbejdet ved at ringe glRotateffør tegning:

    // Drej trekanten på Y-aksen glRotatef (mængde, 0,0f, 1,0f, 0,0f); 

    beløb er selvfølgelig bare en fast værdi. Hvis du vil animere, du bliver nødt til at holde styr på beløbog øg det hver ramme.

    Så vent, hvad der skete med al matrix diskussionen tidligere?

    I dette enkle eksempel behøver vi ikke bekymre os om matricer. Vi ringer simpelthen glRotatef og det tager sig af alt det for os.

    glRotate producerer en rotation af vinkel grader omkring vektoren x y z. Den nuværende matrix (seeglMatrixMode) multipliceres med en rotationsmatrix med produktet, der erstatter den aktuelle matrix, som ifglMultMatrix blev kaldt med følgende matrix som argument:

    x 2 ⁡ 1 - c + cx ⁡ 1 - c - zxzz 1 - c + y s 0 y x 1 - c + z 2 sy 1 - c + cyz ⁡ 1 - c + x sz 2 1 - c + c 0 0 0 0 1 1 - c - x s 0 x zz 1 - c - yyzz 1 - c + xzz 2

    Nå tak for det!

    Konklusion

    Hvad der bliver tydeligt er, at der er meget snak til OpenGL. Men det fortæller ikke os hvad som helst. Hvor er kommunikationen?

    Det eneste, OpenGL fortæller os i dette eksempel er når det er færdigt. Hver operation vil tage en vis tid. Nogle operationer tager utrolig lang tid, andre er utroligt hurtige.

    Sende et vertex til GPU vil være så hurtigt, jeg ville ikke engang vide, hvordan man udtrykker det. At sende tusindvis af hjørner fra CPU'en til GPU'en, hver enkelt ramme, er sandsynligvis ikke noget problem overhovedet.

    Fjernelse af skærmen kan tage en millisekund eller værre (husk, du har normalt kun 16 millisekunder tid til at tegne hver ramme), afhængigt af hvor stor din visning er. For at rydde det, skal OpenGL tegne hver enkelt pixel i den farve, du vil slette til, det kunne være millioner af pixels.

    Bortset fra det, kan vi stort set kun spørge OpenGL om mulighederne i vores grafikkort (maksimal opløsning, maksimal aliasing, maks farvedybde, ...).

    Men vi kan også fylde en tekstur med pixels, der hver især har en bestemt farve. Hver pixel har således en værdi, og tekstur er en kæmpe "fil" fyldt med data. Vi kan indlæse det i grafikkortet (ved at oprette en teksturbuffer), og derefter indlæse en shader, fortæl os at shader at bruge vores tekstur som input og køre nogle yderst tunge beregninger på vores "fil".

    Vi kan så "gøre" resultatet af vores beregning (i form af nye farver) til en ny tekstur.

    Sådan kan du gøre GPU'en til dig på andre måder. Jeg antager, at CUDA udfører lignende det aspekt, men jeg har aldrig haft mulighed for at arbejde med det.

    Vi har kun lidt rørt hele emnet. 3D grafik programmering er et helvede af et dyr.


    Billedkilde


    Har du noget at tilføje til forklaringen? Lyde af i kommentarerne. Vil du læse flere svar fra andre tech-savvy Stack Exchange brugere? Tjek den fulde diskussionstråd her.