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

Shaders and stuff - part 1: ATI

Совсем забросил технические посты с этой всей Америкой и впечатлениями от нее. Попробую потихоньку исправляться, дальнейшим искоренением старых знаний из мозгов.
А тут как раз повод - недавно спросили, на какой версии шейдеров для какой карточки оптимальней писать код, особенно в свете запускания шейдеров ранних версий на новых картах. Ответ слишком долгий, и поэтому я попытаюсь написать его здесь.

Сразу оговорюсь, я пишу в основном с DX point of view, хотя ссылаться на OGL все равно придется. За сегодня успеваю написать про vertex shaders и про pixel shaders на ATI. Pixel shaders на NV - это значительно более долгая история :)


Запускать шейдеры старых версий на новых картах - хочется всем, разумеется ради того, чтобы не переписывать большинство кода для новых карт. Если эффект работает на GF4 и от него требуется работать точно так же на GF FX и G60, то крайне желательно его не трогать. И крайне хочется надеяться, что он будет исполняться на новых картах оптимальным образом, чтобы не проседала производительность. К сожалению, это совсем не всегда так, т.е. понятно, что есть все шансы получить проблемы на картах от различных вендоров (но иногда все окей), но и других граблей хватает. Вплоть до того, что как все помнят - совсем не обязательно что эффективнее всего писать на самой большой версии шейдеров, поддерживаемая картой. Впрочем, по порядку.

Итак, кратенько про vertex shaders.
В vertex shaders особого бардака нету, версии 1.1, 2.0 и 3.0 естественно расширяют друг друга и предыдущая полностью внутри следующей. Поэтому во-первых, максимальная версия, поддерживаемая картой, и есть родная для нее, а во-вторых, любой код написанный более ранней версии будет хорошо запускаться на новой карте. Т.е. чтобы получить приемущество от новой версии, нужно серьезно менять способ отрисовки - скажем, делать меньше DIP'ов за счет большего количества констант, или использовать динамический бранчинг для костей, или уменьшать shader switch за счет тех же ветвлений, и т.д. То есть, просто переписав или скомпилировав код вертекс-шейдера под новую версию - ничего не улучшить. Больше того, и между виедокартами от различных вендоров они переносятся также прозрачно.
И это просто замечательно, на самом деле. Vertex shader такие простые и понятные - всегда есть возможность использовать старый код и не беспокоиться.

Однако сила все больше в pixel, а не vertex шейдерах. Там все запущенеей, по историческим причинам. Вендоры развивались в разную сторону и с разной идеологией внутри.
Начнем с ATI, потому что карты ATI очень точно соответствуют версиям DX.
Итак, pixel shaders на ATI.
Все видеокарты ATI ровно исполняют стандарт DX, и не буквой больше. Версия шейдеров, заявленная картой, всегда оптимальная и четко соотвествует внутренней архитектурой с несколькими несложными ньюансами типа спаривания behind the scenes.

Старенький Radeon 100 (в миру ATI iRadeon 7xxx) был еще DX7 картой и умел накладывать 3 текстуры на 3-х texture stages, абсолютно точных texture stage DX. Так как стейджей у Geforce 2 было всего два, то типично код с Geforce кроме совсем особых случаев нормально работал, и все писали один и тот же codepath, потому что писать отдельные эффекты только для Radeon 7xxx дураков было мало.
Кстати, есть подозрение, что именно он и послужил прототипом ветки видеокарт, которые ATI делает для Nintendo. Карта на GameCube была очень на него похожей, вот как кто-то сольет спеки видеочипа Wii, посмотрим.
Но это совсем уж древняя история.

Первой карточкой с шейдерами у ATI был R200 (в миру Radeon 8500-9200), и он умел ps.1.4., и специально для него DX 8 зааплейтили до DX 8.1.
ps.1.4 умел накладывать 6 текстур и делать один самый настоящий dependent read, в отличие от GF 3-4, которые их умели делать в очень ограниченных пределах, через tex* инструкции.
На этом ps.1.4 было вполне удобно писать и эмулировать ps.1.1-1.3, поэтому код от NV-карт того же поколения опять же хорошо жил. Победой ATI можно считать то, что для ps.1.4 отдельный код уже писали - dependent read очень приятная штука. Можно и параллакс, и рефракшен от суммы normal map, да и 6 текстур - не одна текстура. Тем не менее, R200 приятная карта, потому что все что написано до нее - живет на ней хорошо.
Чтобы поиздеваться над OGL, ATI таки выпустило расширение, соотвествующее ps.1.4 - ATI_fragment_shader, где надо было писать шейдеры примерно в такой форме:
// Pass 1
glPassTexCoordATI(GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI); // N
glPassTexCoordATI(GL_REG_2_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI); // light to vertex vector in light space
glPassTexCoordATI(GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI); // H
glSampleMapATI(GL_REG_4_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI); // L (sample cubemap normalizer)

