Skip to content

Jak współdziałają procesor i GPU, aby renderować grafikę komputerową?

26 de lipiec de 2021
2012 08 21 125825

Jednostka centralna (CPU) i procesor graficzny (GPU) komputera współdziałają w każdej chwili, gdy korzystasz z komputera, zapewniając wyraźny i responsywny interfejs wizualny. Czytaj dalej, aby lepiej zrozumieć, jak ze sobą współpracują.

zdjęcie zrobione przez skennel.

Dzisiejsza sesja pytań i odpowiedzi przychodzi do nas dzięki uprzejmości SuperUser — pododdziału Stack Exchange, społecznościowej grupy witryn internetowych z pytaniami i odpowiedziami.

Pytanie

Czytnik SuperUser Sathya zadał pytanie:

Tutaj możesz zobaczyć zrzut ekranu małego programu C++ o nazwie Triangle.exe z obracającym się trójkątem opartym na API OpenGL.

1627296254 409 Jak wspoldzialaja procesor i GPU aby renderowac grafike komputerowa

Wprawdzie bardzo prosty przykład, ale myślę, że można go zastosować do innych operacji na kartach graficznych.

Byłem po prostu ciekawy i chciałem poznać cały proces od dwukrotnego kliknięcia Triangle.exe pod Windows XP, aż zobaczę obracający się trójkąt na monitorze. Co się dzieje, jak współdziałają CPU (który najpierw obsługuje plik .exe) i GPU (który w końcu wyświetla trójkąt na ekranie)?


Wydaje mi się, że w wyświetlanie tego obracającego się trójkąta zaangażowany jest między innymi następujący sprzęt/oprogramowanie:

Sprzęt komputerowy

  • Dysk twardy
  • Pamięć systemowa (RAM)
  • procesor
  • Pamięć wideo
  • GPU
  • wyświetlacz LCD

Oprogramowanie

  • System operacyjny
  • API DirectX/OpenGL
  • Sterownik Nvidii

Czy ktoś może wyjaśnić ten proces, może z jakimś schematem blokowym dla ilustracji?

Nie powinno to być złożone wyjaśnienie, obejmujące każdy krok (przypuszczam, że wykraczałoby to poza zakres), ale wyjaśnienie, które może zastosować średniozaawansowany informatyk.

Jestem prawie pewien, że wiele osób, które nazwałyby się nawet informatykami, nie potrafiłoby poprawnie opisać tego procesu.

Odpowiedź

1627296254 243 Jak wspoldzialaja procesor i GPU aby renderowac grafike komputerowa

Chociaż wielu członków społeczności odpowiedziało na to pytanie, Oliver Salzburg poszedł o krok dalej i odpowiedział nie tylko szczegółową odpowiedzią, ale także doskonałą grafiką towarzyszącą.

Obraz JasonC, dostępne jako tapeta tutaj.

On pisze:

Postanowiłem napisać trochę o aspekcie programistycznym i o tym, jak komponenty komunikują się ze sobą. Może rzuci trochę światła na pewne obszary.

Prezentacja

Co trzeba zrobić, aby ten pojedynczy obraz, który umieściłeś w swoim pytaniu, został narysowany na ekranie?


Istnieje wiele sposobów na narysowanie trójkąta na ekranie. Dla uproszczenia załóżmy, że nie użyto buforów wierzchołków. (A bufor wierzchołkówto obszar pamięci, w którym przechowujesz współrzędne.) Załóżmy, że program po prostu powiedział potoku przetwarzania grafiki o każdym pojedynczym wierzchołku (wierzchołek to po prostu współrzędna w przestrzeni) z rzędu.

Jednak, zanim będziemy mogli cokolwiek narysować, musimy najpierw uruchomić rusztowanie. Zobaczymy Czemu później:

// 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();

Więc co to zrobiło?

Kiedy piszesz program, który chce używać karty graficznej, zwykle wybierasz jakiś interfejs do sterownika. Niektóre dobrze znane interfejsy do sterownika to:

  • OpenGL
  • Direct3D
  • CUDA

W tym przykładzie będziemy trzymać się OpenGL. Teraz twój interfejs do sterownika jest tym, co daje Ci wszystkie narzędzia potrzebne do stworzenia Twojego programu gadanie do karty graficznej (lub sterownika, który następnie rozmowy do karty).

