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++ 假设如果你调用一个函数,那么这个函数可能会产生各种副作用,包括更改 bind.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;
}

无法side_effect以允许的方式访问k,因为您无法访问另一个翻译单元中的静态数据。因此,代码可以优化为side_effect(); return 0因为 k 不会改变,只要 side_effect() 不在内存中四处寻找。这当然是未定义的行为。

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: Making k const does not help, because it is legal to cast a const away. const-ness can not be used as a optimization hint.

于 2010-08-04T14:22:10.613 回答
2

这将取决于编译器,您最好的选择是测试 - 编译和检查发出的机器代码。

于 2010-08-04T14:18:23.887 回答
2

没有任何级别的优化可以(正确地)删除这些测试。只有当两个参数都是编译时常量且它们都不是,或者编译器可以证明它们不会在测试之间改变值时,它们才能被删除。

由于binded是静态的,编译器无法知道对 GL 函数的调用不会改变它。

于 2010-08-04T14:19:34.067 回答