2

GLSL (具体的には v1.0.17: 私のアプリケーションは WebGL で実行されています) コンパイラは次のような冗長な割り当てを最適化することを読みました:

gl_FragCoord = ProjectionMatrix * ModelViewMatrix * VertexPosition;
. . .
gl_FragCoord = ProjectionMatrix * ModelViewMatrix * VertexPosition;

コンパイラは、関数呼び出し全体で同じ最適化を実行するのに十分スマートですか? 例えば:

void doSomething1(void) {
  . . .
  gl_FragCoord = ProjectionMatrix * ModelViewMatrix * VertexPosition;
}

void doSomething2(void) {
  . . .
  gl_FragCoord = ProjectionMatrix * ModelViewMatrix * VertexPosition;
}

void main(void) {
  doSomething1();
  doSomething2();
}
4

1 に答える 1

5

AMD からGPU ShaderAnalyzerをダウンロードし、次の GLSL プログラムをフィードしました。

uniform mat4 ModelViewMatrix;
attribute vec4 VertexPosition;

void doSomething1(void) {
  gl_Position = ModelViewMatrix * VertexPosition;
}

void doSomething2(void) {
  gl_Position = ModelViewMatrix * VertexPosition;
}

void main(void) {
  doSomething1();
  doSomething2();
}

これにより、Radeon HD 2400 から Radeon HD 6970 までのすべてのカードで次の分解 (または同等のもの) が生成されました。

; --------  Disassembly --------------------
00 CALL_FS NO_BARRIER 
01 ALU: ADDR(32) CNT(16) KCACHE0(CB0:0-15) 
      0  x: MUL         ____,  R1.w,  KC0[3].w      
         y: MUL         ____,  R1.w,  KC0[3].z      
         z: MUL         ____,  R1.w,  KC0[3].y      
         w: MUL         ____,  R1.w,  KC0[3].x      
      1  x: MULADD      R127.x,  R1.z,  KC0[2].w,  PV0.x      
         y: MULADD      R127.y,  R1.z,  KC0[2].z,  PV0.y      
         z: MULADD      R127.z,  R1.z,  KC0[2].y,  PV0.z      
         w: MULADD      R127.w,  R1.z,  KC0[2].x,  PV0.w      
      2  x: MULADD      R127.x,  R1.y,  KC0[1].w,  PV1.x      
         y: MULADD      R127.y,  R1.y,  KC0[1].z,  PV1.y      
         z: MULADD      R127.z,  R1.y,  KC0[1].y,  PV1.z      
         w: MULADD      R127.w,  R1.y,  KC0[1].x,  PV1.w      
      3  x: MULADD      R1.x,  R1.x,  KC0[0].x,  PV2.w      
         y: MULADD      R1.y,  R1.x,  KC0[0].y,  PV2.z      
         z: MULADD      R1.z,  R1.x,  KC0[0].z,  PV2.y      
         w: MULADD      R1.w,  R1.x,  KC0[0].w,  PV2.x      
02 EXP_DONE: POS0, R1
03 EXP_DONE: PARAM0, R0.____
04 ALU: ADDR(48) CNT(1) 
      4  x: NOP         ____      
05 NOP NO_BARRIER 
END_OF_PROGRAM

doSomething2()次に、メソッド内の関数とその呼び出しをコメントアウトしましたmain。結果はまったく同じでした。AMD のツールのすべてのシェーダーが冗長な計算を最適化しました。したがって、この質問に対する答えは「はい」です。一般的なケースでは、GLSL コンパイラはこの最適化を実行するのに十分なほどスマートですが、@nicol-bolas がコメントで指摘した注意事項があります。これがすべてのコンパイラに当てはまるという 100% の保証はありません。もちろん、最も安全な方法は、可能な限りそのような最適化を自分で実行することですが、何らかの理由で最適化を実行できない場合は、これが当てはまります。

更新: Cg (NVIDIA のコンパイラの 1 つ) の下で、2 番目の関数呼び出しをコメント アウトして、またはコメント アウトせずに、同じプログラムをコンパイルしました。どちらの場合も、次の結果が生成されました。

mul r0, v0.y, c1
mad r0, v0.x, c0, r0
mad r0, v0.z, c2, r0
mad oPos, v0.w, c3, r0

そうです、NVIDIA もそれを最適化します。少なくとも、Cg コンパイラは最適化します。Cg でコンパイルされたコードが Intel GPU で実行されるという主張を見つけましたが、これは私の専門知識の範囲外です。

誰かがこれにテスト ケースを追加したい場合は、お気軽にどうぞ。ただし、この時点で、質問に対する適切な回答が得られたと感じています。

于 2012-06-11T21:17:48.527 に答える