インターフェイスの使用に関する制限

現在の GPU ハードウェアでは、シェーダー実行時のスロット情報の変動はサポートされていません。そのため、if ステートメントや switch ステートメントなどの条件式の中でインターフェイスの参照を変更することはできません。

次のシェーダー コードの例は、この制限が発生する状況と使用可能な代替アプローチを示しています。

インターフェイスが次のように宣言されているとします。

 interface A {     float GetRatio();     bool IsGood(); };  interface B {     float GetValue(); };  A arrayA[6]; B arrayB[6]; 

クラスが次のように宣言されているとします。

 class C1 : A {     float var;     float GetRatio() { return 1.0f; }     bool IsGood() { return true; } };  class C2 : C1, B {     float GetRatio() { return C1::GetRatio() * 0.33f; }     float GetValue() { return 5.0f; }     bool IsGood() { return false; } };  class C3 : B {     float var;     float GetValue() { return -1.0f; } };  class C4 : A, B {     float var;     float GetRatio() { return var; }     float GetValue() { return var * 2.0f; }     bool IsGood() { return var > 0.0f; } }; 

条件式 (if ステートメント) の中でインターフェイスの参照を変更することはできません。

 float main() : wicked {     float rev;     {         A a = arrayA[0];         for( uint i = 0; i < 6; ++i )         {             if( arrayA[i].IsGood() )             {                 // This forces the loop to be unrolled,                  // since the slot information is changing.                 a = arrayA[i];                  rev -= arrayA[i-2].GetRatio();             }             else             {                 // This causes an error since the compiler is                 // unable to determine the interface slot                 rev += arrayB[i].GetValue() + a.GetRatio();              }         }     }     return rev; } 

インターフェイス宣言とクラス宣言を変更せずに、インデックスを使用することによって、同じ機能を実現しながら、強制的なループの展開を回避できます。

 float main() : wicked {     float rev;     {         uint index = 0;         for( uint i = 0; i < 6; ++i )         {             if( arrayA[i].IsGood() )             {                 index = i;                 rev -= arrayA[i-2].GetRatio();             }             else             {                 rev += arrayB[i].GetValue() + arrayA[index].GetRatio();             }         }     }     return rev; } 

関連項目

動的リンク