Я работаю над графическим движком OpenGL, который может точно отображать прозрачные сетки. Полный проект доступен здесь; это решение Visual Studio 2017 (вам может потребоваться установить Windows 10 SDK), но оно также включает make-файл для сборки под Linux. Он использует связанные списки фрагментов на графическом процессоре, которые затем сортируются и смешиваются друг с другом.

В частности, это делается с помощью двух буферов и атомарного счетчика: первый буфер содержит для каждого пикселя указатель на заголовок своего списка и атомарно обновляется при рендеринге мешей; второй буфер содержит фактические узлы (узел - это цвет фрагмента и указатель на следующий узел), а атомарный счетчик используется для резервирования уникальной позиции во втором буфере.

Проблема в том, что на моем ноутбуке с дискретной графикой AMD все работает нормально, но вылетает на другом моем ПК nVidia (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);
}

Если я удалю внутреннее, если программа больше не выйдет из строя, но, конечно, результат будет неверным, так как списки не отсортированы. Я начинаю думать, что есть проблема с моей конкретной моделью графической карты , потому что сбой как с двоичным драйвером, так и со стеком с открытым исходным кодом на одной и той же карте, похоже, предполагает это. Но, возможно, в шейдере действительно есть ошибка, которую я не смог найти.

Любая идея? Вот результат, который я хочу:

Correct output

-1
Shepard 17 Авг 2017 в 23:40
Слепой выстрел: замените FragmentNode temp двумя варами с плавающей запятой.
 – 
Ripi2
18 Авг 2017 в 02:02
К сожалению, это не работает.
 – 
Shepard
18 Авг 2017 в 12:44

1 ответ

Лучший ответ

Переключение с пузырьковой сортировки на сортировку по выбору решило проблему. Однако не знаю, почему это вызывало сбой графического процессора.

0
Shepard 22 Авг 2017 в 14:37