DirectX SDK, new vs old

Помогите плз разобраться. Есть проект, который юзает DX SDK аж 2004 года (это как раз dx 9.0c вышел с ps 3.0), и в нем юзается функция D3DXCompileShaderFromFile, и вот мне интересно где она находится (то есть её реализация).

Насколько я знаю в новых sdk эта функция лежит в d3dx9_xx.dll (правильно?), а в том старом sdk — эта функция походу лежит в d3dx9.lib и она прикомпиливается в.ехе, то есть

реализация находится даже не в DLL, а в.lib. Так как в свежей XP винде (где еще dx не ставили) никаких d3dx9.dll и тем более d3dx9_xx.dll нет.

То есть, получается что это мое приложение юзает компилятор шейдеров аж 2004 года, так?! И тогда должно быть так, что с новым sdk откомпиленные шейдеры (новым компилятором) — возможно быстрей будут работать (на новых видеокартах)? Я думаю там не мало должно было поменяться в компиляторе за ~5 лет...

И может, кто имел практику перехода со старых DX SDK на новые — не будет ли проблем? (версии используемых у меня DX-компонентов будут те же).

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Mike Gorchak

Ого, да у вас опыт еще тот:)

А может и не надо юзать компилятор каждый раз, храни в бинарном виде

Да, я над этим тоже думал, но все руки не доходят. Думаю хранить обе версии (исходники и бины) и при загрузке смотреть, если есть бины — грузить их,
иначе — компилировать исходники (и сохранять бины).
А старый компилятор я наверное заверну в отдельную DLL (так как сам компилятор лежит в статической либе, то он прилинкуется и будет жить в моей dll) — и буду юзать её, а sdk пускай уже новый остается.
Кстати, в новом компиляторе можно заюзать флаг D3DXSHADER_USE_LEGACY_D3DX9_31_DLL — как ни странно, юзание этого флага приводит к генерации
более шустрого кода (так как юзается другой, более старый компилятор). Но все равно не дотягивает до 2004г. версии:)
Получается, новый компилер без этого флага дает ~90fps;
тот же компилер с этим флагом — 170−180fps;
и старый компилер (2004г) — ~200fps.
Вот еще нашел на gamedev.net тоже заечание по поводу этого флага и нового компилера.
Чувак говорит что «Once I remove D3DXSHADER_USE_LEGACY_D3DX9_31_DLL it all slows to a crawl».
В общем, Mike Gorchak, благодарю за содействие;)

Думаю проблему можно считать решенной.

Даже при поверхностном просмотре ассемблера видно что старый компилятор сгенерил более быстрый код; развернул цикл (а новый — нет), заюзал хитрые оптимизации — if/else при котором скипается куча кода в некоторых случаях (а новый — никак не отреагировал), отдает приоритет более легковесным операциям. Конечно в некоторых случая новый компилятор справляется тоже совсем не плохо (я и другие шейдеры попроверял), но наверное я буду дальше юзать старый компилер: /

А может и не надо юзать компилятор каждый раз, храни в бинарном виде, чтобы не зависить от SDK. Вполне возможно, что хранить надо будет код под каждый GPU от каждого производителя, если требуется универсальность и высокая производительность одновременно...
Я, когда реализовывал fixed function pipeline в OpenGL ES 1.1 драйвере на железе, которое поддерживало только шейдеры: geometry, vertex и pixel, весь код писал руками в GPU-машинных кодах без использования компиляторов от производителя видеокарты и жёстко вшивал в основной код в виде:
...
// asr (2) g115.14< 1> W g1.14< 2, 2, 1> W −0.1W {align1};
{0×00010020, 0×34001E00, 0×00001400, 0×00000030},
// add (2) g115.0< 1> D g116.0< 2, 2, 1> D g115.14< 2, 2, 1> W {align1};
{0×00800031, 0×20601F21, 0×00A10040, 0×04110203}, ...
Это уже конечный результат после компилирования шейдерного ассемблера в GPU’шный ассемблер. Т.е. фактически потратил неделю на написание всех программ с последующим тестированием, зато я уверен в них на все 100%. И уже забыл, когда к ним возвращался...

Главное не забывать, что шейдерный ассемблер ещё компилируется в GPU’шный, где частенько не бывает нужных команд. К примеру, часто можно ожидать, что DP4 может развернуться в ~20 GPU’шных команд, или шум, или синусы/косинусы реализованы софтварно.

В общем, скомпилил я свой шейдер старым fxc.exe и новым, посмотрел в ассемблер и стало мне грустно...
Мне кажется, реальный ход событий был примерно таков: в 2004 году видеокарты были довольно слабые (относительно ~современных), и чтобы они тянули более-менее третьи шейдеры — разработчики все силы вкладывали в компилятор оных, применя оптимизации где только можно и какие только можно. А по ходу течения времени — карты становились все сильней и сильней, появился SLI, вот и перестали уделять должное внимание оптимизации, мол мощная карта все схавает.

