Семен (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
  • Post a new comment

    Error

    default userpic
  • 20 comments