Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Loading thread using a second OpenGL context  (Read 1614 times)

0 Members and 1 Guest are viewing this topic.

homar

  • Newbie
  • *
  • Posts: 7
    • View Profile
Loading thread using a second OpenGL context
« on: January 07, 2014, 07:32:22 pm »
My plan was to create a loading thread inside of which I load resources such as 3D models, shaders, textures, etc. On the main thread I perform all the game logic and rendering. Then, on my loading thread, I create a sf::Context which is used only for loading.

This is working for loading shaders. However, xserver crashes when attempting to load models. I have narrowed the crash down to the glBufferData() call.

Is it possible call glBufferData() from a second thread using a second OpenGL context? If not, why is it possible to load shaders in the second context?

amir ramezani

  • Jr. Member
  • **
  • Posts: 81
  • i'm a programmer who can't see well
    • View Profile
    • download useful software!
    • Email
Re: Loading thread using a second OpenGL context
« Reply #1 on: January 07, 2014, 07:37:09 pm »
firstly, create your context and initialize it with a function
now initialize 2 threads, one for a function that initialize's the context, another for process the context
now, when you want to process it, you just call the lunch method
but, you have to give the functions in the thread constructor
if you can't see well, you can't test your applications and operating system well
my game engine:
allegro game creator
my operating system:
AmirOS

homar

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Loading thread using a second OpenGL context
« Reply #2 on: January 08, 2014, 12:16:45 am »
This is essentially what I am doing.
Please find below a small example program that reproduces the crash:

#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;
}