Современная графическая плата состоит из следующих частей:
• графический процессор (GPU) — занимается расчетами выводимого изображения, освобождая от этой обязанности центральный процессор, производит рассчеты для обработки команд трехмерной графики. Является основой графической платы, именно от него зависят быстродействие и возможности всего устройства. Современные графические процессоры по сложности мало чем уступают центральному процессору компьютера, и зачастую превосходят их по числу транзисторов. Архитектура современного GPU обычно предполагает наличие нескольких блоков обработки информации, а именно: блок обработки 2D графики, блок обработки 3D графики, в свою очередь, обычно разделяющийся на геометрическое ядро (плюс кэш вершин) и блок растеризации (плюс кэш текстур) и др.
• видеоконтроллер — отвечает за формирование изображения в видеопамяти, дает команды RAMDAC на формирование сигналов развертки для монитора и осуществляет обработку запросов центрального процессора. Кроме этого, обычно присутствуют контроллер внешней шины данных (например PCI или AGP), контроллер внутренней шины данных и контроллер видеопамяти. Ширина внутренней шины и шины видеопамяти обычно шире внешней (64, 128 или 256 разрядов против 16 или 32), во многие видеоконтроллеры встраивается еще и RAMDAC. Современные графические адаптеры (ATI, nVidia) обычно имеют не менее двух видеоконтроллеров, работающих независимо друг от друга и управляющих одновременно одним или несколькими дисплеями каждый.
• видеопамять — выполняет роль кадрового буфера, в котором хранится в цифровом формате изображение, генерируемое и постоянно изменяемое графическим процессором и выводимое на экран монитора (или нескольких мониторов). В видеопамяти хранятся также промежуточные невидимые на экране элементы изображения и другие данные. Видеопамять бывает нескольких типов, различающихся по скорости доступа и рабочей частоте. Современные видеокарты комплектуются памятью типа DDR, DDR2 или GDDR3. Следует также иметь в виду, что помимо видеопамяти, находящейся на видеокарте, современные графические процессоры обычно используют в своей работе часть общей системной памяти компьютера, прямой доступ к которой организуется драйвером видеоадаптера через шину AGP или PCIE.
• цифро-аналоговый преобразователь ЦАП (RAMDAC) — служит для преобразования изображения, формируемого видеоконтроллером, в уровни интенсивности цвета, подаваемые на аналоговый монитор. Возможный диапазон цветности изображения определяется только параметрами RAMDAC. Чаще всего RAMDAC имеет четыре основных блока — три цифроаналоговых преобразователя, по одному на каждый цветовой канал (красный, синий, зеленый, RGB), и SRAM для хранения данных о гамма коррекции. Большинство ЦАП имеют разрядность 8 бит на канал — получается по 256 уровней яркости на каждый основной цвет, что в сумме дает 16.7 млн. цветов (и за счет гамма коррекции есть возможность отображать исходные 16.7 млн. цветов в гораздо большее цветовое пространство). Некоторые RAMDAC имеют разрядность по каждому каналу 10bit (1024 уровня яркости), что позволяет сразу отображать более 1 млрд. цветов, но эта возможность практически не используется. Для поддержки второго монитора часто устанавливают второй ЦАП. Стоит отметить, что мониторы и видеопроекторы подключаемые к цифровому DVI выходу видеокарты для преобразования потока цифровых данных используют собственные цифроаналоговые преобразователи и от характеристик ЦАП видеокарты не зависят.
• видео-ПЗУ (Video ROM) — постоянное запоминающее устройство, в которое записаны видео-BIOS, экранные шрифты, служебные таблицы и т. п. ПЗУ не используется видеоконтроллером напрямую — к нему обращается только центральный процессор. Хранящийся в ПЗУ видео-BIOS обеспечивает инициализацию и работу видеокарты до загрузки основной операционной системы, а также содержит системные данные, которые могут читаться и интерпретироваться видеодрайвером в процессе работы (в зависимости от применяемого метода разделения ответственности между драйвером и BIOS). На многих современных картах устанавливаются электрически перепрограммируемые ПЗУ (EEРROM, Flash ROM), допускающие перезапись видео-BIOS самим пользователем при помощи специальной программы.
• система охлаждения — предназначена для сохранения температурного режима видеопроцессора и видеопамяти в допустимых значениях. Правильная и полнофункциональная работа современного графического адаптера обеспечивается с помощью видеодрайвера — специального программного обеспечения, поставляемого производителем видеочипа и загружаемого в процессе запуска операционной системы. Видеодрайвер выполняет функции интерфейса между системой с запущенными в ней приложениями и видеоадаптером. Так же как и видео-BIOS, видеодрайвер организует и программно контролирует работу всех частей видеоадаптера через специальные регистры управления, доступ к которым идет через соответствующую шину.
====== **Видеопамять** ======
Кроме шины данных, второе узкое место любого видеоадаптера — это пропускная способность (англ. bandwidth) памяти самого видеоадаптера. Причем изначально проблема возникла даже не столько из-за скорости обработки видеоданных (это сейчас часто стоит проблема информационного голода видеокантроллера, когда он данные обрабатывает быстрее чем успевает их читать/писать из/в видеопамять), сколько из-за необходимости доступа к ним со стороны чипа видеоадаптера, центрального процессора, и RAMDAC’а. Дело в том, что при высоких разрешениях и большой глубине цвета для отображения страницы экрана на мониторе необходимо прочитать все эти данные из видеопамяти и преобразовать в аналоговый сигнал который и пойдет на монитор. Если объяснить более понятно и просто, то начнем с того, что то изображение что вы видите на экране монитора хранится не в мониторе, а в памяти видеоадаптера. И его нужно прочитать из памяти и вывести на экран столько раз в секунду, сколько кадров в секунду показывает монитор. Возьмем объем одной страницы экрана при разрешении 1024×768 точек и глубине цвета 24bit (True Color), это составляет 2.25MB. При частоте кадров 75Гц необходимо считывать эту страницу из памяти видеоадаптера 75 раз в секунду (считываемые пиксели передаются в RAMDAC и он преобразовывает цифровые данные о цвете пикселя в аналоговый сигнал поступающий на монитор), причем ни задержаться, ни пропустить пиксель нельзя, следовательно номинально потребная пропускная способность видеопамяти для данного разрешения составляет приблизительно 170MB/сек, и это без учета того, что необходимо и самому видеоконтроллеру писать и читать данные из этой памяти. Для разрешения 1600x1200x32бит при той же частоте кадров 75Гц, номинально потребная пропускная составляет уже 550 МБайт в секунду, для сравнения, процессор Pentium2 имел пиковую скорость работы с памятью 528МБ в секунду. Проблему можно было решать двояко — либо использовать специальные типы памяти, которые позволяют одновременно двум устройствам читать из нее, либо ставить очень быструю память. О типах памяти и пойдет речь.
FPM DRAM — FPM DRAM (Fast Page Mode Dynamic RAM - динамическое ОЗУ с быстрым страничным доступом) — основной тип видеопамяти, идентичный используемой в системных платах. Использует асинхронный доступ, при котором управляющие сигналы жестко не привязаны к тактовой частоте системы. Активно применялся примерно до 1996 г.
VRAM (Video RAM — видеоОЗУ) — так называемая двух-портовая DRAM. Этот тип памяти обеспечивает доступ к данным со стороны сразу двух устройств, то есть есть возможность одновременно писать данные в какую-либо ячейку памяти, и одновременно с этим читать данные из какой-нибудь соседней ячейки. За счет этого позволяет совмещать во времени вывод изображения на экран и его обработку в видеопамяти, что сокращает задержки при доступе и увеличивает скорость работы. То есть RAMDAC может свободно выводить на экран монитора раз за разом экранный буфер ничуть не мешая видео чипу осуществлять какие-либо манипуляции с данными. Но однако это все та же DRAM и скорость у нее не слишком высокая.
WRAM (Window RAM) — вариант VRAM, с увеличенной на ~ 25 % пропускной способностью и поддержкой некоторых часто применяемых функций, таких как отрисовка шрифтов, перемещение блоков изображения и т. п. Применяется практически только на акселераторах фирмы Matrox и Number Nine, поскольку требует специальных методов доступа и обработки данных, наличием всего одного производителя данного типа памяти (Samsung) сильно сократило возможности ее использования. Видеоадаптеры построенные с использованием данного типа памяти не имеют тенденции к падению производительности при установке больших разрешений и частот обновления экрана, на одно-портовой же памяти в таких случаях RAMDAC все большее время занимает шину доступа к видеопамяти и производительность видеоадаптера может сильно упасть.
EDO DRAM (Extended Data Out DRAM — динамическое ОЗУ с расширенным временем удержания данных на выходе) — тип памяти с элементами конвейеризации, позволяющий несколько ускорить обмен блоками данных с видеопамятью приблизительно на 25 %.
SDRAM (Synchronous Dynamic RAM — синхронное динамическое ОЗУ) пришел на замену EDO DRAM и других асинхронных одно-портовых типов памяти. После того, как произведено первое чтение из памяти, или первая запись в память, последующие операции чтения или записи происходят с нулевыми задержками. Этим достигается максимально возможная скорость чтения и записи данных.
DDR DRAM (Double Data Rate) — вариант SDRAM с передачей данных по двум фронтам сигнала, получаем в результате удвоение скорости работы. Дальнейшее развитие пока происходит в виде очередного уплотнения числа пакетов в одном такте шины (DDR2, QDDR и т. п.) SGRAM (Synchronous Graphics RAM — синхронное графическое ОЗУ) вариант DRAM с синхронным доступом. В принципе, работа SGRAM полностью аналогична SDRAM, но дополнительно поддерживаются еще некоторые специфические функции, типа блоковой и масочной записи. В отличие от VRAM и WRAM, SGRAM является одно-портовой, однако может открывать две страницы памяти как одну, эмулируя двухпортовость других типов видеопамяти.
MDRAM (Multibank DRAM — много банковое ОЗУ) — вариант DRAM разработанный фирмой MoSys, организованный в виде множества независимых банков объемом по 32КБ каждый, работающих в конвейерном режиме.
RDRAM (RAMBus DRAM) память использующая специальный канал передачи данных (Rambus Channel), представляющий собой шину данных шириной в один байт. По этому каналу удается передавать информацию очень большими потоками, наивысшая скорость передачи данных для одного канала на сегодняшний момент составляет 1600MB/сек (частота 800MHz, данные передаются по обеим срезам импульса). На один такой канал можно подключить несколько чипов памяти. Контроллер этой памяти работает с одним каналом Rambus, на одном чипе логики можно разместить четыре таких контроллера, значит теоретически можно поддерживать до 4 таких каналов, обеспечивая максимальную пропускную способность в 6.4GB/сек. Минус этой памяти — нужно читать информацию большими блоками, иначе её производительность резко падает.
Акселераторы
Начнём традиционно с истории. Первые видеокарты не были даже не 3D-ускорителями, а не были ускорителями вообще. Они служили лишь как ЦАП (цифро-аналоговый преобразователь) – преобразовывали данные, рассчитанные центральным процессором (представляющий собой цифровой код) в аналоговый сигнал, доступный для отображения на мониторе. Но сложность изображений росла, и дальше так продолжаться не могло. Тенденция усложнения изображений привела к появлению 2D- ускорителя – видеокарты, имеющий свой собственный, пусть и простейший процессор, бравший на себя часть функций, разгружая центральный процессор. Но когда появилась необходимость строить 3D изображения – ситуация осложнилась.
Чтобы построить, скажем, простой фрагмент стены, процессору нужно было выполнить следующие операции: сначала необходимо выделить грани этого объекта, затем наложить текстуры, добавить освещение... а когда таких объектов сотни, их форма сложна, они движутся и перекрываются, отбрасывают тени и т.д. задача становится невероятно сложной. Для помощи процессору в решении этой задачи и были созданы ускорители трёхмерной графики, о работе которых и пойдёт речь в этой статье.
Итак, каждая стадия построения изображения очень ресурсоемка, требует множества расчётов. Вполне логичным выглядит шаг вынесения их из CPU и переправка на специализированный процессор видеокарты. Особенно если учитывать, что графические данные имеют потоковый характер, и вычислительную потребность значительно большую, чем логическую. Каждый новый виток развития ускорителей представляет собой некое поколение, поэтому для начала введём стандартизацию поколений (понимать поколения можно по-разному – я приведу лишь один вариант):
1. Первое поколение, которое было более-менее распространено – это акселераторы, использующие API Direct3D 5 и Glide. Представителем первых была NVIDIA Riva128, а вторых – 3Dfx Voodoo. Карты этого поколения брали на себя только последнюю часть построения сцены – текстурирование и закраску. Все предыдущие этапы выполнял CPU.
2. Второе поколение использовало API Direct3D 6, также в это время началось стремительное возрождение API, разработанного SGI – OpenGL. Представителями карт того времени были NVIDIA RivaTNT и ATI Rage. Это было практически эволюционное развитие карт предыдущего поколения.
3. Третье поколение – Direct3D 7. Именно тогда появились карты, снабженные TCL-блоком, снимавшим с CPU значительную часть нагрузки. Этот блок отвечал за трансформацию, освещение и отсечение. (TCL - Transformaton-Clipping-Lighting) Теперь видеокарта строила сцену самостоятельно – от начала до конца. Представителями этого поколения стали NVIDIA GeForce256 и ATI Radeon.
4. Четвёртое поколении – очередная революция. Кроме прочих новых возможностей API Direct3D 8 (и 8.1) эти карты принесли с собой самую главную возможность – аппаратные шейдеры. Причину их появления мы опишем чуть позже. Представляют это поколение NVIDIA GeForce 3,4 и ATI Radeon 8500, 9000, 9100, 9200.
5. Пятое поколение – это, в основном, развитие шейдерных технологий (версия 2.0), и попытка ввести АА и АФ в ряд обязательных к использованию функций. Это поколение, поддерживает API Direct3D версии до 9.0b включительно, представляют ATI RADEON 9500, 9600, 9700, 9800, Х800, а также NVIDIA GeForce FX 5200, 5500, 5600, 5700, 5800, 5900, 5950.
6. Шестое поколение – это поколение DirectX9.0c. Оно пока включает в себя только одну серию NVIDIA GeForce 6 и платы GeForce 6800Ultra/6800GT/6800 на базе чипа NV40. Эти карты поддерживают шейдеры версии 3.0, и предлагают некоторые другие возможности. Теперь, определившись с общим устройством конвейера и поколениями видеокарт, мы более подробно рассмотрим вершинный и фрагментный процессоры, а также определимся в отличиях версий соответствующих шейдеров.
Причиной появления шейдеров стало отсутствие какой-либо гибкости у фиксированного TCL блока. Быстро стало понятно, что ждать момента, когда производители внесут очередную порцию функций в TCL блок видеокарт – не лучший выход. Такой подход не устраивал никого. Разработчикам не нравилась мысль, что для того, чтобы внести в, например, игру новый эффект им надо годик подождать выхода нового ускорителя. Производителям тоже не светило ничего хорошего – им бы пришлось постоянно увеличивать как сами чипы, так и драйверы к ним. Это и стало причиной появления шейдеров – программ, способных настраивать ускоритель так, как того требует следующая сцена. Шейдер – это программа, которая загружается в ускоритель, и конфигурирует его узлы для обработки соответствующих элементов. Теперь нет ограничения заранее заданным набором способов обработки эффектов. Теперь стало возможно составлять из стандартных инструкций любые программы (ограниченные спецификациями используемой версией шейдера), задающие необходимые эффекты. Шейдеры делятся по своим функциям на вершинные и фрагментные (пиксельные): первые работают с вершинами и треугольниками, заменяя собой функциональность TCL блока (сейчас он практически исчез – в случае необходимости он эмулируется специальным вершинным шейдером). Фрагментные же шейдеры служат для создания программ обработки фрагментов размеров 2х2 пикселя – квадов. Они необходимы для реализации некоторых текстурных эффектов. Шейдеры также характеризуются номером версии - каждая последующая добавляет к предыдущим всё новые и новые возможности. Наиболее свежей спецификацией фрагментных и вершинных шейдеров на сегодняшний день является версия 3.0, поддерживаемая через API DirectX 9с, - на нее и будут ориентироваться как производители акселераторов, так и разработчики новых игр. На их поддержку аппаратурой стоит обращать внимание и пользователям, желающим приобрести современную игровую видеокарту. Обратим внимание на главное отличие шейдеров 3.0 от предыдущих версий (кроме 2.0а) – это DFC – Dynamic Flow Control – динамическое управление потоком. С одной стороны – это великолепная возможность, позволяющая заметно повысить скорость построения сцены, с другой – лишние транзисторы, и как вытекающие побочные эффекты, лишнее тепло и ниже максимальные частоты. Давайте более подробно опишем эту возможность. Представим себе ситуацию, когда для какой-либо вершины (или фрагмента) шейдер нужно выполнить не весь, а только 12% от него. В случае применения DFC мы выполним лишь те необходимые 12%, основываясь на параметрах объекта. Без DFC мы вынуждены выполнить шейдер целиком. Легко заметить, что с DFC мы получим выигрыш без малого в 10 раз, при этом, заплатив пониженной производительностью на вершинах, для которых нужно выполнить все 100% шейдера. Именно по этому в сети до сих пор не утихают споры – хорошо это или нет. Я не буду проводить сравнения – тут каждый сам делает выбор, а лишь отмечу, что я лично сторонник третьей шейдерной модели. Первые шейдеры состояли всего из нескольких команд, и их нетрудно было написать на низкоуровневом языке ассемблера. Хотя сложность отладки ассемблерного кода поначалу отпугнула от шейдеров многих разработчиков… Но с ростом сложности шейдерных эффектов, насчитывающих иногда десятки и сотни команд, возникла необходимость в более удобном, высокоуровневом языке написания шейдеров. Их появилось сразу два: NVIDIA Cg (C for graphics) и Microsoft HLSL (High Level Shading Language) - последний является частью стандарта DirectX 9. Достоинства и недостатки этих языков, и прочие нюансы будут интересны только программистам, так что подробнее на них мы останавливаться не станем. Отметим только, что Cg не получил широкого распространения, ввиду появления нового, более продвинутого GLSL – аналога HLSL для API OpenGL.