2014-01-07 26 views
4

我的計劃是創建一個加載線程,其中我加載了一個遊戲資源;如3D模型,着色器,紋理等。在主線程中,我執行所有的遊戲邏輯和渲染。然後,在我的加載線程上,我創建了一個僅用於加載的sf :: Context(SFML共享OpenGL上下文)。使用第二個共享的OpenGL上下文加載線程

這是加載着色器的工作。但是,嘗試加載模型時,xserver有時會崩潰。我已經將崩潰縮小到了glBufferData()調用。我檢查了我發送的數據沒有問題。

是否可以使用第二個OpenGL上下文從第二個線程調用glBufferData()?如果不是,爲什麼可以在第二個上下文中加載着色器?如果可能的話,會出現什麼問題?

#include <iostream> 
#include <thread> 

#include <GL/glew.h> 
#include <SFML/OpenGL.hpp> 
#include <SFML/Graphics.hpp> 
#include <X11/Xlib.h> 

class ResourceLoader 
{ 
public: 
    void Run() 
    { 
     sf::Context loadingContext; 
     loadingContext.setActive(true); 

     // Some test data. 
     float* testData = new float[3000]; 
     for (unsigned int i = 0; i < 3000; ++i) 
     { 
      testData[i] = 0.0f; 
     } 

     // Create lots of VBOs containing our 
     // test data. 
     for (unsigned int i = 0; i < 1000; ++i) 
     { 
      // Create VBO. 
      GLuint testVBO = 0; 
      glGenBuffers(1, &testVBO); 
      std::cout << "Buffer ID: " << testVBO << std::endl; 

      // Bind VBO. 
      glBindBuffer(GL_ARRAY_BUFFER, testVBO); 

      // Crashes on this call! 
      glBufferData(
       GL_ARRAY_BUFFER, 
       sizeof(float) * 3000, 
       &testData[0], 
       GL_STATIC_DRAW 
      ); 

      // Unbind VBO. 
      glBindBuffer(GL_ARRAY_BUFFER, 0); 

      // Sleep for a bit. 
      std::this_thread::sleep_for(std::chrono::milliseconds(10)); 
     } 

     delete[] testData; 
    } 
}; 

int main() 
{ 
    XInitThreads(); 

    // Create the main window. 
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window", sf::Style::Default, sf::ContextSettings(32)); 
    window.setVerticalSyncEnabled(true); 

    // Make it the active window for OpenGL calls. 
    window.setActive(); 

    // Configure the OpenGL viewport to be the same size as the window. 
    glViewport(0, 0, window.getSize().x, window.getSize().y); 

    // Initialize GLEW. 
    glewExperimental = GL_TRUE; // OSX fix. 
    if (glewInit() != GLEW_OK) 
    { 
     window.close(); 
     exit(1); // failure 
    } 

    // Enable Z-buffer reading and writing. 
    glEnable(GL_DEPTH_TEST); 
    glDepthMask(GL_TRUE); 

    // Create the resource loader. 
    ResourceLoader loader; 

    // Run the resource loader in a separate thread. 
    std::thread loaderThread(&ResourceLoader::Run, &loader); 

    // Detach the loading thread, allowing it to run 
    // in the background. 
    loaderThread.detach(); 

    // Game loop. 
    while (window.isOpen()) 
    { 
     // Event loop. 
     sf::Event event; 
     while (window.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) 
      { 
       window.close(); 
      } 
     } 

     // Clear scren. 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

     // Switch to SFML's OpenGL state. 
     window.pushGLStates(); 
     { 
      // Perform SFML drawing here... 
      sf::RectangleShape rect(sf::Vector2f(100.0f, 100.0f)); 
      rect.setPosition(100.0f, 100.0f); 
      rect.setFillColor(sf::Color(255, 255, 255)); 
      window.draw(rect); 
     } 
     // Switch back to our game rendering OpenGL state. 
     window.popGLStates(); 

     // Perform OpenGL drawing here... 


     // Display the rendered frame. 
     window.display(); 
    } 

    return 0; 
} 
+0

在緩衝之前是否使上下文處於活動狀態?我知道這是在wGL中使用多線程OpenGL時必須要做的事情。 http://www.opengl.org/sdk/docs/man2/xhtml/glXMakeContextCurrent.xml – zero298

+0

是的,我在加載線程入口函數中創建上下文,並立即使用sf :: Context :: setActive(http ://www.sfml-dev.org/documentation/2.0/classsf_1_1Context.php#a0806f915ea81ae1f4e8135a7a3696562) – Homar

+6

頂點緩衝區對象在上下文之間共享,頂點數組對象(以及任何一般的容器對象)不是。另外,負責跟蹤哪個頂點緩衝區對象現在被***綁定的狀態機是按上下文存儲的。所有這些事情一起難以回答你現在寫的問題的方式;導致您調用'glBufferData(...)'的一些實際代碼將非常有用。 –

回答

0

我認爲問題是你在設置GLEW之前調用了glBufferData,所以指向glBufferData的函數指針沒有被初始化。請試試這個順序初始化程序:

  1. 初始化RenderWindow的
  2. 初始化GLEW
  3. 啓動線程,並根據需要創建額外的環境!
相關問題