Ten interfejs z pewnością da ci pewność narzędzia. Narzędzia te przybierają kształt an API które możesz wywołać ze swojego programu.


To API jest tym, co widzimy w powyższym przykładzie. Przyjrzyjmy się bliżej.

Rusztowanie

Zanim naprawdę będziesz mógł zrobić jakikolwiek rzeczywisty rysunek, musisz wykonać organizować coś. Musisz zdefiniować swój rzutnia (obszar, który będzie faktycznie renderowany), swoją perspektywę ( kamera do swojego świata), jakiego antyaliasingu będziesz używać (aby wygładzić krawędzie trójkąta)…

Ale nie będziemy się temu przyglądać. Rzucimy okiem na rzeczy, które musisz zrobić każda rama. Lubić:

Czyszczenie ekranu

Potok graficzny nie wyczyści ekranu dla każdej klatki. Musisz to powiedzieć. Czemu? Dlatego:

1627296254 295 Jak wspoldzialaja procesor i GPU aby renderowac grafike komputerowa

Jeśli nie wyczyścisz ekranu, po prostu przeciągnąć to każda klatka. Dlatego dzwonimy glClear zGL_COLOR_BUFFER_BIT ustawić. Drugi bit (GL_DEPTH_BUFFER_BIT) mówi OpenGL, aby wyczyścić głębokośćbufor. Ten bufor służy do określenia, które piksele znajdują się przed (lub za) innymi pikselami.

Transformacja

1627296254 563 Jak wspoldzialaja procesor i GPU aby renderowac grafike komputerowa
Źródło obrazu

Transformacja to część, w której bierzemy wszystkie współrzędne wejściowe (wierzchołki naszego trójkąta) i stosujemy naszą macierz ModelView. To jest matryca, która wyjaśnia jak nasz Model (wierzchołki) są obracane, skalowane i przesuwane (przesuwane).


Następnie stosujemy naszą macierz projekcji. To przesuwa wszystkie współrzędne tak, aby były skierowane poprawnie na naszą kamerę.

Teraz ponownie przekształcamy się za pomocą naszej macierzy Viewport. Robimy to, aby skalować nasze Model do wielkości naszego monitora. Teraz mamy zestaw wierzchołków, które są gotowe do renderowania!

Do transformacji wrócimy nieco później.

Rysunek

Aby narysować trójkąt, możemy po prostu powiedzieć OpenGL, aby rozpoczął nowy lista trójkątów poprzez dzwonienie glBegin z GL_TRIANGLES stały.
Istnieją również inne formy, które możesz narysować. Jak trójkątny pasek lub trójkątny wachlarz. Są to przede wszystkim optymalizacje, ponieważ wymagają mniejszej komunikacji między procesorem a GPU, aby narysować tę samą liczbę trójkątów.

Następnie możemy dostarczyć listę zestawów 3 wierzchołków, które powinny tworzyć każdy trójkąt. Każdy trójkąt wykorzystuje 3 współrzędne (ponieważ jesteśmy w przestrzeni 3D). Dodatkowo zapewniam również kolor dla każdego wierzchołka, wywołującglColor3f przed powołanie glVertex3f.

Odcień między 3 wierzchołkami (3 rogi trójkąta) jest obliczany przez OpenGLautomatycznie. Interpoluje kolor na całej powierzchni wielokąta.

Interakcja

Teraz po kliknięciu okna. Aplikacja musi tylko uchwycić wiadomość w oknie to sygnalizuje kliknięcie. Następnie możesz uruchomić dowolną akcję w swoim programie.


To dostaje działka trudniejsze, gdy chcesz rozpocząć interakcję ze sceną 3D.

Najpierw musisz wyraźnie wiedzieć, przy którym pikselu użytkownik kliknął okno. Następnie, biorąc swój perspektywicznypod uwagę, możesz obliczyć kierunek promienia, od punktu kliknięcia myszą do swojej sceny. Następnie możesz obliczyć, czy jakiś obiekt w twojej scenie przecina z tym promieniem. Teraz wiesz, czy użytkownik kliknął obiekt.

Jak więc sprawić, by się obracał?

Transformacja

