Чому цей шейдер з геометрії настільки сповільнює мою програму?


27

У мене є програма OpenGL, і я рендерую сітку місцевості. Я переміщую вершини в вершинний буфер і ще не дуже їх забарвлюю в фрагменті шейдера. Я додаю шейдер для геометрії по одній частині.

Перш ніж додати шейдер геометрії, коли я просто програмував кроки затінення фрагмента і вершини трубопроводу, я отримував рамки приблизно 30+. Досить, що я не міг помітити жодної радості. Після додавання шейдера геометрії я отримую близько 5 кадрів в секунду. Чому? Це сукупність шейдера геометрії:

#version 420

layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

void main()
{
    for (int i = 0; i < gl_in.length(); i++)
    {
        gl_Position = gl_in[i].gl_Position;
        EmitVertex();
    }
    EndPrimitive();
}

Це не саме те, що OpenGL робив без шейдера геометрії?

Відповіді:


40

Це не саме те, що OpenGL робив без шейдера геометрії?

Ні, це не так. GS - необов'язковий крок, а не крок, який має за замовчуванням.

Для того, щоб OpenGL виконав шейдер геометрії , він повинен виконати те, що відомо як " примітивна збірка ". Коли ви виведете ряд трикутників черезGL_TRIANGLE_STRIP , OpenGL буде робити внутрішній матеріал для перетворення кожні 3 суміжні вершини в окремий трикутник, змінюючи порядок обмотки відповідним чином.

Зазвичай, коли не використовується GS, цей процес виконується один раз. Якщо ви використовуєте GS, він повинен бути виконаний перед виконанням GS. Але це також повинно бути виконано після GS, оскільки GS може виводити зовсім інший примітивний тип (наприклад, квадроцикли).

Тож тепер ви змушуєте систему робити безліч зайвих робіт ні за що. Зрештою, OpenGL не може припустити, що ваш GS нічого не робить (це нерозв'язна проблема).

Крім того, низка оптимізацій вже не функціонує за наявності GS. Розгляньте індексовану візуалізацію.

Кожен індекс з буфера масиву елементів буде отримувати однакові результати з вершинного шейдера. Таким чином, GPU часто кешує ці виходи в кеш-пам'яті після T & L . Якщо він бачить індекс, який вже знаходиться в кеші, VS не запускається знову; він просто отримує дані з кешу.

Що це"? "Це" - це ... примітивна збірна одиниця . Так, ця річ, яка запускається двічі, коли ви використовуєте GS. Індекс кешування матеріалів? Він працює лише для входів GS.

То що відбувається з виходами ГС? Ну, це залежить від обладнання. Але це має перейти в якийсь буфер пам'яті. І в цьому полягає проблема: цей буфер взагалі не індексується. Це як ситуація з glDrawArrays.

Отже, якщо ви надсилаєте індексний буфер 0, 1, 2, 0, 2, 3, це перекладається на 4 вершини в кеш-пам'яті після T & L. Але буфер вершин пост-GS тепер має 6 вершин. Буфер пост-GS використовує більше місця. Отже, якщо ви зіткнулися з проблемою складання належних списків трикутників або смужок, оптимізованих після T & L, і переходите на GS проходу, як ваш, ви в основному загинули приблизно половину ваших результатів від цієї оптимізації.

Це було не марно, але це боляче.

До цього можна додати той факт, що у багатьох графічних процесорах GL 3.x класу (aka: DX10) були досить невеликі буфери після GS. Чим менше буфер, тим менше викликів GS ви можете мати активні одночасно. Тож ваші технічні засоби ефективно вузькі місця на GS. Оскільки tessellation є важливою особливістю обладнання 4.x класу, більшість таких апаратних засобів мають буфери, достатні для того, щоб зробити важче використання GS можливим.

Тож використання GS з більшою ймовірністю зробить обробку вершин коду вузьким місцем. Звичайно, ви завжди можете використовувати це на вашу користь, зробивши ваші вершини та фрагменти шейдери складнішими, оскільки це просто безкоштовне виконання в цей момент.

Для отримання додаткової інформації про сповільнення, спричинені GS, читайте цю статтю .

Ось основне правило щодо GS: ніколи не використовуйте GS, оскільки ви думаєте, що воно зробить візуалізацію швидше . Ви повинні використовувати його, коли це робить те, що ви намагаєтесь зробити . Якщо ви намагаєтеся зробити оптимізацію, використовуйте щось інше.

Загальні винятки з цього:


Я намагаюся обчислити крутизну кожного багатокутника, взявши його найвищу висоту і віднімаючи його найменшу висоту. Однак, якщо шейдер для геометрії обов'язково сповільнить мене на цю суму, я думаю, я міг би зробити це творчо у вершинній шейдері.
Аві

1
@Аві зауважте, що найвищі та найнижчі точки трикутника не дадуть вам крутості; вам потрібні всі три бали.
sam hocevar

2
Особисто я завжди вважав, що інстанція є більш корисною для точкових спрайтів, ніж GS.
Максим Мінімус

1
Чи виняток для точкових спрайтів узагальнюється до шейдерів layout(points) in;? Або це фіксований розмір виходу? А може, і те й інше?
Філіп
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.