Використання двох шейдерів замість одного з операторами IF


9

Я працював над перенесенням на ES 2.0 відносно великого відкритого джерела ES 1.1.

У OpenGL ES 2.0 (що означає, що все використовує шейдери), я хочу намалювати чайник тричі.

  1. Перший, з рівномірним кольором (ала старий glColor4f).

  2. Другий - з кольором вершини (чайник має також масив кольорів вершин)

  3. Третя, з вершинною текстурою

  4. І, можливо, четвертий, з текстурою та кольором на вершині. І тоді, можливо, 5-й, з нормалами також.

Наскільки я знаю, у мене є два варіанти здійснення. Перший - зробити шейдер, який підтримує все вищезазначене, з рівномірною формою, яка встановлюється для зміни поведінки (наприклад, використання єдиної кольорової рівномірної форми або однорідної кольорової рівномірної форми).

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

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

Відповіді:


10

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

Найгірший випадок із розгалуженням піде приблизно так:

  • обидві сторони гілки оцінюються.
  • інструкція "суміш" або "крок" буде створена компілятором шейдерів і вставлена ​​у ваш код, щоб вирішити, яку сторону використовувати.

І всі ці додаткові інструкції виконуватимуться для кожної вершини або фрагмента, який ви малюєте. Це потенційно мільйони додаткових інструкцій, які слід зважити на вартість зміни шейдера.

" Посібник з програмування OpenGL ES для iOS " Apple (який можна вважати репрезентативним для вашого цільового обладнання) говорить про розгалуження:

Уникайте розгалуження

Гілки відмовляються від шейдерів, оскільки вони можуть зменшити можливість паралельного виконання операцій на процесорах 3D графіки. Якщо ваші шейдери повинні використовувати гілки, дотримуйтесь цих рекомендацій:

  • Найкраща продуктивність: Відгалуження на константі, відоме при складанні шейдера.
  • Прийнятно: Відділення на рівномірній змінній.
  • Потенційно повільно: розгалуження на значення, обчислене всередині шейдера.

Замість створення великого шейдера з багатьма ручками та важелями, створіть менші шейдери, спеціалізовані для конкретних завдань візуалізації. Існує компроміс між зменшенням кількості гілок у ваших шейдерах та збільшенням кількості створених вами шейдерів. Перевірте різні варіанти та виберіть найшвидше рішення.

Навіть якщо ви впевнені, що ви знаходитесь в слоті "Прийнятний", вам все одно потрібно врахувати, що з 4 або 5 випадків для вибору між ними ви збираєтеся збільшувати кількість інструкцій у ваших шейдерах. Ви повинні знати про обмеження кількості інструкцій для вашого цільового обладнання та переконайтесь, що ви не переходите над ними, цитуючи ще раз посилання на Apple:

Реалізації OpenGL ES не потрібні для впровадження резервного програмного забезпечення при перевищенні цих лімітів; натомість шейдер просто не вдається зібрати або зв’язати.

Нічого з цього не означає, що розгалуження - не найкраще рішення для ваших потреб. Ви правильно визначили той факт, що ви повинні профайлювати обидва підходи, тож ось остаточна рекомендація. Але тільки майте на увазі, що коли шейдери стають складнішими, рішення на основі розгалуження може призвести до значно більших накладних витрат, ніж кілька змін шейдерів.


3

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

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

Крім того, є ще кілька способів досягти цього: "Uber-шейдери" та невелика хитрість із тим, як пов'язані програми шейдерних програм OpenGL.

"Uber-шейдери" - це, по суті, перший вибір, мінус розгалуження, але у вас буде кілька шейдерів. Замість того щоб використовувати ifзаяву, можна використовувати препроцесор - #define, #ifdef, #else, #endif, і узагальнювати різні версії, в тому числі власне #defineз для того, що вам потрібно.

vec4 color;
#ifdef PER_VERTEX_COLOR
color = in_color;
#else
color = obj_color;
#endif

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

//ins, outs, uniforms

float getShadowCoefficient();

void main()
{
    //shading stuff goes here

    gl_FragColor = color * getShadowCoefficient();
}

Тоді я міг би мати декілька інших файлів шейдерів, які визначають getShadowCoefficient(), необхідну форму та нічого іншого. Наприклад, shadow_none.glslмістить:

float getShadowCoefficient()
{
    return 1;
}

І shadow_simple.glslмістить (спрощено з мого шейдера, який реалізує CSM):

in vec4 eye_position;

uniform sampler2DShadow shad_tex;
uniform mat4 shad_mat;

float getShadowCoefficient()
{
    vec4 shad_coord = shad_mat * eye_position;
    return texture(shad_tex, shad_coord).x;
}

І ви могли просто вибрати, хочете ви затінення чи ні, пов'язуючи інший shadow_*шейдер. Це рішення може мати великі накладні витрати, але я хотів би подумати, що компілятор GLSL досить хороший, щоб оптимізувати будь-які додаткові накладні витрати порівняно з іншими способами цього. Я не проводив жодних тестів з цього приводу, але я люблю це робити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.