2016-12-22 74 views
1

我在寫一個OpenGL C++包裝器。該包裝旨在減少複雜且易於使用的情況。如何讓C++編譯器知道一個函數是`Idempotent`

例如,我目前希望用戶只需要注意一點OpenGL Context。爲此,我寫了一個類gl_texture_2d。正如我們大家都知道,一個OpenGL texture主要有以下操作:

  1. 設置它的U/V參數爲repeat/mirror
  2. 設置它的min/magfilter作爲linear
  3. .. 。

在此基礎上,我們有:

class gl_texture_2d 
{ 
public: 
    void mirror_u(); // set u parameter as mirror model 
    void mirror_v(); // set v parameter as mirror model 
    void linear_min_filter(); // ... 
    void linear_mag_filter(); // ... 
}; 

那麼,我們知道,只有當the handle of OpenGL texture object目前綁定到OpenGL context,我們才能執行這些操作。 假設我們有一個函數做到這一點: void bind(GLuint htex); //實際上相關GL功能的別名

好了,現在我們可以設計我們的gl_texture_2d用法:

gl_texture_2d tex; 
bind(tex.handle()); 
tex.mirror_u(); 
tex.linear_min_filter(); 
unbind(tex.handle()); 

它證實了GL的邏輯,但它失去了包裝的顯著,對不對?作爲一個用戶,我希望像操作:

gl_texture_2d tex; 
tex.mirror_u(); 
tex.linear_min_filter(); 

爲了實現這一目標,我們必須都實現的功能:

void gl_texture_2d::mirror_u() 
{ 
    glBindTexture(GL_TEXTURE_2D, handle()); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 
    glBindTexture(GL_TEXTURE_2D, 0); 
} 

總是在做綁定操作內部可確保操作是有效的。但成本很高!

的代碼:

tex.mirror_u(); 
tex.mirror_v(); 

將擴大到一對無意義的綁定/解除綁定操作。

那麼,有沒有機制,使編譯器可以知道:

  1. 如果bind(b)緊跟bind(a),該bind(a)可以被刪除;
  2. 如果bind(a)在塊中出現兩次,則最後一次不起作用。

回答

0

您無法在編譯級別執行此操作。相反,如果你真的擔心這類錯誤的時間成本,管理者對象可能是要走的路:

class state_manager { 
    GLuint current_texture; 
    /*Maybe other stuff?*/ 
public: 
    void bind_texture(gl_texture_2d const& tex) { 
     if(tex.handle() != current_texture) { 
      current_texture = tex.handle(); 
      glBindTexture(/*...*/, current_texture); 
     } 
    } 
}; 

int main() { 
    state_manager manager; 
    /*...*/ 
    gl_texture_2d tex; 
    manager.bind(tex); 
    manager.bind(tex); //Won't execute the bind twice in a row! 
    /*Do Stuff with tex bound*/ 

} 
1

如果你使用pre-DSA OpenGL工作,你絕對必須包裝OpenGL調用這直接與你自己的API,那麼用戶可能將不得不知道整個綁定到編輯的事情。畢竟,如果他們爲了渲染目的而綁定了紋理,那麼他們會嘗試修改它,這可能會損壞當前的綁定。

因此,您應該直接在API中構建綁定到編輯的概念。因爲你不能修改OpenGL紋理而沒有綁定它(或沒有DSA),所以紋理對象(它不應該是而不是僅限於2D紋理)實際上不應該具有修改它的函數。 ,你真的應該學習)。它不應該有mirror_u等等;這些功能應該是一個粘合劑對象的一部分:

bound_texture bind(some_texture, tex_unit); 
bind.mirror_u(); 
... 

bound_texture構造結合some_texturetex_unit。其成員函數將修改該紋理(注意:他們需要調用glActiveTexture以確保沒有人更改活動紋理單元)。

bound_texture的析構函數應該自動解除紋理綁定。但是您應該有一個release成員函數,可以手動取消綁定它。

相關問題