Как программы шейдеров GLSL выполняются на конвейере графического оборудования?

По мере того, как я все больше и больше играюсь с OpenGL ES 2.0 и GLSL, я задаюсь вопросом, как именно шейдерные программы выполняются на оборудовании. Я прекрасно понимаю концепции программ вершинных и фрагментных шейдеров, но как они работают с металлом, все еще очень неясно. Слишком часто, читая о графических процессорах, я сталкивался с термином «конвейер» и с тем, что у графического процессора есть определенное количество конвейеров.

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

Но означает ли это, что если GPU имеет n конвейеров, то в любой момент каждый из n конвейеров может выполнять экземпляр шейдерной программы одного геометрического примитива?

Я читал руководство по программированию OpenGL ES 2.0 (около 60%, согласно Kindle), но, возможно, мое все еще развивающееся понимание заставило меня пропустить ответ на этот самый вопрос.

Одна практическая причина, по которой я задаю этот вопрос, касается того, какую работу следует или не следует выполнять на ЦП, а не на ГП. Например, если я работаю с одним потоком обновления и рендеринга, разумно ли выполнять умножение матрицы на вектор на ЦП, где это нужно будет делать в строке всех объектов? Или было бы лучше отдать на аутсорсинг GPU, где шейдерные программы, выполняющие отрисовку нескольких геометрических примитивов, могли бы выполняться одновременно на разных конвейерах?

Я работаю над оптимизацией некоторого кода, чтобы рисовать много квадроциклов на экране с помощью VBO вместо отдельных вызовов рисования для каждого. Но поскольку это считается рендерингом массива, мне нужно будет отправить все матрицы в GPU для каждой вершины, даже несмотря на то, что матрица mvp одинакова для каждых 4 вершин квада, что можно считать ударом по пропускной способности. Но если шейдерные программы выполняются одновременно, а не одна за другой в моем потоке рендеринга на ЦП, возможно, это достойный компромисс. Но у меня нет такого уровня знаний, чтобы говорить так или иначе.


person Joey Carson    schedule 18.04.2013    source источник


Ответы (1)


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

Что касается того, как я оптимизировал свой код, и я думаю, что это довольно стандартная практика, каждый четырехугольник представлен одними и теми же первичными вершинами, которые преобразуются в зависимости от состояния объекта. Объекты поддерживают набор матриц, которые представляют все преобразования, через которые они прошли. При отправке в GL преобразуйте первичные вершины с матрицами, которые поддерживает объект, и отправьте вершины ise в вершинный шейдер. Отправьте матрицу VP как универсальную, поскольку она глобально независима. Теперь я вижу, что в любом случае нет способа отправить матрицу в GL в качестве атрибута, я полагаю, из-за проблем с пропускной способностью.

person Joey Carson    schedule 19.04.2013