让我们考虑以下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.比2快吗? 或者由于明显的编译器优化它们是否相同?
3怎么样?当然这没有意义,但为了清晰我的着色器代码,可能会发生这种冗余纹理查找。我想知道它们是否以某种方式进行了优化/缓存,或者是否应该避免使用它们。
答案 0 :(得分:4)
规范中没有提到GLSL编译器应该进行任何优化。这意味着更好的方法是避免过早的悲观情绪。这段代码
uniform sampler2D t;
void main() {
vec4 val = texture2D(t, coords);
是最好的。没有理由创建浮点变量,因为您始终可以通过val.x
等直接访问矢量组件。
答案 1 :(得分:1)
当然,和其他人一样,它完全取决于实施。但是,虽然编译器可能能够优化那些明显的情况,但实际的“真实世界”问题的情况可能完全不同。
我试图让代码更具可读性和可维护性 重组源,但它可能会导致一些冗余的纹理 查找。提供的示例是最简单的(和合成的)可能的 问题表达的方式。他们没有表达我的真实 的解决方案。
这听起来像你的实际代码与你提供的例子并不完全匹配,因为与简单的vec4 val = texture2D(t, coords);
相比,它们中的三个都是完全荒谬的(是的,即使是第二个,就像已经由 Sergey解释的那样)并且不添加任何可读性或可维护性。
所以我想你的实际的“真实世界”代码你可以用更复杂的方式分离那些纹理调用,可能分成不同的函数,或者分成条件分支,或者只是将它们分开来很多其他指示。如果编译器可以优化这个实际代码是一个完全不同的问题,需要回答这个特定的代码。
所以最后你唯一可以确定的是,示例2永远不会比示例1和3慢。而另一方面,你的3个例子的优化行为并没有告诉你什么实际上,因为那肯定不是你真正的“真实世界”代码,优化器分析这些代码可能会更加复杂。 (如果它确实是您的“真实世界”代码,那么“real”的定义 > “真实”的真实定义和谢尔盖的答案是唯一正确的答案。)