3

GeForce 8600 GTのユニフォームブロック(すべてがGLSL「#version330」に準拠)を介して、intの配列をフラグメントシェーダーに渡そうとしています。

私が持っているアプリの側に:

int MyArray[7102];
…
//filling, binding, etc
…
glBufferData(GL_UNIFORM_BUFFER, sizeof(MyArray), MyArray, GL_DYNAMIC_DRAW);

私のフラグメントシェーダーでは、次のようにブロックに従って宣言します。

layout (std140) uniform myblock
{
int myarray[7102];
};

問題は、glCompileShaderが成功した後、glLinkProgramが適切なストレージリソースをバインドできないことを示すエラーを返すことです。

いくつかの追加の事実:

1)GL_MAX_UNIFORM_BLOCK_SIZEの戻り値65536

2)要素の数を4096に減らすと、正常に機能し、配列タイプとして「int」と「ivec4」のどちらを使用しても違いはありません。4096を超えると、同じ「ストレージエラー」が発生します</ p>

3)「共有」または「パック」を使用すると、すべてが疑わしいとおりに機能します

std140のGLSL3.3仕様を参照した後、次のように位置合わせ/パディングに問題があると想定しています。

「1)メンバーがN個の基本マシンユニットを消費するスカラーである場合、ベースアライメントはNです。

..。

4)メンバーがスカラーまたはベクトルの配列である場合、ベースアラインメントとアレイストライドは、ルール(1)、(2)、および(3)に従って、単一の配列要素のベースアラインメントと一致するように設定され、丸められます。 vec4のベースアライメントまで。配列の最後にパディングがある場合があります。配列に続くメンバーのベースオフセットは、ベースアライメントの次の倍数に切り上げられます。」</ p>

私の質問:

1)「myblock」が7102 * 4 = 28408バイトの4倍を占めるというのは本当ですか?つまり、std140はmyarrayの各メンバーをvec4に拡張し、実際のメモリ使用量は7102 * 4 * 4 = 113632バイトであり、これが問題の原因ですか?

2)「共有」または「パック」で機能する理由は、最適化によってこれらのギャップが解消されるためですか?

3)多分それはドライバーのバグですか?すべての事実は、「…そしてvec4のベースアラインメントに切り上げられた」ことが理由であることを示していますが、intの配列のような単純なものがメモリ制約の点で4分の1の効果を失うことを受け入れるのは非常に困難です。

4)バグではない場合、std140の場合、どのように配列を整理してアクセスする必要がありますか?最適なデータ分散のために「ivec4」を使用できますが、単純なx = myarray [i]の代わりに、x = myarray [i / 4] [i%4]のような方法でパフォーマンスを犠牲にして、各ivec4の個々の要素を参照する必要があります。 ?または私は何かが欠けていて、明らかな解決策がありますか?

4

1 に答える 1

4

1) (…) vec4 のベースアライメントに切り上げ? (…)

はい。

2) 「共有」または「パック」で機能する理由は、最適化によってこれらのギャップが解消されるためですか?

はい; これは最適化のパフォーマンスではありません。

3) 多分それはドライバーのバグですか?

編集いいえ。GPU は、ベクトル化された型付きで自然に動作します。型をパッキングするには、ベクターを分離/多重化するための命令をさらに追加する必要があります。この回答を書いてからしばらくの間、GPU アーキテクチャに大きな変更が加えられました。最近作成された GPU はすべて、強力なスーパースカラー ベクトル化に重点を置いた設計を備えた単一スカラー アーキテクチャです。

4) バグでない場合、std140 の場合、配列を整理してアクセスするにはどうすればよいですか?

このような大きなデータには均一バッファ オブジェクトを使用しないでください。データを 1D テクスチャに入れ、texelFetchそれをインデックス化するために使用します。

于 2012-05-28T08:56:26.900 に答える