1

让我们考虑以下 GLSL 示例:

1.

uniform sampler2D t;
...
void main() {
   float val_r = texture2D(t, coords).r;
   float val_g = texture2D(t, coords).g;
   float val_b = texture2D(t, coords).b;
   float val_a = texture2D(t, coords).a; 

2.

uniform sampler2D t;
...
void main() {
   vec4 data = texture2D(t, coords);
   float val_r = data.r;
   float val_g = data.g;
   float val_b = data.b;
   float val_a = data.a; 

3.

uniform sampler2D t;
...
void main() {
   vec4 data1 = texture2D(t, coords);
   vec4 data2 = texture2D(t, coords);
   vec4 data3 = texture2D(t, coords);
   vec4 data4 = texture2D(t, coords);
   float val_r = data1.r;
   float val_g = data2.g;
   float val_b = data3.b;
   float val_a = data4.a; 

2. 比 1. 快吗?或者由于明显的编译器优化,它们是否相等?

3.呢?当然这没有任何意义,但是为了我的着色器代码的清晰,可能会出现这种冗余的纹理查找。我想知道它们是否以某种方式优化/缓存,或者我是否应该避免它们。

4

2 回答 2

3

规范中没有提到 GLSL 编译器应该进行任何优化。这意味着更好的方法是避免过早悲观。这段代码

uniform sampler2D t;

void main() {
   vec4 val = texture2D(t, coords);

是最好的。没有理由创建浮点变量,因为您始终可以通过val.xetc直接访问向量的组件。

于 2012-11-11T20:17:10.547 回答
1

当然,正如其他人所说,这完全取决于实施。但是,尽管编译器可能能够优化那些明显的情况,但对于您实际的“现实世界”问题,情况可能完全不同。

我试图通过重新组织源代码来使代码更具可读性和可维护性,但这可能会导致一些冗余的纹理查找。提供的示例是问题呈现的最简单(和综合)可能的方式。他们没有提出我真正的解决方案。

这听起来像您的实际代码与您提供的示例并不真正匹配,因为与简单的示例(是的,甚至是第二个,就像Sergeyvec4 val = texture2D(t, coords);已经解释过的那样)相比,它们三个都完全荒谬,并且没有增加任何可读性或可维护性。

所以我猜在你实际的“真实世界”代码中,你以更复杂的方式分离出这些纹理调用,可能是不同的函数,或者是条件分支,或者只是通过大量其他指令将它们分开。如果编译器可以优化这个实际代码是一个完全不同的问题,需要为这个特定代码回答。

所以最后你唯一可以肯定的是,例子2永远不会比例子1和3慢。另一方面,你的3个例子的优化行为实际上并没有告诉你任何事情,因为那肯定不是您实际的“真实世界”代码,优化器分析起来可能会更加复杂。(如果它确实是您的“真实世界”代码,那么您对“真实”的定义与“真实”真实定义并不真正匹配,而Sergey的答案是唯一正确的)。

于 2012-11-16T14:36:59.280 回答