【发布时间】:2019-08-24 01:39:51
【问题描述】:
我正在使用 vulkan 计算着色器开发路径跟踪器。我实现了一个代表bounding volume hierachy 的树。 BVH 的想法是尽量减少需要执行光线相交测试的对象数量。
#1 朴素实施
我的第一个实现非常快,它将树向下遍历到 BVH 树的一个单个叶。但是,光线可能与 多个 叶子相交。然后这段代码会导致一些三角形没有被渲染(尽管它们应该)。
int box_index = -1;
for (int i = 0; i < boxes_count; i++) {
// the first box has no parent, boxes[0].parent is set to -1
if (boxes[i].parent == box_index) {
if (intersect_box(boxes[i], ray)) {
box_index = i;
}
}
}
if (box_index > -1) {
uint a = boxes[box_index].ids_offset;
uint b = a + boxes[box_index].ids_count;
for (uint j = a; j < b; j++) {
uint triangle_id = triangle_references[j];
// triangle intersection code ...
}
}
#2 多叶实现
我的第二个实现说明了多个叶子可能相交的事实。然而,这个实现比实现 #1 慢 36x(好吧,我错过了 #1 中的一些交叉测试,但仍然......)。
bool[boxes.length()] hits;
hits[0] = intersect_box(boxes[0], ray);
for (int i = 1; i < boxes_count; i++) {
if (hits[boxes[i].parent]) {
hits[i] = intersect_box(boxes[i], ray);
} else {
hits[i] = false;
}
}
for (int i = 0; i < boxes_count; i++) {
if (!hits[i]) {
continue;
}
// only leaves have ids_offset and ids_count defined (not set to -1)
if (boxes[i].ids_offset < 0) {
continue;
}
uint a = boxes[i].ids_offset;
uint b = a + boxes[i].ids_count;
for (uint j = a; j < b; j++) {
uint triangle_id = triangle_references[j];
// triangle intersection code ...
}
}
这种性能差异让我发疯。似乎只有一个像if(dynamically_modified_array[some_index]) 这样的语句会对性能产生巨大影响。我怀疑 SPIR-V 或 GPU 编译器不再能够发挥其优化魔力?所以这是我的问题:
这真的是一个优化问题吗?
如果是,我可以将实现#2 转换为更好地优化吗? 我能以某种方式给出优化提示吗?
是否有在着色器中实现 BVH 树查询的标准方法?
【问题讨论】:
标签: glsl compiler-optimization vulkan raytracing bounding-box