Я пытаюсь понять, как работает memoryBarrier () в OpenGL 4.4.
Я попробовал следующее один раз с изображением текстуры и один раз с Shader Storage Buffer Object (SSBO).
Основная идея состоит в том, чтобы создать массив флагов для сколь угодно большого количества объектов, которые необходимо визуализировать в моей сцене, а затем выполнить простой тест в геометрическом шейдере.
Для каждого примитива в GS, если хотя бы одна вершина проходит тест, она
устанавливает соответствующий флаг в массиве в указанном месте
по идентификатору объекта этого примитива (идентификаторы объекта передаются в GS как вершина
атрибуты).
Затем я выполняю memoryBarrier (), чтобы убедиться, что все потоки записали свои значения.
Вот некоторый код из моих шейдеров, чтобы объяснить:
// 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 (), и что было бы наиболее эффективным способом обойти это?
Благодарю.
Задача ещё не решена.