Семен (sim0nsays) wrote,
Семен
sim0nsays

Shaders and stuff - part 2: NV

NV - чудо-компания, законодатель мод, технологий и прочего-прочего в 3D-графике. Не знаю уж как там Интел и NV нынче друг на друга поглядывают в свете покупки ATI, но NV по-прежнему не интересует никакой опыт и стандарт, кроме собственного. Это не то что сильно плохо, мы вот тоже такое любим делать, но остроты жизни серьезно добавляет. Кому добавляет - понятное дело, написателю драйвера и тому, кто этот драйвер пользует, то есть простому негру-девелоперу. Если ATI выпускает железобетонно-простые и быстрые железки, то NV выпускает неонку, у которой внутре вселенная. Так как номер поколения карт уже приближается к десятке, то как эта неонка работает - понимает все меньше и меньше народу, подозреваю даже в самой NV. Оно опять же показательно с точки зрения того, как накапливается легаси, если строить следующее железо на плечах предыдущего.

Вся история NV-карт - история о комбайнерах.


Впрочем, давайте по-порядку.

Для начала, снова чуть-чуть о вертексных шейдерах. Мне тут напоминают, что в vs.3.0 ATI и NV друг от друга сильно отличается - NV умеет честно сэмплировать текстуру в vertex shader, а ATI нет. Это безусловно правда, и marketing bullshit от ATI (тем более на xbox360 это можно делать). ATI рекомендует использовать вместо этого render2vb, что может и является альтернативой, но слишком уж по-другому делается. В результате, так как на NV сэмплирование текстуры в vs страшно тормозное, а на ATI работает геморройно и с хаками, то его не пользует толком никто. Думаю, до DX10 никто и не начнет. И тем не менее, исключая этот момент - vertex shaders очень прозрачно ложатся на железо, что там, что там. Все инструкции, бранчинг и даже то сэмплирование - такая же инструкция, только очень медленная. Ну да, если не попадет в кеш - то страшно медленная, но и всего-то.
Будем считать, я поправился, и лирическое отступление про vs закончено.

Итак, комбайнеры.

Запредельно далекая история - мега-карта Riva (NV3+, она настолько старая, что у нее даже номер чипа однозначный), которая умела накладывать одну текстуру на треугольник, и соответственно у нее был один комбайнер.
Комбайнер у NV может выполнять операцию A*B+C*D, одна из которых может быть только что засэмпленной текстурой. Комбайнер всегда параллельный для rgb(vector) и alpha(scalar) части. Потом появилась возможность заменять операцию на dot, но в Riva этого не было.

У Riva TNT (NV5+) комбайнеров стало два и это было круто, но медленно, совсем весь рендер на двух текстурах делать было нельзя.
Это отлично ложилось на персональные OGL-расширения NV, и плохо на DX, но даже сейчас на саете NV можно найти бумагу, как можно выполнить мега-операцию двух комбайнеров сетапом 8-х стейджей на Riva TNT. Представляете, 8 стейджей на TNT? На Geforce2-то 3 стейджа в хорошую погоду только работали.
NV жгла той Ривой ТНТ, и побеждала всякие Voodoo и остальное.

После этого был Geforce1 (NV10), и он имел те же самые два комбайнера, но которые могли делать еще и dot вместо mul. От этого появилась возможность сделать bump, и через это получать радость. В промышленных масштабах бампа конечно не вытянуть, но демки писать было уже можно. Даже я, помнится, писал. В DX уже стало еще хуже, в OGL все по-прежнему хорошо. А еще у Geforce1 был первый в мире T&L, т.е. хардверная обработка вершин. Интересно, как вообще чип задизайнили для этого, у источников освещения нетривиальные такие формулы. Наверное жосткий хардкод.
Первым Гефорсом NV фактически добила всех остальных конкурентов, и пока не появился Radeon 7xxx вообще не испытывала конкуренции.

