Kaip veikia procesorius ir GPU sąveikauja su kompiuterio grafika?
Jūsų kompiuterio centrinis procesorius (CPU) ir grafikos apdorojimo įrenginys (GPU) sąveikauja kiekvieną kartą, kai naudojate kompiuterį, kad pateiktumėte aiškią ir jautrią vaizdo sąsają. Skaitykite toliau, kad geriau suprastumėte, kaip jie dirba kartu.
Nuotrauka pagal sskennel.
Šiandienos „Klausimų ir atsakymų“ sesijos metu mes galime pasveikinti „SuperUser“ - „Stack Exchange“ padalinį, bendruomenės diską „Q&A“ svetainių grupavimas.
Klausimas
„SuperUser“ skaitytojas „Sathya“ pateikė klausimą:
Čia galite pamatyti smulkios C ++ programos ekraną, vadinamą Triangle.exe su besisukančiu trikampiu pagal „OpenGL API“.
Žinoma, tai labai paprastas pavyzdys, bet manau, kad jis taikomas kitoms grafinių kortelių operacijoms.
Buvau tik smalsu ir norėjau sužinoti visą procesą nuo dvigubo paspaudimo „Triangle.exe“ pagal „Windows XP“, kol pamatysite trikampį, besisukantį monitoriuje. Kas atsitinka, kaip CPU (kuris pirmą kartą tvarko .exe) ir GPU (kuris pagaliau perduoda trikampį ekrane) sąveikauja?
Manau, kad dalyvaujant šio besisukančio trikampio rodyme, be kita ko, yra šios aparatūros / programinės įrangos:
Aparatūra
- HDD
- Sistemos atmintis (RAM)
- CPU
- Vaizdo atmintis
- GPU
- LCD ekranas
Programinė įranga
- Operacinė sistema
- „DirectX / OpenGL“ API
- „Nvidia Driver“
Ar kas nors galėtų paaiškinti procesą, galbūt su tam tikra iliustracijos schema?
Tai neturėtų būti sudėtingas paaiškinimas, apimantis kiekvieną žingsnį (atspėti, kad jis viršytų taikymo sritį), tačiau tarpinis IT vaikinas gali paaiškinti.
Esu tikras, kad daug žmonių, kurie netgi vadins save IT specialistais, negalėtų tinkamai aprašyti šio proceso.
Atsakymas
Nors daugelis bendruomenės narių atsakė į klausimą, Oliveras Salzburgas nuvyko į papildomą mylią ir atsakė ne tik į išsamų atsakymą, bet ir puikią grafiką.
JasonC atvaizdas, prieinamas kaip ekrano užsklanda.
Jis rašo:
Nusprendžiau rašyti šiek tiek apie programavimo aspektą ir tai, kaip komponentai kalba vienas su kitu. Galbūt tai apšviečia tam tikras sritis.
Pristatymas
Ką užtrunka, kad netgi tas vaizdas, kurį paskelbėte savo klausime, būtų užfiksuotas ekrane?
Ekrano trikampį galima nubrėžti daugeliu būdų. Siekiant paprastumo, daroma prielaida, kad nebuvo naudojami vertex buferiai. (A) viršūnių buferisyra atminties sritis, kurioje saugote koordinates.) Tarkime, kad programa paprasčiausiai papasakojo grafikos apdorojimo vamzdynui apie kiekvieną viršūnę (viršūnė yra tik erdvės koordinatė).
Bet, kol mes negalime padaryti nieko, pirmiausia turime paleisti kai kuriuos pastolius. Pamatysime kodėl vėliau:
// Išvalykite ekraną ir gylį buferį (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Atstatyti dabartinę Modelview matricą glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // brėžinys naudojant trikampius glBegin (GL_TRIANGLES); // Red glColor3f (1.0f, 0.0f, 0.0f); // Trikampio viršus (priekyje) glVertex3f (0.0f, 1.0f, 0.0f); // Žalioji glColor3f (0.0f, 1.0f, 0.0f); // Kairysis trikampis (priekis) glVertex3f (-1.0f, -1.0f, 1.0f); // Blue glColor3f (0.0f, 0.0f, 1.0f); // Trikampio teisė (priekinė) glVertex3f (1.0f, -1.0f, 1.0f); // Atliktas brėžinys ();
Taigi, ką tai padarė?
Rašydami programą, kuri nori naudoti vaizdo plokštę, paprastai vairuotojui pasirenkate tam tikrą sąsają. Kai kurios gerai žinomos sąsajos su vairuotoju yra šios:
- OpenGL
- Direct3D
- CUDA
Šiuo pavyzdžiu laikysimės OpenGL. Dabar, jūsų sąsaja su vairuotoju yra tai, kas suteikia jums visas priemones, reikalingas programai sukurti kalbėti į grafikos plokštę (arba vairuotoją, kuris tada derybos į kortelę).
Ši sąsaja privalo suteikti jums tam tikrą informaciją įrankiai. Šios priemonės yra tokios API formos, kurią galite skambinti iš savo programos.
Ši API yra tai, ką matome pirmiau pateiktame pavyzdyje. Pažvelkime arčiau.
Pastoliai
Prieš iš tikrųjų galite padaryti bet kokį faktinį piešinį, turėsite atlikti a sąranka. Turite apibrėžti savo peržiūros sritį (sritį, kuri bus faktiškai suteikta), savo perspektyvą ( kamera į savo pasaulį), kokią anti-aliasą naudosite (kad išlygintumėte trikampio kraštą)…
Bet mes nežiūrėsime į tai. Mes tiesiog žvelgsime į tai, ką turėsite padaryti kiekvieną kadrą. Kaip:
Ekrano išvalymas
Grafinis dujotiekis neketina išvalyti ekrano kiekvienam rėmeliui. Turėsite tai pasakyti. Kodėl? Štai kodėl:
Jei nenorite išvalyti ekrano, paprasčiausiai perimti tai kiekvienas rėmas. Štai kodėl mes vadiname glClear
suGL_COLOR_BUFFER_BIT
nustatyti. Kitas bitas (GL_DEPTH_BUFFER_BIT
) nurodo OpenGL išvalyti gylisbuferio. Šis buferis naudojamas nustatyti, kurie pikseliai yra priešais kitus ar kitokius taškus.
Transformacija
Vaizdo šaltinis
Transformacija - tai dalis, kurioje mes imamės visų įvesties koordinatų (mūsų trikampio viršūnių) ir pritaikome „ModelView“ matricą. Tai matrica aiškina kaip mūsų modelis (viršūnės) pasukamos, sumažinamos ir išverstos (perkeltos).
Toliau taikome savo projekcijos matricą. Tai perkelia visas koordinates taip, kad jos tinkamai susidurtų su fotoaparatu.
Dabar mes dar kartą transformuojame su mūsų „Viewport“ matrica. Mes tai darome, kad galėtume masto modelis prie mūsų monitoriaus dydžio. Dabar turime viršūnių rinkinį, kuris yra paruoštas renderiui!
Vėliau grįšime prie transformacijos.
Brėžinys
Norėdami piešti trikampį, galime tiesiog pasakyti OpenGL pradėti naują trikampių sąrašas skambindami glBegin
su GL_TRIANGLES
pastovus.
Yra ir kitų formų, kurias galite piešti. Kaip trikampis arba trikampis ventiliatorius. Tai pirmiausia yra optimizavimas, nes jiems reikia mažiau ryšio tarp CPU ir GPU, kad būtų sudarytas toks pat trikampių skaičius.
Po to galime pateikti trijų viršūnių rinkinių, kurie turėtų sudaryti kiekvieną trikampį, sąrašą. Kiekvienas trikampis naudoja 3 koordinates (kaip mes esame 3D erdvėje). Be to, taip pat pateikiu a spalva už kiekvieną viršūnę skambinantglColor3f
anksčiau skambinimas glVertex3f
.
Tarp 3 viršūnių (3 trikampio kampai) atspalvį apskaičiuoja OpenGLautomatiškai. Ji interpoliuoja spalvą per visą poligono veidą.
Sąveika
Dabar, kai spustelėsite langą. Programa turi užfiksuoti tik lango pranešimą, kuris signalizuoja apie paspaudimą. Tada galite paleisti bet kokį veiksmą savo programoje.
Tai bus a daug sunkiau, kai norite pradėti sąveikauti su savo 3D scena.
Pirmiausia turite aiškiai žinoti, kuriame taške vartotojas spustelėjo langą. Tada paimkite savo perspektyvaAtsižvelgdami į tai, galite apskaičiuoti spindulio kryptį nuo pelės paspaudimo taško iki savo scenos. Tada galite apskaičiuoti, ar bet koks jūsų scenos objektas susikerta su tuo spinduliu. Dabar žinote, ar naudotojas spustelėjo objektą.
Taigi, kaip jūs jį pasukate?
Transformacija
Žinau, kad yra dviejų tipų transformacijos, kurios paprastai taikomos:
- Matricos transformacija
- Kaulų transformacija
Skirtumas yra tas kaulai paveikti singlą viršūnių. Matricos visada veikia visus traukiamus viršūnius taip pat. Pažvelkime į pavyzdį.
Pavyzdys
Anksčiau mes įkėlėme mūsų tapatybės matrica prieš piešdami trikampį. Tapatybės matrica yra ta, kuri tiesiog suteikia be transformacijos iš viso. Taigi, ką aš piešiu, tai daro tik mano perspektyva. Taigi, trikampis nebus pasukamas.
Jei noriu dabar pasukti, galėčiau arba matematiką (CPU) ir tiesiog paskambinti glVertex3f
sukita koordinatės (kurios pasukamos). Arba galėčiau leisti GPU atlikti visą darbą skambinant glRotatef
prieš piešiant:
// Pasukite trikampį į Y ašį glRotatef (suma, 0.0f, 1.0f, 0.0f);
suma
žinoma, yra tik fiksuota vertė. Jeigu nori animuoti, turėsite sekti suma
ir padidinti kiekvieną rėmelį.
Taigi, palaukite, kas atsitiko visam matricos pokalbiui anksčiau?
Šiame paprastame pavyzdyje nereikia rūpintis matricomis. Mes tiesiog skambiname glRotatef
ir visa tai rūpinasi už mus.
glRotate
sukasikampas
laipsnių aplink vektorių x y z. Dabartinė matrica (seeglMatrixMode) padauginama iš rotacijos matricos su produktu, pakeičiančiu dabartinę matricą, nes ifglMultMatrix buvo pareikalauta su tokia matrica kaip argumentas: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
Na, ačiū už tai!
Išvada
Kas tampa akivaizdu, yra daug kalbėti į OpenGL. Bet tai nesako mus nieko. Kur yra komunikacija?
Vienintelis dalykas, kurį OpenGL mums sako šiame pavyzdyje, yra kai tai daroma. Kiekviena operacija užtruks tam tikrą laiką. Kai kurie veiksmai trunka neįtikėtinai ilgai, kiti yra neįtikėtinai greitai.
Siunčiant viršūnę GPU bus toks greitas, kad net nežinau, kaip tai išreikšti. Tūkstančiai viršūnių siuntimo iš CPU į GPU, kiekvienas rėmelis, greičiausiai nėra problema.
Ekrano išvalymas gali būti milisekundė arba dar blogiau (turėkite omenyje, kad paprastai kiekvienas rėmelis paprastai trunka tik apie 16 milisekundžių), priklausomai nuo to, kiek yra jūsų peržiūros sritis. Jei norite išvalyti, „OpenGL“ turi atkreipti kiekvieną spalvą, kurią norite išvalyti, kad tai būtų milijonai taškų.
Išskyrus tai, mes galime tik paklausti OpenGL tik apie mūsų grafikos adapterio galimybes (maksimali skiriamoji geba, maksimali anti-alias, maksimalus spalvų gylis,…).
Tačiau mes taip pat galime užpildyti tekstūrą su taškais, kurių kiekviena turi tam tikrą spalvą. Taigi kiekvienas pikselis turi vertę, o tekstūra yra milžiniškas „failas“, užpildytas duomenimis. Tai galime įkelti į grafikos plokštę (sukuriant tekstūros buferį), tada įkelti šešėlį, pasakyti, kad šešėlininkas naudoja mūsų tekstūrą kaip įvestį ir paleiskite kai kuriuos itin sunkius skaičiavimus „faile“.
Tada mes galime „apskaičiuoti“ savo skaičiavimo rezultatą (naujų spalvų pavidalu) į naują tekstūrą.
Štai kaip jūs galite padaryti GPU darbą kitais būdais. Manau, kad CUDA atlieka panašų vaidmenį, bet aš niekada neturėjau galimybės su juo dirbti.
Mes iš tikrųjų tik šiek tiek palietėme visą temą. 3D grafikos programavimas yra žvėries pragaras.
Vaizdo šaltinis
Ar ką nors papildyti paaiškinimu? Garsas išjungtas komentaruose. Norite perskaityti daugiau atsakymų iš kitų „tech-savvy Stack Exchange“ vartotojų? Čia rasite visą diskusijų temą.