【问题标题】:GLSL compiler optimization of redundant assignments across functionsGLSL 编译器优化跨函数的冗余分配
【发布时间】:2019-11-22 21:23:54
【问题描述】:

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

【问题讨论】:

  • 这个问题无法回答。编译器优化是特定于编译器的,因此它们会随着新的驱动程序、新的硬件以及不同的硬件而改变。没有实际的答案。实际上,即使是第一种情况也是特定于硬件的,并且不受标准保证
  • 谢谢,但我的意思是一般意义上的问题。很明显,每次编译都会根据自己的算法进行不同的优化(如果有的话)。

标签: optimization compiler-construction glsl webgl


【解决方案1】:

我从 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 编译器可以。我found claims 表示 Cg 编译的代码在英特尔 GPU 上运行,但这超出了我的专业范围,所以就这样吧。

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

【讨论】:

  • -1: "是的:在一般情况下,GLSL 编译器将足够聪明地执行此优化" 这是怎么回事?您已经为精确的一个编译器 演示了它。英伟达会做吗?英特尔呢?这个答案一点都不笼统。
  • Nicol:我添加了使用 NVIDIA 的 Cg 编译器编译的结果,它执行了相同的优化。这就是我要为此付出的所有努力。如果您仍然觉得它需要更多审查,请随时添加其他测试。
猜你喜欢
  • 2020-03-14
  • 1970-01-01
  • 2014-04-18
  • 2013-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多