Какую производительность добавляют условные и неиспользуемые сэмплеры / текстуры в пиксельные шейдеры SM2 / 3? - PullRequest
11 голосов
/ 17 марта 2011

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

Я понятия не имею, насколько производительность влияет на эти две вещи, но, тем более, что мы поддерживаем SM2.0 на интегрированных графических чипах, проблема неэффективности. Итак, означает ли передача текстуры, а не ее использование, дополнительные издержки? И действительно ли использование if просто добавляет пару инструкций, или это может сильно повлиять на вещи из-за остановок и т. Д., Как при оптимизации ЦП?

1 Ответ

20 голосов
/ 19 марта 2011

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

Теперь существует три способа обработки ветвления:

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

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

И, наконец, он может фактически использовать инструкции ветвления.Прежде всего, для отраслевых инструкций требуется умеренное количество команд.И тогда есть трубопровод.У x86 есть длинный последовательный конвейер, который вы легко можете остановить.Графический процессор имеет совершенно другой параллельный конвейер.

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

Поскольку группы фрагментов имеют экранную локализацию, это помогает, есливаши филиалы имеют похожую локацию на экране.Смотрите следующую диаграмму:

http://http.developer.nvidia.com/GPUGems2/elementLinks/34_flow_control_01.jpg

Теперь компилятор шейдера, как правило, очень хорошо выбирает, какой из двух последних методов использовать (для первого метода компилятор будет встроендля вас, но вы должны сделать несколько версий шейдеров самостоятельно).Но если вы оптимизируете производительность, может быть полезно увидеть фактический вывод компилятора.Для этого используйте fxc.exe в DirectX SDK Utilities с опцией /Fc <file>, чтобы получить представление о разборке скомпилированного шейдера.

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

Дополнительная справка: GPUДрагоценные камни 2: Глава 34. Идиомы управления потоком графических процессоров .

...