2016-10-25 3 views
2

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

#version 430 
in vec3 position; 

void main() {{ 
    gl_Position = vec4(position, 1); 
}} 

и фрагмент шейдеры:

#version 430 
layout(early_fragment_tests) in; 

out vec4 out_color; 

layout(std430, binding = 3) buffer out_data { 
    int data[]; 
}; 

void main() {{ 
    atomicAdd(data[gl_PrimitiveID], 1); 
    out_color = vec4(1, gl_PrimitiveID, 0, 1); 
}} 

Как вы можете видеть, что это только увеличивает элемент хранения шейдер объекта буфера.

Затем я кормлю его двумя треугольниками (6 баллов): [-1, -1, 0], [-1, 1, 0], [1, 1, 0], [-1, -1, 0], [1, -1, 0], [-1, 1, -1]. Он правильно отображает красный треугольник и зеленый треугольник, каждый из которых занимает ровно половину окна, но зеленый треугольник сверху - так что видится только половина красного треугольника (1/4 окна).

Конечно, я ожидал, что подсчет будет около 1/4 от размера окна красного треугольника и около 1/2 для зеленого, но они оба равны 1/2! Btw, если я установил все входные координаты Z в ноль, тогда красный треугольник будет сверху, а зеленый полускрыт - в этом случае подсчеты верны.

Во время чтения OpenGL документов (где я нашел вариант early_fragment_tests) я понял, что фрагменты отбрасываются по какой-либо причине (например, тест глубины, как в моем случае) не влияют на атомные счетчики и SSBOs - см here. Но, как показывает мой пример, они явно влияют на них! Есть ли что-нибудь еще, что может решить проблему?

Если это важно, я запускал его под Linux, используя iGPU intel skylake, OpenGL 4.3.

+0

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

+1

В каком порядке вы рисуете треугольники? Когда вы рисуете красный, а затем зеленый, результат не вызывает удивления, поскольку красный треугольник полностью виден в тот момент, когда он отображается. – BDL

+0

Я упомянул, что корм шейдеров двумя треугольниками (6 баллов), и я делаю это одним призывом к DrawArrays. – aplavin

ответ

3

Порядок обработки фрагментов из отдельных треугольников в значительной степени не определен. Ранние фрагментные тесты не заставляют фрагменты каждого треугольника обрабатываться в порядке растеризатора. Хотя OpenGL работает в основном по правилу «как есть» (то есть: все работает «как-бы», оно обрабатывалось по порядку), некогерентный характер доступа к изображениям/сохранению изображений и SSBO памяти означает, что вы не можете полагаться на in- обработки заказа.

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

Между двумя из них должна быть какая-то форма синхронизации, которая гарантирует, что все треугольники в первом проходе закончились до начала второго прохода. К сожалению, OpenGL не имеет достойного способа спросить об этом. Вы могли бы use a fence sync object with glWaitSync, но для этого требуется явный вызов glFlush, что не совсем дешево.

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

  • Нет связанных вопросов^_^