понедельник, 11 января 2010 г.

OIT/A-buffer demo

Наконец-то написал демку.

Ссылки:
Rapidshare.de: Ссылка: oit_dx11.zip
Cкриншот:



Пришлось повозиться с некоторыми вещами, а всё из-за невнимательности :)

В дополнение к A-buffer добавил stencil-routed K-buffer, для полноты подхода. Нужно отметить, что с K-буфером сейчас связаны некоторые артефакты, например, семплирование бортиков текстуры и проблемы в местах пересечения геометрии. Это не мой фейл, а скорее драйверов, т. к. демка с зелёным драконом их NV SDK 10 показывает артефакты ещё похлеще. Забавные, в общем, артефакты.

Update

Сделал fork и начал играться с оптимизациями. Сперва заменил color + depth буферы на один structured буфер. Дело в том, что с точки зрения памяти лучше всего читать/писать элементы, расположенные локально, чем, например, обращаться к элементам с большим страйдом (частично из-за этого MRT и тормозит). Но оказалось, что structured буфер медленнее (в этой программе на 7-10%). Пробовал разный размер структуры, т. е. кратный 16, 32 байтам - ничего. Кстати, в SDK сказано, что при создании structured buffer нужно указывать формат UAV как DXGI_FORMAT_R32_UNKNOWN. Но это ошибка, т. к. такого формата нет, а правильный "формат" - DXGI_FORMAT_UNKNOWN.

Задумался, как оптимизировать scan буфера.

Вообще, по идее, на этом этапе должен происходить read/write contention между различными пассами (d = 0, 1, 2...), но не происходит. Я не эксперт в CUDA или архитектуре Cypress-а, поэтому сложно сказать, почему нет вроде бы обязательных артефактов. С одной стороны, это упрощает жизнь - демка работает, ничего не глючит. С другой стороны, могла бы и быстрее, и не хорошо, когда что-то идёт не так как ожидается (даже если ожидания негативные). Есть догадка, что между двумя вызовами ::Dispatch() может происходить stall CPU-GPU, хотя тоже неясно, отчего именно так? За log(N) * 2 вызовов производительность хорошенько просаживается.

С другой стороны, за падение может отвечать unordered read/write access. Даром это штука наверняка не даётся, да и вообще - это первая его открытая реализация в DirectX. Возможно, что "стройная, как Кипарис" архитектура HD 5000 в этом месте всё же кривовата, и нужно ждать следующего поколения карт. Возможно (и вероятно) драйвер все ещё не отлажен как следует. В общем, одни предположения. Надо курить CUDA и пейпры от AMD, и в виду необкатанных драйверов (да ещё от ATI!), я воздержусь пока от окончательных выводов.

И все же мне удалось немного оптимизировать scan буфера. Я сделал небольшой trick - первые пассы (d = 0..2) я заставил выполняться в одном. Тред теперь оперирует не с двумя индексами, а с вектором из 2^3 = 8 элементов, т. е. данные из UAV загружаются в регистры, там происходят операции суммирования/обмена, а затем данные из регистров записываются в UAV. Я пробовал вектор из 8 и 16 элементов, из 8 быстрее. Старый scan вместе с предыдущими операциями (overdraw, copy) давал ~840 fps, улучшенный - ~1100.

Также на форуме разработчегов игр меня спрашивали, можно ли это заставить работать на DX 10.1. Сейчас, ознакомившись со спецификациями, мне кажется, что да, но со своими затыками. Например, к шейдеру можно подключит только один UAV, а нужно минимум три (color + depth + counter), придётся выкручиваться. Не поддерживается RWBuffer, но можно использовать RWStructuredBuffer. Не поддерживаются атомические операции, но я их пока и не использую.

И последнее. Mecha работает быстрее, при том что depth complexity у неё несоизмеримо больше. Там используются атомические операции для сериализации чтения/записи, что наводит на мысль о том, что у AMD другое понимание, как правильно использовать железо. Ну что ж, буду пробовать :)

2 комментария:

  1. блин, столько шейдеров там, как оно робит то?, хоть стек установки шейдеров нипиши или статью пишешь?

    ОтветитьУдалить