OpenGL 4.4 で memoryBarrier() がどのように機能するかを把握しようとしています。テクスチャ イメージで 1 回、Shader Storage Buffer Object (SSBO) で 1 回、次のことを試しました。基本的な考え方は、シーンでレンダリングする必要がある多くのオブジェクトに対してフラグの配列を作成し、ジオメトリ シェーダーで簡単なテストを実行することです。
GS の各プリミティブについて、少なくとも 1 つの頂点がテストに合格すると、このプリミティブのオブジェクト ID で指定された位置に配列内の対応するフラグが設定されます (オブジェクト ID は頂点属性として 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) に変更すると、すべてのオブジェクトがレンダリングされるように見えます。これは、これらの ID がシェーダーによって読み戻されるまでに -1 が書き込まれないことを意味します。memoryBarrier() にもかかわらず、すべてのシェーダー呼び出しに対して書き込みが首尾一貫して表示されない理由と、これを機能させるための最も効率的な回避策は何かを説明してもらえますか?
ありがとう。