Компактное представление KD-дерева в системах трехмерной визуализации
В системах трехмерной визуализации, используемых в САПР, для повышения скорости визуализации применяется ряд различных способов, в том числе структуры пространственного разбиения и сортировки. Разновидностью таких структур является KDдерево. В большинстве случаев это одна из наиболее эффективных структур пространственного разбиения и сортировки. Среди подходов представления KDдерева в памяти ЭВМ стоит выделить метод, предложенный Ingo Wald [1], и метод, разработанный М. Шевцовым, А. Супиковым и А. Решетовым [2]. В методе [1] для представления узла KDдерева требуется 64 бита информации. В методе [2] представлено расширение данного метода для реализации на x64 платформе, а объем памяти для представления узла KDдерева также равен 64 битам (или 8 байт на узел).
В методе [1] представление узла KDдерева имеет следующий вид:
/* basic 8byte layout for a kdtree node */
struct KDTreeNode {
union{
//position of axisaligned split plane
float split_position;
// or number of leaf primitives
unsigned int items;
}
unsigned int dim_offset_flag;
//’dim_offset_flag’ bits encode multiple data:
// bits[0..1]: encode the split plane dimension
// bits[2..30]: encode an unsigned address offset
// bit[31]: encodes whether node is an inner node or leaf
};
// macros for extracting node information
#define DIMENSION(n) (n>dim_offset_flag & 0x3)
#define ISLEAF(n) (n>dim_offset_flag & (UINT)(1<<31))
#define OFFSET(n) (n>dim_offset_flag & 0x7FFFFFFC)
В предлагаемом в данной статье подходе для представления узла KDдерева требуется 32 бита данных:
/* basic 4byte layout for a kdtree node */
struct KDTreeNode
{
unsigned int dim_offset_split;
//’dim_offset_split’ bits encode multiple data:
// bits[0..1] : split plane dimension{00,01,10}, or leaf{11}
// bits[2..24] : encode an unsigned address offset
// bits[2531] : encodes split plane position relative percentage
};
// macros for extracting node information
#define STATE (n) (n>dim_offset_split & 0x3)
#define OFFSET(n) (n>dim_offset_split & 0x3FFFFF80)
#define SPLIT (n) (n>dim_offset_split & (UINT)(7<<31))
В рамках описания данного подхода будем условно называть неконечные узлы KDдерева ветвями, а конечные узлы — листьями, тогда образ хранения информации об узле KDдерева можно представить в таком виде, как показано на рисунке.
Количество битов для хранения смещения узла в глобальном массиве узлов KDдерева равно значению максимальной глубины данного дерева. В ходе исследований было обнаружено, что максимальная скорость прохода луча по ускоряющей структуре достигается при глубине KDдерева в 2223 уровня, то есть 2223 бита на индекс смещения узла KDдерева. В ходе тестирования на проектах сцен, содержащих от нескольких тысяч до 11 млн примитивов (треугольников), было обнаружено, что дальнейшее увеличение глубины KDдерева не дает существенного роста производительности (как в предлагаемом подходе, так и с использованием представления узла KDдерева, как в подходе [1]) — он может составлять от 1 до 3%. При чрезмерно больших значениях глубины KDдерева скорость визуализации имела тенденцию к снижению. Следует отметить, что размер значительного количества сцен, создаваемых при работе над проектом в САПР в направлениях архитектуры, дизайна, а также при создании трехмерных моделей инженерных и конструкторских разработок, находится ниже отметки 10 млн примитивов. Однако встречаются и проекты, содержащие от 100 млн до нескольких миллиардов примитивов, и с развитием той или иной отрасли, где применяются САПР, увеличивается и количество примитивов в проекте.
При глубине дерева, равной 23, на адресование листа в глобальном массиве листов требуется 22 разряда, что позволяет адресовать 4 194 304 листа. В хорошо сбалансированном KDдереве лист содержит в среднем 24 примитива, следовательно, дерево с максимальной глубиной 23 примерно будет содержать до 16 777 000 примитивов. При необходимости дальнейшего увеличения максимальной емкости KDдерева можно применять иерархию kdподдеревьев. При 22битном индексе листа остается 8 бит, которые можно использовать на адресацию новых поддеревьев, что позволяет адресовать свыше 273 млрд листов с сохранением возможности дальнейшего наращивания количества поддеревьев.
При прохождении по KDдереву, построенному в соответствии с предложенным методом, размеры узлов дерева вычисляются итеративно, где значение позиции секущей плоскости, хранящееся в 7 битах при глубине дерева 23, указано в процентах относительно родительского узла, стоящего уровнем выше. При реализации данного метода прохождения по KDдереву затраты на вычисление конкретных размеров узла можно сократить, используя опережающее вычисление размеров дочерних ячеек средствами блока потоковых вычислений (SIMD).
Таким образом, данный подход позволяет сократить объем памяти, занимаемой KDдеревом, на величину до 50%. Это позволит избежать обращения к файлу подкачки в отдельных случаях и разместить всю структуру KDдерева в ОЗУ. Экономия затрат памяти является основной отличительной особенностью данного подхода. В случае его применения при визуализации проектов, созданных в САПР, в направлениях архитектуры, дизайна, а также инженерных и конструкторских разработок в условиях острой нехватки информационной емкости ОЗУ возможна ситуация, когда размещение всей структуры KDдерева в памяти ОЗУ позволяет избежать значительного падения производительности по отношению к случаю, когда при нехватке памяти ОЗУ используется файл подкачки.
Библиография
- Wald I. Realtime ray tracing and interactive global illumination: PhD thesis. Saarland University, 2004.
- Shevtsov M., Soupikov A., Reshetov A. Efficient acceleration structures layout for rendering on 32 and 64bit manycore architectures. Intel Corp., Graphicon’2009.
- Havran V. Heuristic Ray Shooting Algorithms: PhD thesis. Czech Technical University in Prague, 2001.