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.xベクトルのコンポーネントには常にetcを介して直接アクセスできるため、float 変数を作成する理由はありません。

于 2012-11-11T20:17:10.547 に答える
1

もちろん、他の人が言ったように、それは完全に実装に依存します。ただし、コンパイラはこれらの明白なケースを最適化できる場合がありますが、実際の「現実の」問題では状況がまったく異なる場合があります。

ソースを再編成して、コードを読みやすく保守しやすくしようとしましたが、冗長なテクスチャ ルックアップが発生する可能性がありました。提供された例は、問題を提示するための最も単純な (そして総合的な) 可能な方法でした。彼らは私の本当の解決策を提示していません。

これは、実際のコードが提示された例と実際には一致していないように思えます.3つすべてが単純なものと比較して完全にばかげているためですvec4 val = texture2D(t, coords);(はい、すでにSergeyで説明されているように2番目でも)、読みやすさや保守性を追加していません。

したがって、実際の「現実世界」のコードでは、これらのテクスチャリング呼び出しをはるかに複雑な方法で、おそらく別の関数や条件分岐に分離するか、他の多くの命令で分離するだけだと思います。そして、コンパイラがこの実際のコードを最適化できるかどうかは、この特定のコードについて答える必要があるまったく別の問題です。

したがって、最終的に確実にできる唯一のことは、例 2 が例 1 および 3 よりも遅くなることは決してないということです。一方、3 つの例の最適化動作は実際には何も教えてくれません。これは、実際の「現実世界」のコードではなく、オプティマイザによる分析が任意に複雑になる可能性があります。(そして、それが実際にあなたの「実世界」コードである場合、「実」の定義は「実」実際の定義と実際には一致せず、セルゲイの答えが唯一の正しいものです)。

于 2012-11-16T14:36:59.280 に答える