GLSL编译器优化跨功能的冗余分配

时间:2012-06-04 11:48:06

标签: optimization compiler-construction glsl webgl

我已经读过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();
}

1 个答案:

答案 0 :(得分: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的一个编译器)下编译了相同的程序,有或没有注释掉第二个函数调用,在这两种情况下它产生了以下内容:

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编译器做到了。 I found claims Cg编译的代码在英特尔GPU上运行,但这超出了我的专业知识范围,所以请把它当作它的用途。

如果有人想为此添加测试用例,请随意,但此时我觉得这个问题已经得到了适当的回答。