Ранее я уже пробовал разобраться в шейдерах 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. Хотя можно попробовать хотя бы с софтверной эмуляцией :)