// reg4 = N.L
glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_4_ATI, GL_NONE, GL_NONE,
GL_REG_1_ATI, GL_NONE, GL_NONE,
GL_REG_4_ATI, GL_NONE, GL_2X_BIT_ATI|GL_BIAS_BIT_ATI);

Говорят, когда в саппорт ATI стали обращаться с багами к этому экстеншену, мужики реально удивлялись - неужели кто-то на таком пишет?

А следующием поколением ATI зажгло и покорило мир, потому что во-первых R300 (Radeon 9500+) был мега-железкой, а во-вторых NV слила в том поколении со своими Geforce FX (к гадалке не ходи, это была прощальная месть 3dFX). R300 держит ps.2.0 до последней запятой, но имеет несколько важных ньюансов с точки зрения производительности, главные из которых наличие rgb/alpha спаривания и важность "уровней dependent read". Так как ps.2.0 стал более развернутым в смысле инструкций, то важно понимать, что R300 работает ровно на ps.2.0. Т.е. если скажем у вас получилось написать на ps.1.1 или ps.1.4 шейдер с меньшим количеством инструкций чем на ps.2.0, то это не значит, что на R300 вариант с ps.1.x будет работать быстрее. Будет скорее всего так же. Все это опять же радует - на R300 можно смело запускать все нижние версии шейдеров и ничего не бояться.
Радостная картина омрачается тем, что если в сложном ps.1.x шейдере много тратится на обход ограничений модели (отсутствия свиззлинга, ограничений по read и т.д.), то бывает на ps.2.0 можно написать быстрее. Но это только сложные, простые заживут легко.

R4xx (RadeonX400+) принципиально ничего не поменял - в основном выросла производительность. Ну да, версия поменялась на 2.b но я не помню, чтобы кто-то серьезно пользовался ее фичами, потому что они требовали серьезных измерений, работали кроме R4xx только на NV3x и там страшно тормозили. Может кстати это я что-то в жизни упустил. Вот вы - писали сколько-то кода на 2.b? :)
Именно с этой версии начались всякие секреты типа создания текстуры с хитрым FOURCC() для сжатых normal map, по супер-технологии 3dc. ATI это понравилось и появились кучи таких секретов, сколько-то из них перечислено в посте про D3DCAPS.

Последнее на сейчас поколение ATI на PC - R5xx (Radeon X1000+), и она таки ps.3.0. Основную фичу все знают - dynamic branch, и она у ATI действительно хорошо работает и ей действительно имеет смысл пользоваться. Может конечно PS3-пипл расскажет, что и на NV40 можно так сконструировать pushbuffer, что будет давать бонус не только в вырожденных случаях, но вот у ATI действительно все хорошо. Можно скажем в сплаттинге бранчиться и получать прирост.
Так как 3.0 расширяет 2.0, то и тут все хорошо - можно пускать все предыдущее.


ATI живет стандартами и большей частью им скурпулезно следует. Поддерживают нужную версию DX shaders, все ARB-расширения OGL и for fun обеспечивают некоторый кроссовер.
На ATI в DX жить приятно, общие рекомендации "код меньшей версии запускай сколько хочешь" и "если не нужно, чтобы код работал на старых картах, пиши на последней версии, которая поддерживается" - за редкими исключениями всегда работают. Не надо пытаться писать на старых версиях, чтобы получить лучшую производительность. Вся функциональность карты кроме мелочей на ладони и предсказуема. Можно реюзать много кода для более старых карт не только ATI, но и NV. Красота.

К сожалению, в обратную сторону такой переход нихрена не работает - NV далеко не всегда будет любить код с ATI. А иногда, что удивительно, будет любить еще больше своего собственного.
Об этом - как-нибудь потом.
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.
  • 20 comments
