3

私は OpenGL テクスチャのハンドラーを書いており、安全性とパフォーマンスについて考えています。マークされた if ステートメントを削除する最適化レベルはどれですか?


struct Texture2D {
    GLuint ID;

    inline Texture2D(): ID(0) {};
    inline explicit Texture2D(GLuint id): ID(id) {};
    ~Texture2D();

    void GenTexture(bool regen = false);
    void DeleteTexture();

    void BindTexture();

    void Parameterf( GLenum pname, GLfloat param );
    void Parameteri( GLenum pname, GLint param );
    void glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params );
    void glTexParameteriv( GLenum target, GLenum pname, const GLint *params );

    static Texture2D binded;
};
inline void Texture2D::GenTexture(bool regen) {
    if(ID){
        if(regen)
            DeleteTexture();
        else
            return;
    }

    glGenTextures(1,&ID);
}

inline void Texture2D::DeleteTexture() {
    glDeleteTextures(1,&ID);
    ID = 0;
}

inline void Texture2D::BindTexture() {
    glBindTexture(GL_TEXTURE_2D, ID);
    binded.ID = ID;
}

inline void Texture2D::Parameterf( GLenum pname, GLfloat param ){
    if(binded.ID == ID)                          // THIS
        BindTexture();                           // THIS

    glTexParameterf(GL_TEXTURE_2D,pname,param);
}

inline void Texture2D::Parameteri( GLenum pname, GLint param ){
    if(binded.ID == ID)                          // THIS
        BindTexture();                           // THIS

    glTexParameterf(GL_TEXTURE_2D,pname,param);
}

inline Texture2D::~Texture2D() {
    DeleteTexture();
}

// in this function
void loadTexture(...) {
    Texture2D t;
    t.GenTexture();
    t.BindTexture();
    // if statements in next functions
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
}
4

3 に答える 3

4

なし。

悲しい話ですが、C++ は、関数を呼び出すと、この関数が binded.ID の値を変更するなど、あらゆる種類の副作用を生成する可能性があると想定しています (関数は何らかの方法で実行することを知っています)。

を除外する

呼び出す関数がbindend.ID、直接 (参照することによって) または間接的に (他の誰かがそのポインターを取得して渡したため) について知る合法的な方法がまったくないことを確認した場合。これは簡単な例です(side_effect()別の翻訳単位にあると仮定します)

int side_effect();
int k=1; 

int main()
{
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}

side_effect()k外部として宣言することにより、合法的に使用および変更できます。の呼び出しをside_effect最適化して取り除くことはできません。

int side_effect();
static int k=1; 

int main()
{
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}

別の翻訳単位の statics にアクセスできないため、許可された方法でside_effectアクセスすることはできません。したがって、 side_effect() がメモリ内を動き回らない限り、k は変更されないkため、コードを最適化できます。side_effect(); return 0もちろん、これは未定義の動作です。

int side_effect();
void snitch(int*);

static int k=1; 

int main()
{
    snitch(&k); // !!!
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}

snitch()がその引数を変更可能な場所に保存するかどうかをコンパイラが知る方法がないside_effect()ため、 への呼び出しをside_effect()削除することはできません。

ローカル変数として持っている場合、同じ状況になりkます。未知のルーチンが正当な方法でアクセスできる可能性がある場合k、コンパイラは k の値に基づいて最適化を行うことができません。

PS: constkをキャストすることは合法であるため、const を作成しても役に立ちません。const-ness を最適化のヒントとして使用することはできません。

于 2010-08-04T14:22:10.613 に答える
2

これらのテストを (正しく) 削除できる最適化レベルはありません。両方の引数がコンパイル時の定数であり、どちらもそうでない場合、またはコンパイラがテスト間で値を変更しないことを証明できる場合にのみ、それらを削除できます。

は静的であるためbinded、コンパイラは GL 関数の呼び出しによって変更されないことを認識できません。

于 2010-08-04T14:19:34.067 に答える
2

これはコンパイラに依存し、あなたの最善の策はテストすることです - 発行されたマシンコードをコンパイルして検査します。

于 2010-08-04T14:18:23.887 に答える