Geforce2 (NV15+) стал как всегда картой, закрепляющей новшество архитектуры хорошей производительностью. Два комбайнера - стала супер-технология, которая прямо открывала границы. Можно делать detail, можно делать бамп с текстурой за один проход, в OGL писали настоящий per-pixel render (все же читали Рона Фрейзера?), в DX у меня получилось сделать per-pixel specular :) В DX все было крайне тяжело - потенциально есть 8 стейджей, а гарантированно использовать получается две. Люди писали некие шаманские выражения на 3-4 стейджа и надеялись, что драйвер сможет их скомпилять в комбайнеры. Разумеется, он чаще не мог, зависел от погоды и прочего, и прочего. Оставалось сдаваться и жить с гарантированными 2-мя стейджами и ругаться на жизнь.
Именно тогда появился первый конкурент - Radeon 7xxx, но особой популярности не получил. Комбайнеры жгут и побеждают вселенную.
Geforce 2 GTS - безусловно лучшая в поколении карта.

Про Geforce3 и 4 (NV20+) я буду писать вместе, потому что по функциональности они почти не отличаются, впрочем, сильно отличаются по скорости. Про эти карты мы знаем много и в подробностях, потому что такая же была в xbox1, а это уровень документации на порядки детальнее PC. Угадайте, какой был мега-технологический прорыв придумала NV по сравнению с Geforce2? Ну разумеется, удвоение количества комбайнеров, в GF3/4 их было 4, и 4 текстуры. В DX это называлось ps.1.1-3, 4 текстуры, 8 инструкций, 8 констант - это все и "комилялось" в настройки комбайнеров. Отмечу, что комбайнеры все же немного мощнее ps.1.3 шейдеров, но уже очень близки для практических целей. 8 инструкций - это уже много и можно делать сурьезный рендер. shodan_ru писал статью, как в TBM получается в один пасс уместить diffuse texture, diffuse/specular bump, detail и shadow, а это считай весь рендер.
Но чтобы ими можно было пользоваться - к комбайнерам пришлось добавить костылей, например в шейдерах на 8 инструкций (16 со alpha-спариванием) крайне не хочется делать rgb-pipe и alpha-pipe независимыми, поэтому добавили хак - в alpha-pipe можно читать из blue-channel и таким образом передавать данные rgb и alpha. Есть правила на количество текстурных регистров в одной инструкции, какие каналы могут быть у некоторых инструкций операндами, и т.д. и т.п. Про возможности dependent read я вообще молчу - натуральный балаган. И тем не менее, этим можно пользоваться и с этим можно жить. Комбайнеры подпилили напильником и положили на DX.
Писать на ps.1.1 было сказкой и джедайством, с трюками и песнями. Все например знают, что в t0 можно писать? Давайте вот без читерства и пользования HLSL - как на ps.1.1 сделать max? Отличное было время.

Geforce Ti 4200 - карта всех времен и народов, до сих пор нежно любимая всеми, и безусловно лучшая карта в поколении. 4600 был сильно дороже и лишь чуть-чуть быстрее, и поэтому народной любви не завоевал. Минус-карма NV за маркетинг-буллшит с GF4MX, который на самом деле GF2, а называется GF4. Из-за этого разработчики долго матерясь делали так, чтобы даже продвинутые эффекты запускались на GF2, а через некоторое время забили. Так и писали на коробке - "работает начиная с GF3, исключая GF4MX".