АТИ это конечно хорошо, но у нас, например(в нашей студии в см), код для него пишется по остаточному принципу, типо "не работает на ати? сам дурак что купил :)". Цинично, да, но факт :( И еще не понятно с будущим ати, в связи этой покупкой... Короче ждем поста про нв...

пс: жаль, что я не графический программист... *задумался*
Одна из прелестей ATI состоит в том, что так действительно можно делать. Она умеет запускать почти любой код NV, кроме vertex fetch в sm 3.0. Пока оно у вас еще и быстрее, чем на NV - что вполне возможно, так как у ATI в последнее время хорошие карты - то можно и об оптимизации не задумываться.
Еще несколько лет этот подход упирался в то, что ps.2.0 на NV жили настолько плохо, что приходилось писать совсем особый код, который плохо жил на ATI. Так как сегодня уже можно решить дропнуть NV30 - все значительно лучше.

Вот как раз из-за этого исключения у нас на радионах кое-каие красивости и не видны...
Вы зря. У ATI хороший такой процент рынка.

virtul

11 years ago

Все случаи, которые я помню, были из разряда "у NV работает, у АТИ - нет" :) То есть, бороться за работоспособность всегда приходилось именно с АТИшными картами. Правда, шейдеров это не касается (там ещё старый dx7 код). Недавно вот сообщили, что на последних моделях АТИшных карт игра стала очень сильно тормозить. На предыдущих моделях - всё ок. Карты такой под рукой нет, поэтому найти причину не удаётся. А вот ещё было - на АТИшных картах с отрисовкой через статический VB на моделях иногда пропадают фейсы. Причём на один кадр, на следующем кадре они уже есть. Эдакое мерцание случайных треугольников при определённом положении камеры. Если использовать динамический VB, то бага нет. На картах от NV бага нет в обоих случаях - и со статическим и с динамическим VB. Индексы проверял - они корректные. В общем, проблему так и не нашёл. Пришлось поставить заплатку - на АТИшных картах рисуется всё через динамический VB в убщерб скорости. :(
Ну, про качество драйверов можно говорить всякое. Мой опыт был такой - "у NV работает, у АТИ - нет" означает, что девелоперы сидят в основном на NV. И соответственно наоборот.
Что в общем и целом совсем другая история, чем этот пост :)

dtjurev

11 years ago

sim0nsays

11 years ago

dtjurev

11 years ago

sim0nsays

11 years ago

dtjurev

11 years ago

Deleted comment

У нее не столько "плохо", сколько "сложно". Что само собой через несколько итераций превращается в "плохо".
Семен все прально написано давай про NV, только ведь у нее тоже есть плюсы а не только минусы. так же как и у АТИ
> Говорят, когда в саппорт ATI стали обращаться с багами к этому экстеншену, мужики реально > удивлялись - неужели кто-то на таком пишет?

А я вот не месяц-другой назад 20 штук шейдеров портировал под ати_фрагмент_шейдер, охуенно смешно, ага.
Гы-гы-гы :)
ага! ;))
Дополнения -
1. проверить, что behind the scenes делается не так много, можно в общем-то посмотрев на вывод ati shaderanalyzer (который, к счастью, работает независимо от наличия ati драйвера)
2. с тем, что спаривание делается именно behind the scenes, бывают проблемы - когда без спаривания вылезаешь за 64 инструкции, а со спариванием - нет. А валидатор в рантайме, который про спаривание не в курсе :( Т.е. у ps.2.0 ограничение в 64 векторных ALU, а у R300 - в 64 vec+scalar.

Можешь пояснить про конструирование пушбуффера - чем оно может помочь? Т.е. вот я делаю if (пиксель в тени) сделать PCF 5x5; else return 1; и вижу небольшое падение в сравнении с "сделать PCF 5x5". Как можно такое исправить... пушбуффером?
Ну, я-то совсем не PS3-пипл.
Классический пример силы пушбуффера такой - помнишь, плохо получалось делать image-фильтры на NV из-за того, что переполнялся кеш и сэмплы доставался из памяти, а не из текстурного кеша. На PS3 - люди переключали флаг количества занятых регистров, очередь уменьшалась, кеш не переполнялся. На PC я пытался обмануть драйвер, чтобы он попользовал больше регистров, но это получалось только с неприлично длинным шейдером, который убивал весь бонус.

Теоретически, если детально знать, как работают и почему тормозят ветвления, то можно извлечь что-то полезное кучей ручек, которых нет на PC.
Но я, разумеется, не знаю.
Добрый день, добавьте меня пожалуйста в друзья !