суббота, 31 января 2015 г.

GTX 970

Реакция Гитлера на новую GTX 970:

Интервью с инженером из nVidia:

воскресенье, 25 января 2015 г.

Санкции

В голову пришла фраза:
Бесплатный крым бывает только в мышеловке.

Vectorized Ray-Bounding Intersection

В прошлый раз я уже описывал идею векторизации в тесте пересечении луча и треугольника. В этот раз я решил пойти дальше и применить векторизацию в тесте луча и ограничивающих объёмов: сферы и прямоугольника. Дело в том, что в классических функциях, написанных с расчётом на выполнение на обычном CPU, есть скалярные операции, и это неэффективно ложится на HLSL. Так, например, для сферы необходимо 6 dxasm инструкций, а для прямоугольника - 13, чтобы найти бинарный ответ пересекает-да/нет. Вроде неплохо, но желательно сократить длину процедуры поиска пересечений до минимума.

Для примера возьмём сцену с BVH, где корень имеет несколько дочерних узлов-боксов. Или, например, модель юнита описана сферами вокруг головы, тела и конечностей, в которых в свою очередь подсферами или боксами описываются кластеры треугольников. В этом случае может быть быстрее искать пересечение с чётвёрками узлов за раз и избавиться от скалярных операций.

Я написал две тестовые HLSL функции для сферы и прямоугольника: ray_intersects_vectorized. Промерив кол-во dxasm инструкций на выхлопе, получаем 3 для сферы и ~6 для прямоугольника, или 12 и 25 для их чётвёрок.

 Рис. 1. Vectorized ray-sphere test

Рис. 2. Vectorized ray-box test

Недостатком оптимизации является то, что у нас в BVH или любой другой структуре не всегда под рукой может быть 4 ограничивающих объёма - их может быть 3, или 5, и тогда придётся "подбивать" структуры пустыми данными и тратить на них вычислительные ресурсы. Если же иерархическая структура настроена на поставку четвёрок объёмов за раз, то данный подход представляется оптимальным.

Если взглянуть на функцию пересечения с прямоугольником, можно отметить что выражения
(lo-o)*inv_dir 
(hi-o)*inv_dir

ложатся на dxadm как add+mul, при этом превратить их в mad не представляется возможным из-за порядка операторов. Однако, если мы делаем трассировку лучей в ортографической проекции или от направленного источника света (Солнца), мы можем переписать это в виде
lo*inv_dir-o*inv_dir
hi*inv_dir-o*inv_dir 

где (lo/dir, hi/dir) предвычисляются заранее. Это возможно сделать по той причине, что все лучи имеют одинаковое направление, и рассчитывать деления отдельно для каждого луча не имеет смысла. После этого связки add+mul могут быть заменены на mad (или FMA в новых архитектурах) и функция сократится ещё на шесть инструкций, всего до 19 или ~5 на один примитив.

Рис. 3. Пересечение луча с 4-мя прямоугольниками в ортографической проекции, приблизительно 19 dxasm инструкций. 

воскресенье, 11 января 2015 г.

Ray/Tri Intersection for Directional Light

Анализируя код пересечения луча и треугольника из Fast, Minimum Storage Ray/Triangle Intersection, я понял что применительно к ортографической проекции или построению теней от направленного источника света (Солнца) путём трассировки лучей, мы можем оптимизировать функцию пересечения. Идея оптимизации основана на том, что все лучи от направленного источника имеют одно направление, в отличие от, скажем, точечного источника. Зная, что вектора dir, edge1 и edge2 являются константами для всего примитива, вектор p и параметр det можно предрассчитать заранее и хранить в памяти вместе с вершинными данными. В противном случае, для каждого пикселя тени будут рассчитываться cross и dot операции с одинаковым результатом. Здесь встаёт вопрос о tradeoff между чтением из памяти и вычислениями, но мне была интересна хотя бы теоретическая возможность вычислительной оптимизации.

Я написал шейдер и демо, которые применяют эту идею. Если использовать самый радикальный, векторизованный вариант пересечения луча и 4-х треугольников, на выхлопе получается 28 dxasm инструкций, т. е. 7 инструкций на треугольник. Думается, это рекордный показатель среди всех функций пересечения с треугольником (конечно, беря во внимание ограничения, свойственные методу).


Думается, метод подойдёт для статичной геометрии (например, здания города, отбрасывающие тени от Солнца). В случае, если солнце должно двигаться (меняется вектор dir), нужно делать отдельный проход, в котором значения пересчитываются для каждого треугольника и сохраняются в памяти перед проходом теней.