GLSL虽然循环性能独立于在其中完成的工作



我当前正在尝试在片段着色器中实现路径示踪剂,该片段着色器利用非常简单的BVH

BVH交集的代码基于以下想法:

bool BVHintersects( Ray ray ) {
    Object closestObject;
    vec2 toVisit[100]; // using a stack to keep track which node should be tested against the current ray
    int stackPointer = 1;
    toVisit[0] = vec2(0.0, 0.0);  // coordinates of the root node in the BVH hierarcy    

    while(stackPointer > 0) {
        stackPointer--;  // pop the BVH node to examine
        if(!leaf) {
            // examine the BVH node and eventually update the stackPointer and toVisit
        }
        if(leaf) {
            // examine the leaf and eventually update the closestObject entry
        }
    }
}

上述代码的问题是,在第二盏灯上弹跳时,发生了非常奇怪的事情开始发生,假设我正在以这种方式计算灯光:

vec3 color  = vec3(0.0);
vec3 normal = vec3(0.0);
// first light bounce
bool intersects = BVHintersect(ro, rd, color, normal);
vec3 lightPos = vec3(5, 15, 0);
// updating ray origin & direction
ro = ro + rd * (t - 0.01);
rd = normalize(lightPos - ro);
// second light bounce used only to calculate shadows
bool shadowIntersects = BVHintersect(ro, rd, color, normal);

bvhintersect的第二个电话将无限期地运行,因为while循环从未退出,但是从我在第二个电话上进行的许多测试中,我敢肯定,stackpointer最终会成功地返回0,实际上,如果我放置以下代码在while循环下:

int iterationsMade = 0;
while(stackPointer > 0) {
    iterationsMade++;
    if(iterationsMade > 100) {
        break;
    }
    // the rest of the loop
    // after the functions ends it also returns "iterationsMade"

变量"迭代"始终低于100,while循环不会无限地运行,但是明智的是,即使我做了" 100"迭代,即使"迭代效果"永远不会比说10或20。硬编码的" 100"到更大的价值将线性降低性能

这种行为的可能原因是什么?第二个呼吁bvhintersect将其陷入其中的原因是什么,如果循环效果不超过10-20次迭代?

bvhintersect函数的源:https://pastebin.com/60syrqaz

所以,关于着色器中的循环(或大多数simd情况(有一个有趣的事情:

整个浪潮至少需要执行的时间与最慢的线程一样。因此,如果一个线程需要进行〜100次迭代,则它们都进行了100次迭代。根据您的平台和编译器,循环可能会展开100次迭代(或您选择的任何上限(。break之后的任何内容都不会影响最终输出,但是将必须处理展开的循环的其余部分。并非总是可能的。

有多种方法,但也许最直接的是在最大迭代值较低的多个通过中进行此操作。

我还将通过编译器运行您的着色器并查看生成的代码。与不同的最大迭代进行比较,并查看诸如编译的着色器的长度之类的内容。

有关更多信息,请参见此答案。

相关内容

最新更新