Znam dwa rodzaje przekształceń, które są powszechnie stosowane:

  • Transformacja macierzowa
  • Transformacja oparta na kościach

Różnica polega na tym, że kości wpływa na singiel wierzchołki. Macierze zawsze wpływają na wszystkie rysowane wierzchołki w ten sam sposób. Spójrzmy na przykład.

Przykład

Wcześniej załadowaliśmy nasze macierz jednostkowa przed narysowaniem naszego trójkąta. Macierz tożsamości to taka, która po prostu zapewnia bez transformacji w ogóle. Więc na cokolwiek rysuję, wpływa tylko moja perspektywa. Tak więc trójkąt w ogóle nie zostanie obrócony.

Jeśli chcę go teraz obrócić, mogę sam wykonać obliczenia (na procesorze) i po prostu zadzwonić glVertex3f zinny współrzędne (które są obracane). Albo mogę pozwolić GPU wykonać całą pracę, dzwoniąc glRotatefprzed rysowaniem:

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


amount jest oczywiście tylko stałą wartością. Jeśli chcesz animować, musisz to śledzić amounti zwiększaj ją z każdą klatką.

Więc czekaj, co się stało z wszystkimi wcześniejszymi rozmowami o matrycy?

W tym prostym przykładzie nie musimy przejmować się macierzami. Po prostu dzwonimy glRotatef i troszczy się o to za nas.

glRotate wytwarza obrót angle stopni wokół wektora xyz . Aktualna macierz (patrzglMatrixMode) jest mnożone przez macierz rotacji z iloczynem zastępującym obecną macierz, tak jakbyglMultMatrix zostały wywołane z następującą macierzą jako argumentem:

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

Cóż, dzięki za to!

Wniosek

Oczywiste jest, że dużo się mówi do OpenGL. Ale to nic nie mówi nas byle co. Gdzie jest komunikacja?

Jedyną rzeczą, o której mówi nam OpenGL w tym przykładzie, jest: Kiedy się zakończy. Każda operacja zajmie trochę czasu. Niektóre operacje trwają niewiarygodnie długo, inne są niewiarygodnie szybkie.

Wysyłanie wierzchołka do GPU będzie tak szybko, że nawet nie wiedziałbym, jak to wyrazić. Wysyłanie tysięcy wierzchołków z procesora do GPU, w każdej pojedynczej klatce, najprawdopodobniej nie stanowi żadnego problemu.

Czyszczenie ekranu może zająć milisekundę lub gorzej (pamiętaj, że zwykle masz tylko około 16 milisekund na narysowanie każdej klatki), w zależności od tego, jak duży jest twój widoczny obszar. Aby to wyczyścić, OpenGL musi narysować każdy piksel w kolorze, który chcesz wyczyścić, co może być milionami pikseli.


Poza tym możemy zapytać OpenGL tylko o możliwości naszej karty graficznej (maksymalna rozdzielczość, maksymalny antyaliasing, maksymalna głębia kolorów, …).

Ale możemy również wypełnić teksturę pikselami, z których każdy ma określony kolor. Każdy piksel zawiera więc wartość, a tekstura jest gigantycznym „plikiem” wypełnionym danymi. Możemy to załadować do karty graficznej (tworząc bufor tekstur), a następnie załadować a shader, powiedz temu shaderowi, aby użył naszej tekstury jako danych wejściowych i wykonał bardzo ciężkie obliczenia na naszym „pliku”.

Możemy następnie „wyrenderować” wynik naszych obliczeń (w postaci nowych kolorów) na nową teksturę.

W ten sposób możesz sprawić, by GPU pracował dla Ciebie na inne sposoby. Zakładam, że CUDA działa podobnie do tego aspektu, ale nigdy nie miałem okazji z nim pracować.

Tak naprawdę tylko lekko poruszyliśmy cały temat. Programowanie grafiki 3D to piekielna bestia.

1627296254 243 Jak wspoldzialaja procesor i GPU aby renderowac grafike komputerowa
Źródło obrazu

Masz coś do dodania do wyjaśnienia? Dźwięk w komentarzach. Chcesz przeczytać więcej odpowiedzi od innych doświadczonych technologicznie użytkowników Stack Exchange? Sprawdź pełny wątek dyskusji tutaj.

Czy ten post był pomocny?