memoryBarrier () ведет себя неожиданно в Geometry Shader

Я пытаюсь понять, как работает memoryBarrier () в OpenGL 4.4.
Я попробовал следующее один раз с изображением текстуры и один раз с Shader Storage Buffer Object (SSBO).
Основная идея состоит в том, чтобы создать массив флагов для сколь угодно большого количества объектов, которые необходимо визуализировать в моей сцене, а затем выполнить простой тест в геометрическом шейдере.

  1. Для каждого примитива в GS, если хотя бы одна вершина проходит тест, она
    устанавливает соответствующий флаг в массиве в указанном месте
    по идентификатору объекта этого примитива (идентификаторы объекта передаются в GS как вершина
    атрибуты).

  2. Затем я выполняю memoryBarrier (), чтобы убедиться, что все потоки записали свои значения.

  3. Далее, у меня есть все примитивы, прочитанные из массива flags, и я посылаю вершину, только если установлен флаг.

Вот некоторый код из моих шейдеров, чтобы объяснить:

// Vertex Shader:
#version 440
uniform mat4 model_view;
uniform mat4 projection;
layout(location = 0) in vec3 in_pos;
layout(location = 1) in vec3 in_color;
layout(location = 2) in int lineID;

out VS_GS_INTERFACE
{
vec4 position;
vec4 color;
int lineID;
} vs_out;

void main(void) {
vec4 pos = vec4(in_pos, 1.0);
vs_out.position = pos;
vs_out.color = vec4(in_colo, 1.0);
vs_out.lineID = lineID;

gl_Position = projection * model_view * pos;
}

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

 #version 440
layout (lines) in;
layout (line_strip, max_vertices = 2) out;
layout (std430, binding = 0) buffer BO {
int IDs[];
};
in VS_GS_INTERFACE
{
vec4 position;
vec4 color;
int lineID;
} gs_in[];

out vec4 f_color;

void main()
{
if(gs_in[0].lineID < 500)
{
IDs[gs_in[0].lineID] = 1;
}
else
{
IDs[gs_in[0].lineID] = -1;
}
memoryBarrier();

// read back the flag value
int flag = IDs[gs_in[0].lineID];
if ( flag > 0)
{
int n;
for( n = 0; n < gl_in.length(), n++)
{
f_color = gs_in[n].color;
gl_Position = gl_in[n].gl_Position;
emitVertex();
}
}
}

Независимо от того, какое значение я поместил вместо 500, этот код всегда отображает только 2 объекта. Если я изменяю условие рендеринга в GS на if (flag> = 0), мне кажется, что все объекты рендерится, что означает, что -1 никогда не записывается к моменту, когда эти идентификаторы считываются шейдером.
Может кто-нибудь объяснить, почему записи не видны последовательно для всех вызовов шейдеров, несмотря на memoryBarrier (), и что было бы наиболее эффективным способом обойти это?

Благодарю.

2

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]