А в следующем поколении NV не повезло. Geforce FX(NV30+) был огромным провалом, аццтойной и слишком сложной картой, и собственно и дал ATI возможность стать серьезным конкурентом. If you ask me - я считаю, это была посмертная месть 3dfx (Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway). Но я так, только предполагаю :)
Итак, во что же это вылилось. На дворе был DX9, а значит нужны длинные шейдеры с dependent read и довольно большим количеством временных регистров (уж не 2, как в ps.1.1). Еще ATI давит тем, что у нее floating point, и в спеке DX это прописано. Удвоение количества комбайнеров уже не решает проблему, и NV пришлось призадуматься.
И они придумали! Давайте разбивать длинный шейдер на куски, которые мы сможем исполнить на комбайнерах, а комбайнеры расширим для floating point. Отлично же? Да без базару! И вот на таких идеях появился CineFX, который ядро Geforce FX.
Шейдер разбивается на куски, которые можно исполнить на комбайнерах, и вычисляется несколькими проходами. Промежуточные данных хранятся в специальных регистрах на чипе (а где же еще, нужна максимальная скорость), и поэтому их объем очень ограничен. Это означает, что чем больше временных регистров надо сохранять между "кусками", тем больше они займут этой памяти, и тем меньше пикселей мы сможем обработать в очереди. На практике это означало, что как только временных регистров больше, чем 8 fp32 или 16 fp16 - скорость падает в никуда. А 8 floats - это всего два float4.
Кроме того, расширить комбайнеры на floating point не замедлив их - невозможно, и на NV30 изначально было два блока - floating point и fixed point. На floating point fp16 исполнялись в два раза быстрее fp32, а fixed исполнялся еще в два раза быстрее fp16. Кроме этого, так как нужные еще всякие rcp, rsq и прочее не влезающее в формулу A*B+C*D, то сбоку есть FPU, который умеет их считать. Разумеется, медленно.
Более подробно обо всем этом - читать замечательную статью Inside NV30, написанную по мотивам находок в патентах NV.

Итого, на производительность NV30 влияют два основных фактора - количество "комбайнерных кусков", на которые драйвер смог разбить шейдер, и выбранная точность вычислений. Но есть бонус - можно сэмплить очень много текстур, потому что каждый комбайнер всегда может сэмплить текстуру, именно из этого пошли размены "normalize cubemap vs rsq" и т.д.

И вот по сумме многих причин - в DX9 у ps.2.x (NV-oriented версии ps.2.0) нет fixed точности, а есть только half. Что означает, что в любом случае Ps.2.0+ шейдер будет работать на NV30 в два раза медленнее ps.1.1, в котором fixed-точность. В этом смысле NV30 умел очень и очень хорошо исполнять код предыдущих NV-карт (а фигли, это те же комбайнеры), но очень плохо понимал ps.2.0.
Ирония судьбы оказалась в том, что версия шейдеров для ATI-карт прошлого поколения, ps.1.4 - лучший компромисс для писания на NV30. Он функциональнее ps.1.1, потому что ATI старались сделать удобнее, чем вот те "запутанные шейдеры, которые на самом деле маппятся на комбайнеры", они все еще работают на fixed point, умеют 6 текстур, что довольно много, а все fixed-point регистры влезают в 8 float32. Альтернатив просто не было, ATI-шный стандарт ps.1.4 - стал лучшим способом кодать на Geforce FX.

Длинные шейдеры, не влязащие в ps.1.4 народ с переменным успехом адаптировал под NV30. Код как на ATI не запускался в упор, шейдеры переписывали под lookup texture, под постепенное сэмплирование текстур, под малое количество регистров. Оно pain in the ass, но если рендерять так мало объектов в кадре - сносно жило.

В Geforce 5900 (NV35) попытались немного все исправить, научив fixed ALU помогать делать floating-point инструкции, баланс стал чуть-чуть лучше, но остался проседать.

Итого - NV30 кодается как никакая другая, либо если повезет на ps.1.4, либо мучениями на ps.2.x так, что не заживет больше нигде.
И давайте все же оценим - register combiners в неизмененном виде начались на Riva и прожили аж до FX. Прогресс в том, чтобы делать их больше и растаскивать длинный шейдер на простые куски, которые могут быть на них посчитаны. А вы говорите - легаси...

