6

新しいコンピューティング シェーダーに関する質問がありました。私は現在、粒子システムに取り組んでいます。すべてのパーティクルをシェーダー ストレージ バッファーに格納して、計算シェーダーでそれらにアクセスします。それから私は一次元のワークグループを派遣します。

#define WORK_GROUP_SIZE 128
_shaderManager->useProgram("computeProg");
glDispatchCompute((_numParticles/WORK_GROUP_SIZE), 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

私の計算シェーダー:

#version 430
struct particle{
         vec4 currentPos;
         vec4 oldPos;
};

layout(std430, binding=0) buffer particles{
         struct particle p[];
};

layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
void main(){
         uint gid = gl_GlobalInvocationID.x;

         p[gid].currentPos.x += 100;
}

しかし、どういうわけか、すべての粒子が影響を受けるわけではありません。この例と同じ方法で実行していますが、うまくいきません。http://education.siggraph.org/media/conference/S2012_Materials/ComputeShader_6pp.pdf

編集:

glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT) を呼び出した後、次のように続けます。

_shaderManager->useProgram("shaderProg"); 
glBindBuffer(GL_ARRAY_BUFFER, shaderStorageBufferID); 
glVertexPointer(4,GL_FLOAT,sizeof(glm::vec4), (void*)0);
glEnableClientState(GL_VERTEX_ARRAY); 
glDrawArrays(GL_POINTS, 0, _numParticles); 
glDisableClientState(GL_VERTEX_ARRAY);

この場合、どのビットを使用するのが適切でしょうか?

4

2 に答える 2

8

あなたは後方にあなたの障壁を持っています。これはよくある問題です。

バリアに与えるビットは、データがどのように書き込まれたかではなく、書き込まれたデータをどのように使用するかを記述します。GL_SHADER_STORAGE_BARRIER_BITイメージのロード/ストア (またはストレージ バッファー/アトミック カウンター) を介してバッファー オブジェクトに書き込み、ストレージ バッファーを使用してそのバッファー オブジェクト データを読み取るプロセスがある場合にのみ適切です。

バッファーを頂点属性配列バッファーとして読み取っているため、巧妙にタイトルが付けられたGL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT.

于 2012-10-05T08:56:21.763 に答える
2

問題を解決しました。問題は、私が派遣したワークグループの数だけでした。両方の変数が整数であるため、numParticles/WORK_GROUP_SIZEは四捨五入されます。そのため、パーティクルの数が異なるディスパッチされたワークグループが少なすぎました。

1000個のパーティクルを取得すると、1000/128=7個のワークグループのみがディスパッチされます。すべてのワークグループのサイズは128です。つまり、7 * 128 = 896スレッドになるため、104個のパーティクルはまったく移動しません。numParticles%128の範囲は0 ... 128である可能性があるため、もう1つのワークグループをディスパッチしました。

glDispatchCompute((_numParticles/WORK_GROUP_SIZE)+1, 1, 1);

そして、すべての粒子はこれから動きます。:)

于 2012-10-05T18:57:41.090 に答える