Główna » jak » W jaki sposób procesor i GPU wchodzą w interakcję z renderowaniem grafiki komputerowej?

    W jaki sposób procesor i GPU wchodzą w interakcję z renderowaniem grafiki komputerowej?

    Centralny procesor (CPU) komputera i procesor graficzny (GPU) współdziałają w każdym momencie korzystania z komputera w celu zapewnienia wyraźnego i elastycznego interfejsu graficznego. Czytaj dalej, aby lepiej zrozumieć, jak działają razem.

    zdjęcie zrobione przez sskennel.

    Dzisiejsza sesja pytań i odpowiedzi jest dostępna dzięki uprzejmości SuperUser - podsekcji Stack Exchange, grupy dyskusyjnej poświęconej tematyce społecznościowej.

    Pytanie

    Czytnik SuperUser Sathya zadał pytanie:

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

    Jest to wprawdzie bardzo prosty przykład, ale myślę, że można go zastosować do innych operacji kart graficznych.

    Byłem po prostu ciekawy i chciałem poznać cały proces, klikając dwukrotnie plik Triangle.exe w systemie Windows XP, dopóki nie zobaczę trójkąta obracającego się na monitorze. Co się dzieje, w jaki sposób CPU (który pierwszy obsługuje .exe) i GPU (który ostatecznie wyprowadza trójkąt na ekranie) współdziałają?

    Wydaje mi się, że udział w wyświetlaniu tego obracającego się trójkąta to przede wszystkim następujący sprzęt / oprogramowanie, między innymi:

    Sprzęt komputerowy

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

    Oprogramowanie

    • System operacyjny
    • API DirectX / OpenGL
    • Sterownik Nvidia

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

    Nie powinno to być skomplikowanym wyjaśnieniem, które obejmuje każdy pojedynczy krok (zgadnij, że wykracza poza zakres), ale wyjaśnienie, które pośrednik IT może śledzić.

    Jestem prawie pewna, że ​​wielu ludzi, którzy nazwaliby siebie fachowcami IT, nie potrafiłoby poprawnie opisać tego procesu.

    Odpowiedź

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

    Obraz JasonC, dostępny jako tapeta tutaj.

    On pisze:

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

    Prezentacja

    Co potrzeba, aby nawet pojedynczy obraz, który zamieściłeś w swoim tekście, został narysowany na ekranie?

    Istnieje wiele sposobów narysowania trójkąta na ekranie. Dla uproszczenia załóżmy, że nie użyto buforów wierzchołków. (ZA bufor wierzchołkówjest obszarem pamięci, w którym przechowuje się współrzędne.) Załóżmy, że program po prostu powiedział rurociągowi przetwarzania grafiki o każdym pojedynczym wierzchołku (wierzchołek to tylko współrzędna w przestrzeni) z rzędu.

    Ale, zanim będziemy mogli cokolwiek rysować, musimy najpierw uruchomić rusztowanie. Zobaczymy czemu później:

    // Wyczyść ekran i bufor głębi glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Resetuj bieżącą matrycę widoku modelu glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Rysowanie za pomocą trójkątów glBegin (GL_TRIANGLES); // Red glColor3f (1.0f, 0.0f, 0.0f); // Top Of Triangle (Front) glVertex3f (0.0f, 1.0f, 0.0f); // Zielony 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); // Wykonano rysunek glEnd ();

    Więc co to zrobiło?

    Kiedy piszesz program, który chce korzystać z karty graficznej, zazwyczaj wybierasz jakiś rodzaj interfejsu 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 rozmowa do karty graficznej (lub sterownika, który wtedy rozmowy do karty).

    Ten interfejs z pewnością da ci pewność przybory. Narzędzia te mają postać interfejsu API, który można wywołać z poziomu programu.

    To API jest używane w powyższym przykładzie. Przyjrzyjmy się bliżej.

    Rusztowanie

    Zanim naprawdę możesz wykonać dowolny rysunek, musisz wykonać Ustawiać. Musisz zdefiniować swój rzutnia (obszar, który będzie faktycznie renderowany), twoją perspektywę ( aparat fotograficzny do twojego świata), jakiego antyaliasingu użyjesz (aby wygładzić krawędź trójkąta) ...

    Ale nie będziemy na to patrzeć. Przyjrzymy się tylko temu, co musisz zrobić każda rama. Lubić:

    Czyszczenie ekranu

    Rurka graficzna nie oczyści ekranu z każdej klatki. Musisz to powiedzieć. Czemu? Dlatego:

    Jeśli nie wyczyścisz ekranu, po prostu zremisować to każda klatka. Dlatego dzwonimy glClear zGL_COLOR_BUFFER_BIT zestaw. 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ę z przodu (lub z tyłu) innych pikseli.

    Transformacja


    Źródło obrazu

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

    Następnie stosujemy naszą macierz projekcyjną. Spowoduje to przesunięcie wszystkich współrzędnych w taki sposób, aby prawidłowo ustawiały się one względem naszego aparatu.

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

    Wrócimy do transformacji 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 głównie optymalizacje, ponieważ wymagają mniejszej komunikacji pomię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 (tak jak w przestrzeni 3D). Dodatkowo zapewniam również kolor dla każdego wierzchołka, dzwoniącglColor3f przed powołanie glVertex3f.

    Cień między 3 wierzchołkami (3 rogi trójkąta) jest obliczany przez OpenGLautomatycznie. Będzie interpolować kolor na całej powierzchni wielokąta.

    Interakcja

    Teraz, gdy klikniesz okno. Aplikacja musi jedynie przechwytywać komunikat okna, który sygnalizuje kliknięcie. Następnie możesz uruchomić dowolną akcję w swoim programie.

    To dostaje a los trudniejsze, gdy chcesz rozpocząć interakcję ze sceną 3D.

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

    Więc, jak sprawić, żeby się obracał?

    Transformacja

    Mam świadomość dwóch rodzajów transformacji, które są generalnie stosowane:

    • Transformacja oparta na macierzy
    • Transformacja na bazie kości

    Różnica polega na tym kości wpływają na pojedyncze wierzchołki. Matryce zawsze działają w ten sam sposób na wszystkie narysowane wierzchołki. Spójrzmy na przykład.

    Przykład

    Wcześniej załadowaliśmy nasze macierz jednostkowa przed rysowaniem naszego trójkąta. Macierz tożsamości to taka, która po prostu zapewnia bez transformacji w ogóle. Cokolwiek rysuję, zależy tylko od mojej perspektywy. Tak więc trójkąt nie zostanie w ogóle obrócony.

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

    // Obróć trójkąt na osi Y glRotatef (ilość, 0.0f, 1.0f, 0.0f); 

    ilość jest oczywiście tylko stałą wartością. Jeśli chcesz animować, będziesz musiał śledzić ilośći zwiększ to każdą klatkę.

    Tak więc, poczekaj, co stało się wcześniej z wszystkimi rozmowami matrycowymi?

    W tym prostym przykładzie nie musimy dbać o matryce. Po prostu dzwonimy glRotatef i troszczy się o to wszystko dla nas.

    glRotate wytwarza obrót kąt stopnie wokół wektora x y z. Bieżąca macierz (seeglMatrixMode) jest mnożona przez macierz rotacji z produktem zastępującym bieżącą macierz, tak jak wywołano metodę ifglMultMatrix z następującą macierzą jako jej 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

    Dzięki za to!

    Wniosek

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

    Jedyne, co OpenGL nam w tym przykładzie mówi to Kiedy się zakończy. Każda operacja potrwa pewien czas. Niektóre operacje trwają niezwykle długo, inne są niesamowicie szybkie.

    Wysyłanie wierzchołka na GPU będzie tak szybko, że nawet nie wiem, jak to wyrazić. Wysłanie tysięcy wierzchołków z procesora na GPU, każda pojedyncza klatka jest najprawdopodobniej bez problemu.

    Czyszczenie ekranu może trwać milisekundę lub gorzej (należy pamiętać, że zwykle trzeba mieć około 16 milisekund czasu na narysowanie każdej klatki), w zależności od wielkości ekranu. Aby to wyczyścić, OpenGL musi narysować każdy pojedynczy piksel w kolorze, który chcesz oczyścić, czyli milion pikseli.

    Poza tym możemy prawie tylko zapytać OpenGL o możliwości naszego adaptera graficznego (maksymalna rozdzielczość, maksymalne wygładzanie, 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 ma zatem wartość, a tekstura jest gigantycznym "plikiem" wypełnionym danymi. Możemy załadować to na kartę graficzną (tworząc bufor tekstur), a następnie załadować moduł cieniujący, powiedzieć, że moduł cieniujący użył naszej tekstury jako danych wejściowych i przeprowadzić bardzo ciężkie obliczenia na naszym "pliku".

    Możemy następnie "renderować" wynik naszych obliczeń (w postaci nowych kolorów) do nowej tekstury.

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

    Naprawdę tylko nieznacznie poruszyliśmy cały temat. Programowanie grafiki 3D to piekielna bestia.


    Źródło obrazu


    Czy masz coś do dodania do wyjaśnienia? Dźwięk w komentarzach. Chcesz przeczytać więcej odpowiedzi od innych użytkowników Stack Exchange, którzy znają się na technologii? Sprawdź cały wątek dyskusji tutaj.