2013-07-25 4 views
5

Apple говорит в своих лучших практиках для шейдеров avoid branching, если это возможно, и особенно разветвляется на значения, вычисленные в шейдере. Поэтому я заменил некоторые операторы if встроенной функцией clamp(). Мой вопрос: clamp(), min() и max() могут быть более эффективными или это просто удобство (то есть макро), которые просто расширяются до if блоков?Рекомендации по OpenGL ES для условных обозначений

Я понимаю, что ответ может быть зависимым от реализации. В любом случае, функции, очевидно, более чистые и ясно показывают намерение, которое компилятор мог что-то делать.

+2

Я думаю, что ваше последнее предложение уже отвечает на него довольно хорошо. Помимо того, что они выглядят намного более оптимизированными, они, по меньшей мере, будут, скорее всего, реализованы быстрыми аппаратными командами, чем простой «if». И кроме этого общего предложения (которое должно быть уже достаточно), на практике действительно вполне вероятно, что они используют специальные аппаратные инструкции или условные назначения и не просто функции, обертывающие 'if's. –

ответ

9

Исторически говорящие графические процессоры поддерживали команды на фрагмент, такие как MIN и MAX намного дольше, чем они поддерживали произвольное условное ветвление. Одним из примеров этого в настольном OpenGL является расширение GL_ARB_fragment_program (теперь оно заменено GLSL), в котором явно указано, что он не поддерживает ветвление, но он предоставляет инструкции для MIN и MAX, а также некоторые другие условные инструкции.

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

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

void main() { 
    vec3 N = ...; 
    vec3 L = ...; 
    float NDotL = dot(N, L); 
    if (NDotL > 0.0) 
    { 
     // Lots of very intensive code for an awesome shadowing algorithm that we 
     // want to avoid wasting time on if the fragment is facing away from the light 
    } 
} 

Просто пережатие NDotL до 0-1, а затем всегда обработки теневой код на каждом фрагменте только умножаться через последний срок теневым NDotL будет много затраченных усилий, если NDotL было первоначально < = 0, и теоретически мы можем избежать этих накладных расходов с помощью ветки. Причиной такого рода не всегда является выигрыш в производительности, так это то, что он очень зависит от того, как оборудование реализует ветвление шейдеров.

+0

Отличный обзор. Я должен был реализовывать 'MIN' и' MAX' общие общие 'if' блоки, и я уверен, что вы правы в отношении аппаратной поддержки для них. Большое спасибо! –

+0

Я думаю, что что-то, о чем следует упомянуть, заключается в том, что некоторые графические процессоры не соблюдают стандарты и даже не реализуют ветви вообще. Единственные, на что я наткнулся, - это серия Galaxy Tab от Samsung. Они только молчаливый крах без сообщения или вообще. –

Смежные вопросы