В Geforce 6000+(NV40+) NV проделала тщательную работу над ошибками, но не изменив глобальной концепции. Наконец убрана изначальная функиональность комбайнера и заменена другой, более подходящей. Теперь одновременно работают два блока - один умеет сэмплировать текстуру или делать mad/dot( это дает более гибко управлять tex/alu ratio), другой умеет делать любую арифметическую операцию, ну и конечно умеет спаривание. Они все floating point, достаточно быстрые (fp16 по-прежнему быстрее). Расширили память на чипе под регистры, и теперь именно в количество регистров упирается меньше, но все равно упирается. В таком виде оно уже вполне нормально исполняет ps.2.0-код, и в принципе все предыдущее.
Количество "кусков" все еще принципиально определяет скорость шейдера, но по старым причинам разбиваться стало намного меньше. Но появилась новая причина - dynamic branch, которую NV решило сделать старым способом - разбиением на куски. Еще надо рассказывать, почему оно тормозит?
Но кроме этого и очень медленного texture fetch в vertex shader (т.е. по-русски, кроме SM3.0-фич ;) - хорошая карта. Я вот купил себе на Родине интернациональный Geforce 6600GT и доволен. Вполне сравнялись с ATI в этом поколении, и может даже чуть выше, но на любителя.
Так, не забыть дать дополнительный референс на Inside NV40.

Про Geforce 7000+ (G70, поменялся формат codename, спасибо пацанам с форума ixbt за поправку) во-первых, почти не отличается от NV40, кроме скорости, а во-вторых, мы тоже будем знать про него много, потому что почти он же в PS3, и товарищи нам расскажут.

Напоследок, про Gefroce 8800 (G80), который типа первый DX10 hardware. Я его вживую не видел и не кодал, и ваще не знаю. Больше всего информации, как оно внутре работает, можно извлечь из CUDA Programming Manual, но у меня жосткое подозрение, что мужики в NV почесали затылок, да и расширили концепцию комбайнеров на случай общих ALU. Аплодисменты, что тут можно сказать.


История NV - история собственных стандартов, технологических изобретений и длинного шлейфа OGL-расширений как результата всего этого, но больше всего - история эволюции комбайнеров. Комбайнеры, обрастая фичами, костылями, прикрученными сбоку ALU, особым фреймворком вокруг и так далее - спокойно просуществовали до наших дней. Вы представляете, какой объем работы надо выполнить драйверу, чтобы разложить ps.3.0 шейдер в сотни инструкций до элементов, с которыми работала Riva TNT?
Даже в хардверном бизнесе, когда гораздо легче незаметно подменить железо и написать компилятор в обратную совместимость - все те же проблемы легаси вылезают точно так же, как и в софте. Сделали одно решение, оно потянуло за собой другое, потом мы сделали workaround, потом сделали сверху что-то, что может преобразовать сложное в то, что может быть вычислено старыми способами (словив при этом все проблемы оверхеда), потом решили передизайнить, но этот преобразователь остался, и так далее.

The greatest programming project of all took six days; on the seventh day the programmer rested.
We've been trying to debug the !@#$%* thing ever since. Moral: design before you implement.
(спасибо some41)

Разума и осознания всем нам :)

Отдельное огромное спасибо goes to ironpeter и boris_batkin.
Tags: graphics, tech
Subscribe
  • Post a new comment

    Error

    default userpic
    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 49 comments
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →
Очень интересно, респект :)
У тебя reach аудитории немного другой по сравнению с моим, поэтому попрошу тебя опубликовать в твоём журнале вот чего отдельным постом, если конечно возможно.

"ropotov находится в поиске оригинальных игр для NV1 (она же Diamond Edge 3D, STG-2000). Пожалуйста откликнитесь, очень нужно получить как минимум EXEшники с тех дисков для ретро-обзора, поиск уже идёт несколько лет! Эта самая первая видяшка NVidia работала с quadами, а не с triangles. В список NV1-поддерживаемых игр входят, по видимости, только игры компании SEGA: Nascar Racing, Panzer Dragoon и Virtua Fighter Remix, всё выходило в районе 95-ого года."
Окей :)

