Ранее я уже пробовал разобраться в шейдерах Mecha. Для этого пришлось написать hook-DLL для перехвата вызовов D3DCompileShader(). К сожалению, все шейдеры в демо зашиты в binary blob-ы, и всё, что можно сделать - это получить дизассемблированный код. Разобраться быстро в нём оказалось непросто, т. к. код по работе с OIT был густо перемешан с кодом расчёта освещения, сортировки и т. д. Тогда я отставил эту трудоёмкую задачу, и вот теперь стали доступны детали реализации.
OIT от AMD не использует prefix scan для расчёта смещений для записи фрагментов, как это описано в патенте Microsoft. Вместо этого используется R/W structured буфер, в элементах которого хранятся атрибуты фрагмента (цвет, глубина), и индекс предыдущего (следующего, как посмотреть) фрагмента в списке (если на пиксель экрана накладываются два и более фрагментов). Индекс указывает на элемент в structured buffer. Таким образом, полупрозрачные фрагменты организуются в памяти GPU в linked lists.
Преимущество этого метода в том, что запись в structured буфер всегда происходит последовательно, даже если фрагменты в буфер кадра приходят хаотически. В противовес этому, подход, применённый в DirectX SDK (и у меня), приводит к весьма хаотичному заполнению A-буфера. Для примера, стартовые позиции двух fragment bins для двух соседних пикселей уже различны. Добавьте к этому, что растеризатор выплёвывает фрагменты не линейно, а квадами 2х2, и получается безрадостная картина неупорядоченной записи в UAV (нужно отметить, что по моим тестам, при увеличении разрешения основной bottleneck заключался именно в заполении A-буфера, за ним следовала сортировка, и только потом - относительно дешёвый prefix scan). Поэтому на практике метод AMD на шаге аккумуляции фрагментов должен работать быстрее. Правда, в дополнение также используется т. н. Start Offset Buffer, но его элементы, в которые просходит запись, находятся в тех же позициях, что и фрагменты в буфере кадра.
На этапе сортировки фрагментов происходит traversal по этим linked lists, данные из различных участков памяти собираются в массив и сортируются. Теоретически такой traversal мог бы быть медленнее, чем линейная выборка fragment bins из A-буфера, но здесь мы можем просто читать из UAV, присоединив его как shader resource view. Т. к. random access текстур в GPU хорошо оптимизирован, этот шаг, вероятно, выполняется с хорошей скоростью.
P.S. Жаль только, что не могу реализовать алгоритм - Direct3D 11 железа больше нет под рукой :(
P.P.S. Хотя можно попробовать хотя бы с софтверной эмуляцией :)
На этапе сортировки фрагментов происходит traversal по этим linked lists, данные из различных участков памяти собираются в массив и сортируются. Теоретически такой traversal мог бы быть медленнее, чем линейная выборка fragment bins из A-буфера, но здесь мы можем просто читать из UAV, присоединив его как shader resource view. Т. к. random access текстур в GPU хорошо оптимизирован, этот шаг, вероятно, выполняется с хорошей скоростью.
P.S. Жаль только, что не могу реализовать алгоритм - Direct3D 11 железа больше нет под рукой :(
P.P.S. Хотя можно попробовать хотя бы с софтверной эмуляцией :)
у mecha все данные заархивированны (zip), HLSL-шейдера в этом же архиве (на вскидку не помню, но вроде .pak) - любой архиватор открывает. Модельку доставал оттуда же, а ее дескрипшн через PerfStudio.
ОтветитьУдалить> запись в structured буфер всегда происходит последовательно
откуда информация? Да, и по тестам RWTexture работает быстрее RWSB.
у OIT на 64 слоя самая тяжелая стадия - сборка списка и сортировка, ближайшее время попробую ускорить
а вообще алгоритм в филрейт упирается
меня вот удивило, что счетчик у RWSB оч быстрый - не встречал информации почему?
Интересно как оно все живет на Fermi. В презентации пишут, что мол там лучше Append-буфер использовать. Найти бы кого-нибудь для теста.
>откуда информация? Да, и по тестам RWTexture работает быстрее RWSB.
ОтветитьУдалитьПотому что индексация основана на RWSB hidden counter. Это видно и из слайдов.
>у OIT на 64 слоя самая тяжелая стадия - сборка >списка и сортировка, ближайшее время попробую >ускорить а вообще алгоритм в филрейт упирается
Филлрейт - понятие растяжимое. Во что именно?
Для облегчения сортировки думаю лучше всего маскировать стенселем участки экрана с разным overdraw и запускать сортируюший шейдер с разными глубинами сортировки + earlydepthstencil для реджектинга. Должно быть лучше чем юниформная сортировка для 64 элементов.
>меня вот удивило, что счетчик у RWSB оч быстрый - не встречал информации почему?
Потому что захардкоден в силиконе :)