使用第二个共享OpenGL上下文加载线程

时间:2014-01-07 19:15:03

标签: multithreading opengl sfml

我的计划是创建一个加载线程,我在其中加载游戏资源;例如3D模型,着色器,纹理等。在主线程上,我执行所有游戏逻辑和渲染。然后,在我的加载线程上,我创建了一个仅用于加载的sf :: Context(SFML共享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;
}

1 个答案:

答案 0 :(得分:0)

我认为问题是你在设置GLEW之前调用glBufferData,因此没有初始化glBufferData的函数指针。请尝试此订购以初始化您的程序:

  1. 初始化RenderWindow
  2. 初始化GLEW
  3. 启动线程,并根据需要创建其他上下文!