Использование нескольких проходов рендеринга обычно медленнее, чем использование одного прохода с выводом MRT, но это также зависит от вашей ситуации.
Насколько я понимаю, и f(I)
, и g(I)
сэмплируют входное изображение I
, и если каждый сэмплирует одни и те же (или близко соседние) локации, вы можете значительно извлечь выгоду из кэша текстур между разными операциями - у вас есть сэмплировать входную текстуру только один раз, а не два раза при многопроходном подходе.
Сделав этот подход еще на один шаг вперед: вам вообще нужны промежуточные результаты f(I)
и g(I)
отдельно? Может быть, вы могли бы просто поместить h(f(I),g(I))
непосредственно в один шейдер, чтобы вам не требовалось ни многократных проходов, ни MRT. Если вы хотите иметь возможность динамически комбинировать свои операции, вы все равно можете использовать этот подход и программно комбинировать различные части кода шейдера динамически для реализации операций (где это возможно) и использовать несколько проходов только там, где это абсолютно необходимо.
ИЗМЕНИТЬ
Поскольку вопрос был обновлен, я думаю, что могу дать более конкретные ответы:
То, что я сказал до сих пор, особенно о размещении h(f(I),g(f(I)) в одном шейдере, является хорошей идеей только в том случае, если h (или f и g) не будут нуждаться в соседних пикселях. nxn ядер фильтра, вам потребуется получить доступ к nxn различным входным текселям, и, поскольку эти входные данные не известны напрямую, вам придется вычислять f и g для каждого из них.Если и f, и h являются ядрами фильтра, эффективный размер фильтра равен составная операция будет больше, и гораздо лучше сначала вычислить промежуточные результаты и использовать несколько проходов.
Глядя на конкретную проблему, которую вы описываете, все сводится к следующему.
Если вы используете два отдельных шейдера самым наивным образом, ваш рендеринг будет выглядеть так.
- использовать шейдер1
- выберите некоторый выходной цветовой буфер
- нарисовать четверной
- использовать шейдер2
- выберите другой цветовой буфер
- нарисовать четверной
Каждый вызов отрисовки имеет свои накладные расходы. GL должен будет выполнить дополнительную проверку. Переключение шейдеров может быть здесь самым дорогостоящим дополнительным шагом по сравнению с подходом с комбинированным шейдером, поскольку это может привести к очистке конвейера графического процессора. Кроме того, для каждого вызова отрисовки у вас есть операции обработки вершин, растеризации и интерполяции атрибутов каждого фрагмента. С помощью всего одного шейдера многие из этих накладных расходов исчезают, а описанные до сих пор вычисления для каждого фрагмента могут быть «разделены» для обоих фильтров.
Но если бы не локальность текстуры: я бы все еще наслаждался приростом производительности?
Из-за того, что я сказал до сих пор, и из-за особенностей шейдеров, которые вы представили, я склонен сказать: да. Но эффект будет очень мал или пренебрежимо мал, если мы здесь проигнорируем доступ к текстурам, особенно если мы предположим изображения с разумным высоким разрешением, так что относительные накладные расходы по сравнению с общим объемом работы кажутся небольшими. По крайней мере, я бы сказал, что использование однопроходной установки MRT не будет медленнее. Однако только бенчмаркинг/профилирование очень конкретной реализации на конкретном графическом процессоре даст окончательный ответ.
Почему я сказал "представленные вами шейдеры". Потому что в обоих случаях вы делаете квадрат изображения в одном шейдере. Вы также можете разделить это на два разных шейдера и рендерпасса. В этом случае вы получите дополнительные накладные расходы (к уже упомянутым) для записи промежуточных результатов и необходимости их чтения. Однако, поскольку вы применяете фильтр к промежуточному результату, вам не нужно возводить входной тексель в квадрат более одного раза, но в комбинированном подходе вы это делаете. Если операция возведения в квадрат достаточно дорогая, а размер вашего фильтра достаточно велик, теоретически вы можете сэкономить больше времени, чем это связано с накладными расходами на несколько проходов. Опять же, только бенчмаркинг/профилирование могут сказать вам, где будет безубыточность.
В прошлом я сам сравнивал MRT с несколькими проходами рендеринга, хотя операции обработки изображений, которые меня интересовали, немного отличаются от ваших. Я обнаружил, что в таких сценариях доступ к текстуре является ключевым фактором, и вы можете скрыть множество других вычислений (например, возведение в квадрат значения цвета) в задержке доступа к текстуре. Я думаю, что ваше «Но если бы не локальность текстуры» немного нереально, поскольку это основной вклад в общее время работы. И дело не только в местоположении, но и в общем количестве обращений к текстуре: с вашим подходом с несколькими шейдерами, изображением размером w*h
и 1D-фильтром размера n
вы получите 2*w*h*n
обращений к текстуре в целом. , в то время как при комбинированном подходе вы просто сократитесь до *w*h*n
, и это будет иметь огромное значение в прошлом.
Для AMD FirePro V9800 с размером изображения 1920x1080 и простым копированием пикселей в два выходных буфера путем рендеринга текстурированных quds я получил за два прохода: ~0,320 мс (даже без переключения шейдеров) против 1 прохода MRT: ~0,230 мс. Таким образом, время выполнения было сокращено «всего» на 30%, но это было только с одной выборкой текстуры на вызов шейдера. Я ожидаю, что с ядрами фильтров эта цифра будет приближаться к 50%-му уменьшению с увеличением размера ядра (хотя я этого не измерял).
person
derhass
schedule
02.05.2014
I
в качестве идентификатора и пишете вопрос, то выделите его, чтобы легче было отличить идентификаторI
от я (вы). - person t.niese   schedule 02.05.2014a
изrgba
, когда мне не нужна прозрачность. Но поскольку вы занимаетесь обработкой изображений, вам, вероятно, понадобится весь цвет, который вы можете получить, и в этом случае рассмотрите предложение @Freddy. - person zero298   schedule 02.05.2014