вторник, 19 января 2010 г.

OIT/A-buffer demo: improvements

После различных твиков разогнал демку OIT.

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



Как видно, fps удалось поднять c 300 до 450 на той же сцене. Главным образом за счёт того, что:
a) Первый проход, в котором подсчитывается overdraw, заменён на fixed-function блендинг;
б) При сортировке алгоритм bitonic sort заменён на inline реализацию odd-even merge sort.

Также я приложил два .exe, второй использует structured buffer для хранения color и depth, но по каким-то причинам этот способ медленнее (хотя и более удобен для программирования).

P.S. Кстати, в прошлом варианте был баг (он обнаружился в Windows 7 64-bit), из-за чего программа не запускалась. Почему баг "прокатил" в моей 32-bit OS, непонятно.

And for english speaking guys:

BTW, there was a bug in the previous demo (it was detected on Windows 7 64-bit), because of this bug the program simply crashes on start. I don't know why it works on my 32-bit OS. The link to the new, unbuggy demo, is provided.

Update

Иду по улице, двигаю байтики в голове. Думаю над down-sweep: вот мы запускаем в массив нолик и он начинает путешествовать со сдвигом... Вдруг - бац! Там же ноль в начало буфера попадает, у меня же exclusive prefix sum! А значит, из пиксельного шейдера можно выкинуть movc и ещё пару инструкций, которые по недосмотру остались от демки из SDK!

Пришлось подправить шейдер и перезалить архив, а то глупо получилось....

Кстати, наткнулся на таблицу различий между Compute Shader 4.0 и 5.0:

http://www.legitreviews.com/article/1001/2/

Большая часть этой информации содержится в SDK, но в таблице есть одно уместное замечание:
Unordered Access Views Bound to Pixel Shader
Shader Model 4.0: Not supported
Shader Model 5.0: 8
Allows pixel shaders to access compute shader data for interoperability with rendering pipeline
В SDK прямо об этом не говорится. В разделе Using Compute Shader on DX10 написано:
Only one unordered access view can be bound to the shader.
Only RWStructuredBuffers and RWByteAddressBuffers are available as unordered access views.
А в каком именно типе шейдеров доступен UAV - не сказано. Но если зайти в HLSL/Reference/Shader Models/Shader Model 5.0/Objects и прошерстить все объекты, то можно выяснить, что для RWByteAddressBuffer и RWStructuredBuffer сделана пометка Available for compute shader in Direct3D 11 on some Direct3D 10 devices.

Т. к. scattered write абсолютно необходим при аккумуляции фрагментов в пиксельном шейдере, можно сделать вывод, что A-buffer нереализуем в SM 4.0 (4.1). Уверен, это ограничение продиктовано недостатками архитектуры предыдущих чипов ATI.

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

  1. Не понятна одна вещь по CS. Во всех примерах почему-то используется numthreads(1, 1, 1). Один мультипроцессор одновременно исполняет пачку тредов, из-за чего в CUDA рекомендуют делать грид с ячейками NxN, а не 1х1, таким образом получается что большая часть блока SM простаивает. Вы пробовали играться с этой размерностью?

    ОтветитьУдалить
  2. Конечно, один тред - это недопустимо. Это так пишут демки для SDK (студенты наверное, какие-то). Для NVidia - нужно минимум 32 треда, ATI - 64 (размер warp). Оптимально - группы по 128-256 тредов.

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