Оптимизация обхода BVH с помощью графического процессора
Я создал ограничивающую иерархию томов, которая генерируется каждый кадр. Из-за его использования каждый узел должен иметь двух дочерних элементов, ни больше, ни меньше.
Обход - единственное самое дорогое вычисление для моей программы на данный момент, и он предотвращает запуск больших сцен (>2k треугольников) с приемлемой частотой кадров. Я в недоумении относительно того, как это может быть выполнено быстрее. Простой квадрат с 16 треугольниками вносит заметное падение кадра, когда через него проходит много лучей.
Чтобы обойти это, я использовал концепции, приведенные в статье по этой ссылке, где каждая нить пересекает следующий код.
Что можно сделать, чтобы увеличить скорость?
На данный момент эта функция используется в гораздо более крупном ядре. Поможет ли его изоляция внутри собственного вызова диспетчеризации за счет использования большего объема памяти для хранения выходных данных?
//o= origin , d =direction, bestT = the intersection distance
bool FindBVHIntersect(vec3 o, vec3 d,inout float bestT){
//starting at the root of the bvh(0) the locations of the two children are found (near , far)
uint current=0;
uint last=0;
uint near=uint(bvh[current].w);
uint far=uint(bvh[current+1].w);
//max distance to test intersection
float distance=4294967295.0f;
bool success=false;
bool run= true;
while(run){
//update the children's location
near=uint(bvh[current].w);
far=uint(bvh[current+1].w);
//traversing up from the last child
//ending
if(last==far&¤t==0){
run=false;
continue;
}
//go to the parent of the node
else if(last==far){
last=current;
current=bvhAtomics[current/2].y;
continue;
}
//depending on the last position, pick a child
uint tryChild= (last==bvhAtomics[current/2].y)?near:far;
bool delve;
//test the AABB
if(tryChild==near){
delve=FindAABBIntersect(bvh[current].xyz,bvh[current+1].xyz,o,d,0.0f,distance);
}
else{
delve=true;
}
//if the child is a node and needs to be delved. A triangle intersection test.
if(delve&&tryChild>=(nodeSize-1)*2){
float pt;
float ob1;
float ob2;
uint bvhPos=uint(bvh[tryChild+2].x);
uvec3 indPos=indices[bvhPos].xyz;
bool tr = FindTriangleIntersect(vertices[indPos.x].xyz, vertices[indPos.y].xyz, vertices[indPos.z].xyz, o, d, pt, ob1, ob2 );
if(tr){
distance=pt;
float t = pt;
if (t > 0 && t < bestT) {
bestT = t;
success=true;
}
}
last=tryChild;
}
//switching children or setting up for climbing up the tree
else if(delve){
last =current;
current=tryChild;
}
else{
last=far;
}
}
return success;
}
Я пытался минимизировать доступ к памяти в контексте алгоритма, однако расхождение, которое, как я полагаю, является проблемой, кажется невозможным преодолеть препятствие.