概要
自分向けのメモです。メモなのでたぶんどこか間違ってます。
以下のルールを守らないと
(nvoglv64.dll) で例外がスローされました
のエラーが発生したり、バッファがおかしくなったりする
ルール
- ComputeBufferに渡せるデータは、intやfloatといった一般的な型とその構造体のみ。当たり前だがスマートポインタとか自分のクラスをそのまま渡そうとするとエラーになる
- glm::vec3 val--> float val[3] のように複数型は配列にする
- OpenGL ComputeBuffer (std430/std140)のvec3は16バイトごとにオフセットする(vec4も16バイト)
- かなりの沼ポイント
- そのことを知らずにvec3としてfloat[3]を使用していると段々バッファのオフセットがずれていってGPGPUの挙動がおかしくなる
- 例えば中心の方に動かないオブジェクトがあったら、vec3を4バイトオフセットとして使用していて最後の方のデータが足りずに0になっている
- ベクトルを渡すときはvec4を使った方が安全
- (当たり前だが)Compute ShaderのDispatchの前にshader programをバインドしないといけない
- バッファをCompute Shaderや通常のShaderにアタッチするとき、glBindBufferBase(OpenGL)やSSBOのbinding(GLSL)にインデックスを指定するが、このインデックスは『各バッファーごとに一つ割り当てて全体で共通(重複なし)なもの』にしなければならない。
- 例えば、あるCompute ShaderにバッファをglBindBufferBaseで3を指定してアタッチした場合、そのShaderのbindingも3で他のShaderでそのバッファを使う場合も3を指定する
- メモリのパディングに要注意
- セルフでパディング入れないとバグるよ
- デバイスごとのグループ数やスレッド数の最大値に注意
-
下記の関数で取れる
- GL_MAX_COMPUTE_WORK_GROUP_COUNT: 最大スレッド数
- GL_MAX_COMPUTE_WORK_GROUP_COUNT: たぶんローカルサイズに指定できる値の最大値(?)でも下記の値を超えてはいけない
- GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: ローカルサイズの x, y, zの積の最大値
-
int MaxGroupNum[3];
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &MaxGroupNum[0]);
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &MaxGroupNum[1]);
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &MaxGroupNum[2]);
int MaxThreadsSize[3];
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &MaxThreadsSize[0]);
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &MaxThreadsSize[1]);
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &MaxThreadsSize[2]);
int MaxThreadsNum;
glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &MaxThreadsNum);
[DEBUG] MaxGroupNum=> x: 2147483647, y: 65535, z: 65535
[DEBUG] MaxThreadsSize=> x: 1024, y: 1024, z: 64
[DEBUG] MaxThreadsNum: 1024
(MaxGroupNumのxってこんなに大きいの?なんか指定間違ってそう)
MaxThreadsNumが1024なので立方体で計算したいなら 8 * 8 * 8 = 512 にするしかない
参考
https://qiita.com/hoboaki/items/b188c4495f4708c19002
https://qiita.com/RT-EGG/items/74b2e68a9bfd4bdfa3ab
https://logicalbeat.jp/blog/4032/
https://www.khronos.org/opengl/wiki/Compute_Shader
https://antongerdelan.net/opengl/compute.html