Начална » как да » Как процесора и GPU взаимодействат с компютърната графика?

    Как процесора и GPU взаимодействат с компютърната графика?

    Централният процесор на компютъра (CPU) и графичният процесор (GPU) взаимодействат всеки момент, когато използвате компютъра си, за да ви предоставят ясен и отзивчив визуален интерфейс. Прочетете, за да разберете по-добре как работят заедно.

    Снимка от sskennel.

    Днешната сесия на въпросите и отговорите идва с любезното съдействие на SuperUser - подразделение на Stack Exchange, обединяващо групи от уебсайтове с въпроси и отговори.

    Въпроса

    Читателят на SuperUser Сатя постави въпроса:

    Тук можете да видите екранна снимка на малка програма C ++, наречена Triangle.exe с въртящ се триъгълник, базирана на OpenGL API.

    Вярно е, че това е много основен пример, но мисля, че е приложим за други операции с графични карти.

    Бях просто любопитен и исках да знам целия процес от двойно кликване върху Triangle.exe под Windows XP, докато не видя триъгълника, който се върти на монитора. Какво се случва, как CPU (който първо обработва .exe) и GPU (който накрая извежда триъгълника на екрана) взаимодействат?

    Предполагам, че при показването на този въртящ се триъгълник е главно следният хардуер / софтуер:

    железария

    • HDD
    • Системна памет (RAM)
    • процесор
    • Видео памет
    • GPU
    • ЛСД дисплей

    Софтуер

    • Операционна система
    • API за DirectX / OpenGL
    • Nvidia драйвер

    Може ли някой да обясни процеса, може би с някаква схема за илюстрация?

    Това не бива да е сложно обяснение, което да обхваща всяка отделна стъпка (предполагам, че ще излезе извън обхвата), но обяснение за междинния ИТ човек може да последва.

    Сигурен съм, че много хора, които дори се наричат ​​ИТ специалисти, не могат да опишат правилно този процес.

    Отговорът

    Въпреки, че мнозина от членовете на общността отговориха на въпроса, Оливър Залцбург отиде допълнително и отговори не само с подробен отговор, но и с отлични съпътстващи графики.

    Изображение от JasonC, наличен като тапет тук.

    Той пише:

    Реших да напиша малко за аспекта на програмирането и как компонентите говорят помежду си. Може би ще хвърли малко светлина върху някои области.

    Презентацията

    Какво е необходимо, за да има дори един-единствен образ, който сте написали във вашия въпрос, нарисуван на екрана?

    Има много начини да нарисувате триъгълник на екрана. За простота, нека предположим, че не са използвани върхови буфери. (А буферен връхе област от паметта, в която се съхраняват координатите.) Да предположим, че програмата просто е казала на графичния процесор за всеки отделен връх (един връх е само координата в пространството) подред.

    Но, преди да можем да нарисуваме нещо, първо трябва да изпълним някакво скеле. Ще видим защо по късно:

    // Изчистване на екрана и буфера на дълбочината glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Нулиране на текущата матрица за преглед на модела glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Рисуване с триъгълници glBegin (GL_TRIANGLES); // Червен glColor3f (1.0f, 0.0f, 0.0f); // Top Of Triangle (Фронт) glVertex3f (0.0f, 1.0f, 0.0f); // Зелен glColor3f (0.0f, 1.0f, 0.0f); // Ляво от триъгълник (отпред) glVertex3f (-1.0f, -1.0f, 1.0f); // Blue glColor3f (0.0f, 0.0f, 1.0f); // дясно от триъгълник (отпред) glVertex3f (1.0f, -1.0f, 1.0f); // Done Drawing glEnd ();

    И така, какво направи това??

    Когато напишете програма, която иска да използва графичната карта, обикновено ще изберете някакъв интерфейс за драйвера. Някои добре познати интерфейси към драйвера са:

    • OpenGL
    • Direct3D
    • CUDA

    За този пример ще се придържаме към OpenGL. Сега, твоята интерфейс към водача е това, което ви дава всички инструменти, от които се нуждаете, за да направите вашата програма говоря на графичната карта (или на драйвера, който след това преговори към картата).

    Този интерфейс е длъжен да ви даде сигурност инструменти. Тези инструменти приемат формата на API, която можете да извикате от вашата програма.

    Този API е това, което виждаме да се използва в примера по-горе. Нека погледнем отблизо.

    Скелето

    Преди да можете да направите някакво реално рисуване, ще трябва да извършите a настройвам. Трябва да определите своя визуален прозорец (областта, която действително ще бъде визуализирана), вашата перспектива ( камера във вашия свят), какъв анти-алиасинг ще използвате (за изглаждане на ръбовете на триъгълника)…

    Но ние няма да гледаме на това. Просто ще надникнем в нещата, които ще трябва да направите всяка рамка. Като:

    Изчистване на екрана

    Графичният конвейер няма да изчисти екрана за вас всеки кадър. Ще трябва да го разкажете. Защо? Това е причината:

    Ако не изчистите екрана, просто ще го направите изтегли всеки кадър. Затова се обаждаме glClear сGL_COLOR_BUFFER_BIT комплект. Другият бит (GL_DEPTH_BUFFER_BIT) казва на OpenGL да изчисти дълбочинабуфер. Този буфер се използва, за да се определи кои пиксели са в предните (или зад) други пиксели.

    Трансформация


    Източник на изображение

    Трансформацията е частта, в която вземаме всички входни координати (върховете на нашия триъгълник) и прилагаме нашата ModelView матрица. Това е матрицата обяснява как ни модел (върховете) са завъртени, мащабирани и преведени (преместени).

    След това прилагаме нашата Проекционна матрица. Това премества всички координати, така че те да са изправени пред нашата камера правилно.

    Сега отново се трансформираме с нашата Viewport матрица. Ние правим това, за да увеличим нашето модел до размера на нашия монитор. Сега имаме набор от върхове, които са готови да бъдат визуализирани!

    Ще се върнем към трансформацията малко по-късно.

    чертеж

    За да начертаем триъгълник, можем просто да кажем на OpenGL да започне ново списък с триъгълници чрез обаждане glBegin с GL_TRIANGLES постоянен.
    Има и други форми, които можете да рисувате. Като триъгълна лента или триъгълник. Това са предимно оптимизации, тъй като те изискват по-малко комуникация между процесора и графичния процесор, за да се извлече същото количество триъгълници.

    След това можем да предоставим списък от групи от 3 върха, които трябва да съставят всеки триъгълник. Всеки триъгълник използва 3 координати (както сме в 3D-пространството). Освен това предлагам също цвят за всеки връх, чрез обажданеglColor3f преди повикване glVertex3f.

    В сянка между 3-те върха (трите ъгъла на триъгълника) се изчислява от OpenGLавтоматично. Той ще интерполира цвета върху цялото лице на полигона.

    взаимодействие

    Сега, когато кликнете върху прозореца. Приложението трябва само да улови съобщението в прозореца, което сигнализира за кликване. След това можете да изпълните всяко действие в програмата, което искате.

    Това става много по-трудно, след като искате да започнете да взаимодействате с вашата 3D сцена.

    Първо трябва ясно да се знае на кой пиксел потребителят е натиснал прозореца. След това, като си перспективапредвид, можете да изчислите посоката на лъча, от точката на щракване на мишката върху вашата сцена. След това можете да изчислите дали някой обект от вашата сцена пресича с този лъч. Сега знаете дали потребителят е натиснал даден обект.

    И така, как да я въртите?

    Трансформация

    Запознат съм с два вида трансформации, които обикновено се прилагат:

    • Матрична трансформация
    • Костна трансформация

    Разликата е в това кости засягат единично върхове. Матриците винаги засягат всички изтеглени върхове по същия начин. Нека да разгледаме един пример.

    пример

    По-рано натоварихме идентичност матрица преди да начертаем нашия триъгълник. Матрицата на идентичността е тази, която просто осигурява няма трансформация изобщо. Така че, каквото и да рисувам, се влияе само от моята перспектива. Така че триъгълникът изобщо няма да се върти.

    Ако искам да го завъртя сега, бих могъл или да се справя сам (на CPU) и просто да се обадя glVertex3f сдруг координати (които се завъртат). Или бих позволил на GPU да върши цялата работа, като се обади glRotatefпреди чертане:

    // Завъртане на триъгълника върху ос Y glRotatef (количество, 0.0f, 1.0f, 0.0f); 

    количество разбира се, е само фиксирана стойност. Ако искаш вдъхновявам, ще трябва да следите количествои увеличавайте всяка рамка.

    Така че, чакай, какво се случи с всички матрични разговори по-рано?

    В този прост пример не е нужно да се грижим за матриците. Ние просто се обаждаме glRotatef и се грижи за всичко това за нас.

    glRotate произвежда завъртане на ъгъл градуса около вектора x y z. Текущата матрица (seeglMatrixMode) се умножава с ротационна матрица, като продуктът заменя текущата матрица, като ifglMultMatrix се нарича със следната матрица като аргумент:

    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 0 s 0 x ⁢ z ⁡ 1 - c - y ⁢ sy ⁢ z ⁡ 1 - c + x ⁢ sz 2 - 1 - c + c 0 0 0 0 1

    Благодаря за това!

    заключение

    Това, което става очевидно, е, че много се говори да се OpenGL. Но това не е ясно нас нищо. Къде е комуникацията?

    Единственото нещо, което OpenGL ни казва в този пример е когато свърши. Всяка операция ще отнеме известно време. Някои операции вземат невероятно дълго време, други са невероятно бързи.

    Изпращане на връх на GPU ще бъде толкова бързо, че дори не знам как да го изразя. Изпращането на хиляди върхове от процесора към графичния процесор, всеки отделен кадър, най-вероятно няма проблем.

    Изчистване на екрана може да отнеме милисекунда или по-лошо (имайте предвид, че обикновено имате само около 16 милисекунди от времето, за да нарисувате всеки кадър), в зависимост от това колко голям е вашият изглед. За да го изчистите, OpenGL трябва да нарисува всеки един пиксел в цвета, който искате да изчистите, което може да бъде милиони пиксели.

    Освен това, ние можем да поискаме от OpenGL почти само възможностите на нашия графичен адаптер (макс. Резолюция, максимално анти-алиасинг, максимална дълбочина на цветовете,…).

    Но можем да запълним и текстура с пиксели, всеки от които има специфичен цвят. По този начин всеки пиксел държи стойност, а текстурата е гигантски “файл”, напълнен с данни. Можем да заредим това в графичната карта (чрез създаване на буфер за текстура), след това да заредим шейдър, да кажем на този шейдър да използва текстурата ни като вход и да изпълни някои изключително тежки изчисления на нашия „файл“..

    След това можем да „превърнем” резултата от нашето изчисление (под формата на нови цветове) в нова текстура.

    Така можете да накарате графичния процесор да работи за вас по други начини. Предполагам, че CUDA работи подобно на този аспект, но никога не съм имал възможност да работя с него.

    Наистина само леко докоснахме цялата тема. 3D графичното програмиране е адски звяр.


    Източник на изображението


    Имате ли какво да добавите към обяснението? Звукът е изключен в коментарите. Искате ли да прочетете повече отговори от други технологични потребители на Stack Exchange? Вижте пълната тема за дискусия тук.