Hvordan interagerer CPU'en og GPU'en med at gengive computergrafik?

Indholdsfortegnelse:

Video: Hvordan interagerer CPU'en og GPU'en med at gengive computergrafik?

Video: Hvordan interagerer CPU'en og GPU'en med at gengive computergrafik?
Video: How to Make Ubuntu Look Like Windows 11 | 22.04 GNOME 43 / 42 | Linux 2024, Marts
Hvordan interagerer CPU'en og GPU'en med at gengive computergrafik?
Hvordan interagerer CPU'en og GPU'en med at gengive computergrafik?
Anonim
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.
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 & 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.
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, som 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.
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å visse 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 med 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) på en række.

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

// Clear The Screen And The Depth Buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset The Current Modelview Matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Drawing Using Triangles glBegin(GL_TRIANGLES); // Red glColor3f(1.0f,0.0f,0.0f); // Top Of Triangle (Front) glVertex3f( 0.0f, 1.0f, 0.0f); // Green glColor3f(0.0f,1.0f,0.0f); // Left Of Triangle (Front) glVertex3f(-1.0f,-1.0f, 1.0f); // Blue glColor3f(0.0f,0.0f,1.0f); // Right Of Triangle (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 så foredrag til kortet).

Denne grænseflade er forpligtet til at give dig sikker værktøjer. Disse værktøjer har form af en 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.

Stilladset

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:

Rydning af skærmen

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

Image
Image

Hvis du ikke rydder skærmen, vil du simpelthen trække over det hver ramme. Derfor kalder vi

glClear

med

GL_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
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 ringe

glColor3f

Før ringer

glVertex3f

Skyggen mellem de 3 hjørner (de tre hjørner af trekanten) beregnes af OpenGL automatisk. 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
  • Bone-baseret 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 læste 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

glRotatef

før tegning:

// Rotate The Triangle On The Y axis glRotatef(amount,0.0f,1.0f,0.0f);

amount

er selvfølgelig bare en fast værdi. Hvis du vil animere, du bliver nødt til at holde styr på

amount

og øg det hver ramme.

Så vent, hvad er der sket 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

angle

grader omkring vektoren x y z. Den aktuelle 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 y 1 - c - zxxzz 1 - c + y s 0 y x 1 - c + z 2 sy 1 - c + cyz 1 - c - x s 0 x zz 1 - c - yzz 1 - c + xzz 2 1 - c + c 0 0 0 0 1

Nå tak for det!

Konklusion

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

Det eneste, som 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'en vil være så hurtig, 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.

Rydning 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 rydde 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, maks anti-aliasing, max 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.

Det er sådan, du kan gøre GPU'en til at arbejde for dig på andre måder. Jeg antager, at CUDA udfører ligner 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
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.

Anbefalede: