6

OpenGL仕様は嘘です(またはこれはバグですか?)... std140のレイアウトを参照して、共有ユニフォームバッファを使用すると、次のように述べられています。

「表 e L-1 に示されている一連のルールは、GLSL コンパイラによって std140 修飾された均一なブロックにメンバーをレイアウトするために使用されます。ブロック内のメンバーのオフセットは、ブロック内の前のメンバーのサイズに基づいて累積されます (問題の変数の前に宣言されたもの)、および開始オフセット最初のメンバーの開始オフセットは常にゼロです。

スカラー変数の型 (bool、int、uint、float) - 基本的なマシン タイプのスカラーのサイズ"

( http://www.opengl-redbook.com/appendices/AppL.pdf )

したがって、この情報を利用して、シェーダーに次のような均一なブロックをセットアップします。

// Spotlight.

layout (std140) uniform Spotlight
{
    float Light_Intensity;
    vec4  Light_Ambient;
    vec3  Light_Position;   
};

... CPU側でセットアップした後続のstd140レイアウトでは機能しないことを発見するだけです。つまり、最初の 4 バイトは float (GLfloat のマシン スカラー型のサイズ) であり、次の 16 バイトは vec4 であり、次の 12 バイトは vec3 です (ルールを考慮して最後に 4 バイトが残ります)。 vec3 が実際には vec4 であること)。

CPU 側を変更して float を vec4 と同じサイズ (つまり 16 バイト) に指定し、オフセットとバッファー サイズをこの仮定で行うと、シェーダーは意図したとおりに動作します。

したがって、仕様が間違っているか、このコンテキストでの「スカラー」の意味を誤解しているか、ATI にドライバーのバグがあるかのいずれかです。誰かこの謎に光を当てることができますか?

4

1 に答える 1

13

リンク先の PDFはOpenGL 仕様ではありません。どこから入手したかはわかりませんが、これがルールの完全なリストではないことは確かです。常にソースを確認してください。仕様は、多くの人が主張するほど読みにくいものではありません。

はい、基本タイプの変数のサイズは、基本マシン タイプと同じサイズです (つまり、4 バイト)。ただし、サイズだけでは変数の位置は決まりません。

各型には基本アラインメントがあり、その型が均一ブロック内のどこにあるかに関係なく、全体的なバイト オフセットがそのアラインメントに適合する必要があります。a のベース アラインメントは、vec4その基本型 (つまり、float) のアラインメントの 4 倍です。したがって、a のベース アラインメントvec4は 16 です。

4 バイト後に終了するためLight_Intensity、コンパイラは 12 バイトのパディングを挿入する必要がありLight_Ambient ます。これは 16 バイト境界にある必要があるため、コンパイラは 12 バイトの空きスペースを使用します。

ATI には、std140 レイアウトに関するドライバーのバグがいくつかありますが、これはその 1 つではありません。

原則として、構造体にパディングを明示的に配置するのが好きで、避けvec3ています (16 バイトのアラインメントがあるため)。これらを行うことで、通常、コンパイラのバグが減り、物事がどこに行き、実際にどれだけのスペースが必要かについての偶発的な誤解が減ります。

于 2011-09-17T01:34:57.753 に答える