Даже при поверхностном просмотре ассемблера видно что старый компилятор сгенерил более быстрый код; развернул цикл (а новый — нет), заюзал хитрые оптимизации — if/else при котором скипается куча кода в некоторых случаях (а новый — никак не отреагировал), отдает приоритет более легковесным операциям. Конечно в некоторых случая новый компилятор справляется тоже совсем не плохо (я и другие шейдеры попроверял), но наверное я буду дальше юзать старый компилер: /

Формат следующий: три RT: D3DFMT_A8R8G8B8 (цвет), D3DFMT_A2B10G10R10 (нормаль), D3DFMT_R32F (глубина).
Да, кстати запись в MRT происходит нормально (то есть, по времени, как и ожидаю). Еще утром провел некие исследования (сейчас нет доступа к проекту):
весь рендер (а он не так прост, юзаются еще дополнительные аккумулирующие RT, постпроцессинг, разные материалы) дает 90 фпс с новым sdk, и ~200 со старым.
Отключаю использование этого проблемного шейдера освещения (то есть, тупо коментарю код который собирает MRT и делает освещение) — с новым sdk 350 фпс, со старым 290.
То есть, выходит что не считая этого проблемного шейдера — польза от нового sdk ощутима и она есть, как только юзается проблемный шейдер — эта польза сводится на нет и приложение замедляется в ~2 раза (по сравнению со старым sdk). В общем, сегодня вечером буду «разбирать» этот шейдер по кускам пока не пойму в чем дело.

ps. Проект в DX Debug (с макс. уровнем дебага) не выдает ни одного эрора в output.

Та тут не все так просто, юзается Deferred shading, и бочит как раз главный шейдер который собирает MRT и делает освещение.

А у Render Target’ов формат какой? Хотя от компилятора это врядли зависит, но может перед записью в MRTs происходит постоянное конвертирование int32 -> float16 -> float32, или что-то подобное... PerfHUD скажет:)

Mike Gorchak

Не загружаешь все ALU и самплеры полностью.

Берешь под свою видюху тулзу и смотришь, где bottleneck

Да возможно, хотя я так изначально думал про старый компилятор, а тут новый и так напортачил...

Вот все собираюсь дотянуться до PerfHUD, наверное сегодня таки дотянусь...

Да, и не делай универсальных pixel/fragment shader’ов, лучше иметь 100 штук под каждый случай жизни, чем 1 универсальный.

Та тут не все так просто, юзается Deferred shading, и бочит как раз главный шейдер который собирает MRT и делает освещение.
И там уже нечего менять/оптимизировать, и не разбить на мелкие куски; ну разве что менять архитектуру:)
Если в начале этого шейдера ставить return «что-то» — и потихоньку его сдвигать вниз (то есть, постепенно добавлять операций на выполнение) — можно наблюдать
как проседает fps на достаточно простых операциях типа умножения, деления; и это на GF GTX 285! Наверное нужно будет сравнить ассемблерный аутпут
старого компилера и нового, сдается мне что новый компилер с этим шейдером какую-то лажу генерит.

И повторюсь, что со старым sdk этот шейдер прекрасно работает.

Да, и не делай универсальных pixel/fragment shader’ов, лучше иметь 100 штук под каждый случай жизни, чем 1 универсальный.

Прийдется теперь долго разбираться почему так, а то и на старой версии sdk может прийдется остаться.

Не загружаешь все ALU и самплеры полностью.
Берешь под свою видюху тулзу и смотришь, где bottleneck:
Intel GPA: software.intel.com/...cles/intel-gpa
nVidia PerfHUD: developer.nvidia.com/...rfhud_home.html

ATI/AMD ShaderAnalyzer: developer.amd.com/...es/default.aspx

Перешел на новый SDK, никаких проблем, проект скомпилился с первого раза без единой ошибки.
И вроде как шейдеры пошустрее стали отрабатывать, но не все... кроме одного (!), самого главного.
Теперь приложение выдает в два раза меньше fps из-за одного шейдера: (

Прийдется теперь долго разбираться почему так, а то и на старой версии sdk может прийдется остаться.

dx 9.0c і dx 9.0 — то ж різні версії. При переході з одного на інший великих проблем не має бути. Якщо перейдеш на новішу версію SDK (dx 9.0c) то і в юзера має бути та версія DirectX, щоб проект запустився.

На рахунок того чи будуть швидще компілитися шейдери і т.д. В SDK всьо написано що нового добавили, що змінилося.

Підписатись на коментарі