高级 GLSL 着色器在 AMD 上运行良好,但在 nVidia 上崩溃

Advanced GLSL shader runs fine on AMD but crashes on nVidia

我正在使用 OpenGL 图形引擎,它可以准确地渲染透明网格。完整项目可用 here;它是一个 Visual Studio 2017 解决方案(您可能需要安装 Windows 10 SDK),但还包括一个在 Linux 下构建的 makefile。它使用 GPU 上的片段链表,然后对这些片段进行排序和前后混合。

更具体地说,这是通过两个缓冲区和一个原子计数器完成的:第一个缓冲区为每个像素保存一个指向其列表头部的指针,并在渲染网格时自动更新;第二个缓冲区保存实际节点(一个节点是片段的颜色和指向下一个节点的指针)并且原子计数器用于在第二个缓冲区中保留唯一位置。

问题是在我的带有独立 AMD 显卡的笔记本电脑上一切正常,但在我的另一台 nVidia PC(GT 740,非常便宜)上却崩溃了。 它在 Windows 和 Linux 上以及在官方驱动程序和开源堆栈上都崩溃 。导致这种情况的代码在排序着色器中(请参阅 TODO 注释):

int listBegin = listsHeads[getPixelBufferIndex()];

if(listBegin != -1)
{
    // Sort linked list using bubble sort
    bool swapped;
    do
    {
        // Start at list head
        swapped = false;
        int previousNode = listBegin;
        int currentNode = listsNodes[listBegin].nextNode;

        // Loop until list end
        while(currentNode != -1)
        {
            // Furthest first
            float previousDepth = listsNodes[previousNode].depth;
            float currentDepth = listsNodes[currentNode].depth;

            // TODO fix crash on nVidia
            if(previousDepth < currentDepth)
            {
                swapped = true;
                FragmentNode temp;
                temp.color = listsNodes[currentNode].color;
                temp.meshId = listsNodes[currentNode].meshId;

                listsNodes[currentNode].color = listsNodes[previousNode].color;
                listsNodes[currentNode].depth = previousDepth;
                listsNodes[currentNode].meshId = listsNodes[previousNode].meshId;

                listsNodes[previousNode].color = temp.color;
                listsNodes[previousNode].depth = currentDepth;
                listsNodes[previousNode].meshId = temp.meshId;
            }
            previousNode = currentNode;
            currentNode = listsNodes[currentNode].nextNode;                 
        }
    }
    while(swapped);
}

如果程序不再崩溃,我删除了内部,但是结果当然是不正确的,因为列表没有排序。 我开始认为我的特定显卡型号有问题,因为在同一张卡上同时使用二进制驱动程序和开源堆栈崩溃似乎表明了这一点。但也许着色器中实际上存在我找不到的错误。

有什么想法吗?这是我想要的输出:

从冒泡排序切换到选择排序解决了这个问题。但是不知道为什么它会导致 GPU 崩溃。