среда, 12 мая 2010 г.

A-buffer through per-pixel linked lists

Написал новую демку OIT, использующую предложенную ATI методику работы с A-буфером.

Ссылка: oit_ppll_dx11.

Доступны четыре режима: стандартный блендинг, A-буфер с построением префиксной суммы, A-буфер с построением связанных списков, K-буфер. Отлаживал в reference rasterizer на своём ноутбуке.

Как и ожидалось, подход ATI оказался более эффективным. Тестирование на HD 5850 в разрешении 1024x1024 показало прирост скорости в районе 2x-3x. Для более сложных моделей с высоким overdraw отрыв должен быть ещё больше.

Я применил одну банальную оптимизацию для снижения GPR usage. В A-буфере цвета теперь упакованы в uint, и в шейдере сортировки массив цветов, определённый как float4 a[8] заменён на uint a[8], что позволяет оперировать существенно меньшим объёмом данных при сортировке. Распаковка цвета осуществляется непосредственно перед смешиванием. GPU Shader Analyzer показывает такие цифры для Cypress (5870):

Вариант с float4 - 36 GPR, 125 ALU.
Вариант с uint - 26 GPR, 100 ALU.

Для сортируемых массивов малого размера это даёт хоть и небольшой, но всё же прирост скорости. Думается, для массива из 64 элементов прирост скорости будет ощутимым, т. к. без оптимизации мультипроцессор GPU может упереться в величину регистрового файла.

Как ещё одно средство оптимизации сортировки сложных моделей можно предложить маскировать стенселем участки кадра с разным overdraw и запускать несколько сортирующих шейдеров, рассчитанных на определённое количество слоёв (8, 16, 32, 64). Это должно быть быстрее, т. к. максимальный overdraw обычно достигается редко.

Досадным фактом является то, что сортировка методом K-буфера даёт артефакты в изображении, при том что сам алгоритм реализован без ошибок. В первый раз я списал это на проблемы "сырых" драйверов для ATI 5xxx, но теперь они вновь всплыли, уже на дискретной ATI HD 4330. Более того, отлаживая код под reference rasterizer, я обнаружил, что артефакты остаются, и это натолкнуло меня на мысль, что причина кроется в чём-то ином.

Заинтересовавшись проблемой K-буфера, я попытался локализовать причину артефактов, или хотя бы получить мнение о их природе. Я решил ограничиться двумя плоскостями и просмотреть два отрисованных слоя отдельно, без сортировки и блендинга. Вот что получилось:


На первый взгляд всё правильно, но при внимательном рассмотрении можно заметить, что второй слой растеризатор отрисовал несколько иным образом, заметны различия в ступеньках между первой перекрывающей плоскостью (красной), и перекрытой (зелёной), которая попала во второй слой. Между ступеньками есть gap:


который и порождает артефакты:


Причина подобного поведения растеризатора стала загадкой. Случайно я вспомнил, что до сих пор отлаживал код только под reference rasterizer и в feature level 10.1, тогда как мои первые реализации K-буфера работали в feature level 10.0. Я поменял level на 10.0, запустил демку и о чудо, никаких артефактов!


(Note: небольшие артефакты в месте пересечения плоскостей обусловлены тем, что задействован depth буфер с форматом пониженной точности R16_UNORM).

Переключив несколько раз feature level и убедившись, что артефакты то исчезают, то появляются вновь, я заглянул в справку DirectX SDK, а именно, в Windows Graphics/Direct3D 10/Programming Guide/Direct3D 10.1 Features. Там нашёлся следующий пункт:

Rasterization Rules - The rules for rasterization have changed for lines, in addition, new functionality has been added.

MultisampleEnable only affects line rasterization (points and triangles are unaffected), and is used to choose a line drawing algorithm. This means that some multisample rasterization from Direct3D 10 are no longer supported.

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

  1. Порядок сбивается, когда полигон растеризуется не во все сэмлы или в разном порядке (когда, например, смежные полигоны рисуются не подряд, а хаотично). Как вариант решения, можно использовать edge-detect + блюр по "правильным соседям".

    Вообще, мне не понятно будет ли работать демка k-buffer с драконом на произвольной сцене. Не видел информации. Где гарантии, что кромка полигона попадает во все мультисэмлы? В общем, случае, по идее, на границе стенсил должен ломаться. Судя из картинки 10.0 этого не происходит. Где магия?

    ОтветитьУдалить
  2. Кстати, забыл сказать, что демка "зеленый дракон" (stencil-routed OIT) ломается на HD5670. Дает кучу тонких белых полос на стыках, которые оч похожи на указанный артефакт. Я не дебажил ее, но с большой долей вероятности это именно указанный в предыдущем посте артефакт. Если интересно, то могу скриншот выложить :)

    ОтветитьУдалить
  3. Я тоже запускал эту демку из SDK, при большом depth complexity появлялись артефакты. Но в моей программе их-то больше нет.

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