kunaifusu

10 years ago

Да, интересно, спасибо.
Молодец как всегда.
Только Inside NV40 - это http://www.3dcenter.de/artikel/nv40_technik/index_e.php
А то я по-ненецки даже молчать не могу!
Ой, спасибо. Не посмотрел.
Спасибо, очень интересно.
Так вот как оно всё было.. )))
Огромное спасибо ;)
Спасибо, очень интересно.

Только есть один вопрос - почему тогда гораздо меньше проблем с нвидиевскими драйверами, как под венду, так и, особенно, под линух?
Смотря с какой стороны смотреть. Со стороны корректности работы - NV лучше пишет драйвера, вот и все. Может, потому что опыт больше, может, потому что больше денег на это тратит. Со стороны затрат времени в драйвере - NV сливает.

Anonymous

10 years ago

sim0nsays

10 years ago

aruslan

10 years ago

sim0nsays

10 years ago

sim0nsays

10 years ago

Пасиб, полезно знать историю =)
За текст респект, про t0 не знал :-)
С другой стороны, не знаю, почему, подумалось, что интересно было бы податься в MS, но что-то лень :-) Плотють наверняка мало :-)
Мужик, ты чо. Это же США, а не Европа. Платют больше, цены меньше, налоги тоже меньше.
Но я эта, без рекрутинка ;)
Ты как-то очень ловко поставил знак равенства между первым T&L и hardware T&L. Впрочем, даже если столь далекий от понимания кишков человек, как я, это отметил, то, думаю, это вообще непринципиально.
Легаси - это геморрой, несомненно. Кажется, впервые я об этом задумался, когда лет пять-восемь назад услыхал, что в новой версии VC были специально добавлены старые ошибки для совместимости. А что делать-то?.. Есть способы обхода таких вещей помимо вырезания workaround'ов и, возможно, извращенной перезагрузки функций? :)

У меня сейчас Ti4200. Не нарадуюсь, хоть и тормозит по черному во многих играх приложениях.
вообще конкретно в geforce 1 был вполне себе первый он же хардварный T&L.
особенно под opengl.

vikky_13

8 years ago

Спасибо большое, все по конкретике. Всегда красиво писал тех посты!
Познавательно. дай бог что бы и дальше так.
> shodan_ru писал статью, как в TBM получается в один пасс уместить diffuse texture, diffuse/specular bump, detail и shadow, а это считай весь рендер.

Где он писал про это дело? Надеюсь не в вашем закрытом gamedeff'е? ;-)
Не-а. В gamedeveloper russia, кажется.

Deleted comment

sim0nsays

10 years ago

__kas__

10 years ago

sim0nsays

10 years ago

сразу перескочив на nv10,
да и glint geometry unit(T&L) появился лет на 5 раньше Nv10 :-), но работал только под FFP GLля и не всем был доступен.
Это которые Riva TNT/TNT2? Ну, там ничего нового в смысле пиксельной обработки. Тот же 1 комбайнер.
У меня стоит 8800GTX, судя по 3Дмарку, скорость подросла не намного.
Слашыл что теперь все блоки шейдеров унифицированы.
Есть такой же пул квадов как у АТИ.
Ну, унифицированы да, DX10 к этому более или менее распологает. Nifty details не знаю, вот :)

Anonymous

February 1 2007, 20:55:49 UTC 10 years ago

Geforce2 (NV15+) внес принципиальное новшество - два комбайнера, и соответственно две текстуры
Не совсем понял. Две текстуры были, кажется, ещё на TNT'шках?
Ох ты етить, точно же, и на Geforce1 два. В окончательный маразм впал за давностью лет.
Спасибо вам огромне.
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →