我正在使用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);
}
如果程序不再崩溃,我删除内部,但当然结果不正确,因为列表没有排序。 我开始认为我的特定显卡模型存在问题,因为在同一张卡上使用二进制驱动程序和开源堆栈崩溃似乎表明了这一点。但也许在着色器中实际上有一个我找不到的错误。
有什么想法吗?这是我想要的输出:
答案 0 :(得分:0)
从冒泡排序切换到选择排序解决了这个问题。不知道为什么它会崩溃GPU。