Russian Qt Forum
Ноябрь 01, 2024, 14:20 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: GLSL комбинирование шейдеров/эффектов  (Прочитано 4113 раз)
Torvald
Самовар
**
Offline Offline

Сообщений: 119


Просмотр профиля
« : Июль 07, 2013, 00:08 »

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

Код
C
uniform int mode;
 
void main() {
   if (mode==1){
       ...
   }
   if (mode==2){
       ...
   }
   if (mode==3){
       ...
   }
}

и в функции отрисовки:

Код
C++ (Qt)
void GLWidget::paintGL(){
   glClear(GL_COLOR_BUFFER_BIT);
   program->setUniformValue("mode", 1);
   ...
   program->setUniformValue("mode", 2);
   ...
   program->setUniformValue("mode", 3);
   ...
}

Однако что то мне подсказывает, что условия в шейдерах - это нехорошо.
Подскажите, пожалуйста, как в таких случаях обычно поступают? Мне за один кадр нужно применить несколько эффектов в разных ситуациях.
Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 119


Просмотр профиля
« Ответ #1 : Июль 07, 2013, 00:16 »

А хотя я тут подумал, в данном случае условия это не так уж и плохо. Ведь при таком раскладе все ядра гпу выполняют только одну ветку. То есть включил первый режим - все ядра исполняют первую ветку. Переключил во второй режим - вторую ветку, и т. д.
Условия в шейдерах использовать плохо в том случае, когда одновременно требуетя исполнение нескольких веток, ведь, на сколько я помню, в пределах одного мультипроцессора все ядра могут выполнять только одинаковые инструкции - то есть только одну ветку.

Проверил - фпс действительно не падает. Но все равно хотелось бы услышать как поступают грамотные люди в таких ситуациях)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Июль 07, 2013, 09:47 »

А хотя я тут подумал, в данном случае условия это не так уж и плохо. Ведь при таком раскладе все ядра гпу выполняют только одну ветку.
Все-таки лучше писать GPU (понятнее  Улыбающийся). В общем случае нет, ВСЕ ветки выполняются, даже если они неактивны. Этот финт капитально бьет по ушам нормального программиста, привыкнуть к нему трудно. Насколько мне известно, новые/крутые карты умеют это отрабатывать, но старые/рядовые нет, в чем мне пришлось убедиться. Так что fps может заметно упасть при такой склейке шейдеров.

Лучшее/грамотное решение. Простого/дешевого я не нашел - и смирился с возможным падением fps. Обычные советы - "разбивайте на неск шейдеров" или "рендерите в неск проходов". Нет уж, мне здоровье не позволяет
Записан
Torvald
Самовар
**
Offline Offline

Сообщений: 119


Просмотр профиля
« Ответ #3 : Июль 07, 2013, 10:35 »

Спасибо, а что значит "разбивайте на несколько шейдеров"? Как их переключать потом? Как это вообще сделать в Qt? Интересно было бы потестить.

На счет веток:
к примеру мультипроцессор (это понятие я взял из лекций по CUDA, не знаю на сколько он применим к видеокартам не от nvidia) выполняет 64 нити. Далее два варианта:
1) (мой случай) все 64 нити выполняются по одной ветке. Что произойдет: сначала все 64 нити пройдут по одной ветке, потом  по другой. Но в такой ситуации в случае неактивной ветки все произойдет очень быстро - всего несколько инструкций же.
2) допустим половина нитей идет по одной ветке, половина - по другой (в моем случае это почти исключено, так как последовательность операций подразумевает, что все вычисления производятся сначала по одной ветке, потом по другой). Что произойдет: да то же самое по сути - сначала все 64 нити пройдут по одной ветке, потом по другой. Итого падение производительности в два раза, так как неактивные ветки просто выполняют вычисления впустую.

Я правильно понял?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июль 07, 2013, 11:05 »

а что значит "разбивайте на несколько шейдеров"? Как их переключать потом? Как это вообще сделать в Qt?
Создаем 2 (или больше) копий шейдера. Из первого вырезаете все что можно, оставляете только то что нужно первой ветке, также для второго и.т.п. Число вариантов растет в геометрической прогрессии (с каждым if). Потом вместо изменения переменной подключаете нужный шейдер

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

Я правильно понял?
Нет. Это у нормальных людей код не выполняется если условие false. В GLSL это не так (или по крайней мере часто не так). Код грузит карту даже если эта ветка не должна сработать никогда. Идиотизм но факт.

Вообще не лезьте в этот ужасный мир hardware  Улыбающийся Посмотрите в отладчике что делает карта (gDebugger на Вындоуз) - и пусть на этом сердце успокоится
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.126 секунд. Запросов: 23.